create-byan-agent 1.1.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. package/CHANGELOG.md +250 -177
  2. package/LICENSE +21 -21
  3. package/README.md +1245 -421
  4. package/bin/create-byan-agent-backup.js +220 -220
  5. package/bin/create-byan-agent-fixed.js +301 -301
  6. package/bin/create-byan-agent.js +322 -301
  7. package/lib/errors.js +61 -0
  8. package/lib/exit-codes.js +54 -0
  9. package/lib/platforms/claude-code.js +113 -0
  10. package/lib/platforms/codex.js +92 -0
  11. package/lib/platforms/copilot-cli.js +123 -0
  12. package/lib/platforms/index.js +14 -0
  13. package/lib/platforms/vscode.js +51 -0
  14. package/lib/utils/config-loader.js +79 -0
  15. package/lib/utils/file-utils.js +104 -0
  16. package/lib/utils/git-detector.js +35 -0
  17. package/lib/utils/logger.js +64 -0
  18. package/lib/utils/node-detector.js +58 -0
  19. package/lib/utils/os-detector.js +74 -0
  20. package/lib/utils/yaml-utils.js +87 -0
  21. package/lib/yanstaller/backuper.js +308 -0
  22. package/lib/yanstaller/detector.js +141 -0
  23. package/lib/yanstaller/index.js +93 -0
  24. package/lib/yanstaller/installer.js +225 -0
  25. package/lib/yanstaller/interviewer.js +250 -0
  26. package/lib/yanstaller/recommender.js +298 -0
  27. package/lib/yanstaller/troubleshooter.js +498 -0
  28. package/lib/yanstaller/validator.js +578 -0
  29. package/lib/yanstaller/wizard.js +211 -0
  30. package/package.json +61 -55
  31. package/templates/.github/agents/bmad-agent-bmad-master.md +15 -15
  32. package/templates/.github/agents/bmad-agent-bmb-agent-builder.md +15 -15
  33. package/templates/.github/agents/bmad-agent-bmb-module-builder.md +15 -15
  34. package/templates/.github/agents/bmad-agent-bmb-workflow-builder.md +15 -15
  35. package/templates/.github/agents/bmad-agent-bmm-analyst.md +15 -15
  36. package/templates/.github/agents/bmad-agent-bmm-architect.md +15 -15
  37. package/templates/.github/agents/bmad-agent-bmm-dev.md +15 -15
  38. package/templates/.github/agents/bmad-agent-bmm-pm.md +15 -15
  39. package/templates/.github/agents/bmad-agent-bmm-quick-flow-solo-dev.md +15 -15
  40. package/templates/.github/agents/bmad-agent-bmm-quinn.md +15 -15
  41. package/templates/.github/agents/bmad-agent-bmm-sm.md +15 -15
  42. package/templates/.github/agents/bmad-agent-bmm-tech-writer.md +15 -15
  43. package/templates/.github/agents/bmad-agent-bmm-ux-designer.md +15 -15
  44. package/templates/.github/agents/bmad-agent-byan-test.md +32 -0
  45. package/templates/.github/agents/bmad-agent-byan.md +224 -224
  46. package/templates/.github/agents/bmad-agent-carmack.md +18 -0
  47. package/templates/.github/agents/bmad-agent-cis-brainstorming-coach.md +15 -15
  48. package/templates/.github/agents/bmad-agent-cis-creative-problem-solver.md +15 -15
  49. package/templates/.github/agents/bmad-agent-cis-design-thinking-coach.md +15 -15
  50. package/templates/.github/agents/bmad-agent-cis-innovation-strategist.md +15 -15
  51. package/templates/.github/agents/bmad-agent-cis-presentation-master.md +15 -15
  52. package/templates/.github/agents/bmad-agent-cis-storyteller.md +15 -15
  53. package/templates/.github/agents/bmad-agent-marc.md +48 -48
  54. package/templates/.github/agents/bmad-agent-patnote.md +48 -0
  55. package/templates/.github/agents/bmad-agent-rachid.md +47 -47
  56. package/templates/.github/agents/bmad-agent-tea-tea.md +15 -15
  57. package/templates/.github/agents/bmad-agent-test-dynamic.md +21 -0
  58. package/templates/.github/agents/expert-merise-agile.md +1 -0
  59. package/templates/.github/agents/franck.md +379 -0
  60. package/templates/_bmad/bmb/agents/agent-builder.md +59 -59
  61. package/templates/_bmad/bmb/agents/byan-test.md +116 -116
  62. package/templates/_bmad/bmb/agents/byan.md +215 -215
  63. package/templates/_bmad/bmb/agents/marc.md +303 -303
  64. package/templates/_bmad/bmb/agents/module-builder.md +60 -60
  65. package/templates/_bmad/bmb/agents/patnote.md +495 -495
  66. package/templates/_bmad/bmb/agents/rachid.md +184 -184
  67. package/templates/_bmad/bmb/agents/workflow-builder.md +61 -61
  68. package/templates/_bmad/bmb/workflows/byan/data/mantras.yaml +272 -272
  69. package/templates/_bmad/bmb/workflows/byan/data/templates.yaml +59 -59
  70. package/templates/_bmad/bmb/workflows/byan/delete-agent-workflow.md +657 -657
  71. package/templates/_bmad/bmb/workflows/byan/edit-agent-workflow.md +688 -688
  72. package/templates/_bmad/bmb/workflows/byan/interview-workflow.md +753 -753
  73. package/templates/_bmad/bmb/workflows/byan/quick-create-workflow.md +450 -450
  74. package/templates/_bmad/bmb/workflows/byan/templates/base-agent-template.md +79 -79
  75. package/templates/_bmad/bmb/workflows/byan/validate-agent-workflow.md +676 -676
  76. package/templates/_bmad/core/agents/carmack.md +238 -238
@@ -0,0 +1,498 @@
1
+ /**
2
+ * TROUBLESHOOTER Module
3
+ *
4
+ * Diagnoses and fixes common installation errors.
5
+ *
6
+ * Phase 5: 40h development
7
+ *
8
+ * @module yanstaller/troubleshooter
9
+ */
10
+
11
+ const path = require('path');
12
+ const os = require('os');
13
+ const fs = require('fs-extra');
14
+ const { execSync } = require('child_process');
15
+ const fileUtils = require('../utils/file-utils');
16
+ const detector = require('./detector');
17
+ const validator = require('./validator');
18
+
19
+ /**
20
+ * @typedef {Object} DiagnosticResult
21
+ * @property {string} error - Error type
22
+ * @property {string} cause - Root cause
23
+ * @property {string} solution - Recommended solution
24
+ * @property {boolean} canAutoFix - Whether auto-fix is available
25
+ * @property {Function} [autoFix] - Auto-fix function
26
+ * @property {string} errorCode - Unique error code
27
+ * @property {string} severity - 'critical' | 'warning' | 'info'
28
+ */
29
+
30
+ /**
31
+ * @typedef {Object} TroubleshootResult
32
+ * @property {boolean} success - All issues fixed
33
+ * @property {DiagnosticResult[]} diagnostics - Detected issues
34
+ * @property {string[]} fixed - Successfully fixed issues
35
+ * @property {string[]} pending - Issues requiring manual fix
36
+ */
37
+
38
+ // Error code patterns
39
+ const ERROR_PATTERNS = {
40
+ NODE_VERSION: /node.*version|unsupported.*node/i,
41
+ PERMISSION: /EACCES|EPERM|permission denied/i,
42
+ NOT_FOUND: /ENOENT|not found|cannot find/i,
43
+ GIT_MISSING: /git.*not found|git.*command/i,
44
+ DISK_SPACE: /ENOSPC|no space left/i,
45
+ NETWORK: /ETIMEDOUT|ECONNREFUSED|network/i,
46
+ CORRUPTED: /corrupted|invalid.*format|parse error/i,
47
+ MISSING_DEP: /cannot find module|module not found/i
48
+ };
49
+
50
+ /**
51
+ * Diagnostic functions for specific error types
52
+ */
53
+
54
+ async function diagnoseNodeVersion(error, context) {
55
+ const detectionResult = await detector.detect();
56
+ const currentVersion = detectionResult.node.version;
57
+ const requiredVersion = '16.0.0';
58
+
59
+ return {
60
+ error: error.message,
61
+ errorCode: 'NODE_VERSION',
62
+ cause: `Node.js version ${currentVersion} is too old`,
63
+ solution: suggestNodeUpgrade(currentVersion, requiredVersion),
64
+ canAutoFix: false,
65
+ severity: 'critical'
66
+ };
67
+ }
68
+
69
+ async function diagnosePermission(error, context) {
70
+ const projectRoot = context.projectRoot || process.cwd();
71
+
72
+ return {
73
+ error: error.message,
74
+ errorCode: 'PERMISSION',
75
+ cause: 'Insufficient file permissions',
76
+ solution: `Run with elevated permissions or fix permissions on: ${projectRoot}`,
77
+ canAutoFix: true,
78
+ autoFix: async () => await fixPermissions(projectRoot),
79
+ severity: 'critical'
80
+ };
81
+ }
82
+
83
+ async function diagnoseNotFound(error, context) {
84
+ // Extract file path from error if possible
85
+ const match = error.message.match(/['"]([^'"]+)['"]/);
86
+ const missingPath = match ? match[1] : 'unknown file';
87
+
88
+ return {
89
+ error: error.message,
90
+ errorCode: 'NOT_FOUND',
91
+ cause: `Required file or directory not found: ${missingPath}`,
92
+ solution: 'Re-run installation or check file paths',
93
+ canAutoFix: true,
94
+ autoFix: async () => await repairStructure(context.projectRoot),
95
+ severity: 'critical'
96
+ };
97
+ }
98
+
99
+ async function diagnoseGitMissing(error, context) {
100
+ return {
101
+ error: error.message,
102
+ errorCode: 'GIT_MISSING',
103
+ cause: 'Git is not installed or not in PATH',
104
+ solution: 'Install Git from https://git-scm.com/ and add to PATH',
105
+ canAutoFix: false,
106
+ severity: 'warning'
107
+ };
108
+ }
109
+
110
+ async function diagnoseDiskSpace(error, context) {
111
+ return {
112
+ error: error.message,
113
+ errorCode: 'DISK_SPACE',
114
+ cause: 'Insufficient disk space',
115
+ solution: 'Free up disk space and retry installation',
116
+ canAutoFix: false,
117
+ severity: 'critical'
118
+ };
119
+ }
120
+
121
+ async function diagnoseNetwork(error, context) {
122
+ return {
123
+ error: error.message,
124
+ errorCode: 'NETWORK',
125
+ cause: 'Network connection failed',
126
+ solution: 'Check internet connection and retry. If behind proxy, configure npm proxy settings',
127
+ canAutoFix: false,
128
+ severity: 'warning'
129
+ };
130
+ }
131
+
132
+ async function diagnoseCorrupted(error, context) {
133
+ return {
134
+ error: error.message,
135
+ errorCode: 'CORRUPTED',
136
+ cause: 'Configuration file or installation is corrupted',
137
+ solution: 'Delete corrupted files and reinstall',
138
+ canAutoFix: true,
139
+ autoFix: async () => await resetConfig(context.projectRoot),
140
+ severity: 'critical'
141
+ };
142
+ }
143
+
144
+ async function diagnoseMissingDep(error, context) {
145
+ // Extract module name from error
146
+ const match = error.message.match(/module ['"]([^'"]+)['"]/i);
147
+ const moduleName = match ? match[1] : 'unknown';
148
+
149
+ return {
150
+ error: error.message,
151
+ errorCode: 'MISSING_DEP',
152
+ cause: `Missing Node.js dependency: ${moduleName}`,
153
+ solution: 'Run: npm install',
154
+ canAutoFix: true,
155
+ autoFix: async () => await reinstallDependencies(context.projectRoot),
156
+ severity: 'critical'
157
+ };
158
+ }
159
+
160
+ /**
161
+ * Diagnose installation error
162
+ *
163
+ * @param {Error} error - Installation error
164
+ * @param {Object} context - Installation context
165
+ * @returns {Promise<DiagnosticResult>}
166
+ */
167
+ async function diagnose(error, context = {}) {
168
+ const errorMsg = error.message || String(error);
169
+
170
+ // Pattern match against known errors
171
+ if (ERROR_PATTERNS.NODE_VERSION.test(errorMsg)) {
172
+ return diagnoseNodeVersion(error, context);
173
+ }
174
+
175
+ if (ERROR_PATTERNS.PERMISSION.test(errorMsg)) {
176
+ return diagnosePermission(error, context);
177
+ }
178
+
179
+ if (ERROR_PATTERNS.NOT_FOUND.test(errorMsg)) {
180
+ return diagnoseNotFound(error, context);
181
+ }
182
+
183
+ if (ERROR_PATTERNS.GIT_MISSING.test(errorMsg)) {
184
+ return diagnoseGitMissing(error, context);
185
+ }
186
+
187
+ if (ERROR_PATTERNS.DISK_SPACE.test(errorMsg)) {
188
+ return diagnoseDiskSpace(error, context);
189
+ }
190
+
191
+ if (ERROR_PATTERNS.NETWORK.test(errorMsg)) {
192
+ return diagnoseNetwork(error, context);
193
+ }
194
+
195
+ if (ERROR_PATTERNS.CORRUPTED.test(errorMsg)) {
196
+ return diagnoseCorrupted(error, context);
197
+ }
198
+
199
+ if (ERROR_PATTERNS.MISSING_DEP.test(errorMsg)) {
200
+ return diagnoseMissingDep(error, context);
201
+ }
202
+
203
+ // Unknown error
204
+ return {
205
+ error: errorMsg,
206
+ errorCode: 'UNKNOWN',
207
+ cause: 'Unknown error type',
208
+ solution: 'Check error message and logs for details',
209
+ canAutoFix: false,
210
+ severity: 'warning'
211
+ };
212
+ }
213
+
214
+ /**
215
+ * Auto-fix permission error
216
+ *
217
+ * @param {string} targetPath - File path with permission issue
218
+ * @returns {Promise<void>}
219
+ */
220
+ async function fixPermissions(targetPath) {
221
+ const platform = os.platform();
222
+
223
+ try {
224
+ if (platform === 'win32') {
225
+ // Windows: Use icacls to grant full control
226
+ execSync(`icacls "${targetPath}" /grant ${os.userInfo().username}:F /T`, {
227
+ stdio: 'ignore'
228
+ });
229
+ } else {
230
+ // Unix/macOS: Use chmod
231
+ await fs.chmod(targetPath, 0o755);
232
+
233
+ // Recursively fix subdirectories
234
+ const stat = await fs.stat(targetPath);
235
+ if (stat.isDirectory()) {
236
+ const items = await fs.readdir(targetPath);
237
+ for (const item of items) {
238
+ await fixPermissions(path.join(targetPath, item));
239
+ }
240
+ }
241
+ }
242
+ } catch (error) {
243
+ throw new Error(`Failed to fix permissions: ${error.message}`);
244
+ }
245
+ }
246
+
247
+ /**
248
+ * Suggest Node.js upgrade
249
+ *
250
+ * @param {string} currentVersion - Current Node version
251
+ * @param {string} requiredVersion - Required Node version
252
+ * @returns {string} - Upgrade instructions
253
+ */
254
+ function suggestNodeUpgrade(currentVersion, requiredVersion) {
255
+ const platform = os.platform();
256
+
257
+ let instructions = `Current Node.js: ${currentVersion}, Required: ${requiredVersion}+\n\n`;
258
+
259
+ switch (platform) {
260
+ case 'win32':
261
+ instructions += 'Windows: Download from https://nodejs.org/ or use:\n';
262
+ instructions += ' winget install OpenJS.NodeJS.LTS';
263
+ break;
264
+ case 'darwin':
265
+ instructions += 'macOS:\n';
266
+ instructions += ' brew upgrade node\n';
267
+ instructions += ' Or download from https://nodejs.org/';
268
+ break;
269
+ case 'linux':
270
+ instructions += 'Linux:\n';
271
+ instructions += ' # Using nvm (recommended):\n';
272
+ instructions += ' nvm install --lts\n';
273
+ instructions += ' # Or using apt:\n';
274
+ instructions += ' curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -\n';
275
+ instructions += ' sudo apt-get install -y nodejs';
276
+ break;
277
+ default:
278
+ instructions += 'Download from https://nodejs.org/';
279
+ }
280
+
281
+ return instructions;
282
+ }
283
+
284
+ /**
285
+ * Check common issues
286
+ *
287
+ * @param {Object} config - Installation config
288
+ * @returns {Promise<string[]>} - List of detected issues
289
+ */
290
+ async function checkCommonIssues(config = {}) {
291
+ const issues = [];
292
+
293
+ try {
294
+ // Check 1: Node.js version
295
+ const detectionResult = await detector.detect();
296
+ const nodeVersion = detectionResult.node.version;
297
+ const majorVersion = parseInt(nodeVersion.split('.')[0]);
298
+
299
+ if (majorVersion < 16) {
300
+ issues.push(`Node.js ${nodeVersion} is outdated (require 16+)`);
301
+ }
302
+
303
+ // Check 2: Git availability
304
+ if (!detectionResult.git.detected) {
305
+ issues.push('Git is not installed');
306
+ }
307
+
308
+ // Check 3: Write permission
309
+ const projectRoot = config.projectRoot || process.cwd();
310
+ try {
311
+ await fs.access(projectRoot, fs.constants.W_OK);
312
+ } catch {
313
+ issues.push(`No write permission in ${projectRoot}`);
314
+ }
315
+
316
+ // Check 4: Disk space (at least 100MB)
317
+ try {
318
+ const stats = await fs.statfs || await fs.stat(projectRoot);
319
+ // This is a rough check, might not work on all platforms
320
+ if (stats.bavail && stats.bsize) {
321
+ const availableSpace = stats.bavail * stats.bsize;
322
+ if (availableSpace < 100 * 1024 * 1024) {
323
+ issues.push('Low disk space (< 100MB available)');
324
+ }
325
+ }
326
+ } catch {
327
+ // Disk space check failed, skip
328
+ }
329
+
330
+ // Check 5: Network connectivity (optional check)
331
+ try {
332
+ // Simple check: try to resolve nodejs.org
333
+ require('dns').resolve('nodejs.org', (err) => {
334
+ if (err) {
335
+ issues.push('Network connectivity issue');
336
+ }
337
+ });
338
+ } catch {
339
+ // Network check failed, skip
340
+ }
341
+
342
+ // Check 6: Dependencies installed
343
+ const requiredDeps = ['fs-extra', 'js-yaml', 'chalk'];
344
+ for (const dep of requiredDeps) {
345
+ try {
346
+ require.resolve(dep);
347
+ } catch {
348
+ issues.push(`Missing dependency: ${dep}`);
349
+ }
350
+ }
351
+
352
+ } catch (error) {
353
+ issues.push(`Health check error: ${error.message}`);
354
+ }
355
+
356
+ return issues;
357
+ }
358
+
359
+ /**
360
+ * Repair _bmad/ directory structure
361
+ *
362
+ * @param {string} projectRoot - Project root directory
363
+ * @returns {Promise<void>}
364
+ */
365
+ async function repairStructure(projectRoot) {
366
+ const installer = require('./installer');
367
+
368
+ try {
369
+ await installer.createBmadStructure(projectRoot);
370
+ } catch (error) {
371
+ throw new Error(`Failed to repair structure: ${error.message}`);
372
+ }
373
+ }
374
+
375
+ /**
376
+ * Reset corrupted config files
377
+ *
378
+ * @param {string} projectRoot - Project root directory
379
+ * @returns {Promise<void>}
380
+ */
381
+ async function resetConfig(projectRoot) {
382
+ const installer = require('./installer');
383
+
384
+ try {
385
+ // Recreate default config
386
+ const defaultConfig = {
387
+ userName: 'User',
388
+ language: 'English',
389
+ mode: 'minimal',
390
+ agents: []
391
+ };
392
+
393
+ await installer.createModuleConfig('bmb', defaultConfig, projectRoot);
394
+ } catch (error) {
395
+ throw new Error(`Failed to reset config: ${error.message}`);
396
+ }
397
+ }
398
+
399
+ /**
400
+ * Reinstall npm dependencies
401
+ *
402
+ * @param {string} projectRoot - Project root directory
403
+ * @returns {Promise<void>}
404
+ */
405
+ async function reinstallDependencies(projectRoot) {
406
+ try {
407
+ execSync('npm install', {
408
+ cwd: projectRoot,
409
+ stdio: 'inherit'
410
+ });
411
+ } catch (error) {
412
+ throw new Error(`Failed to reinstall dependencies: ${error.message}`);
413
+ }
414
+ }
415
+
416
+ /**
417
+ * Reinstall missing agents
418
+ *
419
+ * @param {string[]} agents - Agent names to reinstall
420
+ * @param {string} projectRoot - Project root directory
421
+ * @returns {Promise<void>}
422
+ */
423
+ async function reinstallAgents(agents, projectRoot) {
424
+ const installer = require('./installer');
425
+
426
+ for (const agentName of agents) {
427
+ try {
428
+ await installer.copyAgentFile(agentName, projectRoot);
429
+ } catch (error) {
430
+ // Continue with other agents even if one fails
431
+ console.warn(`Failed to reinstall ${agentName}: ${error.message}`);
432
+ }
433
+ }
434
+ }
435
+
436
+ /**
437
+ * Run full troubleshooting with auto-fixes
438
+ *
439
+ * @param {Object} config - Installation config
440
+ * @returns {Promise<TroubleshootResult>}
441
+ */
442
+ async function troubleshoot(config) {
443
+ const diagnostics = [];
444
+ const fixed = [];
445
+ const pending = [];
446
+
447
+ // Run validation first
448
+ const validationResult = await validator.validate(config);
449
+
450
+ if (validationResult.success) {
451
+ return {
452
+ success: true,
453
+ diagnostics: [],
454
+ fixed: [],
455
+ pending: []
456
+ };
457
+ }
458
+
459
+ // Diagnose each error
460
+ for (const check of validationResult.checks) {
461
+ if (!check.passed) {
462
+ const error = new Error(check.message || `${check.name} failed`);
463
+ const diagnostic = await diagnose(error, config);
464
+ diagnostics.push(diagnostic);
465
+
466
+ // Try auto-fix if available
467
+ if (diagnostic.canAutoFix && diagnostic.autoFix) {
468
+ try {
469
+ await diagnostic.autoFix();
470
+ fixed.push(diagnostic.errorCode);
471
+ } catch (fixError) {
472
+ pending.push(`${diagnostic.errorCode}: ${fixError.message}`);
473
+ }
474
+ } else {
475
+ pending.push(diagnostic.errorCode);
476
+ }
477
+ }
478
+ }
479
+
480
+ return {
481
+ success: pending.length === 0,
482
+ diagnostics,
483
+ fixed,
484
+ pending
485
+ };
486
+ }
487
+
488
+ module.exports = {
489
+ diagnose,
490
+ fixPermissions,
491
+ suggestNodeUpgrade,
492
+ checkCommonIssues,
493
+ repairStructure,
494
+ resetConfig,
495
+ reinstallDependencies,
496
+ reinstallAgents,
497
+ troubleshoot
498
+ };