UNPKG

zai-mcp-server

Version:

🚀 REVOLUTIONARY AI-to-AI Collaboration Platform v6.1! NEW: Advanced Debugging Tools with Screenshot Analysis, Console Error Parsing, Automated Fix Generation, 5 Specialized Debugging Agents, Visual UI Analysis, JavaScript Error Intelligence, CSS/HTML Fix

857 lines (751 loc) • 26.3 kB
import { EventEmitter } from 'events'; /** * Semantic Understanding for AI-to-AI Communication * Analyzes user intentions and code semantics for better understanding */ export class SemanticAnalyzer extends EventEmitter { constructor() { super(); this.intentionPatterns = this.initializeIntentionPatterns(); this.codeSemantics = new Map(); // file -> semantic analysis this.userIntentHistory = new Map(); // loopId -> intent history this.domainKnowledge = this.initializeDomainKnowledge(); this.contextualMappings = new Map(); // context -> semantic mappings } /** * Initialize intention patterns * @returns {Object} - Intention patterns */ initializeIntentionPatterns() { return { improvement: { patterns: [ /improve|enhance|optimize|better|upgrade/i, /make.*better|increase.*performance|reduce.*time/i, /fix.*issue|solve.*problem|address.*concern/i ], confidence: 0.8, category: 'enhancement' }, creation: { patterns: [ /create|build|develop|implement|add/i, /new.*feature|fresh.*start|from.*scratch/i, /generate.*code|write.*function|design.*component/i ], confidence: 0.9, category: 'development' }, refactoring: { patterns: [ /refactor|restructure|reorganize|clean.*up/i, /simplify.*code|reduce.*complexity|modularize/i, /extract.*function|split.*component|separate.*concerns/i ], confidence: 0.85, category: 'maintenance' }, testing: { patterns: [ /test|coverage|qa|quality.*assurance/i, /unit.*test|integration.*test|e2e.*test/i, /verify.*functionality|validate.*behavior/i ], confidence: 0.9, category: 'quality' }, performance: { patterns: [ /performance|speed|fast|slow|optimization/i, /memory.*usage|cpu.*usage|load.*time/i, /cache|lazy.*load|bundle.*size/i ], confidence: 0.85, category: 'performance' }, security: { patterns: [ /security|secure|auth|authorization|authentication/i, /vulnerability|exploit|sanitize|validate/i, /encrypt|decrypt|hash|token/i ], confidence: 0.9, category: 'security' }, ui_ux: { patterns: [ /ui|ux|user.*interface|user.*experience/i, /design|layout|styling|visual|appearance/i, /responsive|mobile|accessibility|usability/i ], confidence: 0.8, category: 'frontend' }, api: { patterns: [ /api|endpoint|route|service|backend/i, /rest|graphql|microservice|database/i, /crud|http|request|response/i ], confidence: 0.85, category: 'backend' } }; } /** * Initialize domain knowledge * @returns {Object} - Domain knowledge base */ initializeDomainKnowledge() { return { technologies: { frontend: ['react', 'vue', 'angular', 'svelte', 'html', 'css', 'javascript', 'typescript'], backend: ['nodejs', 'python', 'java', 'go', 'rust', 'php', 'ruby', 'c#'], database: ['mysql', 'postgresql', 'mongodb', 'redis', 'sqlite', 'cassandra'], cloud: ['aws', 'azure', 'gcp', 'docker', 'kubernetes', 'serverless'], testing: ['jest', 'mocha', 'cypress', 'selenium', 'junit', 'pytest'] }, patterns: { architectural: ['mvc', 'mvvm', 'microservices', 'monolith', 'serverless', 'event-driven'], design: ['singleton', 'factory', 'observer', 'strategy', 'decorator', 'adapter'], data: ['repository', 'active-record', 'data-mapper', 'unit-of-work'] }, concepts: { performance: ['caching', 'lazy-loading', 'code-splitting', 'bundling', 'minification'], security: ['authentication', 'authorization', 'encryption', 'sanitization', 'validation'], quality: ['testing', 'coverage', 'linting', 'documentation', 'code-review'] } }; } /** * Parse user intentions from request * @param {string} userRequest - User's request * @returns {Object} - Parsed intentions */ parseUserIntentions(userRequest) { console.error(`[SEMANTIC ANALYZER] Parsing user intentions: "${userRequest}"`); const intentions = []; const requestLower = userRequest.toLowerCase(); // Analyze against intention patterns for (const [intentType, intentData] of Object.entries(this.intentionPatterns)) { let confidence = 0; const matches = []; for (const pattern of intentData.patterns) { const match = requestLower.match(pattern); if (match) { matches.push(match[0]); confidence += intentData.confidence / intentData.patterns.length; } } if (confidence > 0) { intentions.push({ type: intentType, category: intentData.category, confidence: Math.min(confidence, 1), matches, priority: this.calculateIntentionPriority(intentType, confidence, matches) }); } } // Extract implicit requirements const implicitRequirements = this.extractImplicitRequirements(userRequest); // Identify technology context const technologyContext = this.identifyTechnologyContext(userRequest); // Suggest related improvements const relatedImprovements = this.suggestRelatedImprovements(intentions); const result = { originalRequest: userRequest, primaryIntentions: intentions.filter(i => i.confidence > 0.6).sort((a, b) => b.confidence - a.confidence), secondaryIntentions: intentions.filter(i => i.confidence <= 0.6 && i.confidence > 0.3), implicitRequirements, technologyContext, relatedImprovements, complexity: this.assessRequestComplexity(userRequest, intentions), scope: this.determineScope(userRequest, intentions), timestamp: new Date() }; console.error(`[SEMANTIC ANALYZER] Found ${result.primaryIntentions.length} primary intentions`); return result; } /** * Calculate intention priority * @param {string} intentType - Type of intention * @param {number} confidence - Confidence score * @param {Array} matches - Pattern matches * @returns {number} - Priority score */ calculateIntentionPriority(intentType, confidence, matches) { const priorityWeights = { security: 1.0, testing: 0.9, performance: 0.8, creation: 0.7, improvement: 0.6, refactoring: 0.5, ui_ux: 0.4, api: 0.6 }; const baseWeight = priorityWeights[intentType] || 0.5; const matchBonus = matches.length * 0.1; return Math.min(baseWeight + matchBonus, 1) * confidence; } /** * Extract implicit requirements * @param {string} userRequest - User's request * @returns {Array} - Implicit requirements */ extractImplicitRequirements(userRequest) { const requirements = []; const requestLower = userRequest.toLowerCase(); // Performance implications if (requestLower.includes('fast') || requestLower.includes('slow')) { requirements.push({ type: 'performance', requirement: 'Performance optimization needed', confidence: 0.8 }); } // Scalability implications if (requestLower.includes('scale') || requestLower.includes('growth') || requestLower.includes('load')) { requirements.push({ type: 'scalability', requirement: 'Scalability considerations required', confidence: 0.7 }); } // Maintainability implications if (requestLower.includes('maintain') || requestLower.includes('complex') || requestLower.includes('messy')) { requirements.push({ type: 'maintainability', requirement: 'Code maintainability improvement needed', confidence: 0.6 }); } // Accessibility implications if (requestLower.includes('user') || requestLower.includes('accessible') || requestLower.includes('mobile')) { requirements.push({ type: 'accessibility', requirement: 'Accessibility and usability considerations', confidence: 0.5 }); } // Testing implications if (requestLower.includes('reliable') || requestLower.includes('stable') || requestLower.includes('bug')) { requirements.push({ type: 'testing', requirement: 'Testing and quality assurance needed', confidence: 0.7 }); } return requirements; } /** * Identify technology context * @param {string} userRequest - User's request * @returns {Object} - Technology context */ identifyTechnologyContext(userRequest) { const context = { frontend: [], backend: [], database: [], cloud: [], testing: [] }; const requestLower = userRequest.toLowerCase(); for (const [category, technologies] of Object.entries(this.domainKnowledge.technologies)) { for (const tech of technologies) { if (requestLower.includes(tech)) { context[category].push({ technology: tech, confidence: 0.9 }); } } } return context; } /** * Suggest related improvements * @param {Array} intentions - Parsed intentions * @returns {Array} - Related improvement suggestions */ suggestRelatedImprovements(intentions) { const suggestions = []; intentions.forEach(intention => { switch (intention.type) { case 'ui_ux': suggestions.push( 'Consider accessibility improvements', 'Add responsive design enhancements', 'Implement performance optimizations for UI' ); break; case 'performance': suggestions.push( 'Add performance monitoring', 'Implement caching strategies', 'Consider code splitting and lazy loading' ); break; case 'security': suggestions.push( 'Conduct security audit', 'Implement input validation', 'Add authentication and authorization' ); break; case 'testing': suggestions.push( 'Increase test coverage', 'Add integration tests', 'Implement automated testing pipeline' ); break; case 'api': suggestions.push( 'Add API documentation', 'Implement rate limiting', 'Add error handling and validation' ); break; } }); return [...new Set(suggestions)]; // Remove duplicates } /** * Assess request complexity * @param {string} userRequest - User's request * @param {Array} intentions - Parsed intentions * @returns {Object} - Complexity assessment */ assessRequestComplexity(userRequest, intentions) { let complexityScore = 0; const factors = []; // Multiple intentions increase complexity if (intentions.length > 2) { complexityScore += 0.3; factors.push('Multiple intentions detected'); } // Cross-domain requirements increase complexity const categories = [...new Set(intentions.map(i => i.category))]; if (categories.length > 2) { complexityScore += 0.2; factors.push('Cross-domain requirements'); } // Complex keywords const complexKeywords = ['architecture', 'microservice', 'distributed', 'enterprise', 'scalable']; if (complexKeywords.some(keyword => userRequest.toLowerCase().includes(keyword))) { complexityScore += 0.3; factors.push('Complex architectural requirements'); } // Length and detail if (userRequest.length > 200) { complexityScore += 0.1; factors.push('Detailed requirements'); } const level = complexityScore >= 0.7 ? 'high' : complexityScore >= 0.4 ? 'medium' : 'low'; return { level, score: complexityScore, factors }; } /** * Determine scope * @param {string} userRequest - User's request * @param {Array} intentions - Parsed intentions * @returns {Object} - Scope determination */ determineScope(userRequest, intentions) { const requestLower = userRequest.toLowerCase(); let scope = 'component'; const indicators = []; // System-wide scope indicators if (requestLower.includes('entire') || requestLower.includes('whole') || requestLower.includes('all')) { scope = 'system'; indicators.push('System-wide keywords detected'); } // Module scope indicators if (requestLower.includes('module') || requestLower.includes('service') || requestLower.includes('package')) { scope = 'module'; indicators.push('Module-level keywords detected'); } // File scope indicators if (requestLower.includes('file') || requestLower.includes('class') || requestLower.includes('function')) { scope = 'file'; indicators.push('File-level keywords detected'); } // Multiple categories suggest broader scope const categories = [...new Set(intentions.map(i => i.category))]; if (categories.length > 2 && scope === 'component') { scope = 'module'; indicators.push('Multiple categories suggest broader scope'); } return { level: scope, indicators, estimatedFiles: this.estimateAffectedFiles(scope), estimatedEffort: this.estimateEffort(scope, intentions.length) }; } /** * Estimate affected files * @param {string} scope - Scope level * @returns {number} - Estimated number of files */ estimateAffectedFiles(scope) { const estimates = { file: 1, component: 3, module: 8, system: 20 }; return estimates[scope] || 3; } /** * Estimate effort * @param {string} scope - Scope level * @param {number} intentionCount - Number of intentions * @returns {string} - Effort estimate */ estimateEffort(scope, intentionCount) { const baseEffort = { file: 1, component: 2, module: 4, system: 8 }; const effort = (baseEffort[scope] || 2) * Math.max(1, intentionCount / 2); if (effort <= 2) {return 'low';} if (effort <= 5) {return 'medium';} if (effort <= 10) {return 'high';} return 'very_high'; } /** * Understand code semantics * @param {string} filePath - File path * @param {string} codeContent - Code content * @returns {Object} - Semantic analysis */ understandCodeSemantics(filePath, codeContent) { console.error(`[SEMANTIC ANALYZER] Analyzing code semantics for ${filePath}`); const semantics = { filePath, timestamp: new Date(), businessLogic: this.extractBusinessLogic(codeContent), architecturalPatterns: this.identifyArchitecturalPatterns(codeContent), designPatterns: this.identifyDesignPatterns(codeContent), dependencies: this.analyzeDependencies(codeContent), complexity: this.analyzeCodeComplexity(codeContent), purpose: this.inferPurpose(filePath, codeContent), qualityMetrics: this.calculateQualityMetrics(codeContent) }; this.codeSemantics.set(filePath, semantics); this.emit('semanticsAnalyzed', { filePath, semantics }); return semantics; } /** * Extract business logic * @param {string} codeContent - Code content * @returns {Array} - Business logic elements */ extractBusinessLogic(codeContent) { const businessLogic = []; // Look for business-related function names const businessPatterns = [ /function\s+(\w*(?:calculate|process|validate|generate|create|update|delete|handle)\w*)/gi, /const\s+(\w*(?:calculate|process|validate|generate|create|update|delete|handle)\w*)\s*=/gi, /class\s+(\w*(?:Manager|Service|Controller|Handler|Processor)\w*)/gi ]; businessPatterns.forEach(pattern => { const matches = codeContent.match(pattern); if (matches) { matches.forEach(match => { businessLogic.push({ type: 'function', name: match, confidence: 0.7 }); }); } }); return businessLogic; } /** * Identify architectural patterns * @param {string} codeContent - Code content * @returns {Array} - Architectural patterns */ identifyArchitecturalPatterns(codeContent) { const patterns = []; // MVC pattern if (/controller|model|view/i.test(codeContent)) { patterns.push({ pattern: 'MVC', confidence: 0.8 }); } // Repository pattern if (/repository|repo/i.test(codeContent)) { patterns.push({ pattern: 'Repository', confidence: 0.9 }); } // Service pattern if (/service|provider/i.test(codeContent)) { patterns.push({ pattern: 'Service', confidence: 0.7 }); } // Observer pattern if (/observer|subscribe|emit|event/i.test(codeContent)) { patterns.push({ pattern: 'Observer', confidence: 0.6 }); } return patterns; } /** * Identify design patterns * @param {string} codeContent - Code content * @returns {Array} - Design patterns */ identifyDesignPatterns(codeContent) { const patterns = []; // Singleton pattern if (/getInstance|singleton/i.test(codeContent)) { patterns.push({ pattern: 'Singleton', confidence: 0.9 }); } // Factory pattern if (/factory|create\w+/i.test(codeContent)) { patterns.push({ pattern: 'Factory', confidence: 0.7 }); } // Strategy pattern if (/strategy|algorithm/i.test(codeContent)) { patterns.push({ pattern: 'Strategy', confidence: 0.6 }); } return patterns; } /** * Analyze dependencies * @param {string} codeContent - Code content * @returns {Object} - Dependency analysis */ analyzeDependencies(codeContent) { const imports = []; const exports = []; // ES6 imports const importMatches = codeContent.match(/import\s+.*\s+from\s+['"`]([^'"`]+)['"`]/g); if (importMatches) { importMatches.forEach(match => { const moduleMatch = match.match(/from\s+['"`]([^'"`]+)['"`]/); if (moduleMatch) { imports.push({ module: moduleMatch[1], type: moduleMatch[1].startsWith('.') ? 'local' : 'external' }); } }); } // Exports const exportMatches = codeContent.match(/export\s+(?:default\s+)?(?:class|function|const|let|var)\s+(\w+)/g); if (exportMatches) { exportMatches.forEach(match => { const nameMatch = match.match(/(\w+)$/); if (nameMatch) { exports.push(nameMatch[1]); } }); } return { imports, exports, externalDependencies: imports.filter(imp => imp.type === 'external').length, localDependencies: imports.filter(imp => imp.type === 'local').length }; } /** * Analyze code complexity * @param {string} codeContent - Code content * @returns {Object} - Complexity analysis */ analyzeCodeComplexity(codeContent) { let cyclomaticComplexity = 1; // Base complexity // Count decision points const decisionPatterns = [ /\bif\s*\(/g, /\belse\s+if\b/g, /\bwhile\s*\(/g, /\bfor\s*\(/g, /\bswitch\s*\(/g, /\bcatch\s*\(/g, /\?\s*.*\s*:/g // Ternary operators ]; decisionPatterns.forEach(pattern => { const matches = codeContent.match(pattern); if (matches) { cyclomaticComplexity += matches.length; } }); const lines = codeContent.split('\n').length; const functions = (codeContent.match(/function\s+\w+|=>\s*{|=>\s*\w+/g) || []).length; return { cyclomaticComplexity, linesOfCode: lines, functionCount: functions, averageComplexityPerFunction: functions > 0 ? cyclomaticComplexity / functions : 0, complexityLevel: cyclomaticComplexity <= 5 ? 'low' : cyclomaticComplexity <= 10 ? 'medium' : 'high' }; } /** * Infer purpose from file path and content * @param {string} filePath - File path * @param {string} codeContent - Code content * @returns {Object} - Purpose inference */ inferPurpose(filePath, codeContent) { const pathSegments = filePath.toLowerCase().split('/'); const fileName = pathSegments[pathSegments.length - 1]; let purpose = 'utility'; const indicators = []; // Infer from path if (pathSegments.includes('components') || pathSegments.includes('component')) { purpose = 'component'; indicators.push('Located in components directory'); } else if (pathSegments.includes('services') || pathSegments.includes('service')) { purpose = 'service'; indicators.push('Located in services directory'); } else if (pathSegments.includes('utils') || pathSegments.includes('utilities')) { purpose = 'utility'; indicators.push('Located in utilities directory'); } else if (pathSegments.includes('tests') || pathSegments.includes('test')) { purpose = 'test'; indicators.push('Located in test directory'); } // Infer from filename if (fileName.includes('test') || fileName.includes('spec')) { purpose = 'test'; indicators.push('Test file naming pattern'); } else if (fileName.includes('config') || fileName.includes('settings')) { purpose = 'configuration'; indicators.push('Configuration file naming pattern'); } // Infer from content if (/describe\s*\(|it\s*\(|test\s*\(/i.test(codeContent)) { purpose = 'test'; indicators.push('Contains test functions'); } else if (/export\s+default\s+class.*Component|extends\s+Component/i.test(codeContent)) { purpose = 'component'; indicators.push('Contains React/Vue component'); } else if (/router|route|endpoint/i.test(codeContent)) { purpose = 'routing'; indicators.push('Contains routing logic'); } return { primary: purpose, indicators, confidence: indicators.length * 0.3 }; } /** * Calculate quality metrics * @param {string} codeContent - Code content * @returns {Object} - Quality metrics */ calculateQualityMetrics(codeContent) { const lines = codeContent.split('\n'); const nonEmptyLines = lines.filter(line => line.trim().length > 0); const commentLines = lines.filter(line => /^\s*\/\/|^\s*\/\*|\*\//.test(line)); return { totalLines: lines.length, codeLines: nonEmptyLines.length, commentLines: commentLines.length, commentRatio: commentLines.length / nonEmptyLines.length, averageLineLength: nonEmptyLines.reduce((sum, line) => sum + line.length, 0) / nonEmptyLines.length, maintainabilityIndex: this.calculateMaintainabilityIndex(codeContent) }; } /** * Calculate maintainability index * @param {string} codeContent - Code content * @returns {number} - Maintainability index (0-100) */ calculateMaintainabilityIndex(codeContent) { const complexity = this.analyzeCodeComplexity(codeContent); const quality = this.calculateQualityMetrics(codeContent); // Simplified maintainability index calculation let index = 100; // Penalize high complexity if (complexity.cyclomaticComplexity > 10) { index -= (complexity.cyclomaticComplexity - 10) * 2; } // Reward good commenting if (quality.commentRatio > 0.1) { index += 5; } // Penalize very long functions if (complexity.averageComplexityPerFunction > 15) { index -= 10; } return Math.max(0, Math.min(100, index)); } /** * Get semantic analysis report * @param {string} filePath - File path (optional) * @returns {Object} - Semantic analysis report */ getSemanticAnalysisReport(filePath = null) { if (filePath) { return this.codeSemantics.get(filePath) || null; } const allAnalyses = Array.from(this.codeSemantics.values()); return { timestamp: new Date(), totalFiles: allAnalyses.length, averageComplexity: allAnalyses.reduce((sum, analysis) => sum + analysis.complexity.cyclomaticComplexity, 0) / allAnalyses.length, purposeDistribution: this.calculatePurposeDistribution(allAnalyses), qualityOverview: this.calculateQualityOverview(allAnalyses), architecturalPatterns: this.summarizeArchitecturalPatterns(allAnalyses) }; } /** * Calculate purpose distribution * @param {Array} analyses - Array of semantic analyses * @returns {Object} - Purpose distribution */ calculatePurposeDistribution(analyses) { const distribution = {}; analyses.forEach(analysis => { const purpose = analysis.purpose.primary; distribution[purpose] = (distribution[purpose] || 0) + 1; }); return distribution; } /** * Calculate quality overview * @param {Array} analyses - Array of semantic analyses * @returns {Object} - Quality overview */ calculateQualityOverview(analyses) { if (analyses.length === 0) {return {};} const totalMaintainability = analyses.reduce((sum, analysis) => sum + analysis.qualityMetrics.maintainabilityIndex, 0); const totalCommentRatio = analyses.reduce((sum, analysis) => sum + analysis.qualityMetrics.commentRatio, 0); return { averageMaintainability: totalMaintainability / analyses.length, averageCommentRatio: totalCommentRatio / analyses.length, highComplexityFiles: analyses.filter(a => a.complexity.complexityLevel === 'high').length, wellDocumentedFiles: analyses.filter(a => a.qualityMetrics.commentRatio > 0.15).length }; } /** * Summarize architectural patterns * @param {Array} analyses - Array of semantic analyses * @returns {Object} - Architectural patterns summary */ summarizeArchitecturalPatterns(analyses) { const patternCounts = {}; analyses.forEach(analysis => { analysis.architecturalPatterns.forEach(pattern => { patternCounts[pattern.pattern] = (patternCounts[pattern.pattern] || 0) + 1; }); }); return patternCounts; } }