UNPKG

incize

Version:

AI Commit Copilot for Power Developers

201 lines (200 loc) 8.48 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MockAIAnalyzer = void 0; class MockAIAnalyzer { /** * Analyze diff using mock AI (offline mode) */ async analyze(_prompt) { // Simulate API delay await this.simulateDelay(1000 + Math.random() * 2000); // Mock analyzer doesn't need the full context, just simulate analysis const diff = { files: [], summary: { additions: 0, deletions: 0, totalChanges: 0 } }; const commit = { hash: 'mock', author: 'mock', date: 'mock', message: 'mock', branch: 'mock' }; // Generate mock analysis based on diff characteristics const analysis = this.generateMockAnalysis(diff, commit); return analysis; } /** * Generate realistic mock analysis */ generateMockAnalysis(diff, commit) { const languages = [...new Set(diff.files.map((f) => f.language).filter(Boolean))]; // Calculate risk score based on changes const riskScore = this.calculateRiskScore(diff); const riskLevel = this.getRiskLevel(riskScore); // Generate summary based on change characteristics const summary = this.generateSummary(diff, commit); // Generate suggestions based on file types and changes const suggestions = this.generateSuggestions(diff, languages); // Generate changelog entry const changelog = this.generateChangelog(diff, commit); // Generate test suggestions const testSuggestions = this.generateTestSuggestions(diff, languages); // Calculate confidence based on analysis quality const confidence = this.calculateConfidence(diff); return { summary, riskScore, riskLevel, suggestions, changelog, testSuggestions, confidence }; } /** * Calculate risk score based on diff characteristics */ calculateRiskScore(diff) { const { additions, deletions, totalChanges } = diff.summary; const fileCount = diff.files.length; const languages = diff.files.map((f) => f.language).filter(Boolean); let riskScore = 0; // High risk factors if (totalChanges > 500) riskScore += 30; if (fileCount > 10) riskScore += 20; if (languages.includes('JavaScript') || languages.includes('TypeScript')) riskScore += 10; if (languages.includes('Python')) riskScore += 5; if (languages.includes('Go') || languages.includes('Rust')) riskScore -= 5; // Check for sensitive files const sensitivePatterns = ['config', 'secret', 'password', 'key', 'token', 'auth']; const hasSensitiveFiles = diff.files.some((f) => sensitivePatterns.some(pattern => f.path.toLowerCase().includes(pattern))); if (hasSensitiveFiles) riskScore += 25; // Check for large deletions if (deletions > additions * 2) riskScore += 15; return Math.min(100, Math.max(0, riskScore)); } /** * Get risk level from score */ getRiskLevel(score) { if (score < 20) return 'low'; if (score < 50) return 'medium'; if (score < 80) return 'high'; return 'critical'; } /** * Generate summary based on changes */ generateSummary(diff, _commit) { const { additions, deletions, totalChanges } = diff.summary; const fileCount = diff.files.length; const languages = [...new Set(diff.files.map((f) => f.language).filter(Boolean))]; if (fileCount === 0) { return 'No changes detected in this commit.'; } const changeType = additions > deletions ? 'additions' : 'modifications'; const languageText = languages.length > 0 ? ` in ${languages.join(', ')}` : ''; return `Updated ${fileCount} file(s) with ${totalChanges} line changes (${changeType})${languageText}.`; } /** * Generate suggestions based on file types and changes */ generateSuggestions(diff, languages) { const suggestions = []; // Language-specific suggestions if (languages.includes('JavaScript') || languages.includes('TypeScript')) { suggestions.push('Consider adding TypeScript types for better type safety'); suggestions.push('Review for potential null/undefined access patterns'); } if (languages.includes('Python')) { suggestions.push('Consider adding type hints for better code documentation'); suggestions.push('Review for proper exception handling'); } if (languages.includes('Go')) { suggestions.push('Ensure proper error handling for all function calls'); suggestions.push('Consider adding unit tests for new functions'); } // General suggestions based on change volume const { totalChanges } = diff.summary; if (totalChanges > 100) { suggestions.push('Large change detected - consider breaking into smaller commits'); } if (diff.files.length > 5) { suggestions.push('Multiple files changed - ensure changes are logically grouped'); } // Security suggestions const hasConfigFiles = diff.files.some((f) => f.path.includes('config') || f.path.includes('secret')); if (hasConfigFiles) { suggestions.push('Review configuration changes for sensitive data exposure'); } return suggestions.slice(0, 3); // Limit to 3 suggestions } /** * Generate changelog entry */ generateChangelog(diff, commit) { const { additions, deletions } = diff.summary; const fileCount = diff.files.length; const languages = [...new Set(diff.files.map((f) => f.language).filter(Boolean))]; const changeType = additions > deletions ? 'Added' : 'Modified'; const languageText = languages.length > 0 ? ` (${languages.join(', ')})` : ''; return `${changeType} ${fileCount} file(s)${languageText} - ${commit.message}`; } /** * Generate test suggestions */ generateTestSuggestions(diff, languages) { const suggestions = []; // Language-specific test suggestions if (languages.includes('JavaScript') || languages.includes('TypeScript')) { suggestions.push('Add Jest unit tests for new functions'); suggestions.push('Consider integration tests for API endpoints'); } if (languages.includes('Python')) { suggestions.push('Add pytest unit tests for new modules'); suggestions.push('Consider adding doctests for documentation'); } if (languages.includes('Go')) { suggestions.push('Add Go test files for new packages'); suggestions.push('Consider table-driven tests for edge cases'); } // General test suggestions const { totalChanges } = diff.summary; if (totalChanges > 50) { suggestions.push('Large changes detected - ensure comprehensive test coverage'); } return suggestions.slice(0, 2); // Limit to 2 suggestions } /** * Calculate confidence based on analysis quality */ calculateConfidence(diff) { const { totalChanges } = diff.summary; const fileCount = diff.files.length; const languages = diff.files.map((f) => f.language).filter(Boolean); let confidence = 0.7; // Base confidence // Higher confidence for smaller, focused changes if (totalChanges < 50) confidence += 0.1; if (fileCount < 3) confidence += 0.1; // Higher confidence for well-known languages const knownLanguages = ['JavaScript', 'TypeScript', 'Python', 'Go', 'Rust']; const hasKnownLanguages = languages.some((lang) => knownLanguages.includes(lang)); if (hasKnownLanguages) confidence += 0.1; // Lower confidence for very large changes if (totalChanges > 200) confidence -= 0.2; return Math.min(1.0, Math.max(0.0, confidence)); } /** * Simulate API delay */ async simulateDelay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } } exports.MockAIAnalyzer = MockAIAnalyzer;