create-byan-agent 2.7.1 → 2.7.2
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/create-byan-agent-v2.js +1 -1
- package/lib/domain-questions.js +235 -0
- package/lib/errors.js +61 -0
- package/lib/exit-codes.js +54 -0
- package/lib/phase2-chat.js +534 -0
- package/lib/platforms/claude-code.js +196 -0
- package/lib/platforms/codex.js +92 -0
- package/lib/platforms/copilot-cli.js +123 -0
- package/lib/platforms/index.js +14 -0
- package/lib/platforms/vscode.js +51 -0
- package/lib/project-agents-generator.js +238 -0
- package/lib/utils/config-loader.js +79 -0
- package/lib/utils/file-utils.js +104 -0
- package/lib/utils/git-detector.js +35 -0
- package/lib/utils/logger.js +64 -0
- package/lib/utils/node-detector.js +58 -0
- package/lib/utils/os-detector.js +74 -0
- package/lib/utils/yaml-utils.js +87 -0
- package/lib/yanstaller/agent-launcher.js +348 -0
- package/lib/yanstaller/backuper.js +108 -0
- package/lib/yanstaller/detector.js +141 -0
- package/lib/yanstaller/index.js +139 -0
- package/lib/yanstaller/installer.js +140 -0
- package/lib/yanstaller/interviewer.js +88 -0
- package/lib/yanstaller/platform-selector.js +328 -0
- package/lib/yanstaller/recommender.js +102 -0
- package/lib/yanstaller/troubleshooter.js +89 -0
- package/lib/yanstaller/validator.js +198 -0
- package/lib/yanstaller/wizard.js +109 -0
- package/package.json +3 -1
- package/setup-turbo-whisper.js +687 -0
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Phase 2 Chat - Integrated conversation within the wizard
|
|
3
|
+
*
|
|
4
|
+
* Provides an in-wizard chat experience with the yanstaller-phase2 agent
|
|
5
|
+
* using copilot/codex CLI for AI responses.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { spawnSync } = require('child_process');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const os = require('os');
|
|
11
|
+
const fs = require('fs-extra');
|
|
12
|
+
const inquirer = require('inquirer');
|
|
13
|
+
const chalk = require('chalk');
|
|
14
|
+
const ora = require('ora');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Cross-platform CLI command execution
|
|
18
|
+
* Uses spawnSync without shell on Unix (no character interpretation)
|
|
19
|
+
* Uses shell on Windows for .cmd file support
|
|
20
|
+
*/
|
|
21
|
+
function runCliCommand(cmd, args, cwd, stdinInput) {
|
|
22
|
+
const isWindows = process.platform === 'win32';
|
|
23
|
+
const opts = {
|
|
24
|
+
encoding: 'utf8',
|
|
25
|
+
cwd: cwd,
|
|
26
|
+
timeout: 60000,
|
|
27
|
+
maxBuffer: 1024 * 1024,
|
|
28
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
if (stdinInput) opts.input = stdinInput;
|
|
32
|
+
if (isWindows) opts.shell = true;
|
|
33
|
+
|
|
34
|
+
const res = spawnSync(cmd, args, opts);
|
|
35
|
+
if (res.error) throw res.error;
|
|
36
|
+
|
|
37
|
+
// Check for non-zero exit code with stderr
|
|
38
|
+
if (res.status !== 0 && res.stderr) {
|
|
39
|
+
const stderr = res.stderr.toString().trim();
|
|
40
|
+
if (stderr) throw new Error(stderr);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return (res.stdout || '').toString();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Build the initial context prompt from Phase 1 answers
|
|
48
|
+
*/
|
|
49
|
+
function buildPhase1Context(interviewAnswers, detectedPlatforms, userName, language) {
|
|
50
|
+
const platformsDetected = [];
|
|
51
|
+
if (detectedPlatforms.copilot) platformsDetected.push('GitHub Copilot CLI');
|
|
52
|
+
if (detectedPlatforms.codex) platformsDetected.push('OpenAI Codex');
|
|
53
|
+
if (detectedPlatforms.claude) platformsDetected.push('Claude Code');
|
|
54
|
+
if (detectedPlatforms.vscode) platformsDetected.push('VSCode');
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
user_name: userName || 'Developer',
|
|
58
|
+
communication_language: language || 'Francais',
|
|
59
|
+
project_type: interviewAnswers.projectType,
|
|
60
|
+
objectives: interviewAnswers.objectives,
|
|
61
|
+
team_size: interviewAnswers.teamSize,
|
|
62
|
+
experience: interviewAnswers.experience,
|
|
63
|
+
connectivity: interviewAnswers.connectivity,
|
|
64
|
+
gpu_available: interviewAnswers.gpu,
|
|
65
|
+
methodology: interviewAnswers.methodology,
|
|
66
|
+
domain: interviewAnswers.domain,
|
|
67
|
+
frequency: interviewAnswers.frequency,
|
|
68
|
+
quality_level: interviewAnswers.quality,
|
|
69
|
+
platforms_detected: platformsDetected,
|
|
70
|
+
platforms_string: platformsDetected.join(', ') || 'None'
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Generate the pre-prompt for Phase 2 agent
|
|
76
|
+
*/
|
|
77
|
+
function generatePhase2Preprompt(context) {
|
|
78
|
+
return `
|
|
79
|
+
## Profil Utilisateur Phase 1
|
|
80
|
+
|
|
81
|
+
- **Nom**: ${context.user_name}
|
|
82
|
+
- **Langue**: ${context.communication_language}
|
|
83
|
+
- **Type de projet**: ${context.project_type}
|
|
84
|
+
- **Domaine**: ${context.domain}
|
|
85
|
+
- **Objectifs**: ${Array.isArray(context.objectives) ? context.objectives.join(', ') : context.objectives}
|
|
86
|
+
- **Taille équipe**: ${context.team_size}
|
|
87
|
+
- **Expérience AI**: ${context.experience}
|
|
88
|
+
- **Connectivité**: ${context.connectivity}
|
|
89
|
+
- **GPU disponible**: ${context.gpu_available}
|
|
90
|
+
- **Méthodologie**: ${context.methodology}
|
|
91
|
+
- **Fréquence utilisation**: ${context.frequency}
|
|
92
|
+
- **Niveau qualité**: ${context.quality_level}
|
|
93
|
+
- **Plateformes détectées**: ${context.platforms_string}
|
|
94
|
+
|
|
95
|
+
## Écosystème BYAN - Agents Disponibles
|
|
96
|
+
|
|
97
|
+
### 🏛️ Hermes - Dispatcher Universel (NOUVEAU v2.3.2)
|
|
98
|
+
**Point d'entrée intelligent vers tout l'écosystème BYAN**
|
|
99
|
+
- **Rôle**: Router intelligent + Agent directory + Pipeline orchestrator
|
|
100
|
+
- **Invocation**: \`@hermes\`
|
|
101
|
+
- **Capabilities**:
|
|
102
|
+
- [LA] Liste 35+ agents par module (core, bmm, bmb, cis, tea)
|
|
103
|
+
- [REC] Smart routing: décris ta tâche → Hermes recommande les meilleurs agents
|
|
104
|
+
- [PIPE] Pipelines multi-agents (Feature Complete, Bug Fix, Idea→Code, etc.)
|
|
105
|
+
- [@agent] Invocation directe d'agents
|
|
106
|
+
- [?agent] Quick help sans charger l'agent
|
|
107
|
+
- **Quand recommander Hermes**: Toujours! C'est le meilleur point de départ pour découvrir et utiliser les agents BYAN.
|
|
108
|
+
|
|
109
|
+
### 📦 Core Module (Foundation)
|
|
110
|
+
- **bmad-master**: Executor & Orchestrator (workflows, tasks)
|
|
111
|
+
- **yanstaller**: Smart installer (c'est moi!)
|
|
112
|
+
- **expert-merise-agile**: Conception Merise Agile + MCD/MCT
|
|
113
|
+
|
|
114
|
+
### 🔨 BMB Module (Builders)
|
|
115
|
+
- **byan**: Agent creator via interview (12 questions, 64 mantras)
|
|
116
|
+
- **byan-v2**: Optimized BYAN v2
|
|
117
|
+
- **agent-builder**: Construction expert
|
|
118
|
+
- **marc**: GitHub Copilot integration specialist
|
|
119
|
+
- **rachid**: NPM/NPX deployment specialist
|
|
120
|
+
- **carmack**: Token optimizer
|
|
121
|
+
- **patnote**: Update manager
|
|
122
|
+
|
|
123
|
+
### 💼 BMM Module (Management - SDLC)
|
|
124
|
+
- **analyst** (Mary): Business analysis, market research
|
|
125
|
+
- **architect** (Winston): System design, tech stack
|
|
126
|
+
- **dev** (Amelia): Implementation, coding
|
|
127
|
+
- **pm** (John): Product management, PRD
|
|
128
|
+
- **sm** (Bob): Scrum master, sprint planning
|
|
129
|
+
- **quinn**: QA engineer, tests
|
|
130
|
+
- **tech-writer** (Paige): Documentation
|
|
131
|
+
- **ux-designer** (Sally): UX/UI design
|
|
132
|
+
- **quick-flow-solo-dev** (Barry): Fast brownfield dev
|
|
133
|
+
|
|
134
|
+
### 🎨 CIS Module (Creative & Innovation)
|
|
135
|
+
- **brainstorming-coach** (Carson): Ideation sessions
|
|
136
|
+
- **creative-problem-solver** (Dr. Quinn): Problem solving
|
|
137
|
+
- **design-thinking-coach** (Maya): Design thinking
|
|
138
|
+
- **innovation-strategist** (Victor): Innovation strategy
|
|
139
|
+
- **presentation-master** (Caravaggio): Presentations, slides
|
|
140
|
+
- **storyteller** (Sophia): Storytelling, narratives
|
|
141
|
+
|
|
142
|
+
### 🧪 TEA Module (Testing)
|
|
143
|
+
- **tea** (Murat): Master test architect (ATDD, NFR, CI/CD)
|
|
144
|
+
|
|
145
|
+
## Workflows Prédéfinis (via Hermes)
|
|
146
|
+
|
|
147
|
+
1. **Feature Complete**: PM → Architect → UX → SM → Dev → Tea
|
|
148
|
+
2. **Idea to Code**: PM → Architect → SM → Quick Flow
|
|
149
|
+
3. **New Agent**: BYAN (handles entire flow)
|
|
150
|
+
4. **Refactoring**: Architect → Dev → Tea
|
|
151
|
+
5. **Bug Fix**: Dev → Quinn
|
|
152
|
+
6. **Documentation**: Analyst → Tech Writer
|
|
153
|
+
7. **Quality Complete**: Tea → Quinn → code-review
|
|
154
|
+
|
|
155
|
+
## Instructions
|
|
156
|
+
|
|
157
|
+
Tu es YANSTALLER Phase 2. Commence par accueillir ${context.user_name} avec un résumé de son profil, puis engage une conversation pour configurer son écosystème d'agents BYAN.
|
|
158
|
+
|
|
159
|
+
**IMPORTANT**: Tu connais maintenant HERMES (v2.3.2) - le dispatcher universel. Recommande-le systématiquement comme point d'entrée pour découvrir et orchestrer les agents.
|
|
160
|
+
|
|
161
|
+
Adapte tes questions au domaine "${context.domain}" et au niveau d'expérience "${context.experience}".
|
|
162
|
+
|
|
163
|
+
Quand l'utilisateur dit "finaliser", "terminer" ou "c'est bon", génère la configuration JSON finale.
|
|
164
|
+
`.trim();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Send a message to the AI and get a response
|
|
169
|
+
*
|
|
170
|
+
* @param {string} message User message
|
|
171
|
+
* @param {string} systemContext System context/preprompt
|
|
172
|
+
* @param {string} conversationHistory Previous conversation
|
|
173
|
+
* @param {string} selectedPlatform Selected AI platform
|
|
174
|
+
* @param {string} projectRoot Project root directory
|
|
175
|
+
* @returns {Promise<string>} AI response
|
|
176
|
+
*/
|
|
177
|
+
async function sendChatMessage(message, systemContext, conversationHistory, selectedPlatform, projectRoot) {
|
|
178
|
+
const fullPrompt = `${systemContext}
|
|
179
|
+
|
|
180
|
+
## Historique de conversation:
|
|
181
|
+
${conversationHistory}
|
|
182
|
+
|
|
183
|
+
## Message utilisateur:
|
|
184
|
+
${message}
|
|
185
|
+
|
|
186
|
+
## Instructions:
|
|
187
|
+
Réponds de manière concise et naturelle. Si l'utilisateur dit "finaliser", génère le JSON de configuration.
|
|
188
|
+
Continue la conversation pour comprendre le projet et personnaliser les agents.`;
|
|
189
|
+
|
|
190
|
+
let result = '';
|
|
191
|
+
|
|
192
|
+
try {
|
|
193
|
+
if (selectedPlatform === 'copilot') {
|
|
194
|
+
result = runCliCommand('copilot', ['-p', fullPrompt, '-s'], projectRoot);
|
|
195
|
+
} else if (selectedPlatform === 'codex') {
|
|
196
|
+
// Codex takes prompt as argument to exec command
|
|
197
|
+
// --skip-git-repo-check needed when not in a trusted git repo
|
|
198
|
+
result = runCliCommand('codex', ['exec', '--skip-git-repo-check', fullPrompt], projectRoot);
|
|
199
|
+
} else if (selectedPlatform === 'claude') {
|
|
200
|
+
// Claude: separate system prompt from user query
|
|
201
|
+
// -p treats arg as user query; system context goes via --append-system-prompt-file
|
|
202
|
+
const claudeSystemCtx = `${systemContext}\n\n## Historique de conversation:\n${conversationHistory}\n\n## Instructions:\nRéponds de manière concise et naturelle. Si l'utilisateur dit "finaliser", génère le JSON de configuration.\nContinue la conversation pour comprendre le projet et personnaliser les agents.`;
|
|
203
|
+
const tmpFile = path.join(os.tmpdir(), `byan-claude-ctx-${Date.now()}.txt`);
|
|
204
|
+
fs.writeFileSync(tmpFile, claudeSystemCtx, 'utf8');
|
|
205
|
+
try {
|
|
206
|
+
result = runCliCommand('claude', [
|
|
207
|
+
'-p', message,
|
|
208
|
+
'--append-system-prompt-file', tmpFile
|
|
209
|
+
], projectRoot);
|
|
210
|
+
} finally {
|
|
211
|
+
try { fs.unlinkSync(tmpFile); } catch(e) {}
|
|
212
|
+
}
|
|
213
|
+
} else {
|
|
214
|
+
throw new Error(`Platform not supported: ${selectedPlatform}`);
|
|
215
|
+
}
|
|
216
|
+
} catch (error) {
|
|
217
|
+
const errMsg = (error.message || '').toLowerCase();
|
|
218
|
+
console.error(chalk.red(`\n❌ Erreur ${selectedPlatform}: ${error.message}`));
|
|
219
|
+
|
|
220
|
+
// Platform-specific login guidance
|
|
221
|
+
if (selectedPlatform === 'claude' && (errMsg.includes('auth') || errMsg.includes('api') || errMsg.includes('key') || errMsg.includes('login') || errMsg.includes('401'))) {
|
|
222
|
+
console.log('');
|
|
223
|
+
console.log(chalk.yellow(' 💡 Pour se connecter à Claude Code:'));
|
|
224
|
+
console.log(chalk.cyan(' 1. claude login'));
|
|
225
|
+
console.log(chalk.gray(' 2. ou: export ANTHROPIC_API_KEY=sk-ant-...'));
|
|
226
|
+
console.log(chalk.gray(' 3. ou dans Claude Code: /login'));
|
|
227
|
+
} else if (selectedPlatform === 'copilot') {
|
|
228
|
+
console.log(chalk.gray(' → copilot auth'));
|
|
229
|
+
} else if (selectedPlatform === 'codex') {
|
|
230
|
+
console.log(chalk.gray(' → codex login'));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
result = `Désolé, erreur de communication avec ${selectedPlatform}. Réessayez ou tapez "skip".`;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
result = result.replace(/\x1b\[[0-9;]*m/g, '').trim();
|
|
237
|
+
return result;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Launch integrated chat within the wizard
|
|
242
|
+
*
|
|
243
|
+
* @param {Object} options Configuration options
|
|
244
|
+
* @param {Object} options.interviewAnswers Phase 1 answers
|
|
245
|
+
* @param {Object} options.detectedPlatforms Detected AI platforms
|
|
246
|
+
* @param {string} options.selectedPlatform Selected AI platform to use
|
|
247
|
+
* @param {string} options.projectRoot Project root directory
|
|
248
|
+
* @param {string} options.templateDir Templates directory
|
|
249
|
+
* @param {string} options.userName User name
|
|
250
|
+
* @param {string} options.language Communication language
|
|
251
|
+
* @returns {Promise<Object|null>} Phase 2 results or null if cancelled
|
|
252
|
+
*/
|
|
253
|
+
async function launchPhase2Chat(options) {
|
|
254
|
+
const {
|
|
255
|
+
interviewAnswers,
|
|
256
|
+
detectedPlatforms,
|
|
257
|
+
selectedPlatform,
|
|
258
|
+
projectRoot,
|
|
259
|
+
templateDir,
|
|
260
|
+
userName,
|
|
261
|
+
language
|
|
262
|
+
} = options;
|
|
263
|
+
|
|
264
|
+
// Build context from Phase 1
|
|
265
|
+
const context = buildPhase1Context(interviewAnswers, detectedPlatforms, userName, language);
|
|
266
|
+
const systemContext = generatePhase2Preprompt(context);
|
|
267
|
+
|
|
268
|
+
// Pre-copy Phase 2 agent to project
|
|
269
|
+
const phase2AgentSource = path.join(templateDir, '.github', 'agents', 'bmad-agent-yanstaller-phase2.md');
|
|
270
|
+
const githubAgentsDir = path.join(projectRoot, '.github', 'agents');
|
|
271
|
+
|
|
272
|
+
if (await fs.pathExists(phase2AgentSource)) {
|
|
273
|
+
await fs.ensureDir(githubAgentsDir);
|
|
274
|
+
await fs.copy(phase2AgentSource, path.join(githubAgentsDir, 'bmad-agent-yanstaller-phase2.md'), { overwrite: true });
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Display Phase 2 header
|
|
278
|
+
console.log('');
|
|
279
|
+
console.log(chalk.magenta('╔════════════════════════════════════════════════════════════╗'));
|
|
280
|
+
console.log(chalk.magenta('║') + ' ' + chalk.magenta('║'));
|
|
281
|
+
console.log(chalk.magenta('║') + ` ${chalk.bold('💬 PHASE 2 - Conversation Yanstaller')} ` + chalk.magenta('║'));
|
|
282
|
+
console.log(chalk.magenta('║') + ` ${chalk.gray(`Mode interactif - Domaine: ${context.domain}`)} ` + chalk.magenta('║'));
|
|
283
|
+
console.log(chalk.magenta('║') + ' ' + chalk.magenta('║'));
|
|
284
|
+
console.log(chalk.magenta('╚════════════════════════════════════════════════════════════╝'));
|
|
285
|
+
console.log('');
|
|
286
|
+
console.log(chalk.gray(' Commandes: "finaliser" | "skip" | "aide"'));
|
|
287
|
+
console.log('');
|
|
288
|
+
|
|
289
|
+
// Check if any AI platform is available
|
|
290
|
+
if (!detectedPlatforms.copilot && !detectedPlatforms.codex && !detectedPlatforms.claude) {
|
|
291
|
+
console.log(chalk.yellow(' ⚠ Aucune plateforme AI détectée pour le chat.'));
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Get initial AI greeting
|
|
296
|
+
const spinner = ora('Yanstaller réfléchit...').start();
|
|
297
|
+
let conversationHistory = '';
|
|
298
|
+
|
|
299
|
+
const initialMessage = `Commence par accueillir l'utilisateur ${context.user_name} avec un résumé de son profil (domaine: ${context.domain}, objectifs: ${context.objectives ? context.objectives.join(', ') : 'non spécifiés'}) et pose ta première question pour personnaliser son installation BYAN.`;
|
|
300
|
+
|
|
301
|
+
const greeting = await sendChatMessage(initialMessage, systemContext, '', selectedPlatform, projectRoot);
|
|
302
|
+
spinner.stop();
|
|
303
|
+
|
|
304
|
+
console.log(chalk.cyan(' Yanstaller:'));
|
|
305
|
+
console.log(chalk.white(' ' + greeting.split('\n').join('\n ')));
|
|
306
|
+
console.log('');
|
|
307
|
+
|
|
308
|
+
conversationHistory += `Assistant: ${greeting}\n\n`;
|
|
309
|
+
|
|
310
|
+
// Chat loop using inquirer (avoids readline/inquirer conflict)
|
|
311
|
+
let phase2Config = null;
|
|
312
|
+
let continueChat = true;
|
|
313
|
+
|
|
314
|
+
while (continueChat) {
|
|
315
|
+
// Get user input using inquirer
|
|
316
|
+
const { userInput } = await inquirer.prompt([
|
|
317
|
+
{
|
|
318
|
+
type: 'input',
|
|
319
|
+
name: 'userInput',
|
|
320
|
+
message: '> Vous:',
|
|
321
|
+
prefix: ' '
|
|
322
|
+
}
|
|
323
|
+
]);
|
|
324
|
+
|
|
325
|
+
const input = userInput.trim().toLowerCase();
|
|
326
|
+
|
|
327
|
+
// Handle special commands
|
|
328
|
+
if (input === 'skip' || input === 'passer') {
|
|
329
|
+
console.log(chalk.gray(' Phase 2 ignorée.'));
|
|
330
|
+
return null;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (input === 'aide' || input === 'help') {
|
|
334
|
+
console.log('');
|
|
335
|
+
console.log(chalk.cyan(' Commandes disponibles:'));
|
|
336
|
+
console.log(chalk.gray(' finaliser - Générer la configuration et continuer'));
|
|
337
|
+
console.log(chalk.gray(' skip - Passer cette phase'));
|
|
338
|
+
console.log(chalk.gray(' aide - Afficher cette aide'));
|
|
339
|
+
console.log('');
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Add user message to history
|
|
344
|
+
conversationHistory += `Utilisateur: ${userInput}\n\n`;
|
|
345
|
+
|
|
346
|
+
// Check for finalization
|
|
347
|
+
const wantsFinal = input.includes('finaliser') ||
|
|
348
|
+
input.includes('terminer') ||
|
|
349
|
+
input.includes('c\'est bon') ||
|
|
350
|
+
input.includes('fini');
|
|
351
|
+
|
|
352
|
+
// Send to AI
|
|
353
|
+
const chatSpinner = ora('Yanstaller réfléchit...').start();
|
|
354
|
+
|
|
355
|
+
let aiPrompt = userInput;
|
|
356
|
+
if (wantsFinal) {
|
|
357
|
+
aiPrompt = `${userInput}
|
|
358
|
+
|
|
359
|
+
IMPORTANT: L'utilisateur veut finaliser. Génère maintenant la configuration JSON complète avec ce format exact:
|
|
360
|
+
\`\`\`json
|
|
361
|
+
{
|
|
362
|
+
"coreAgents": [...],
|
|
363
|
+
"optionalAgents": [...],
|
|
364
|
+
"agentRelationships": [...],
|
|
365
|
+
"projectStructure": {...},
|
|
366
|
+
"customAgentsToCreate": [...],
|
|
367
|
+
"recommendedModel": "string",
|
|
368
|
+
"rationale": "string"
|
|
369
|
+
}
|
|
370
|
+
\`\`\``;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
const response = await sendChatMessage(aiPrompt, systemContext, conversationHistory, selectedPlatform, projectRoot);
|
|
374
|
+
chatSpinner.stop();
|
|
375
|
+
|
|
376
|
+
console.log('');
|
|
377
|
+
console.log(chalk.cyan(' Yanstaller:'));
|
|
378
|
+
console.log(chalk.white(' ' + response.split('\n').join('\n ')));
|
|
379
|
+
console.log('');
|
|
380
|
+
|
|
381
|
+
conversationHistory += `Assistant: ${response}\n\n`;
|
|
382
|
+
|
|
383
|
+
// Try to extract JSON config from response
|
|
384
|
+
const jsonMatch = response.match(/```json\s*([\s\S]*?)```/) ||
|
|
385
|
+
response.match(/\{[\s\S]*"coreAgents"[\s\S]*\}/);
|
|
386
|
+
|
|
387
|
+
if (jsonMatch) {
|
|
388
|
+
try {
|
|
389
|
+
const jsonStr = jsonMatch[1] || jsonMatch[0];
|
|
390
|
+
phase2Config = JSON.parse(jsonStr.trim());
|
|
391
|
+
console.log(chalk.green(' ✓ Configuration extraite!'));
|
|
392
|
+
console.log('');
|
|
393
|
+
continueChat = false;
|
|
394
|
+
} catch (e) {
|
|
395
|
+
// JSON parse failed, continue conversation
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// If user wanted to finalize but we didn't get valid JSON
|
|
400
|
+
if (wantsFinal && !phase2Config) {
|
|
401
|
+
console.log(chalk.yellow(' ⚠ Configuration non générée. Réessayez "finaliser" ou "skip".'));
|
|
402
|
+
console.log('');
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
return phase2Config;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Fallback: Generate default config based on Phase 1 answers only
|
|
411
|
+
*/
|
|
412
|
+
function generateDefaultConfig(interviewAnswers, detectedPlatforms, selectedPlatform) {
|
|
413
|
+
const domain = interviewAnswers.domain;
|
|
414
|
+
const quality = interviewAnswers.quality;
|
|
415
|
+
|
|
416
|
+
// Domain-based defaults
|
|
417
|
+
const domainConfigs = {
|
|
418
|
+
'devops': {
|
|
419
|
+
coreAgents: [
|
|
420
|
+
{ name: 'byan', role: 'Meta-agent creator', expertise: ['agent orchestration'], complexity: 'simple' },
|
|
421
|
+
{ name: 'architect', role: 'Infrastructure design', expertise: ['cloud architecture', 'IaC'], complexity: 'complex' },
|
|
422
|
+
{ name: 'devops', role: 'CI/CD pipeline management', expertise: ['automation', 'deployment'], complexity: 'complex' },
|
|
423
|
+
{ name: 'security', role: 'Security scanning', expertise: ['container security', 'vulnerability analysis'], complexity: 'medium' }
|
|
424
|
+
],
|
|
425
|
+
optionalAgents: [
|
|
426
|
+
{ name: 'quinn', role: 'QA automation', expertise: ['testing'], when: 'Integration tests needed' }
|
|
427
|
+
],
|
|
428
|
+
customAgentsToCreate: [
|
|
429
|
+
{ name: 'pipeline-orchestrator', template: 'dev', focus: 'CI/CD optimization', mantras: ['IA-3 Automate Repeatable Work'] }
|
|
430
|
+
],
|
|
431
|
+
projectStructure: { type: 'monorepo', folders: ['infra/', 'pipelines/', 'scripts/'], keyFiles: ['.github/workflows/', 'Dockerfile'] }
|
|
432
|
+
},
|
|
433
|
+
'web': {
|
|
434
|
+
coreAgents: [
|
|
435
|
+
{ name: 'byan', role: 'Meta-agent creator', expertise: ['agent orchestration'], complexity: 'simple' },
|
|
436
|
+
{ name: 'ux-designer', role: 'User experience design', expertise: ['UI/UX', 'accessibility'], complexity: 'medium' },
|
|
437
|
+
{ name: 'dev', role: 'Frontend development', expertise: ['React', 'CSS', 'TypeScript'], complexity: 'medium' },
|
|
438
|
+
{ name: 'quinn', role: 'QA automation', expertise: ['E2E testing', 'visual regression'], complexity: 'medium' }
|
|
439
|
+
],
|
|
440
|
+
optionalAgents: [
|
|
441
|
+
{ name: 'tech-writer', role: 'Documentation', expertise: ['docs'], when: 'API documentation needed' }
|
|
442
|
+
],
|
|
443
|
+
customAgentsToCreate: [
|
|
444
|
+
{ name: 'component-architect', template: 'architect', focus: 'Component library design', mantras: ['IA-24 Clean Code'] }
|
|
445
|
+
],
|
|
446
|
+
projectStructure: { type: 'monorepo', folders: ['src/', 'components/', 'tests/'], keyFiles: ['package.json', 'tsconfig.json'] }
|
|
447
|
+
},
|
|
448
|
+
'backend/API': {
|
|
449
|
+
coreAgents: [
|
|
450
|
+
{ name: 'byan', role: 'Meta-agent creator', expertise: ['agent orchestration'], complexity: 'simple' },
|
|
451
|
+
{ name: 'architect', role: 'API design', expertise: ['REST', 'GraphQL', 'database'], complexity: 'complex' },
|
|
452
|
+
{ name: 'dev', role: 'Backend development', expertise: ['Node.js', 'Python', 'Go'], complexity: 'medium' },
|
|
453
|
+
{ name: 'data-analyst', role: 'Data modeling', expertise: ['Merise', 'SQL'], complexity: 'medium' }
|
|
454
|
+
],
|
|
455
|
+
optionalAgents: [
|
|
456
|
+
{ name: 'security', role: 'API security', expertise: ['OWASP'], when: 'Production deployment' }
|
|
457
|
+
],
|
|
458
|
+
customAgentsToCreate: [
|
|
459
|
+
{ name: 'api-designer', template: 'architect', focus: 'API contract design', mantras: ['IA-1 Trust But Verify'] }
|
|
460
|
+
],
|
|
461
|
+
projectStructure: { type: 'microservices', folders: ['src/', 'api/', 'models/', 'tests/'], keyFiles: ['openapi.yaml', 'docker-compose.yml'] }
|
|
462
|
+
},
|
|
463
|
+
'data/ML': {
|
|
464
|
+
coreAgents: [
|
|
465
|
+
{ name: 'byan', role: 'Meta-agent creator', expertise: ['agent orchestration'], complexity: 'simple' },
|
|
466
|
+
{ name: 'data-analyst', role: 'Data engineering', expertise: ['ETL', 'data modeling'], complexity: 'complex' },
|
|
467
|
+
{ name: 'dev', role: 'ML development', expertise: ['Python', 'TensorFlow', 'PyTorch'], complexity: 'complex' },
|
|
468
|
+
{ name: 'architect', role: 'Data architecture', expertise: ['data lakes', 'pipelines'], complexity: 'complex' }
|
|
469
|
+
],
|
|
470
|
+
optionalAgents: [
|
|
471
|
+
{ name: 'quinn', role: 'Model validation', expertise: ['testing'], when: 'Model accuracy validation needed' }
|
|
472
|
+
],
|
|
473
|
+
customAgentsToCreate: [
|
|
474
|
+
{ name: 'ml-ops', template: 'devops', focus: 'ML pipeline automation', mantras: ['IA-3 Automate Repeatable Work'] }
|
|
475
|
+
],
|
|
476
|
+
projectStructure: { type: 'monorepo', folders: ['data/', 'models/', 'notebooks/', 'pipelines/'], keyFiles: ['requirements.txt', 'dvc.yaml'] }
|
|
477
|
+
},
|
|
478
|
+
'mobile': {
|
|
479
|
+
coreAgents: [
|
|
480
|
+
{ name: 'byan', role: 'Meta-agent creator', expertise: ['agent orchestration'], complexity: 'simple' },
|
|
481
|
+
{ name: 'ux-designer', role: 'Mobile UX', expertise: ['iOS HIG', 'Material Design'], complexity: 'medium' },
|
|
482
|
+
{ name: 'dev', role: 'Mobile development', expertise: ['React Native', 'Flutter', 'Swift'], complexity: 'medium' },
|
|
483
|
+
{ name: 'quinn', role: 'Mobile testing', expertise: ['device testing', 'performance'], complexity: 'medium' }
|
|
484
|
+
],
|
|
485
|
+
optionalAgents: [
|
|
486
|
+
{ name: 'architect', role: 'App architecture', expertise: ['offline-first'], when: 'Offline support needed' }
|
|
487
|
+
],
|
|
488
|
+
customAgentsToCreate: [
|
|
489
|
+
{ name: 'platform-specialist', template: 'dev', focus: 'Platform-specific optimizations', mantras: ['IA-24 Clean Code'] }
|
|
490
|
+
],
|
|
491
|
+
projectStructure: { type: 'monorepo', folders: ['src/', 'ios/', 'android/', 'shared/'], keyFiles: ['app.json', 'package.json'] }
|
|
492
|
+
},
|
|
493
|
+
'multi-domain': {
|
|
494
|
+
coreAgents: [
|
|
495
|
+
{ name: 'byan', role: 'Meta-agent creator', expertise: ['agent orchestration'], complexity: 'simple' },
|
|
496
|
+
{ name: 'analyst', role: 'Requirements analysis', expertise: ['Merise', 'user stories'], complexity: 'medium' },
|
|
497
|
+
{ name: 'architect', role: 'System design', expertise: ['full-stack architecture'], complexity: 'complex' },
|
|
498
|
+
{ name: 'dev', role: 'Full-stack development', expertise: ['versatile'], complexity: 'medium' }
|
|
499
|
+
],
|
|
500
|
+
optionalAgents: [
|
|
501
|
+
{ name: 'pm', role: 'Project management', expertise: ['prioritization'], when: 'Multiple stakeholders' }
|
|
502
|
+
],
|
|
503
|
+
customAgentsToCreate: [],
|
|
504
|
+
projectStructure: { type: 'monorepo', folders: ['frontend/', 'backend/', 'shared/', 'docs/'], keyFiles: ['package.json', 'docker-compose.yml'] }
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
const config = domainConfigs[domain] || domainConfigs['multi-domain'];
|
|
509
|
+
|
|
510
|
+
// Add common fields
|
|
511
|
+
config.agentRelationships = [
|
|
512
|
+
{ from: 'analyst', to: 'architect', type: 'informs', description: 'Requirements inform architecture decisions' },
|
|
513
|
+
{ from: 'architect', to: 'dev', type: 'triggers', description: 'Architecture triggers implementation' }
|
|
514
|
+
];
|
|
515
|
+
|
|
516
|
+
// Set model based on quality and selected platform
|
|
517
|
+
if (selectedPlatform === 'claude') {
|
|
518
|
+
config.recommendedModel = quality === 'critical' ? 'claude-sonnet-4' : 'claude-haiku-4.5';
|
|
519
|
+
} else {
|
|
520
|
+
config.recommendedModel = quality === 'critical' ? 'claude-sonnet-4' :
|
|
521
|
+
quality === 'production' ? 'gpt-5.1-codex' : 'gpt-5-mini';
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
config.rationale = `Configuration par défaut pour projet ${domain}. Personnalisez via la conversation Phase 2 pour plus de précision.`;
|
|
525
|
+
|
|
526
|
+
return config;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
module.exports = {
|
|
530
|
+
launchPhase2Chat,
|
|
531
|
+
generateDefaultConfig,
|
|
532
|
+
buildPhase1Context,
|
|
533
|
+
generatePhase2Preprompt
|
|
534
|
+
};
|