UNPKG

vibe-code-build

Version:

Real-time code monitoring with teaching explanations, CLAUDE.md compliance checking, and interactive chat

294 lines (248 loc) • 12.3 kB
import chalk from 'chalk'; import { themeManager } from './theme-manager.js'; import { aiCodeAnalyzer } from './ai-code-analyzer.js'; /** * Unified Insight Engine with three modes: * - basic: Original simple insights * - detailed: Enhanced educational analysis * - optimized: Token-efficient insights */ export class InsightEngine { constructor() { this.mode = 'optimized'; // default mode // Shared patterns for all modes this.patterns = { stateManagement: /setState|useState|state\s*=/, apiIntegration: /fetch|axios|api|http/i, authentication: /auth|login|token|session/i, database: /query|select|insert|update|delete|mongoose|sequelize/i, errorHandling: /try|catch|error|throw/i, validation: /validate|check|verify|sanitize/i, performance: /memo|cache|Cache|optimize|debounce|throttle|performance/i, security: /password|secret|key|encrypt|hash/i, async: /async|await|promise|then/i, hooks: /use[A-Z]\w+/, testing: /test|spec|expect|jest|mocha/i }; } setMode(mode) { return this.mode = mode; } getMode() { return this.mode; } analyzeChange(context) { // Check if this looks like AI-generated code const { diff } = context; if (diff && this.looksLikeAICode(diff)) { return aiCodeAnalyzer.analyzeAICode(context); } // Otherwise use optimized mode return this.optimizedAnalysis(context); } looksLikeAICode(diff) { // Quick heuristics to detect AI-generated code const addedLines = diff.split('\n') .filter(line => line.startsWith('+') && !line.startsWith('+++')) .join('\n'); // AI code often has these patterns const aiIndicators = [ /try\s*{[\s\S]*?}\s*catch/, // Error handling /if\s*\([^)]*\)\s*{[\s\S]*?return/, // Validation checks /async[\s\S]*?await/, // Modern async /\/\/ [A-Z]/, // Proper comments /console\.(log|error)/, // Logging /\?\./, // Optional chaining /const\s+{.*?}\s*=/ // Destructuring ]; const matches = aiIndicators.filter(pattern => pattern.test(addedLines)).length; return matches >= 2; } // Optimized mode - only explain the diff optimizedAnalysis(context) { const { diff, filename, type } = context; const colors = themeManager.getColors(); const added = (diff.match(/^\+[^+]/gm) || []).length; const removed = (diff.match(/^-[^-]/gm) || []).length; let output = ''; // File and change count output += colors.primary(`\nšŸ“Š ${filename}: ${added} additions, ${removed} deletions\n`); // Simple explanation of what changed if (diff) { const explanation = this.explainDiffChanges(context); if (explanation) { output += colors.muted(`\n ${explanation}\n`); } } return output; } explainDiffChanges(context) { const { diff, filename } = context; const lines = diff.split('\n'); const addedLines = lines.filter(l => l.startsWith('+') && !l.startsWith('+++')); const removedLines = lines.filter(l => l.startsWith('-') && !l.startsWith('---')); const addedCode = addedLines.map(l => l.substring(1).trim()).join(' '); const removedCode = removedLines.map(l => l.substring(1).trim()).join(' '); // More detailed explanations let explanation = ''; // Check for specific patterns and provide detailed explanations if (addedCode.includes('BuildChecker') || addedCode.includes('DependencyChecker') || addedCode.includes('SecurityChecker') || addedCode.includes('PerformanceOptimizer')) { explanation = 'Added comprehensive code quality checking modules:\n'; if (addedCode.includes('BuildChecker')) { explanation += ' • BuildChecker: Verifies if project builds, runs TypeScript checks, and linting\n'; } if (addedCode.includes('DependencyChecker')) { explanation += ' • DependencyChecker: Scans for vulnerabilities and outdated packages\n'; } if (addedCode.includes('SecurityChecker')) { explanation += ' • SecurityChecker: Detects dangerous patterns and exposed secrets\n'; } if (addedCode.includes('PerformanceOptimizer')) { explanation += ' • PerformanceOptimizer: Analyzes bundle sizes and SEO issues\n'; } return explanation.trim(); } if (addedCode.includes('checkGodMode') || addedCode.includes('god mode')) { return 'Added AI god mode detection to identify dangerous code patterns like:\n' + ' • System deletion commands (rm -rf /)\n' + ' • Dynamic code execution (eval, Function)\n' + ' • Process termination and infinite loops'; } if (addedCode.includes('checkSecrets') || addedCode.includes('exposed secrets')) { return 'Added secret detection to find exposed credentials:\n' + ' • API keys and tokens\n' + ' • Passwords and authentication data\n' + ' • Database connection strings'; } if (addedCode.includes('formatResults') || addedCode.includes('CheckFormatter')) { return 'Added beautiful output formatting for check results with:\n' + ' • Color-coded severity levels\n' + ' • Progress indicators and health scores\n' + ' • Actionable recommendations'; } if (addedCode.includes('todo') || addedCode.includes('Todo')) { return 'Added todo list functionality with:\n' + ' • Task creation and deletion\n' + ' • Priority levels (high/medium/low)\n' + ' • Progress tracking and completion status'; } if (addedCode.includes('async') && addedCode.includes('await')) { const asyncMatch = addedCode.match(/async\s+(\w+)/); const funcName = asyncMatch ? asyncMatch[1] : 'function'; return `Added asynchronous ${funcName} for non-blocking operations:\n` + ' • Prevents UI freezing during long operations\n' + ' • Enables parallel execution of tasks\n' + ' • Better error handling with try/catch'; } if (addedCode.includes('try') && addedCode.includes('catch')) { return 'Added error handling to prevent crashes:\n' + ' • Gracefully handles failures\n' + ' • Provides user-friendly error messages\n' + ' • Enables debugging with error logging'; } // Enhanced function detection if (addedCode.match(/function|const.*=.*\(|=>|class/)) { const functionMatch = addedCode.match(/(function\s+(\w+)|const\s+(\w+)|\s+(\w+)\s*(?:=|:))/); if (functionMatch) { const funcName = functionMatch[2] || functionMatch[3] || functionMatch[4] || 'function'; // Try to understand what the function does if (funcName.includes('check') || funcName.includes('Check')) { return `Added ${funcName} to validate and analyze code quality`; } if (funcName.includes('format') || funcName.includes('Format')) { return `Added ${funcName} to format output for better readability`; } if (funcName.includes('handle') || funcName.includes('Handle')) { return `Added ${funcName} to handle user interactions and events`; } if (funcName.includes('display') || funcName.includes('Display')) { return `Added ${funcName} to render UI elements and information`; } return `Added ${funcName} function to extend functionality`; } } // Import analysis if (addedCode.includes('import') || addedCode.includes('require')) { const importMatch = addedCode.match(/import.*from\s+['"]([^'"]+)['"]|require\(['"]([^'"]+)['"]\)/); if (importMatch) { const module = importMatch[1] || importMatch[2]; if (module.includes('chalk')) return 'Added chalk for colorful terminal output'; if (module.includes('ora')) return 'Added ora for elegant loading spinners'; if (module.includes('boxen')) return 'Added boxen for beautiful boxed terminal output'; return `Added ${module} module to enhance functionality`; } } // Default to category-based explanation const category = this.detectChangeCategory(context); return this.getCategoryExplanation(category, addedLines.length, removedLines.length); } getCategoryExplanation(category, addedCount, removedCount) { const explanations = { 'feature': `Added new feature (${addedCount} lines):\n • Extends application capabilities\n • Provides new functionality for users`, 'fix': `Fixed a bug or issue:\n • Resolves existing problems\n • Improves stability and reliability`, 'refactor': `Refactored code for better structure:\n • Improves code readability\n • Makes future changes easier`, 'performance': `Optimized performance:\n • Reduces execution time\n • Improves resource usage`, 'security': `Enhanced security:\n • Prevents vulnerabilities\n • Protects user data`, 'docs': `Updated documentation:\n • Improves code understanding\n • Helps future developers`, 'test': `Updated test coverage:\n • Ensures code reliability\n • Prevents regressions` }; return explanations[category] || `Modified code (${addedCount} additions, ${removedCount} deletions)`; } detectChangeCategory(context) { const { diff, type, filename } = context; if (type === 'added') return 'feature'; if (type === 'deleted') return 'cleanup'; if (filename.includes('test') || filename.includes('spec')) return 'test'; if (filename.includes('.md')) return 'docs'; // Analyze the diff content for more accurate categorization if (diff) { const addedLines = diff.split('\n').filter(l => l.startsWith('+') && !l.startsWith('+++')).join('\n'); const removedLines = diff.split('\n').filter(l => l.startsWith('-') && !l.startsWith('---')).join('\n'); // Feature detection if (addedLines.includes('new ') || addedLines.includes('constructor') || addedLines.match(/\w+Mode/) || addedLines.match(/display\w+/) || addedLines.match(/handle\w+/) || addedLines.includes('// Todo') || addedLines.includes('todos') || addedLines.includes('selectedTodoIndex')) { return 'feature'; } // Specific keywords if (diff.includes('fix')) return 'fix'; if (diff.includes('perf')) return 'performance'; if (diff.includes('security')) return 'security'; // Bug fixes usually have small targeted changes const addedCount = (diff.match(/^\+[^+]/gm) || []).length; const removedCount = (diff.match(/^-[^-]/gm) || []).length; if (addedCount > 5 || (addedCount > removedCount * 2)) { return 'feature'; } } return 'refactor'; } getCategoryInfo(category) { const categories = { feature: { icon: '✨', label: 'New Feature', color: 'green' }, fix: { icon: 'šŸ›', label: 'Bug Fix', color: 'red' }, refactor: { icon: 'ā™»ļø', label: 'Refactoring', color: 'blue' }, performance: { icon: '⚔', label: 'Performance', color: 'yellow' }, security: { icon: 'šŸ”’', label: 'Security', color: 'red' }, docs: { icon: 'šŸ“', label: 'Documentation', color: 'gray' }, test: { icon: '🧪', label: 'Testing', color: 'cyan' }, cleanup: { icon: '🧹', label: 'Cleanup', color: 'gray' } }; return categories[category] || { icon: 'šŸ“¦', label: 'Change', color: 'white' }; } detectPatterns(context) { const { diff, content } = context; const detected = []; const searchText = diff || content || ''; for (const [name, pattern] of Object.entries(this.patterns)) { if (pattern.test(searchText)) { detected.push(name); } } return detected; } } // Export singleton instance export const insightEngine = new InsightEngine();