create-byan-agent 1.2.5 → 1.2.6
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 +4 -1
- package/README.md +8 -0
- package/bin/create-byan-agent.js +335 -4
- package/lib/yanstaller/interviewer.js +61 -55
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,10 +5,13 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [1.2.
|
|
8
|
+
## [1.2.6] - 2026-02-04
|
|
9
9
|
|
|
10
10
|
### Added
|
|
11
11
|
- **Interactive override**: `--interactive` flag to force prompts even without TTY (useful in npm scripts).
|
|
12
|
+
- **Agent-assisted interview**: Copilot CLI can answer installer questions automatically (fallback to classic prompts).
|
|
13
|
+
- **Provider fallback**: If Copilot CLI is unavailable, use Codex CLI, then Claude CLI when available.
|
|
14
|
+
- **Agent provider override**: `--agent-provider=codex|copilot|claude` to force the interview source.
|
|
12
15
|
|
|
13
16
|
### Changed
|
|
14
17
|
- **Interview defaults**: Preselect detected or provided platforms during the interview.
|
package/README.md
CHANGED
|
@@ -1028,6 +1028,14 @@ create-byan-agent --mode=custom --platforms=copilot-cli
|
|
|
1028
1028
|
|
|
1029
1029
|
# Install on all supported platforms
|
|
1030
1030
|
create-byan-agent --platforms=all
|
|
1031
|
+
|
|
1032
|
+
# Disable agent-assisted interview (fallback to classic prompts)
|
|
1033
|
+
create-byan-agent --no-agent-interview
|
|
1034
|
+
|
|
1035
|
+
# Agent-assisted interview provider (auto selection)
|
|
1036
|
+
# Priority: Copilot CLI → Codex CLI → Claude CLI (if available)
|
|
1037
|
+
# Override provider explicitly (if installed):
|
|
1038
|
+
# create-byan-agent --agent-provider=codex
|
|
1031
1039
|
|
|
1032
1040
|
# Full installation without backup
|
|
1033
1041
|
create-byan-agent --mode=full --no-backup
|
package/bin/create-byan-agent.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const path = require('path');
|
|
4
|
-
const { program } = require('commander');
|
|
4
|
+
const { program } = require('commander');
|
|
5
|
+
const { spawnSync, execSync } = require('child_process');
|
|
6
|
+
const fs = require('fs');
|
|
7
|
+
const os = require('os');
|
|
5
8
|
const chalk = require('chalk');
|
|
6
9
|
|
|
7
10
|
// YANSTALLER Modules
|
|
@@ -14,7 +17,7 @@ const wizard = require('../lib/yanstaller/wizard');
|
|
|
14
17
|
const backuper = require('../lib/yanstaller/backuper');
|
|
15
18
|
const logger = require('../lib/utils/logger');
|
|
16
19
|
|
|
17
|
-
const YANSTALLER_VERSION = '1.2.
|
|
20
|
+
const YANSTALLER_VERSION = '1.2.6';
|
|
18
21
|
|
|
19
22
|
function parseList(value) {
|
|
20
23
|
if (!value) return [];
|
|
@@ -43,6 +46,239 @@ function expandAllPlatforms(list) {
|
|
|
43
46
|
return list;
|
|
44
47
|
}
|
|
45
48
|
|
|
49
|
+
function getCopilotCommand() {
|
|
50
|
+
try {
|
|
51
|
+
execSync('copilot --version', { stdio: 'ignore' });
|
|
52
|
+
return 'copilot';
|
|
53
|
+
} catch {}
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const isWin = process.platform === 'win32';
|
|
57
|
+
const probe = isWin ? 'where copilot' : 'which copilot';
|
|
58
|
+
const out = execSync(probe, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
|
|
59
|
+
const first = String(out).split(/\r?\n/).find(Boolean);
|
|
60
|
+
return first || null;
|
|
61
|
+
} catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function getCodexCommand() {
|
|
67
|
+
try {
|
|
68
|
+
execSync('codex --version', { stdio: 'ignore' });
|
|
69
|
+
return 'codex';
|
|
70
|
+
} catch {}
|
|
71
|
+
|
|
72
|
+
try {
|
|
73
|
+
const isWin = process.platform === 'win32';
|
|
74
|
+
const probe = isWin ? 'where codex' : 'which codex';
|
|
75
|
+
const out = execSync(probe, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
|
|
76
|
+
const first = String(out).split(/\r?\n/).find(Boolean);
|
|
77
|
+
return first || null;
|
|
78
|
+
} catch {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function getClaudeCommand() {
|
|
84
|
+
try {
|
|
85
|
+
execSync('claude --version', { stdio: 'ignore' });
|
|
86
|
+
return 'claude';
|
|
87
|
+
} catch {}
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const isWin = process.platform === 'win32';
|
|
91
|
+
const probe = isWin ? 'where claude' : 'which claude';
|
|
92
|
+
const out = execSync(probe, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
|
|
93
|
+
const first = String(out).split(/\r?\n/).find(Boolean);
|
|
94
|
+
return first || null;
|
|
95
|
+
} catch {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function stripAnsi(input) {
|
|
101
|
+
return input.replace(/\u001b\[[0-9;]*m/g, '');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function extractJson(text) {
|
|
105
|
+
const cleaned = stripAnsi(text).trim();
|
|
106
|
+
try {
|
|
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;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
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
|
+
} else {
|
|
175
|
+
result = spawnSync(copilotCmd, ['-p', prompt], spawnOptions);
|
|
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' };
|
|
194
|
+
}
|
|
195
|
+
const platforms = (detection && Array.isArray(detection.platforms)) ? detection.platforms : [];
|
|
196
|
+
const detectedNames = platforms.filter(p => p.detected).map(p => p.name);
|
|
197
|
+
const recommendedAgents = (recommendation && recommendation.agents) ? recommendation.agents : [];
|
|
198
|
+
const recommendedMode = (recommendation && recommendation.mode) ? recommendation.mode : 'recommended';
|
|
199
|
+
|
|
200
|
+
const prompt = [
|
|
201
|
+
'You are BYAN installer assistant.',
|
|
202
|
+
'Based on the project context, provide installation preferences as STRICT JSON only.',
|
|
203
|
+
'Do not include any extra text, markdown, or code fences.',
|
|
204
|
+
'If you must include extra text, wrap JSON between <json> and </json>.',
|
|
205
|
+
'',
|
|
206
|
+
`Project root: ${projectRoot}`,
|
|
207
|
+
`Detected platforms: ${detectedNames.join(', ') || 'none'}`,
|
|
208
|
+
`Recommended agents: ${recommendedAgents.join(', ') || 'none'}`,
|
|
209
|
+
`Recommended mode: ${recommendedMode}`,
|
|
210
|
+
'',
|
|
211
|
+
'Return JSON with keys:',
|
|
212
|
+
'userName (string), language (English|Francais), mode (recommended|minimal|full|custom),',
|
|
213
|
+
'agents (array of strings; required if mode=custom),',
|
|
214
|
+
'platforms (array from: copilot-cli,vscode,codex,claude-code),',
|
|
215
|
+
'createSampleAgent (boolean), createBackup (boolean).',
|
|
216
|
+
'',
|
|
217
|
+
'If unsure, choose recommended mode, recommended agents, and detected platforms.',
|
|
218
|
+
'JSON only.'
|
|
219
|
+
].join('\n');
|
|
220
|
+
|
|
221
|
+
const spawnOptions = { encoding: 'utf8', maxBuffer: 10 * 1024 * 1024, shell: process.platform === 'win32' };
|
|
222
|
+
const result = spawnSync(codexCmd, ['exec', prompt], spawnOptions);
|
|
223
|
+
if (result.error) {
|
|
224
|
+
return { error: result.error.message };
|
|
225
|
+
}
|
|
226
|
+
if (result.status !== 0) {
|
|
227
|
+
return { error: result.stderr || 'codex returned non-zero status' };
|
|
228
|
+
}
|
|
229
|
+
const parsed = extractJson(result.stdout || '');
|
|
230
|
+
if (!parsed) {
|
|
231
|
+
return { error: 'Failed to parse JSON from codex output' };
|
|
232
|
+
}
|
|
233
|
+
return { data: parsed };
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function runClaudeInterview({ recommendation, detection, projectRoot }) {
|
|
237
|
+
const claudeCmd = getClaudeCommand();
|
|
238
|
+
if (!claudeCmd) {
|
|
239
|
+
return { error: 'Claude CLI not found in PATH' };
|
|
240
|
+
}
|
|
241
|
+
const platforms = (detection && Array.isArray(detection.platforms)) ? detection.platforms : [];
|
|
242
|
+
const detectedNames = platforms.filter(p => p.detected).map(p => p.name);
|
|
243
|
+
const recommendedAgents = (recommendation && recommendation.agents) ? recommendation.agents : [];
|
|
244
|
+
const recommendedMode = (recommendation && recommendation.mode) ? recommendation.mode : 'recommended';
|
|
245
|
+
|
|
246
|
+
const prompt = [
|
|
247
|
+
'You are BYAN installer assistant.',
|
|
248
|
+
'Based on the project context, provide installation preferences as STRICT JSON only.',
|
|
249
|
+
'Do not include any extra text, markdown, or code fences.',
|
|
250
|
+
'If you must include extra text, wrap JSON between <json> and </json>.',
|
|
251
|
+
'',
|
|
252
|
+
`Project root: ${projectRoot}`,
|
|
253
|
+
`Detected platforms: ${detectedNames.join(', ') || 'none'}`,
|
|
254
|
+
`Recommended agents: ${recommendedAgents.join(', ') || 'none'}`,
|
|
255
|
+
`Recommended mode: ${recommendedMode}`,
|
|
256
|
+
'',
|
|
257
|
+
'Return JSON with keys:',
|
|
258
|
+
'userName (string), language (English|Francais), mode (recommended|minimal|full|custom),',
|
|
259
|
+
'agents (array of strings; required if mode=custom),',
|
|
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' };
|
|
278
|
+
}
|
|
279
|
+
return { data: parsed };
|
|
280
|
+
}
|
|
281
|
+
|
|
46
282
|
// ASCII Art Banner
|
|
47
283
|
const banner = `
|
|
48
284
|
${chalk.blue('╔════════════════════════════════════════════════════════════╗')}
|
|
@@ -155,11 +391,104 @@ async function main(options = {}) {
|
|
|
155
391
|
createBackup: options.backup !== false
|
|
156
392
|
};
|
|
157
393
|
} else {
|
|
394
|
+
const wantsAgentInterview = options.agentInterview !== false;
|
|
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
|
+
|
|
158
486
|
logger.info(chalk.bold('\nSTEP 3/7: Interview\n'));
|
|
159
487
|
const preferredPlatforms = expandAllPlatforms(normalizePlatforms(parseList(options.platforms)));
|
|
160
488
|
answers = await interviewer.ask(recommendations, {
|
|
161
489
|
detection,
|
|
162
|
-
preferredPlatforms
|
|
490
|
+
preferredPlatforms: agentDefaults ? agentDefaults.platforms : preferredPlatforms,
|
|
491
|
+
defaults: agentDefaults || undefined
|
|
163
492
|
});
|
|
164
493
|
|
|
165
494
|
if (options.backup === false) {
|
|
@@ -245,7 +574,9 @@ program
|
|
|
245
574
|
.version(YANSTALLER_VERSION)
|
|
246
575
|
.option('--silent', 'Silent installation (no prompts)')
|
|
247
576
|
.option('--interactive', 'Force interactive prompts even without TTY')
|
|
248
|
-
.option('--
|
|
577
|
+
.option('--no-agent-interview', 'Disable agent-assisted interview (Copilot CLI)')
|
|
578
|
+
.option('--agent-provider <provider>', 'Agent interview provider: auto|copilot|codex|claude')
|
|
579
|
+
.option('--agents <agents>', 'Comma-separated list of agents to install')
|
|
249
580
|
.option('--platforms <platforms>', 'Comma-separated list of platforms (copilot-cli,vscode,claude-code,codex)')
|
|
250
581
|
.option('--mode <mode>', 'Installation mode: recommended, custom, minimal, full')
|
|
251
582
|
.option('--no-backup', 'Skip pre-install backup')
|
|
@@ -53,6 +53,7 @@ function buildDefaultPlatforms(options = {}) {
|
|
|
53
53
|
* @returns {Promise<InterviewResult>}
|
|
54
54
|
*/
|
|
55
55
|
async function ask(recommendation, options = {}) {
|
|
56
|
+
const defaults = options.defaults || {};
|
|
56
57
|
logger.info(chalk.bold('\n🎙️ YANSTALLER Quick Interview\n'));
|
|
57
58
|
logger.info('Just 5-7 questions to personalize your BYAN installation (<5 min)\n');
|
|
58
59
|
|
|
@@ -62,7 +63,7 @@ async function ask(recommendation, options = {}) {
|
|
|
62
63
|
type: 'input',
|
|
63
64
|
name: 'userName',
|
|
64
65
|
message: 'What\'s your name?',
|
|
65
|
-
default: 'Developer',
|
|
66
|
+
default: defaults.userName || 'Developer',
|
|
66
67
|
validate: (input) => input.trim().length > 0 || 'Name cannot be empty'
|
|
67
68
|
}
|
|
68
69
|
]);
|
|
@@ -77,12 +78,13 @@ async function ask(recommendation, options = {}) {
|
|
|
77
78
|
{ name: 'English', value: 'English' },
|
|
78
79
|
{ name: 'Français', value: 'Francais' }
|
|
79
80
|
],
|
|
80
|
-
default: 'English'
|
|
81
|
+
default: (defaults.language === 'Francais' || defaults.language === 'English') ? defaults.language : 'English'
|
|
81
82
|
}
|
|
82
83
|
]);
|
|
83
84
|
|
|
84
85
|
// Q3: Installation mode (with recommendation)
|
|
85
|
-
const recommendedMode = recommendation ? recommendation.mode : 'recommended';
|
|
86
|
+
const recommendedMode = recommendation ? recommendation.mode : 'recommended';
|
|
87
|
+
const defaultMode = defaults.mode || recommendedMode;
|
|
86
88
|
const modeChoices = [
|
|
87
89
|
{
|
|
88
90
|
name: `Recommended - Based on your project (${recommendation ? recommendation.agents.length : 7} agents)`,
|
|
@@ -112,7 +114,7 @@ async function ask(recommendation, options = {}) {
|
|
|
112
114
|
name: 'mode',
|
|
113
115
|
message: 'Installation mode?',
|
|
114
116
|
choices: modeChoices,
|
|
115
|
-
default:
|
|
117
|
+
default: defaultMode
|
|
116
118
|
}
|
|
117
119
|
]);
|
|
118
120
|
|
|
@@ -124,7 +126,7 @@ async function ask(recommendation, options = {}) {
|
|
|
124
126
|
type: 'checkbox',
|
|
125
127
|
name: 'agents',
|
|
126
128
|
message: 'Select agents to install:',
|
|
127
|
-
choices: getAgentChoices(),
|
|
129
|
+
choices: getAgentChoices(defaults.agents),
|
|
128
130
|
pageSize: 15,
|
|
129
131
|
validate: (input) => input.length > 0 || 'Select at least one agent'
|
|
130
132
|
}
|
|
@@ -181,7 +183,7 @@ async function ask(recommendation, options = {}) {
|
|
|
181
183
|
type: 'confirm',
|
|
182
184
|
name: 'createSample',
|
|
183
185
|
message: 'Launch BYAN agent creator after installation?',
|
|
184
|
-
default: false
|
|
186
|
+
default: typeof defaults.createSampleAgent === 'boolean' ? defaults.createSampleAgent : false
|
|
185
187
|
}
|
|
186
188
|
]);
|
|
187
189
|
|
|
@@ -191,7 +193,7 @@ async function ask(recommendation, options = {}) {
|
|
|
191
193
|
type: 'confirm',
|
|
192
194
|
name: 'createBackup',
|
|
193
195
|
message: 'Create backup of existing _bmad/ directory? (if exists)',
|
|
194
|
-
default: true
|
|
196
|
+
default: typeof defaults.createBackup === 'boolean' ? defaults.createBackup : true
|
|
195
197
|
}
|
|
196
198
|
]);
|
|
197
199
|
|
|
@@ -235,54 +237,58 @@ async function askQuestion(question, type, choices = []) {
|
|
|
235
237
|
*
|
|
236
238
|
* @returns {Array<{name: string, value: string, checked: boolean}>}
|
|
237
239
|
*/
|
|
238
|
-
function getAgentChoices() {
|
|
239
|
-
|
|
240
|
-
// BMB Module - Builders
|
|
241
|
-
{ name: '
|
|
242
|
-
{ name: '
|
|
243
|
-
{ name: '
|
|
244
|
-
{ name: '
|
|
245
|
-
{ name: '
|
|
246
|
-
|
|
247
|
-
// BMM Module - Development Team
|
|
248
|
-
{ name: '
|
|
249
|
-
{ name: '
|
|
250
|
-
{ name: '
|
|
251
|
-
{ name: '
|
|
252
|
-
{ name: '
|
|
253
|
-
{ name: '
|
|
254
|
-
{ name: '
|
|
255
|
-
{ name: '
|
|
256
|
-
|
|
257
|
-
// TEA Module - Testing
|
|
258
|
-
{ name: '
|
|
259
|
-
|
|
260
|
-
// CIS Module - Innovation
|
|
261
|
-
{ name: '
|
|
262
|
-
{ name: '
|
|
263
|
-
{ name: '
|
|
264
|
-
{ name: '
|
|
265
|
-
{ name: '
|
|
266
|
-
{ name: '
|
|
267
|
-
|
|
268
|
-
// Core Module
|
|
269
|
-
{ name: '
|
|
270
|
-
{ name: '
|
|
271
|
-
|
|
272
|
-
// Specialized
|
|
273
|
-
{ name: '
|
|
274
|
-
{ name: '
|
|
275
|
-
|
|
276
|
-
// Quick Flow Variants
|
|
277
|
-
{ name: '
|
|
278
|
-
];
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
240
|
+
function getAgentChoices(checkedAgents = []) {
|
|
241
|
+
const choices = [
|
|
242
|
+
// BMB Module - Builders
|
|
243
|
+
{ name: 'BYAN - Agent Creator & Intelligent Interview', value: 'byan', checked: true },
|
|
244
|
+
{ name: 'RACHID - NPM/NPX Deployment Specialist', value: 'rachid', checked: true },
|
|
245
|
+
{ name: 'Agent Builder - Direct agent creation', value: 'agent-builder', checked: false },
|
|
246
|
+
{ name: 'Module Builder - Module scaffolding', value: 'module-builder', checked: false },
|
|
247
|
+
{ name: 'Workflow Builder - Workflow creation', value: 'workflow-builder', checked: false },
|
|
248
|
+
|
|
249
|
+
// BMM Module - Development Team
|
|
250
|
+
{ name: 'MARY (Analyst) - Requirements & Domain Expert', value: 'analyst', checked: false },
|
|
251
|
+
{ name: 'JOHN (PM) - Product Management', value: 'pm', checked: false },
|
|
252
|
+
{ name: 'WINSTON (Architect) - System Architecture', value: 'architect', checked: false },
|
|
253
|
+
{ name: 'AMELIA (Dev) - Implementation Specialist', value: 'dev', checked: true },
|
|
254
|
+
{ name: 'BOB (SM) - Scrum Master', value: 'sm', checked: false },
|
|
255
|
+
{ name: 'QUINN (QA) - Quality Assurance', value: 'quinn', checked: false },
|
|
256
|
+
{ name: 'SALLY (UX) - UX/UI Design', value: 'ux-designer', checked: false },
|
|
257
|
+
{ name: 'PAIGE (Tech Writer) - Documentation', value: 'tech-writer', checked: true },
|
|
258
|
+
|
|
259
|
+
// TEA Module - Testing
|
|
260
|
+
{ name: 'MURAT (TEA) - Test Architecture Expert', value: 'tea', checked: false },
|
|
261
|
+
|
|
262
|
+
// CIS Module - Innovation
|
|
263
|
+
{ name: 'CARSON - Brainstorming Coach', value: 'brainstorming-coach', checked: false },
|
|
264
|
+
{ name: 'DR. QUINN - Design Thinking Coach', value: 'design-thinking-coach', checked: false },
|
|
265
|
+
{ name: 'MAYA - Creative Problem Solver', value: 'creative-problem-solver', checked: false },
|
|
266
|
+
{ name: 'VICTOR - Innovation Strategist', value: 'innovation-strategist', checked: false },
|
|
267
|
+
{ name: 'Presentation Master', value: 'presentation-master', checked: false },
|
|
268
|
+
{ name: 'Storyteller', value: 'storyteller', checked: false },
|
|
269
|
+
|
|
270
|
+
// Core Module
|
|
271
|
+
{ name: 'Party Mode - Multi-agent orchestration', value: 'party-mode', checked: false },
|
|
272
|
+
{ name: 'BMAD Master - Platform orchestrator', value: 'bmad-master', checked: false },
|
|
273
|
+
|
|
274
|
+
// Specialized
|
|
275
|
+
{ name: 'MARC - GitHub Copilot CLI Integration', value: 'marc', checked: false },
|
|
276
|
+
{ name: 'PATNOTE - Update Manager', value: 'patnote', checked: false },
|
|
277
|
+
|
|
278
|
+
// Quick Flow Variants
|
|
279
|
+
{ name: 'Quick Flow Solo Dev', value: 'quick-flow-solo-dev', checked: false }
|
|
280
|
+
];
|
|
281
|
+
|
|
282
|
+
if (Array.isArray(checkedAgents) && checkedAgents.length > 0) {
|
|
283
|
+
return choices.map(choice => ({
|
|
284
|
+
...choice,
|
|
285
|
+
checked: checkedAgents.includes(choice.value)
|
|
286
|
+
}));
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return choices;
|
|
290
|
+
}
|
|
291
|
+
|
|
286
292
|
function getAllAgents() {
|
|
287
293
|
return getAgentChoices().map(choice => choice.value);
|
|
288
294
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-byan-agent",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.6",
|
|
4
4
|
"description": "NPX installer for BYAN ecosystem - Agent creators (BYAN, BYAN-Test) with deployment (RACHID), integration (MARC), updates (PATNOTE), and optimization (CARMACK)",
|
|
5
5
|
"bin": {
|
|
6
6
|
"create-byan-agent": "bin/create-byan-agent.js"
|