@cpretzinger/boss-claude 1.0.0 → 1.0.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.
Files changed (87) hide show
  1. package/README.md +304 -1
  2. package/bin/boss-claude.js +1138 -0
  3. package/bin/commands/mode.js +250 -0
  4. package/bin/onyx-guard.js +259 -0
  5. package/bin/onyx-guard.sh +251 -0
  6. package/bin/prompts.js +284 -0
  7. package/bin/rollback.js +85 -0
  8. package/bin/setup-wizard.js +492 -0
  9. package/config/.env.example +17 -0
  10. package/lib/README.md +83 -0
  11. package/lib/agent-logger.js +61 -0
  12. package/lib/agents/memory-engineers/github-memory-engineer.js +251 -0
  13. package/lib/agents/memory-engineers/postgres-memory-engineer.js +633 -0
  14. package/lib/agents/memory-engineers/qdrant-memory-engineer.js +358 -0
  15. package/lib/agents/memory-engineers/redis-memory-engineer.js +383 -0
  16. package/lib/agents/memory-supervisor.js +526 -0
  17. package/lib/agents/registry.js +135 -0
  18. package/lib/auto-monitor.js +131 -0
  19. package/lib/checkpoint-hook.js +112 -0
  20. package/lib/checkpoint.js +319 -0
  21. package/lib/commentator.js +213 -0
  22. package/lib/context-scribe.js +120 -0
  23. package/lib/delegation-strategies.js +326 -0
  24. package/lib/hierarchy-validator.js +643 -0
  25. package/lib/index.js +15 -0
  26. package/lib/init-with-mode.js +261 -0
  27. package/lib/init.js +44 -6
  28. package/lib/memory-result-aggregator.js +252 -0
  29. package/lib/memory.js +35 -7
  30. package/lib/mode-enforcer.js +473 -0
  31. package/lib/onyx-banner.js +169 -0
  32. package/lib/onyx-identity.js +214 -0
  33. package/lib/onyx-monitor.js +381 -0
  34. package/lib/onyx-reminder.js +188 -0
  35. package/lib/onyx-tool-interceptor.js +341 -0
  36. package/lib/onyx-wrapper.js +315 -0
  37. package/lib/orchestrator-gate.js +334 -0
  38. package/lib/output-formatter.js +296 -0
  39. package/lib/postgres.js +1 -1
  40. package/lib/prompt-injector.js +220 -0
  41. package/lib/prompts.js +532 -0
  42. package/lib/session.js +153 -6
  43. package/lib/setup/README.md +187 -0
  44. package/lib/setup/env-manager.js +785 -0
  45. package/lib/setup/error-recovery.js +630 -0
  46. package/lib/setup/explain-scopes.js +385 -0
  47. package/lib/setup/github-instructions.js +333 -0
  48. package/lib/setup/github-repo.js +254 -0
  49. package/lib/setup/import-credentials.js +498 -0
  50. package/lib/setup/index.js +62 -0
  51. package/lib/setup/init-postgres.js +785 -0
  52. package/lib/setup/init-redis.js +456 -0
  53. package/lib/setup/integration-test.js +652 -0
  54. package/lib/setup/progress.js +357 -0
  55. package/lib/setup/rollback.js +670 -0
  56. package/lib/setup/rollback.test.js +452 -0
  57. package/lib/setup/setup-with-rollback.example.js +351 -0
  58. package/lib/setup/summary.js +400 -0
  59. package/lib/setup/test-github-setup.js +10 -0
  60. package/lib/setup/test-postgres-init.js +98 -0
  61. package/lib/setup/verify-setup.js +102 -0
  62. package/lib/task-agent-worker.js +235 -0
  63. package/lib/token-monitor.js +466 -0
  64. package/lib/tool-wrapper-integration.js +369 -0
  65. package/lib/tool-wrapper.js +387 -0
  66. package/lib/validators/README.md +497 -0
  67. package/lib/validators/config.js +583 -0
  68. package/lib/validators/config.test.js +175 -0
  69. package/lib/validators/github.js +310 -0
  70. package/lib/validators/github.test.js +61 -0
  71. package/lib/validators/index.js +15 -0
  72. package/lib/validators/postgres.js +525 -0
  73. package/package.json +98 -13
  74. package/scripts/benchmark-memory.js +433 -0
  75. package/scripts/check-secrets.sh +12 -0
  76. package/scripts/fetch-todos.mjs +148 -0
  77. package/scripts/graceful-shutdown.sh +156 -0
  78. package/scripts/install-onyx-hooks.js +373 -0
  79. package/scripts/install.js +119 -18
  80. package/scripts/redis-monitor.js +284 -0
  81. package/scripts/redis-setup.js +412 -0
  82. package/scripts/test-memory-retrieval.js +201 -0
  83. package/scripts/validate-exports.js +68 -0
  84. package/scripts/validate-package.js +120 -0
  85. package/scripts/verify-onyx-deployment.js +309 -0
  86. package/scripts/verify-redis-deployment.js +354 -0
  87. package/scripts/verify-redis-init.js +219 -0
@@ -0,0 +1,630 @@
1
+ /**
2
+ * BOSS CLAUDE - Error Recovery System
3
+ * Detects common setup failures and provides actionable fix suggestions
4
+ */
5
+
6
+ import chalk from 'chalk';
7
+
8
+ /**
9
+ * Error categories with detection patterns and recovery steps
10
+ */
11
+ export const ERROR_PATTERNS = {
12
+ // Authentication & Token Errors
13
+ INVALID_TOKEN: {
14
+ patterns: [
15
+ /invalid.*token/i,
16
+ /authentication.*failed/i,
17
+ /unauthorized/i,
18
+ /401/,
19
+ /EAUTH/,
20
+ /token.*expired/i,
21
+ /token.*malformed/i
22
+ ],
23
+ severity: 'critical',
24
+ category: 'Authentication',
25
+ fixes: [
26
+ 'Verify your ANTHROPIC_API_KEY is correct',
27
+ 'Check if token has expired or been revoked',
28
+ 'Ensure token starts with "sk-ant-"',
29
+ 'Visit https://console.anthropic.com to generate a new token',
30
+ 'Update .env file with: ANTHROPIC_API_KEY=your-token-here'
31
+ ],
32
+ documentation: 'https://docs.anthropic.com/claude/reference/getting-started-with-the-api'
33
+ },
34
+
35
+ MISSING_TOKEN: {
36
+ patterns: [
37
+ /token.*required/i,
38
+ /api.*key.*not.*found/i,
39
+ /ANTHROPIC_API_KEY.*undefined/i,
40
+ /missing.*credentials/i
41
+ ],
42
+ severity: 'critical',
43
+ category: 'Configuration',
44
+ fixes: [
45
+ 'Create .env file in project root if it doesn\'t exist',
46
+ 'Add: ANTHROPIC_API_KEY=your-anthropic-api-key',
47
+ 'For global setup: boss-claude config set ANTHROPIC_API_KEY',
48
+ 'Restart your terminal after setting environment variables',
49
+ 'Ensure .env file is not in .gitignore (or use .env.local)'
50
+ ],
51
+ documentation: 'README.md#configuration'
52
+ },
53
+
54
+ // Network & Connectivity
55
+ NETWORK_ERROR: {
56
+ patterns: [
57
+ /ECONNREFUSED/,
58
+ /ETIMEDOUT/,
59
+ /ENOTFOUND/,
60
+ /network.*error/i,
61
+ /connection.*timeout/i,
62
+ /socket.*hang.*up/i,
63
+ /ECONNRESET/
64
+ ],
65
+ severity: 'high',
66
+ category: 'Network',
67
+ fixes: [
68
+ 'Check your internet connection',
69
+ 'Verify firewall is not blocking outbound HTTPS (port 443)',
70
+ 'Try pinging api.anthropic.com',
71
+ 'If using proxy, set HTTP_PROXY and HTTPS_PROXY env vars',
72
+ 'Check if VPN is interfering with API access',
73
+ 'Wait a moment and retry - might be temporary network issue'
74
+ ],
75
+ documentation: null
76
+ },
77
+
78
+ DNS_ERROR: {
79
+ patterns: [
80
+ /ENOTFOUND.*api\.anthropic\.com/i,
81
+ /getaddrinfo.*ENOTFOUND/i,
82
+ /DNS.*resolution.*failed/i
83
+ ],
84
+ severity: 'high',
85
+ category: 'Network',
86
+ fixes: [
87
+ 'Check DNS settings: Try using 8.8.8.8 or 1.1.1.1',
88
+ 'Flush DNS cache: sudo dscacheutil -flushcache (macOS)',
89
+ 'Test DNS: nslookup api.anthropic.com',
90
+ 'Check /etc/hosts for incorrect entries',
91
+ 'Restart network interface or router'
92
+ ],
93
+ documentation: null
94
+ },
95
+
96
+ // Redis Connection Errors
97
+ REDIS_CONNECTION: {
98
+ patterns: [
99
+ /ECONNREFUSED.*6379/,
100
+ /Redis.*connection.*failed/i,
101
+ /redis.*not.*running/i,
102
+ /could.*not.*connect.*redis/i
103
+ ],
104
+ severity: 'medium',
105
+ category: 'Redis',
106
+ fixes: [
107
+ 'Start Redis: redis-server (or brew services start redis on macOS)',
108
+ 'Check if Redis is running: redis-cli ping',
109
+ 'Verify Redis port (default 6379) is not blocked',
110
+ 'Install Redis if missing: brew install redis (macOS) or apt-get install redis (Linux)',
111
+ 'Boss Claude will work without Redis (offline mode) but progress won\'t persist'
112
+ ],
113
+ documentation: 'README.md#redis-setup'
114
+ },
115
+
116
+ REDIS_AUTH: {
117
+ patterns: [
118
+ /NOAUTH.*Authentication.*required/i,
119
+ /Redis.*authentication.*failed/i,
120
+ /invalid.*password/i
121
+ ],
122
+ severity: 'medium',
123
+ category: 'Redis',
124
+ fixes: [
125
+ 'Check REDIS_URL in .env includes password if required',
126
+ 'Format: redis://default:password@host:port',
127
+ 'Verify Redis requirepass in redis.conf',
128
+ 'For local Redis without auth, remove password from REDIS_URL',
129
+ 'Test connection: redis-cli -a your-password ping'
130
+ ],
131
+ documentation: null
132
+ },
133
+
134
+ // File System & Permissions
135
+ PERMISSION_DENIED: {
136
+ patterns: [
137
+ /EACCES/,
138
+ /permission.*denied/i,
139
+ /EPERM/,
140
+ /operation.*not.*permitted/i
141
+ ],
142
+ severity: 'high',
143
+ category: 'Permissions',
144
+ fixes: [
145
+ 'Check file/directory permissions: ls -la',
146
+ 'For npm global installs: Use sudo (or fix npm permissions)',
147
+ 'Fix npm permissions: npm config set prefix ~/.npm-global',
148
+ 'Add to PATH: export PATH=~/.npm-global/bin:$PATH',
149
+ 'For config files: chmod 644 ~/.boss-claude/config.json',
150
+ 'For directories: chmod 755 ~/.boss-claude'
151
+ ],
152
+ documentation: 'https://docs.npmjs.com/resolving-eacces-permissions-errors'
153
+ },
154
+
155
+ FILE_NOT_FOUND: {
156
+ patterns: [
157
+ /ENOENT/,
158
+ /no.*such.*file/i,
159
+ /cannot.*find.*module/i,
160
+ /module.*not.*found/i
161
+ ],
162
+ severity: 'medium',
163
+ category: 'File System',
164
+ fixes: [
165
+ 'Verify file path is correct',
166
+ 'Run: npm install (might be missing dependencies)',
167
+ 'Check if .boss-claude directory exists in home folder',
168
+ 'Create config directory: mkdir -p ~/.boss-claude',
169
+ 'Reinstall package: npm uninstall -g @cpretzinger/boss-claude && npm install -g @cpretzinger/boss-claude'
170
+ ],
171
+ documentation: null
172
+ },
173
+
174
+ // Rate Limiting & API Errors
175
+ RATE_LIMIT: {
176
+ patterns: [
177
+ /rate.*limit/i,
178
+ /429/,
179
+ /too.*many.*requests/i,
180
+ /quota.*exceeded/i
181
+ ],
182
+ severity: 'medium',
183
+ category: 'API Limits',
184
+ fixes: [
185
+ 'Wait 60 seconds before retrying',
186
+ 'Check your API usage at https://console.anthropic.com',
187
+ 'Verify you haven\'t exceeded your plan limits',
188
+ 'Consider upgrading your Anthropic plan if needed',
189
+ 'Implement exponential backoff in your automation'
190
+ ],
191
+ documentation: 'https://docs.anthropic.com/claude/reference/rate-limits'
192
+ },
193
+
194
+ API_ERROR: {
195
+ patterns: [
196
+ /500/,
197
+ /502/,
198
+ /503/,
199
+ /504/,
200
+ /internal.*server.*error/i,
201
+ /service.*unavailable/i,
202
+ /bad.*gateway/i
203
+ ],
204
+ severity: 'low',
205
+ category: 'API',
206
+ fixes: [
207
+ 'Anthropic API may be experiencing issues',
208
+ 'Check status: https://status.anthropic.com',
209
+ 'Wait a few minutes and retry',
210
+ 'If persistent, contact Anthropic support',
211
+ 'Your data is safe - Boss Claude will retry automatically'
212
+ ],
213
+ documentation: 'https://status.anthropic.com'
214
+ },
215
+
216
+ // Package & Dependencies
217
+ DEPENDENCY_ERROR: {
218
+ patterns: [
219
+ /Cannot.*find.*package/i,
220
+ /Module.*not.*found.*node_modules/i,
221
+ /peer.*dependency/i,
222
+ /incompatible.*version/i
223
+ ],
224
+ severity: 'high',
225
+ category: 'Dependencies',
226
+ fixes: [
227
+ 'Run: npm install (or npm install -g for global)',
228
+ 'Clear npm cache: npm cache clean --force',
229
+ 'Delete node_modules: rm -rf node_modules package-lock.json',
230
+ 'Reinstall: npm install',
231
+ 'Check Node.js version: node --version (requires 18+)'
232
+ ],
233
+ documentation: null
234
+ },
235
+
236
+ NODE_VERSION: {
237
+ patterns: [
238
+ /node.*version/i,
239
+ /requires.*node/i,
240
+ /engine.*node/i,
241
+ /unsupported.*engine/i
242
+ ],
243
+ severity: 'critical',
244
+ category: 'Environment',
245
+ fixes: [
246
+ 'Boss Claude requires Node.js 18 or higher',
247
+ 'Check version: node --version',
248
+ 'Update Node.js: https://nodejs.org',
249
+ 'Use nvm: nvm install 20 && nvm use 20',
250
+ 'Or use fnm: fnm install 20 && fnm use 20'
251
+ ],
252
+ documentation: 'https://nodejs.org'
253
+ },
254
+
255
+ // JSON & Data Errors
256
+ JSON_PARSE_ERROR: {
257
+ patterns: [
258
+ /unexpected.*token/i,
259
+ /JSON\.parse/i,
260
+ /invalid.*JSON/i,
261
+ /malformed.*JSON/i
262
+ ],
263
+ severity: 'medium',
264
+ category: 'Data',
265
+ fixes: [
266
+ 'Config file may be corrupted',
267
+ 'Backup and remove: mv ~/.boss-claude/config.json ~/.boss-claude/config.json.bak',
268
+ 'Restart Boss Claude to regenerate config',
269
+ 'Manually fix JSON syntax if you can identify the error',
270
+ 'Validate JSON: cat config.json | python -m json.tool'
271
+ ],
272
+ documentation: null
273
+ }
274
+ };
275
+
276
+ /**
277
+ * Detect error type from error message or stack
278
+ * @param {Error|string} error - Error object or message
279
+ * @returns {Object|null} Matched error pattern or null
280
+ */
281
+ export function detectErrorType(error) {
282
+ const errorMessage = error instanceof Error ?
283
+ `${error.message} ${error.stack || ''}` :
284
+ String(error);
285
+
286
+ for (const [type, config] of Object.entries(ERROR_PATTERNS)) {
287
+ for (const pattern of config.patterns) {
288
+ if (pattern.test(errorMessage)) {
289
+ return { type, ...config };
290
+ }
291
+ }
292
+ }
293
+
294
+ return null;
295
+ }
296
+
297
+ /**
298
+ * Format error recovery suggestions
299
+ * @param {Error|string} error - Error to analyze
300
+ * @returns {string} Formatted recovery message
301
+ */
302
+ export function formatErrorRecovery(error) {
303
+ const detected = detectErrorType(error);
304
+
305
+ if (!detected) {
306
+ return formatGenericError(error);
307
+ }
308
+
309
+ const { type, severity, category, fixes, documentation } = detected;
310
+
311
+ const severityColor = {
312
+ critical: chalk.red.bold,
313
+ high: chalk.red,
314
+ medium: chalk.yellow,
315
+ low: chalk.blue
316
+ }[severity] || chalk.white;
317
+
318
+ let output = '\n';
319
+ output += chalk.red('═'.repeat(70)) + '\n';
320
+ output += severityColor(` ERROR DETECTED: ${category}`) + '\n';
321
+ output += chalk.red('═'.repeat(70)) + '\n\n';
322
+
323
+ output += chalk.bold('Original Error:\n');
324
+ output += chalk.gray(error instanceof Error ? error.message : String(error)) + '\n\n';
325
+
326
+ output += chalk.bold.cyan('🔧 Suggested Fixes:\n\n');
327
+
328
+ fixes.forEach((fix, index) => {
329
+ output += chalk.white(` ${index + 1}. ${fix}\n`);
330
+ });
331
+
332
+ if (documentation) {
333
+ output += '\n' + chalk.bold.blue('📚 Documentation:\n');
334
+ output += chalk.cyan(` ${documentation}\n`);
335
+ }
336
+
337
+ output += '\n' + chalk.yellow('💡 Tip: ') + chalk.white('Run "boss-claude doctor" for automated diagnosis\n');
338
+ output += chalk.red('═'.repeat(70)) + '\n';
339
+
340
+ return output;
341
+ }
342
+
343
+ /**
344
+ * Format generic error (unrecognized pattern)
345
+ * @param {Error|string} error - Error object
346
+ * @returns {string} Formatted error message
347
+ */
348
+ function formatGenericError(error) {
349
+ let output = '\n';
350
+ output += chalk.red('═'.repeat(70)) + '\n';
351
+ output += chalk.red.bold(' UNEXPECTED ERROR') + '\n';
352
+ output += chalk.red('═'.repeat(70)) + '\n\n';
353
+
354
+ output += chalk.bold('Error Message:\n');
355
+ output += chalk.gray(error instanceof Error ? error.message : String(error)) + '\n\n';
356
+
357
+ if (error instanceof Error && error.stack) {
358
+ output += chalk.bold('Stack Trace:\n');
359
+ output += chalk.gray(error.stack.split('\n').slice(0, 5).join('\n')) + '\n\n';
360
+ }
361
+
362
+ output += chalk.bold.cyan('🔧 General Troubleshooting:\n\n');
363
+ output += chalk.white(' 1. Run: boss-claude doctor (automated diagnosis)\n');
364
+ output += chalk.white(' 2. Check logs: ~/.boss-claude/logs/\n');
365
+ output += chalk.white(' 3. Verify configuration: boss-claude config list\n');
366
+ output += chalk.white(' 4. Test connectivity: boss-claude status\n');
367
+ output += chalk.white(' 5. Report issue: https://github.com/cpretzinger/boss-claude/issues\n');
368
+
369
+ output += '\n' + chalk.red('═'.repeat(70)) + '\n';
370
+
371
+ return output;
372
+ }
373
+
374
+ /**
375
+ * Run automated diagnostics
376
+ * @returns {Promise<Object>} Diagnostic results
377
+ */
378
+ export async function runDiagnostics() {
379
+ const results = {
380
+ timestamp: new Date().toISOString(),
381
+ checks: {},
382
+ issues: [],
383
+ recommendations: []
384
+ };
385
+
386
+ // Check 1: Environment variables
387
+ results.checks.anthropicKey = {
388
+ status: process.env.ANTHROPIC_API_KEY ? 'pass' : 'fail',
389
+ message: process.env.ANTHROPIC_API_KEY ?
390
+ 'ANTHROPIC_API_KEY is set' :
391
+ 'ANTHROPIC_API_KEY is missing'
392
+ };
393
+
394
+ if (!process.env.ANTHROPIC_API_KEY) {
395
+ results.issues.push({
396
+ severity: 'critical',
397
+ category: 'Configuration',
398
+ message: 'Missing ANTHROPIC_API_KEY',
399
+ fix: 'Set in .env or environment: export ANTHROPIC_API_KEY=your-key'
400
+ });
401
+ }
402
+
403
+ // Check 2: Node.js version
404
+ const nodeVersion = process.version;
405
+ const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0]);
406
+ results.checks.nodeVersion = {
407
+ status: majorVersion >= 18 ? 'pass' : 'fail',
408
+ message: `Node.js ${nodeVersion} (requires 18+)`,
409
+ version: nodeVersion
410
+ };
411
+
412
+ if (majorVersion < 18) {
413
+ results.issues.push({
414
+ severity: 'critical',
415
+ category: 'Environment',
416
+ message: `Node.js version ${nodeVersion} is too old`,
417
+ fix: 'Update to Node.js 18 or higher: https://nodejs.org'
418
+ });
419
+ }
420
+
421
+ // Check 3: Redis connectivity
422
+ try {
423
+ const { createClient } = await import('redis');
424
+ const redisUrl = process.env.REDIS_URL || 'redis://localhost:6379';
425
+ const client = createClient({ url: redisUrl });
426
+
427
+ await client.connect();
428
+ await client.ping();
429
+ await client.quit();
430
+
431
+ results.checks.redis = {
432
+ status: 'pass',
433
+ message: 'Redis is connected and responsive',
434
+ url: redisUrl.replace(/:[^:]*@/, ':****@') // Hide password
435
+ };
436
+ } catch (redisError) {
437
+ results.checks.redis = {
438
+ status: 'warn',
439
+ message: 'Redis not available (offline mode)',
440
+ error: redisError.message
441
+ };
442
+ results.recommendations.push({
443
+ category: 'Performance',
444
+ message: 'Install Redis for persistent progress tracking',
445
+ fix: 'brew install redis && brew services start redis (macOS)'
446
+ });
447
+ }
448
+
449
+ // Check 4: File permissions
450
+ try {
451
+ const fs = await import('fs');
452
+ const os = await import('os');
453
+ const path = await import('path');
454
+
455
+ const configDir = path.join(os.homedir(), '.boss-claude');
456
+ const configPath = path.join(configDir, 'config.json');
457
+
458
+ // Try to access config directory
459
+ try {
460
+ await fs.promises.access(configDir, fs.constants.R_OK | fs.constants.W_OK);
461
+ results.checks.permissions = {
462
+ status: 'pass',
463
+ message: 'Config directory is readable and writable'
464
+ };
465
+ } catch {
466
+ results.checks.permissions = {
467
+ status: 'warn',
468
+ message: 'Config directory has permission issues'
469
+ };
470
+ results.issues.push({
471
+ severity: 'medium',
472
+ category: 'Permissions',
473
+ message: 'Cannot access ~/.boss-claude directory',
474
+ fix: 'chmod 755 ~/.boss-claude'
475
+ });
476
+ }
477
+ } catch (err) {
478
+ results.checks.permissions = {
479
+ status: 'error',
480
+ message: 'Could not check file permissions',
481
+ error: err.message
482
+ };
483
+ }
484
+
485
+ // Check 5: Network connectivity
486
+ try {
487
+ const https = await import('https');
488
+
489
+ await new Promise((resolve, reject) => {
490
+ const req = https.get('https://api.anthropic.com', { timeout: 5000 }, (res) => {
491
+ results.checks.network = {
492
+ status: res.statusCode === 200 || res.statusCode === 404 ? 'pass' : 'warn',
493
+ message: `API endpoint reachable (HTTP ${res.statusCode})`
494
+ };
495
+ resolve();
496
+ });
497
+
498
+ req.on('error', (err) => {
499
+ results.checks.network = {
500
+ status: 'fail',
501
+ message: 'Cannot reach Anthropic API',
502
+ error: err.message
503
+ };
504
+ results.issues.push({
505
+ severity: 'high',
506
+ category: 'Network',
507
+ message: 'Network connectivity issue',
508
+ fix: 'Check internet connection and firewall settings'
509
+ });
510
+ reject(err);
511
+ });
512
+
513
+ req.on('timeout', () => {
514
+ req.destroy();
515
+ results.checks.network = {
516
+ status: 'fail',
517
+ message: 'API connection timeout'
518
+ };
519
+ reject(new Error('Timeout'));
520
+ });
521
+ }).catch(() => {});
522
+ } catch (err) {
523
+ results.checks.network = {
524
+ status: 'error',
525
+ message: 'Network check failed',
526
+ error: err.message
527
+ };
528
+ }
529
+
530
+ return results;
531
+ }
532
+
533
+ /**
534
+ * Format diagnostic results for display
535
+ * @param {Object} results - Diagnostic results
536
+ * @returns {string} Formatted output
537
+ */
538
+ export function formatDiagnostics(results) {
539
+ let output = '\n';
540
+ output += chalk.cyan('═'.repeat(70)) + '\n';
541
+ output += chalk.cyan.bold(' BOSS CLAUDE DIAGNOSTICS') + '\n';
542
+ output += chalk.cyan('═'.repeat(70)) + '\n\n';
543
+
544
+ output += chalk.bold('System Checks:\n\n');
545
+
546
+ for (const [check, result] of Object.entries(results.checks)) {
547
+ const statusIcon = {
548
+ pass: chalk.green('✓'),
549
+ warn: chalk.yellow('⚠'),
550
+ fail: chalk.red('✗'),
551
+ error: chalk.red('✗')
552
+ }[result.status] || '?';
553
+
554
+ output += ` ${statusIcon} ${chalk.bold(check)}: ${result.message}\n`;
555
+
556
+ if (result.error) {
557
+ output += chalk.gray(` Error: ${result.error}\n`);
558
+ }
559
+ }
560
+
561
+ if (results.issues.length > 0) {
562
+ output += '\n' + chalk.bold.red('Issues Found:\n\n');
563
+ results.issues.forEach((issue, index) => {
564
+ const severityColor = {
565
+ critical: chalk.red.bold,
566
+ high: chalk.red,
567
+ medium: chalk.yellow
568
+ }[issue.severity] || chalk.white;
569
+
570
+ output += severityColor(` ${index + 1}. [${issue.severity.toUpperCase()}] ${issue.message}\n`);
571
+ output += chalk.white(` Fix: ${issue.fix}\n\n`);
572
+ });
573
+ }
574
+
575
+ if (results.recommendations.length > 0) {
576
+ output += chalk.bold.blue('Recommendations:\n\n');
577
+ results.recommendations.forEach((rec, index) => {
578
+ output += chalk.white(` ${index + 1}. ${rec.message}\n`);
579
+ output += chalk.gray(` ${rec.fix}\n\n`);
580
+ });
581
+ }
582
+
583
+ if (results.issues.length === 0) {
584
+ output += '\n' + chalk.green.bold('✓ All critical checks passed!\n');
585
+ }
586
+
587
+ output += chalk.cyan('═'.repeat(70)) + '\n';
588
+
589
+ return output;
590
+ }
591
+
592
+ /**
593
+ * Handle error with recovery suggestions
594
+ * @param {Error} error - Error to handle
595
+ * @param {boolean} exitOnCritical - Exit process on critical errors
596
+ */
597
+ export function handleError(error, exitOnCritical = false) {
598
+ console.error(formatErrorRecovery(error));
599
+
600
+ const detected = detectErrorType(error);
601
+ if (exitOnCritical && detected?.severity === 'critical') {
602
+ process.exit(1);
603
+ }
604
+ }
605
+
606
+ /**
607
+ * Create error recovery middleware for async operations
608
+ * @param {Function} fn - Async function to wrap
609
+ * @returns {Function} Wrapped function with error recovery
610
+ */
611
+ export function withErrorRecovery(fn) {
612
+ return async (...args) => {
613
+ try {
614
+ return await fn(...args);
615
+ } catch (error) {
616
+ handleError(error);
617
+ throw error;
618
+ }
619
+ };
620
+ }
621
+
622
+ export default {
623
+ ERROR_PATTERNS,
624
+ detectErrorType,
625
+ formatErrorRecovery,
626
+ runDiagnostics,
627
+ formatDiagnostics,
628
+ handleError,
629
+ withErrorRecovery
630
+ };