create-byan-agent 1.2.6 → 2.0.0-alpha.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.
- package/CHANGELOG.md +196 -388
- package/LICENSE +21 -21
- package/README.md +420 -1264
- package/bin/create-byan-agent-backup.js +220 -220
- package/bin/create-byan-agent-fixed.js +301 -301
- package/bin/create-byan-agent-v2.js +492 -0
- package/bin/create-byan-agent.js +296 -561
- package/package.json +68 -64
- package/templates/.github/agents/bmad-agent-bmad-master.md +15 -15
- package/templates/.github/agents/bmad-agent-bmb-agent-builder.md +15 -15
- package/templates/.github/agents/bmad-agent-bmb-module-builder.md +15 -15
- package/templates/.github/agents/bmad-agent-bmb-workflow-builder.md +15 -15
- package/templates/.github/agents/bmad-agent-bmm-analyst.md +15 -15
- package/templates/.github/agents/bmad-agent-bmm-architect.md +15 -15
- package/templates/.github/agents/bmad-agent-bmm-dev.md +15 -15
- package/templates/.github/agents/bmad-agent-bmm-pm.md +15 -15
- package/templates/.github/agents/bmad-agent-bmm-quick-flow-solo-dev.md +15 -15
- package/templates/.github/agents/bmad-agent-bmm-quinn.md +15 -15
- package/templates/.github/agents/bmad-agent-bmm-sm.md +15 -15
- package/templates/.github/agents/bmad-agent-bmm-tech-writer.md +15 -15
- package/templates/.github/agents/bmad-agent-bmm-ux-designer.md +15 -15
- package/templates/.github/agents/bmad-agent-byan-test.md +32 -32
- package/templates/.github/agents/bmad-agent-byan.md +224 -224
- package/templates/.github/agents/bmad-agent-carmack.md +18 -18
- package/templates/.github/agents/bmad-agent-cis-brainstorming-coach.md +15 -15
- package/templates/.github/agents/bmad-agent-cis-creative-problem-solver.md +15 -15
- package/templates/.github/agents/bmad-agent-cis-design-thinking-coach.md +15 -15
- package/templates/.github/agents/bmad-agent-cis-innovation-strategist.md +15 -15
- package/templates/.github/agents/bmad-agent-cis-presentation-master.md +15 -15
- package/templates/.github/agents/bmad-agent-cis-storyteller.md +15 -15
- package/templates/.github/agents/bmad-agent-marc.md +48 -48
- package/templates/.github/agents/bmad-agent-patnote.md +48 -48
- package/templates/.github/agents/bmad-agent-rachid.md +47 -47
- package/templates/.github/agents/bmad-agent-tea-tea.md +15 -15
- package/templates/.github/agents/bmad-agent-test-dynamic.md +21 -21
- package/templates/.github/agents/franck.md +379 -379
- package/templates/_bmad/bmb/agents/agent-builder.md +59 -59
- package/templates/_bmad/bmb/agents/byan-test.md +116 -116
- package/templates/_bmad/bmb/agents/byan.md +215 -215
- package/templates/_bmad/bmb/agents/marc.md +303 -303
- package/templates/_bmad/bmb/agents/module-builder.md +60 -60
- package/templates/_bmad/bmb/agents/patnote.md +495 -495
- package/templates/_bmad/bmb/agents/rachid.md +184 -184
- package/templates/_bmad/bmb/agents/workflow-builder.md +61 -61
- package/templates/_bmad/bmb/workflows/byan/data/mantras.yaml +272 -272
- package/templates/_bmad/bmb/workflows/byan/data/templates.yaml +59 -59
- package/templates/_bmad/bmb/workflows/byan/delete-agent-workflow.md +657 -657
- package/templates/_bmad/bmb/workflows/byan/edit-agent-workflow.md +688 -688
- package/templates/_bmad/bmb/workflows/byan/interview-workflow.md +753 -753
- package/templates/_bmad/bmb/workflows/byan/quick-create-workflow.md +450 -450
- package/templates/_bmad/bmb/workflows/byan/templates/base-agent-template.md +79 -79
- package/templates/_bmad/bmb/workflows/byan/validate-agent-workflow.md +676 -676
- package/templates/_bmad/core/agents/carmack.md +238 -238
- package/lib/errors.js +0 -61
- package/lib/exit-codes.js +0 -54
- package/lib/platforms/claude-code.js +0 -113
- package/lib/platforms/codex.js +0 -92
- package/lib/platforms/copilot-cli.js +0 -123
- package/lib/platforms/index.js +0 -14
- package/lib/platforms/vscode.js +0 -51
- package/lib/utils/config-loader.js +0 -79
- package/lib/utils/file-utils.js +0 -117
- package/lib/utils/git-detector.js +0 -35
- package/lib/utils/logger.js +0 -64
- package/lib/utils/node-detector.js +0 -58
- package/lib/utils/os-detector.js +0 -74
- package/lib/utils/yaml-utils.js +0 -87
- package/lib/yanstaller/backuper.js +0 -308
- package/lib/yanstaller/detector.js +0 -141
- package/lib/yanstaller/index.js +0 -93
- package/lib/yanstaller/installer.js +0 -226
- package/lib/yanstaller/interviewer.js +0 -301
- package/lib/yanstaller/recommender.js +0 -308
- package/lib/yanstaller/troubleshooter.js +0 -498
- package/lib/yanstaller/validator.js +0 -602
- package/lib/yanstaller/wizard.js +0 -229
- package/templates/.github/agents/expert-merise-agile.md +0 -1
package/bin/create-byan-agent.js
CHANGED
|
@@ -1,587 +1,322 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
const path = require('path');
|
|
4
|
-
const { program } = require('commander');
|
|
5
|
-
const { spawnSync, execSync } = require('child_process');
|
|
6
|
-
const fs = require('fs');
|
|
7
|
-
const os = require('os');
|
|
8
|
-
const chalk = require('chalk');
|
|
9
|
-
|
|
10
|
-
// YANSTALLER Modules
|
|
11
|
-
const detector = require('../lib/yanstaller/detector');
|
|
12
|
-
const recommender = require('../lib/yanstaller/recommender');
|
|
13
|
-
const interviewer = require('../lib/yanstaller/interviewer');
|
|
14
|
-
const installer = require('../lib/yanstaller/installer');
|
|
15
|
-
const validator = require('../lib/yanstaller/validator');
|
|
16
|
-
const wizard = require('../lib/yanstaller/wizard');
|
|
17
|
-
const backuper = require('../lib/yanstaller/backuper');
|
|
18
|
-
const logger = require('../lib/utils/logger');
|
|
19
|
-
|
|
20
|
-
const YANSTALLER_VERSION = '1.2.6';
|
|
1
|
+
#!/usr/bin/env node
|
|
21
2
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { program } = require('commander');
|
|
6
|
+
const inquirer = require('inquirer');
|
|
7
|
+
const chalk = require('chalk');
|
|
8
|
+
const ora = require('ora');
|
|
9
|
+
const yaml = require('js-yaml');
|
|
30
10
|
|
|
31
|
-
|
|
32
|
-
if (!name) return name;
|
|
33
|
-
const lower = String(name).toLowerCase();
|
|
34
|
-
if (lower === 'claude') return 'claude-code';
|
|
35
|
-
return lower;
|
|
36
|
-
}
|
|
11
|
+
const BYAN_VERSION = '1.1.3';
|
|
37
12
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
13
|
+
// ASCII Art Banner
|
|
14
|
+
const banner = `
|
|
15
|
+
${chalk.blue('╔════════════════════════════════════════════════════════════╗')}
|
|
16
|
+
${chalk.blue('║')} ${chalk.blue('║')}
|
|
17
|
+
${chalk.blue('║')} ${chalk.bold('🏗️ BYAN INSTALLER v' + BYAN_VERSION)} ${chalk.blue('║')}
|
|
18
|
+
${chalk.blue('║')} ${chalk.gray('Builder of YAN - Agent Creator')} ${chalk.blue('║')}
|
|
19
|
+
${chalk.blue('║')} ${chalk.blue('║')}
|
|
20
|
+
${chalk.blue('║')} ${chalk.gray('Methodology: Merise Agile + TDD + 64 Mantras')} ${chalk.blue('║')}
|
|
21
|
+
${chalk.blue('║')} ${chalk.blue('║')}
|
|
22
|
+
${chalk.blue('╚════════════════════════════════════════════════════════════╝')}
|
|
23
|
+
`;
|
|
41
24
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
25
|
+
// Source template directory (where BYAN package files are)
|
|
26
|
+
const getTemplateDir = () => {
|
|
27
|
+
// ✅ FIX #1: Correct path for npm/npx installation
|
|
28
|
+
// When running from node_modules/create-byan-agent/bin/
|
|
29
|
+
// We need to go up ONE level to reach templates/
|
|
30
|
+
const npmPackagePath = path.join(__dirname, '..', 'templates');
|
|
31
|
+
if (fs.existsSync(npmPackagePath)) {
|
|
32
|
+
console.log(chalk.gray(`[DEBUG] Template dir found: ${npmPackagePath}`));
|
|
33
|
+
return npmPackagePath;
|
|
45
34
|
}
|
|
46
|
-
return list;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function getCopilotCommand() {
|
|
50
|
-
try {
|
|
51
|
-
execSync('copilot --version', { stdio: 'ignore' });
|
|
52
|
-
return 'copilot';
|
|
53
|
-
} catch {}
|
|
54
35
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return
|
|
61
|
-
} catch {
|
|
62
|
-
return null;
|
|
36
|
+
// ✅ FIX #2: Alternative check for development mode
|
|
37
|
+
// If running from source during development
|
|
38
|
+
const devPath = path.join(__dirname, '..', '..', 'templates');
|
|
39
|
+
if (fs.existsSync(devPath)) {
|
|
40
|
+
console.log(chalk.gray(`[DEBUG] Dev template dir found: ${devPath}`));
|
|
41
|
+
return devPath;
|
|
63
42
|
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function getCodexCommand() {
|
|
67
|
-
try {
|
|
68
|
-
execSync('codex --version', { stdio: 'ignore' });
|
|
69
|
-
return 'codex';
|
|
70
|
-
} catch {}
|
|
71
43
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
} catch {
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
44
|
+
// ❌ Fallback: This shouldn't happen in production
|
|
45
|
+
console.error(chalk.red('⚠️ WARNING: Template directory not found!'));
|
|
46
|
+
console.error(chalk.red(` Searched: ${npmPackagePath}`));
|
|
47
|
+
console.error(chalk.red(` Also searched: ${devPath}`));
|
|
48
|
+
return null;
|
|
49
|
+
};
|
|
82
50
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
} catch {}
|
|
51
|
+
// Main installer
|
|
52
|
+
async function install() {
|
|
53
|
+
console.clear();
|
|
54
|
+
console.log(banner);
|
|
88
55
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
return JSON.parse(cleaned);
|
|
108
|
-
} catch {
|
|
109
|
-
const xmlMatch = cleaned.match(/<json>[\s\S]*?<\/json>/i);
|
|
110
|
-
if (xmlMatch) {
|
|
111
|
-
const inner = xmlMatch[0].replace(/<\/?json>/gi, '').trim();
|
|
112
|
-
try {
|
|
113
|
-
return JSON.parse(inner);
|
|
114
|
-
} catch {
|
|
115
|
-
return null;
|
|
56
|
+
const projectRoot = process.cwd();
|
|
57
|
+
|
|
58
|
+
// Step 1: Detect project type
|
|
59
|
+
const spinner = ora('Detecting project type...').start();
|
|
60
|
+
|
|
61
|
+
const isGitRepo = await fs.pathExists(path.join(projectRoot, '.git'));
|
|
62
|
+
const hasPackageJson = await fs.pathExists(path.join(projectRoot, 'package.json'));
|
|
63
|
+
const hasPyProject = await fs.pathExists(path.join(projectRoot, 'pyproject.toml'));
|
|
64
|
+
|
|
65
|
+
if (!isGitRepo && !hasPackageJson && !hasPyProject) {
|
|
66
|
+
spinner.warn('Not in a recognized project directory');
|
|
67
|
+
|
|
68
|
+
const { continueAnyway } = await inquirer.prompt([
|
|
69
|
+
{
|
|
70
|
+
type: 'confirm',
|
|
71
|
+
name: 'continueAnyway',
|
|
72
|
+
message: 'BYAN works best in a project with version control. Continue anyway?',
|
|
73
|
+
default: false
|
|
116
74
|
}
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
if (!continueAnyway) {
|
|
78
|
+
console.log(chalk.yellow('Installation cancelled.'));
|
|
79
|
+
process.exit(0);
|
|
117
80
|
}
|
|
118
|
-
const match = cleaned.match(/\{[\s\S]*\}/);
|
|
119
|
-
if (!match) return null;
|
|
120
|
-
try {
|
|
121
|
-
return JSON.parse(match[0]);
|
|
122
|
-
} catch {
|
|
123
|
-
return null;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function runCopilotInterview({ recommendation, detection, projectRoot }) {
|
|
129
|
-
const copilotCmd = getCopilotCommand();
|
|
130
|
-
if (!copilotCmd) {
|
|
131
|
-
return { error: 'Copilot CLI not found in PATH' };
|
|
132
|
-
}
|
|
133
|
-
const platforms = (detection && Array.isArray(detection.platforms)) ? detection.platforms : [];
|
|
134
|
-
const detectedNames = platforms.filter(p => p.detected).map(p => p.name);
|
|
135
|
-
const recommendedAgents = (recommendation && recommendation.agents) ? recommendation.agents : [];
|
|
136
|
-
const recommendedMode = (recommendation && recommendation.mode) ? recommendation.mode : 'recommended';
|
|
137
|
-
|
|
138
|
-
const prompt = [
|
|
139
|
-
'You are BYAN installer assistant.',
|
|
140
|
-
'Based on the project context, provide installation preferences as STRICT JSON only.',
|
|
141
|
-
'Do not include any extra text, markdown, or code fences.',
|
|
142
|
-
'If you must include extra text, wrap JSON between <json> and </json>.',
|
|
143
|
-
'',
|
|
144
|
-
`Project root: ${projectRoot}`,
|
|
145
|
-
`Detected platforms: ${detectedNames.join(', ') || 'none'}`,
|
|
146
|
-
`Recommended agents: ${recommendedAgents.join(', ') || 'none'}`,
|
|
147
|
-
`Recommended mode: ${recommendedMode}`,
|
|
148
|
-
'',
|
|
149
|
-
'Return JSON with keys:',
|
|
150
|
-
'userName (string), language (English|Francais), mode (recommended|minimal|full|custom),',
|
|
151
|
-
'agents (array of strings; required if mode=custom),',
|
|
152
|
-
'platforms (array from: copilot-cli,vscode,codex,claude-code),',
|
|
153
|
-
'createSampleAgent (boolean), createBackup (boolean).',
|
|
154
|
-
'',
|
|
155
|
-
'If unsure, choose recommended mode, recommended agents, and detected platforms.',
|
|
156
|
-
'JSON only.'
|
|
157
|
-
].join('\n');
|
|
158
|
-
|
|
159
|
-
const spawnOptions = { encoding: 'utf8', maxBuffer: 10 * 1024 * 1024 };
|
|
160
|
-
let result;
|
|
161
|
-
|
|
162
|
-
if (process.platform === 'win32') {
|
|
163
|
-
const tmpFile = path.join(os.tmpdir(), `byan-copilot-prompt-${Date.now()}.txt`);
|
|
164
|
-
fs.writeFileSync(tmpFile, prompt, 'utf8');
|
|
165
|
-
const psFile = path.join(os.tmpdir(), `byan-copilot-run-${Date.now()}.ps1`);
|
|
166
|
-
const psContent = [
|
|
167
|
-
`$p = Get-Content -Raw '${tmpFile}'`,
|
|
168
|
-
'copilot -p $p'
|
|
169
|
-
].join('\n');
|
|
170
|
-
fs.writeFileSync(psFile, psContent, 'utf8');
|
|
171
|
-
result = spawnSync('powershell.exe', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', psFile], spawnOptions);
|
|
172
|
-
try { fs.unlinkSync(tmpFile); } catch {}
|
|
173
|
-
try { fs.unlinkSync(psFile); } catch {}
|
|
174
81
|
} else {
|
|
175
|
-
|
|
176
|
-
}
|
|
177
|
-
if (result.error) {
|
|
178
|
-
return { error: result.error.message };
|
|
179
|
-
}
|
|
180
|
-
if (result.status !== 0) {
|
|
181
|
-
return { error: result.stderr || 'copilot returned non-zero status' };
|
|
182
|
-
}
|
|
183
|
-
const parsed = extractJson(result.stdout || '');
|
|
184
|
-
if (!parsed) {
|
|
185
|
-
return { error: 'Failed to parse JSON from copilot output' };
|
|
186
|
-
}
|
|
187
|
-
return { data: parsed };
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
function runCodexInterview({ recommendation, detection, projectRoot }) {
|
|
191
|
-
const codexCmd = getCodexCommand();
|
|
192
|
-
if (!codexCmd) {
|
|
193
|
-
return { error: 'Codex CLI not found in PATH' };
|
|
82
|
+
spinner.succeed('Project detected');
|
|
194
83
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
''
|
|
257
|
-
'
|
|
258
|
-
'
|
|
259
|
-
|
|
260
|
-
'platforms (array from: copilot-cli,vscode,codex,claude-code),',
|
|
261
|
-
'createSampleAgent (boolean), createBackup (boolean).',
|
|
262
|
-
'',
|
|
263
|
-
'If unsure, choose recommended mode, recommended agents, and detected platforms.',
|
|
264
|
-
'JSON only.'
|
|
265
|
-
].join('\n');
|
|
266
|
-
|
|
267
|
-
const spawnOptions = { encoding: 'utf8', maxBuffer: 10 * 1024 * 1024 };
|
|
268
|
-
const result = spawnSync(claudeCmd, ['-p', prompt], spawnOptions);
|
|
269
|
-
if (result.error) {
|
|
270
|
-
return { error: result.error.message };
|
|
271
|
-
}
|
|
272
|
-
if (result.status !== 0) {
|
|
273
|
-
return { error: result.stderr || 'claude returned non-zero status' };
|
|
274
|
-
}
|
|
275
|
-
const parsed = extractJson(result.stdout || '');
|
|
276
|
-
if (!parsed) {
|
|
277
|
-
return { error: 'Failed to parse JSON from claude output' };
|
|
84
|
+
|
|
85
|
+
// Step 2: Platform selection
|
|
86
|
+
const { platform } = await inquirer.prompt([
|
|
87
|
+
{
|
|
88
|
+
type: 'list',
|
|
89
|
+
name: 'platform',
|
|
90
|
+
message: 'Select platform to install for:',
|
|
91
|
+
choices: [
|
|
92
|
+
{ name: 'GitHub Copilot CLI', value: 'copilot' },
|
|
93
|
+
{ name: 'VSCode', value: 'vscode' },
|
|
94
|
+
{ name: 'Claude Code', value: 'claude' },
|
|
95
|
+
{ name: 'Codex', value: 'codex' },
|
|
96
|
+
{ name: 'All platforms', value: 'all' }
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
]);
|
|
100
|
+
|
|
101
|
+
// Step 3: User configuration
|
|
102
|
+
const config = await inquirer.prompt([
|
|
103
|
+
{
|
|
104
|
+
type: 'input',
|
|
105
|
+
name: 'userName',
|
|
106
|
+
message: 'Your name:',
|
|
107
|
+
default: 'Developer'
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
type: 'list',
|
|
111
|
+
name: 'language',
|
|
112
|
+
message: 'Communication language:',
|
|
113
|
+
choices: ['Francais', 'English'],
|
|
114
|
+
default: 'English'
|
|
115
|
+
}
|
|
116
|
+
]);
|
|
117
|
+
|
|
118
|
+
// Step 4: Create directory structure
|
|
119
|
+
const installSpinner = ora('Creating directory structure...').start();
|
|
120
|
+
|
|
121
|
+
const bmadDir = path.join(projectRoot, '_bmad');
|
|
122
|
+
const bmbDir = path.join(bmadDir, 'bmb');
|
|
123
|
+
const githubAgentsDir = path.join(projectRoot, '.github', 'agents');
|
|
124
|
+
|
|
125
|
+
await fs.ensureDir(path.join(bmadDir, 'bmb', 'agents'));
|
|
126
|
+
await fs.ensureDir(path.join(bmadDir, 'bmb', 'workflows', 'byan', 'steps'));
|
|
127
|
+
await fs.ensureDir(path.join(bmadDir, 'bmb', 'workflows', 'byan', 'templates'));
|
|
128
|
+
await fs.ensureDir(path.join(bmadDir, 'bmb', 'workflows', 'byan', 'data'));
|
|
129
|
+
await fs.ensureDir(path.join(bmadDir, 'core'));
|
|
130
|
+
await fs.ensureDir(path.join(bmadDir, '_config'));
|
|
131
|
+
await fs.ensureDir(path.join(bmadDir, '_memory'));
|
|
132
|
+
await fs.ensureDir(path.join(bmadDir, '_output'));
|
|
133
|
+
await fs.ensureDir(githubAgentsDir);
|
|
134
|
+
|
|
135
|
+
installSpinner.succeed('Directory structure created');
|
|
136
|
+
|
|
137
|
+
// Step 5: Copy BYAN files from template
|
|
138
|
+
const copySpinner = ora('Installing BYAN files...').start();
|
|
139
|
+
|
|
140
|
+
const templateDir = getTemplateDir();
|
|
141
|
+
|
|
142
|
+
// ✅ FIX #3: Validate template directory before proceeding
|
|
143
|
+
if (!templateDir) {
|
|
144
|
+
copySpinner.fail('❌ Template directory not found! Cannot proceed.');
|
|
145
|
+
console.error(chalk.red('\nInstallation failed: Missing template files.'));
|
|
146
|
+
console.error(chalk.yellow('This usually means the package was not installed correctly.'));
|
|
147
|
+
console.error(chalk.yellow('Try reinstalling: npm install -g create-byan-agent'));
|
|
148
|
+
process.exit(1);
|
|
278
149
|
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
const
|
|
284
|
-
${chalk.blue('╔════════════════════════════════════════════════════════════╗')}
|
|
285
|
-
${chalk.blue('║')} ${chalk.blue('║')}
|
|
286
|
-
${chalk.blue('║')} ${chalk.bold('🏗️ YANSTALLER v' + YANSTALLER_VERSION)} ${chalk.blue('║')}
|
|
287
|
-
${chalk.blue('║')} ${chalk.gray('Intelligent BYAN Installer')} ${chalk.blue('║')}
|
|
288
|
-
${chalk.blue('║')} ${chalk.blue('║')}
|
|
289
|
-
${chalk.blue('║')} ${chalk.gray('Methodology: Merise Agile + TDD + 64 Mantras')} ${chalk.blue('║')}
|
|
290
|
-
${chalk.blue('║')} ${chalk.gray('29 Agents • Multi-Platform • Auto-Fix')} ${chalk.blue('║')}
|
|
291
|
-
${chalk.blue('║')} ${chalk.blue('║')}
|
|
292
|
-
${chalk.blue('╚════════════════════════════════════════════════════════════╝')}
|
|
293
|
-
`;
|
|
294
|
-
|
|
295
|
-
/**
|
|
296
|
-
* Main YANSTALLER Installation Flow
|
|
297
|
-
*
|
|
298
|
-
* Orchestrates the 7-step intelligent installation:
|
|
299
|
-
* 1. DETECT - Platform & project analysis
|
|
300
|
-
* 2. RECOMMEND - Intelligent agent recommendations
|
|
301
|
-
* 3. INTERVIEW - 7-question personalization
|
|
302
|
-
* 4. BACKUP - Pre-install safety (optional)
|
|
303
|
-
* 5. INSTALL - Core installation
|
|
304
|
-
* 6. VALIDATE - 10 automated checks
|
|
305
|
-
* 7. WIZARD - Post-install actions
|
|
306
|
-
*/
|
|
307
|
-
async function main(options = {}) {
|
|
308
|
-
try {
|
|
309
|
-
console.clear();
|
|
310
|
-
console.log(banner);
|
|
311
|
-
|
|
312
|
-
const projectRoot = process.cwd();
|
|
313
|
-
|
|
314
|
-
// STEP 1: DETECT - Platform & Project Analysis
|
|
315
|
-
logger.info(chalk.bold('\n🔍 STEP 1/7: Detection\n'));
|
|
316
|
-
const detection = await detector.detect({ projectRoot });
|
|
317
|
-
|
|
318
|
-
const platformNames = detection.platforms ? detection.platforms.map(p => p.name).join(', ') : 'none';
|
|
319
|
-
logger.info(`✓ Platforms detected: ${chalk.cyan(platformNames)}`);
|
|
320
|
-
if (detection.projectType) {
|
|
321
|
-
logger.info(`✓ Project type: ${chalk.cyan(detection.projectType)}`);
|
|
322
|
-
}
|
|
323
|
-
if (detection.framework) {
|
|
324
|
-
logger.info(`✓ Framework: ${chalk.cyan(detection.framework)}`);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
// STEP 2: RECOMMEND - Intelligent Agent Selection
|
|
328
|
-
logger.info(chalk.bold('\n🎯 STEP 2/7: Recommendations\n'));
|
|
329
|
-
const recommendations = await recommender.recommend({
|
|
330
|
-
projectRoot,
|
|
331
|
-
detection
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
if (recommendations.agents && recommendations.agents.length > 0) {
|
|
335
|
-
logger.info(`✓ Recommended agents: ${chalk.cyan(recommendations.agents.join(', '))}`);
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
// STEP 3: INTERVIEW - 7-Question Personalization
|
|
339
|
-
const isSilent = !!options.silent;
|
|
340
|
-
const forceInteractive = !!options.interactive;
|
|
341
|
-
const hasTty = !!process.stdin.isTTY;
|
|
342
|
-
const forceSilent = !hasTty && !isSilent && !forceInteractive;
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
// ✅ FIX #4: Copy agent files from _bmad/bmb/agents
|
|
153
|
+
const agentsSource = path.join(templateDir, '_bmad', 'bmb', 'agents');
|
|
154
|
+
const agentsDest = path.join(bmbDir, 'agents');
|
|
343
155
|
|
|
344
|
-
if (
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
156
|
+
if (await fs.pathExists(agentsSource)) {
|
|
157
|
+
await fs.copy(agentsSource, agentsDest, { overwrite: true });
|
|
158
|
+
copySpinner.text = 'Copied agent files...';
|
|
159
|
+
console.log(chalk.green(` ✓ Agents: ${agentsSource} → ${agentsDest}`));
|
|
160
|
+
} else {
|
|
161
|
+
copySpinner.warn(`⚠ Agent source not found: ${agentsSource}`);
|
|
349
162
|
}
|
|
350
163
|
|
|
351
|
-
|
|
164
|
+
// ✅ FIX #5: Copy workflow files from _bmad/bmb/workflows/byan
|
|
165
|
+
const workflowsSource = path.join(templateDir, '_bmad', 'bmb', 'workflows', 'byan');
|
|
166
|
+
const workflowsDest = path.join(bmbDir, 'workflows', 'byan');
|
|
352
167
|
|
|
353
|
-
if (
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
const parsedPlatforms = expandAllPlatforms(normalizePlatforms(parseList(options.platforms)));
|
|
358
|
-
|
|
359
|
-
let mode = options.mode || (parsedAgents.length > 0 ? 'custom' : (recommendations.mode || 'minimal'));
|
|
360
|
-
let agents = parsedAgents;
|
|
361
|
-
|
|
362
|
-
if (agents.length === 0) {
|
|
363
|
-
if (mode === 'recommended' && recommendations && recommendations.agents) {
|
|
364
|
-
agents = recommendations.agents;
|
|
365
|
-
} else if (mode === 'minimal' || mode === 'full') {
|
|
366
|
-
agents = recommender.getAgentList(mode);
|
|
367
|
-
} else if (mode === 'custom') {
|
|
368
|
-
logger.warn('Custom mode selected without agents. Falling back to recommendations.');
|
|
369
|
-
agents = recommendations.agents || ['byan'];
|
|
370
|
-
mode = 'recommended';
|
|
371
|
-
} else {
|
|
372
|
-
agents = recommendations.agents || ['byan'];
|
|
373
|
-
mode = recommendations.mode || 'minimal';
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
let targetPlatforms = parsedPlatforms;
|
|
378
|
-
if (targetPlatforms.length === 0) {
|
|
379
|
-
targetPlatforms = (detection.platforms || [])
|
|
380
|
-
.filter(p => p.detected)
|
|
381
|
-
.map(p => normalizePlatformName(p.name));
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
answers = {
|
|
385
|
-
userName: 'Developer',
|
|
386
|
-
language: 'English',
|
|
387
|
-
mode,
|
|
388
|
-
agents,
|
|
389
|
-
targetPlatforms,
|
|
390
|
-
createSampleAgent: false,
|
|
391
|
-
createBackup: options.backup !== false
|
|
392
|
-
};
|
|
168
|
+
if (await fs.pathExists(workflowsSource)) {
|
|
169
|
+
await fs.copy(workflowsSource, workflowsDest, { overwrite: true });
|
|
170
|
+
copySpinner.text = 'Copied workflow files...';
|
|
171
|
+
console.log(chalk.green(` ✓ Workflows: ${workflowsSource} → ${workflowsDest}`));
|
|
393
172
|
} else {
|
|
394
|
-
|
|
395
|
-
const useAgentInterview = wantsAgentInterview;
|
|
396
|
-
|
|
397
|
-
let agentDefaults = null;
|
|
398
|
-
|
|
399
|
-
if (useAgentInterview) {
|
|
400
|
-
let provider = null;
|
|
401
|
-
const requestedProvider = options.agentProvider ? String(options.agentProvider).toLowerCase() : 'auto';
|
|
402
|
-
const hasCopilot = !!getCopilotCommand();
|
|
403
|
-
const hasCodex = !!getCodexCommand();
|
|
404
|
-
const hasClaude = !!getClaudeCommand();
|
|
405
|
-
|
|
406
|
-
if (requestedProvider !== 'auto') {
|
|
407
|
-
if (requestedProvider === 'copilot' && hasCopilot) provider = 'copilot';
|
|
408
|
-
if (requestedProvider === 'codex' && hasCodex) provider = 'codex';
|
|
409
|
-
if (requestedProvider === 'claude' && hasClaude) provider = 'claude';
|
|
410
|
-
|
|
411
|
-
if (!provider) {
|
|
412
|
-
logger.info(`Requested agent provider "${requestedProvider}" is not available. Falling back to auto selection.`);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
if (!provider) {
|
|
417
|
-
if (hasCopilot) {
|
|
418
|
-
provider = 'copilot';
|
|
419
|
-
} else if (hasCodex) {
|
|
420
|
-
provider = 'codex';
|
|
421
|
-
} else if (hasClaude) {
|
|
422
|
-
provider = 'claude';
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
if (provider) {
|
|
427
|
-
const label = provider === 'copilot' ? 'Copilot CLI' : provider === 'codex' ? 'Codex CLI' : 'Claude CLI';
|
|
428
|
-
logger.info(chalk.bold('\nSTEP 3/7: Interview (agent-assisted)\n'));
|
|
429
|
-
logger.info(`Launching agent-assisted interview via ${label}...`);
|
|
430
|
-
|
|
431
|
-
const agentResult = provider === 'copilot'
|
|
432
|
-
? runCopilotInterview({ recommendation: recommendations, detection, projectRoot })
|
|
433
|
-
: provider === 'codex'
|
|
434
|
-
? runCodexInterview({ recommendation: recommendations, detection, projectRoot })
|
|
435
|
-
: runClaudeInterview({ recommendation: recommendations, detection, projectRoot });
|
|
436
|
-
|
|
437
|
-
if (agentResult && agentResult.data) {
|
|
438
|
-
logger.info(`${label} returned JSON defaults.`);
|
|
439
|
-
const data = agentResult.data;
|
|
440
|
-
const agentMode = data.mode || 'recommended';
|
|
441
|
-
|
|
442
|
-
let agentPlatforms = Array.isArray(data.platforms) ? data.platforms : [];
|
|
443
|
-
agentPlatforms = expandAllPlatforms(normalizePlatforms(agentPlatforms));
|
|
444
|
-
if (agentPlatforms.length === 0) {
|
|
445
|
-
agentPlatforms = (detection.platforms || [])
|
|
446
|
-
.filter(p => p.detected)
|
|
447
|
-
.map(p => normalizePlatformName(p.name));
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
let agentAgents = Array.isArray(data.agents) ? data.agents : [];
|
|
451
|
-
if (agentAgents.length === 0) {
|
|
452
|
-
if (agentMode === 'recommended' && recommendations && recommendations.agents) {
|
|
453
|
-
agentAgents = recommendations.agents;
|
|
454
|
-
} else if (agentMode === 'minimal' || agentMode === 'full') {
|
|
455
|
-
agentAgents = recommender.getAgentList(agentMode);
|
|
456
|
-
} else if (agentMode === 'custom') {
|
|
457
|
-
agentAgents = recommendations.agents || ['byan'];
|
|
458
|
-
} else {
|
|
459
|
-
agentAgents = recommendations.agents || ['byan'];
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
const language = data.language === 'Francais' ? 'Francais' : 'English';
|
|
464
|
-
|
|
465
|
-
agentDefaults = {
|
|
466
|
-
userName: data.userName || 'Developer',
|
|
467
|
-
language,
|
|
468
|
-
mode: agentMode,
|
|
469
|
-
agents: agentAgents,
|
|
470
|
-
platforms: agentPlatforms,
|
|
471
|
-
createSampleAgent: !!data.createSampleAgent,
|
|
472
|
-
createBackup: data.createBackup !== false
|
|
473
|
-
};
|
|
474
|
-
|
|
475
|
-
logger.info('Agent provided recommended defaults. You can edit them below.');
|
|
476
|
-
} else {
|
|
477
|
-
const errMsg = agentResult && agentResult.error ? agentResult.error : 'unknown error';
|
|
478
|
-
logger.info(`Agent interview unavailable: ${errMsg}`);
|
|
479
|
-
logger.info('Continuing with standard interactive interview.');
|
|
480
|
-
}
|
|
481
|
-
} else {
|
|
482
|
-
logger.info('No agent CLI detected (Copilot/Codex/Claude). Continuing with standard interactive interview.');
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
logger.info(chalk.bold('\nSTEP 3/7: Interview\n'));
|
|
487
|
-
const preferredPlatforms = expandAllPlatforms(normalizePlatforms(parseList(options.platforms)));
|
|
488
|
-
answers = await interviewer.ask(recommendations, {
|
|
489
|
-
detection,
|
|
490
|
-
preferredPlatforms: agentDefaults ? agentDefaults.platforms : preferredPlatforms,
|
|
491
|
-
defaults: agentDefaults || undefined
|
|
492
|
-
});
|
|
493
|
-
|
|
494
|
-
if (options.backup === false) {
|
|
495
|
-
answers.createBackup = false;
|
|
496
|
-
}
|
|
173
|
+
copySpinner.warn(`⚠ Workflow source not found: ${workflowsSource}`);
|
|
497
174
|
}
|
|
498
175
|
|
|
499
|
-
//
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
} catch (error) {
|
|
507
|
-
logger.warn(`⚠ Backup failed (non-critical): ${error.message}`);
|
|
508
|
-
}
|
|
509
|
-
} else {
|
|
510
|
-
logger.info(chalk.bold('\n⏭️ STEP 4/7: Backup (skipped)\n'));
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
// STEP 5: INSTALL - Core Installation
|
|
514
|
-
logger.info(chalk.bold('\n🚀 STEP 5/7: Installation\n'));
|
|
515
|
-
const installResult = await installer.install({
|
|
516
|
-
projectRoot,
|
|
517
|
-
agents: answers.agents,
|
|
518
|
-
targetPlatforms: answers.targetPlatforms,
|
|
519
|
-
userName: answers.userName,
|
|
520
|
-
language: answers.language,
|
|
521
|
-
mode: answers.mode
|
|
522
|
-
});
|
|
523
|
-
|
|
524
|
-
logger.info(`✓ Installed ${chalk.cyan(installResult.agentsInstalled)} agents`);
|
|
525
|
-
if (installResult.errors && installResult.errors.length > 0) {
|
|
526
|
-
logger.warn(`⚠ ${installResult.errors.length} installation errors`);
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
// STEP 6: VALIDATE - 10 Automated Checks
|
|
530
|
-
logger.info(chalk.bold('\n✅ STEP 6/7: Validation\n'));
|
|
531
|
-
const validation = await validator.validate({ projectRoot });
|
|
532
|
-
|
|
533
|
-
if (validation.valid) {
|
|
534
|
-
logger.info(chalk.green('✓ All validation checks passed!'));
|
|
535
|
-
} else {
|
|
536
|
-
logger.warn(chalk.yellow(`⚠ ${validation.errors.length} errors, ${validation.warnings.length} warnings`));
|
|
537
|
-
if (validation.errors.length > 0) {
|
|
538
|
-
validation.errors.forEach(err => logger.error(` ✗ ${err}`));
|
|
539
|
-
}
|
|
540
|
-
if (validation.warnings.length > 0) {
|
|
541
|
-
validation.warnings.forEach(warn => logger.warn(` ⚠ ${warn}`));
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
// STEP 7: WIZARD - Post-Install Actions
|
|
546
|
-
if (isSilent || forceSilent) {
|
|
547
|
-
logger.info(chalk.bold('\nSTEP 7/7: Post-Install Wizard (skipped - silent)\n'));
|
|
176
|
+
// ✅ FIX #6: Copy .github/agents files (stubs for Copilot CLI detection)
|
|
177
|
+
const githubAgentsSource = path.join(templateDir, '.github', 'agents');
|
|
178
|
+
|
|
179
|
+
if (await fs.pathExists(githubAgentsSource)) {
|
|
180
|
+
await fs.copy(githubAgentsSource, githubAgentsDir, { overwrite: true });
|
|
181
|
+
copySpinner.text = 'Copied Copilot CLI agent stubs...';
|
|
182
|
+
console.log(chalk.green(` ✓ GitHub agents: ${githubAgentsSource} → ${githubAgentsDir}`));
|
|
548
183
|
} else {
|
|
549
|
-
|
|
550
|
-
await wizard.show({
|
|
551
|
-
agents: answers.agents,
|
|
552
|
-
targetPlatforms: answers.targetPlatforms,
|
|
553
|
-
mode: answers.mode,
|
|
554
|
-
projectRoot,
|
|
555
|
-
userName: answers.userName,
|
|
556
|
-
language: answers.language
|
|
557
|
-
});
|
|
184
|
+
copySpinner.warn(`⚠ GitHub agents source not found: ${githubAgentsSource}`);
|
|
558
185
|
}
|
|
559
186
|
|
|
187
|
+
copySpinner.succeed('BYAN files installed');
|
|
560
188
|
} catch (error) {
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
.
|
|
579
|
-
.
|
|
580
|
-
|
|
581
|
-
.
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
189
|
+
copySpinner.fail('Error copying files');
|
|
190
|
+
console.error(chalk.red('Details:'), error.message);
|
|
191
|
+
console.error(chalk.red('Stack:'), error.stack);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Step 6: Create config.yaml
|
|
195
|
+
const configSpinner = ora('Generating configuration...').start();
|
|
196
|
+
|
|
197
|
+
const configContent = {
|
|
198
|
+
bmb_creations_output_folder: "{project-root}/_bmad-output/bmb-creations",
|
|
199
|
+
user_name: config.userName,
|
|
200
|
+
communication_language: config.language,
|
|
201
|
+
document_output_language: config.language,
|
|
202
|
+
output_folder: "{project-root}/_bmad-output",
|
|
203
|
+
platform: platform
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
const configPath = path.join(bmbDir, 'config.yaml');
|
|
207
|
+
await fs.writeFile(configPath, yaml.dump(configContent), 'utf8');
|
|
208
|
+
|
|
209
|
+
configSpinner.succeed('Configuration generated');
|
|
210
|
+
|
|
211
|
+
// Step 7: Create package.json script
|
|
212
|
+
const shortcutSpinner = ora('Creating shortcuts...').start();
|
|
213
|
+
|
|
214
|
+
if (hasPackageJson) {
|
|
215
|
+
const pkgPath = path.join(projectRoot, 'package.json');
|
|
216
|
+
const pkg = await fs.readJson(pkgPath);
|
|
217
|
+
|
|
218
|
+
if (!pkg.scripts) pkg.scripts = {};
|
|
219
|
+
|
|
220
|
+
if (!pkg.scripts.byan) {
|
|
221
|
+
pkg.scripts.byan = 'echo "BYAN agent installed. Use: copilot and type /agent"';
|
|
222
|
+
await fs.writeJson(pkgPath, pkg, { spaces: 2 });
|
|
223
|
+
shortcutSpinner.succeed('NPM script added');
|
|
224
|
+
} else {
|
|
225
|
+
shortcutSpinner.info('NPM script already exists');
|
|
226
|
+
}
|
|
227
|
+
} else {
|
|
228
|
+
shortcutSpinner.succeed('Shortcuts created');
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Step 8: Verification
|
|
232
|
+
const verifySpinner = ora('Verifying installation...').start();
|
|
233
|
+
|
|
234
|
+
const checks = [
|
|
235
|
+
{ name: 'Agents directory', path: path.join(bmbDir, 'agents') },
|
|
236
|
+
{ name: 'BYAN agent', path: path.join(bmbDir, 'agents', 'byan.md') },
|
|
237
|
+
{ name: 'RACHID agent', path: path.join(bmbDir, 'agents', 'rachid.md') },
|
|
238
|
+
{ name: 'MARC agent', path: path.join(bmbDir, 'agents', 'marc.md') },
|
|
239
|
+
{ name: 'Workflows', path: path.join(bmbDir, 'workflows', 'byan') },
|
|
240
|
+
{ name: 'Config', path: configPath },
|
|
241
|
+
{ name: 'GitHub agents dir', path: githubAgentsDir },
|
|
242
|
+
{ name: 'BYAN stub', path: path.join(githubAgentsDir, 'bmad-agent-byan.md') },
|
|
243
|
+
{ name: 'RACHID stub', path: path.join(githubAgentsDir, 'bmad-agent-rachid.md') },
|
|
244
|
+
{ name: 'MARC stub', path: path.join(githubAgentsDir, 'bmad-agent-marc.md') }
|
|
245
|
+
];
|
|
246
|
+
|
|
247
|
+
let passed = 0;
|
|
248
|
+
let failed = [];
|
|
249
|
+
|
|
250
|
+
for (const check of checks) {
|
|
251
|
+
if (await fs.pathExists(check.path)) {
|
|
252
|
+
passed++;
|
|
253
|
+
} else {
|
|
254
|
+
failed.push(check.name);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (passed === checks.length) {
|
|
259
|
+
verifySpinner.succeed(`Verification: ${passed}/${checks.length} checks passed ✅`);
|
|
260
|
+
} else {
|
|
261
|
+
verifySpinner.warn(`Verification: ${passed}/${checks.length} checks passed`);
|
|
262
|
+
if (failed.length > 0) {
|
|
263
|
+
console.log(chalk.yellow(' Missing:'), failed.join(', '));
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Success message
|
|
268
|
+
console.log('');
|
|
269
|
+
console.log(chalk.green('╔════════════════════════════════════════════════════════════╗'));
|
|
270
|
+
console.log(chalk.green('║ ║'));
|
|
271
|
+
console.log(chalk.green('║ ✅ BYAN INSTALLATION COMPLETE! ║'));
|
|
272
|
+
console.log(chalk.green('║ ║'));
|
|
273
|
+
console.log(chalk.green('╚════════════════════════════════════════════════════════════╝'));
|
|
274
|
+
console.log('');
|
|
275
|
+
|
|
276
|
+
console.log(chalk.bold('Installation Summary:'));
|
|
277
|
+
console.log(` • Platform: ${chalk.cyan(platform)}`);
|
|
278
|
+
console.log(` • Installation Directory: ${chalk.cyan(bmbDir)}`);
|
|
279
|
+
console.log(` • Configuration: ${chalk.cyan(configPath)}`);
|
|
280
|
+
console.log(` • User: ${chalk.cyan(config.userName)}`);
|
|
281
|
+
console.log(` • Language: ${chalk.cyan(config.language)}`);
|
|
282
|
+
console.log(` • Agents Installed: ${chalk.cyan('BYAN, RACHID, MARC')}`);
|
|
283
|
+
console.log('');
|
|
284
|
+
|
|
285
|
+
console.log(chalk.bold('Next Steps:'));
|
|
286
|
+
console.log('');
|
|
287
|
+
console.log(chalk.yellow('1. Activate agents in GitHub Copilot CLI:'));
|
|
288
|
+
console.log(` ${chalk.blue('copilot')}`);
|
|
289
|
+
console.log(` Then type: ${chalk.blue('/agent')}`);
|
|
290
|
+
console.log(` Select: ${chalk.cyan('byan')} (create agents)`);
|
|
291
|
+
console.log(` ${chalk.cyan('rachid')} (NPM deployment)`);
|
|
292
|
+
console.log(` ${chalk.cyan('marc')} (Copilot CLI integration)`);
|
|
293
|
+
console.log('');
|
|
294
|
+
|
|
295
|
+
console.log(chalk.yellow('2. Create your first agent with BYAN:'));
|
|
296
|
+
console.log(' [INT] Start Intelligent Interview (30-45 min)');
|
|
297
|
+
console.log(' [QC] Quick Create (10 min)');
|
|
298
|
+
console.log('');
|
|
299
|
+
|
|
300
|
+
console.log(chalk.yellow('3. Deploy with RACHID:'));
|
|
301
|
+
console.log(' Use RACHID to publish BYAN to npm');
|
|
302
|
+
console.log(' Validate package.json and dependencies');
|
|
303
|
+
console.log('');
|
|
304
|
+
|
|
305
|
+
console.log(chalk.yellow('4. Integrate with MARC:'));
|
|
306
|
+
console.log(' Use MARC to test /agent detection');
|
|
307
|
+
console.log(' Validate .github/agents/ structure');
|
|
308
|
+
console.log('');
|
|
309
|
+
|
|
310
|
+
console.log(chalk.gray('Need help? Type \'/bmad-help\' when BYAN is active'));
|
|
311
|
+
console.log('');
|
|
312
|
+
console.log(chalk.blue('Happy agent building! 🏗️'));
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// CLI Program
|
|
316
|
+
program
|
|
317
|
+
.name('create-byan-agent')
|
|
318
|
+
.description('Install BYAN - Builder of YAN agent creator with RACHID and MARC')
|
|
319
|
+
.version(BYAN_VERSION)
|
|
320
|
+
.action(install);
|
|
321
|
+
|
|
322
|
+
program.parse(process.argv);
|