UNPKG

vibe-code-build

Version:

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

267 lines (229 loc) 9.34 kB
import chalk from 'chalk'; import { themeManager } from './theme-manager.js'; /** * AI Code Analyzer - Detects and explains AI-generated code patterns * Provides detailed explanations of what AI code does and why */ export class AICodeAnalyzer { constructor() { this.aiPatterns = { // Common AI code generation patterns errorHandling: { pattern: /try\s*{[\s\S]*?}\s*catch\s*\((\w+)\)\s*{[\s\S]*?}/, explain: 'AI added comprehensive error handling to prevent crashes' }, asyncAwait: { pattern: /async\s+(\w+)[\s\S]*?await\s+/, explain: 'AI implemented asynchronous operations for better performance' }, validation: { pattern: /if\s*\(!?\w+(\.\w+)*\)\s*{[\s\S]*?(throw|return|console\.(error|warn))/, explain: 'AI added input validation to ensure data integrity' }, logging: { pattern: /console\.(log|info|warn|error)\([^)]+\)/, explain: 'AI added logging for debugging and monitoring' }, typeChecking: { pattern: /typeof\s+\w+\s*===?\s*['"][^'"]+['"]|instanceof\s+\w+/, explain: 'AI added type checking for runtime safety' }, nullChecks: { pattern: /\w+\s*\?\.\w+|\w+\s*&&\s*\w+\.\w+|\w+\s*\|\|\s*['"\[\{]/, explain: 'AI added null/undefined checks to prevent errors' }, arrayMethods: { pattern: /\.(map|filter|reduce|forEach|find|some|every)\(/, explain: 'AI used modern array methods for cleaner, functional code' }, destructuring: { pattern: /const\s*{[^}]+}\s*=|const\s*\[[^\]]+\]\s*=/, explain: 'AI used destructuring for cleaner variable extraction' }, templateLiterals: { pattern: /`[^`]*\$\{[^}]+\}[^`]*`/, explain: 'AI used template literals for string formatting' }, promises: { pattern: /new\s+Promise\s*\(|\.then\s*\(|\.catch\s*\(/, explain: 'AI implemented Promise-based asynchronous flow' }, comments: { pattern: /\/\/\s*[A-Z][\s\S]*?\n|\/\*[\s\S]*?\*\//, explain: 'AI added helpful comments to explain the code' } }; this.codeQualityPatterns = { modular: { pattern: /export\s+(default\s+)?(?:class|function|const)|import\s+.*\s+from/, explain: 'Code follows modular design principles' }, defensive: { pattern: /if\s*\([^)]*\)\s*{[\s\S]*?return[\s\S]*?}|guard|validate|check/i, explain: 'Code includes defensive programming practices' }, documented: { pattern: /\/\*\*[\s\S]*?\*\/|@param|@returns|@throws/, explain: 'Code includes JSDoc documentation' }, tested: { pattern: /describe\s*\(|it\s*\(|test\s*\(|expect\s*\(/, explain: 'Code includes test cases' } }; } analyzeAICode(context) { const { diff, filename, type } = context; const colors = themeManager.getColors(); if (!diff) return ''; const analysis = this.detectAIPatterns(diff); if (analysis.patterns.length === 0) { return this.fallbackAnalysis(context); } let output = colors.primary('\n🤖 AI Code Analysis:\n'); // Explain what the AI did output += colors.secondary('\n📝 What the AI implemented:\n'); analysis.patterns.forEach(({ name, explanation, example }) => { output += colors.muted(` • ${explanation}\n`); if (example) { output += colors.accent(` Example: ${this.truncateCode(example)}\n`); } }); // Explain why these patterns are good if (analysis.quality.length > 0) { output += colors.secondary('\n✨ Code quality improvements:\n'); analysis.quality.forEach(quality => { output += colors.success(` • ${quality}\n`); }); } // Provide learning insights output += colors.secondary('\n💡 Why this matters:\n'); output += this.explainBenefits(analysis.patterns); // Suggest improvements if needed const suggestions = this.suggestImprovements(diff); if (suggestions.length > 0) { output += colors.secondary('\n🎯 Potential improvements:\n'); suggestions.forEach(suggestion => { output += colors.warning(` • ${suggestion}\n`); }); } return output; } detectAIPatterns(diff) { const patterns = []; const quality = []; const addedLines = diff.split('\n') .filter(line => line.startsWith('+') && !line.startsWith('+++')) .map(line => line.substring(1)) .join('\n'); // Check for AI patterns for (const [name, { pattern, explain }] of Object.entries(this.aiPatterns)) { const match = addedLines.match(pattern); if (match) { patterns.push({ name, explanation: explain, example: match[0] }); } } // Check code quality patterns for (const [name, { pattern, explain }] of Object.entries(this.codeQualityPatterns)) { if (pattern.test(addedLines)) { quality.push(explain); } } // Detect specific AI code generation patterns if (this.looksLikeAIGenerated(addedLines)) { patterns.push({ name: 'ai-generated', explanation: 'This appears to be AI-generated code with consistent style and comprehensive handling' }); } return { patterns, quality }; } looksLikeAIGenerated(code) { // AI-generated code often has these characteristics const indicators = [ code.includes('try {') && code.includes('} catch'), // Comprehensive error handling code.match(/if\s*\([^)]+\)\s*{/g)?.length > 2, // Multiple validation checks code.includes('console.log') || code.includes('console.error'), // Logging code.match(/\/\/ [A-Z]/g)?.length > 1, // Multiple comments code.includes('async') && code.includes('await'), // Modern async patterns code.includes('const') && !code.includes('var'), // Modern JS syntax code.match(/\?\./g)?.length > 0 // Optional chaining ]; const score = indicators.filter(Boolean).length; return score >= 3; } explainBenefits(patterns) { const colors = themeManager.getColors(); const benefits = []; const hasErrorHandling = patterns.some(p => p.name === 'errorHandling'); const hasValidation = patterns.some(p => p.name === 'validation'); const hasAsync = patterns.some(p => p.name === 'asyncAwait'); const hasNullChecks = patterns.some(p => p.name === 'nullChecks'); if (hasErrorHandling) { benefits.push('Error handling prevents app crashes and improves user experience'); } if (hasValidation) { benefits.push('Input validation prevents bugs and security vulnerabilities'); } if (hasAsync) { benefits.push('Async/await makes code more readable than callbacks or raw promises'); } if (hasNullChecks) { benefits.push('Null checks prevent "Cannot read property of undefined" errors'); } if (benefits.length === 0) { benefits.push('This code follows modern JavaScript best practices'); benefits.push('The implementation is robust and production-ready'); } return benefits.map(b => colors.muted(` • ${b}`)).join('\n') + '\n'; } suggestImprovements(diff) { const suggestions = []; const addedLines = diff.split('\n') .filter(line => line.startsWith('+')) .join('\n'); // Check for potential improvements if (addedLines.includes('console.log') && !addedLines.includes('if')) { suggestions.push('Consider adding environment checks for console.log statements'); } if (addedLines.includes('catch(error)') && !addedLines.includes('console.error')) { suggestions.push('Consider logging errors in catch blocks for debugging'); } if (addedLines.match(/function\s+\w+\s*\(/g) && !addedLines.includes('/**')) { suggestions.push('Consider adding JSDoc comments for better documentation'); } if (addedLines.includes('setTimeout') || addedLines.includes('setInterval')) { suggestions.push('Remember to clear timers to prevent memory leaks'); } if (addedLines.length > 200 && !addedLines.includes('export')) { suggestions.push('Consider breaking this into smaller, modular functions'); } return suggestions; } fallbackAnalysis(context) { const colors = themeManager.getColors(); const { diff, filename } = context; const added = (diff.match(/^\+[^+]/gm) || []).length; const removed = (diff.match(/^-[^-]/gm) || []).length; let output = colors.primary(`\n📊 Code changes in ${filename}:\n`); output += colors.muted(` Added ${added} lines, removed ${removed} lines\n`); // Try to provide some generic insights if (added > removed) { output += colors.muted(` • New functionality has been added\n`); } else if (removed > added) { output += colors.muted(` • Code has been simplified or cleaned up\n`); } else { output += colors.muted(` • Code has been refactored\n`); } return output; } truncateCode(code, maxLength = 50) { if (code.length <= maxLength) return code; return code.substring(0, maxLength) + '...'; } } export const aiCodeAnalyzer = new AICodeAnalyzer();