UNPKG

embedia

Version:

Zero-configuration AI chatbot integration CLI - direct file copy with embedded API keys

223 lines (183 loc) • 8.17 kB
const chalk = require('chalk'); const ora = require('ora'); const fs = require('fs-extra'); const path = require('path'); // Import diagnostic tools const HealthChecker = require('../health/healthChecker'); const BuildVerifier = require('../validation/buildVerifier'); const ConflictScanner = require('../conflicts/conflictScanner'); const ProjectAnalyzer = require('../analysis/projectAnalyzer'); /** * Doctor command - Comprehensive diagnostics and auto-fix for Embedia installations */ async function doctorCommand(options = {}) { console.log(chalk.bold.blue('\n🩺 Embedia Doctor - Diagnostic & Repair Tool\n')); const projectPath = process.cwd(); try { // Phase 1: Project Analysis if (!options.skipAnalysis) { console.log(chalk.bold('šŸ“Š Phase 1: Project Analysis\n')); const spinner = ora('Analyzing project structure...').start(); const analyzer = new ProjectAnalyzer(); const analysis = await analyzer.analyze(projectPath); spinner.succeed('Project analysis complete'); console.log(chalk.gray(` Framework: ${analysis.framework.name} ${analysis.framework.version}`)); console.log(chalk.gray(` Router: ${analysis.routerType}`)); console.log(chalk.gray(` TypeScript: ${analysis.typescript.isTypeScript ? 'Yes' : 'No'}`)); } // Phase 2: Health Check console.log(chalk.bold('\nšŸ„ Phase 2: Health Check\n')); const healthChecker = new HealthChecker(projectPath); const healthResults = await healthChecker.runHealthCheck(); if (healthResults.score === 100) { console.log(chalk.green('āœ… All health checks passed!')); } else { console.log(chalk.yellow(`āš ļø Health Score: ${healthResults.score}%`)); if (healthResults.issues.length > 0) { console.log(chalk.yellow('\nIssues Found:')); healthResults.issues.forEach(issue => { console.log(chalk.red(` āŒ ${issue.name}`)); console.log(chalk.gray(` ${issue.error}`)); if (issue.solution) { console.log(chalk.blue(` → ${issue.solution}`)); } }); } } // Phase 3: Build Verification (for Next.js projects) if (analysis?.framework?.name === 'next') { console.log(chalk.bold('\nšŸ”Ø Phase 3: Build Verification\n')); const buildVerifier = new BuildVerifier(projectPath); const buildResults = await buildVerifier.quickVerify(); if (buildResults.passed) { console.log(chalk.green('āœ… Build integrity verified')); } else { console.log(chalk.red('āŒ Build issues detected:')); buildResults.issues.forEach(issue => { console.log(chalk.red(` - ${issue}`)); }); if (options.fix) { console.log(chalk.blue('\nšŸ”§ Attempting auto-fix...')); const fixes = await buildVerifier.attemptAutoFix(); if (fixes.length > 0) { console.log(chalk.green('āœ… Applied fixes:')); fixes.forEach(fix => { console.log(chalk.green(` - ${fix}`)); }); } } } } // Phase 4: Conflict Detection if (options.conflicts) { console.log(chalk.bold('\nšŸ” Phase 4: Conflict Detection\n')); const spinner = ora('Scanning for conflicts...').start(); const scanner = new ConflictScanner(); const conflicts = await scanner.scanProject(projectPath); if (conflicts.length === 0) { spinner.succeed('No conflicts found'); } else { spinner.warn(`Found ${conflicts.length} potential conflicts`); // Group conflicts by type const conflictTypes = {}; conflicts.forEach(conflict => { if (!conflictTypes[conflict.type]) { conflictTypes[conflict.type] = []; } conflictTypes[conflict.type].push(conflict); }); // Display conflicts by type Object.entries(conflictTypes).forEach(([type, typeConflicts]) => { console.log(chalk.yellow(`\n${type} Conflicts (${typeConflicts.length}):`)); const displayLimit = 5; typeConflicts.slice(0, displayLimit).forEach(conflict => { console.log(chalk.gray(` - ${conflict.file}`)); if (conflict.pattern) { console.log(chalk.gray(` Pattern: ${conflict.pattern}`)); } }); if (typeConflicts.length > displayLimit) { console.log(chalk.gray(` ... and ${typeConflicts.length - displayLimit} more`)); } }); } } // Phase 5: Auto-fix if (options.fix) { console.log(chalk.bold('\nšŸ”§ Phase 5: Auto-Fix\n')); const fixes = []; // Fix 1: Missing dependencies if (healthResults.issues.some(i => i.name === 'Dependencies Installed' && !i.success)) { const spinner = ora('Installing missing dependencies...').start(); try { const { execSync } = require('child_process'); execSync('npm install @google/generative-ai', { cwd: projectPath, stdio: 'pipe' }); spinner.succeed('Dependencies installed'); fixes.push('Installed missing dependencies'); } catch (error) { spinner.fail('Failed to install dependencies'); } } // Fix 2: Missing environment variables if (healthResults.issues.some(i => i.name === 'Environment Variables' && !i.success)) { const spinner = ora('Setting up environment files...').start(); try { const envPath = path.join(projectPath, '.env.local'); const envExamplePath = path.join(projectPath, '.env.example'); if (!await fs.pathExists(envPath)) { await fs.writeFile(envPath, 'GEMINI_API_KEY=your_api_key_here\n'); fixes.push('Created .env.local file'); } if (!await fs.pathExists(envExamplePath)) { await fs.writeFile(envExamplePath, 'GEMINI_API_KEY=your_api_key_here\n'); fixes.push('Created .env.example file'); } spinner.succeed('Environment files set up'); } catch (error) { spinner.fail('Failed to set up environment files'); } } // Fix 3: Integration issues if (healthResults.issues.some(i => i.name === 'Integration Status' && !i.success)) { console.log(chalk.yellow('\nāš ļø Integration issues require manual intervention')); console.log(chalk.blue('Please follow the integration instructions provided during installation')); } if (fixes.length > 0) { console.log(chalk.green(`\nāœ… Applied ${fixes.length} fixes:`)); fixes.forEach(fix => { console.log(chalk.green(` - ${fix}`)); }); console.log(chalk.blue('\nšŸ’” Run "npx embedia doctor" again to verify fixes')); } else { console.log(chalk.gray('\nNo automatic fixes available')); } } // Summary console.log(chalk.bold('\nšŸ“‹ Summary\n')); if (healthResults.score === 100 && (!buildResults || buildResults.passed)) { console.log(chalk.green('āœ… Your Embedia installation is healthy!')); } else { console.log(chalk.yellow('āš ļø Some issues need attention')); if (!options.fix) { console.log(chalk.blue('\nšŸ’” Run "npx embedia doctor --fix" to attempt automatic fixes')); } } // Recommendations if (healthResults.recommendations && healthResults.recommendations.length > 0) { console.log(chalk.bold('\nšŸ’” Recommendations:\n')); healthResults.recommendations.forEach(rec => { console.log(chalk.blue(` • ${rec}`)); }); } } catch (error) { console.error(chalk.red(`\nāŒ Doctor encountered an error: ${error.message}\n`)); if (process.env.DEBUG) { console.error(chalk.gray(error.stack)); } process.exit(1); } } module.exports = doctorCommand;