UNPKG

ai-debug-local-mcp

Version:

🎯 ENHANCED AI GUIDANCE v4.1.2: Dramatically improved tool descriptions help AI users choose the right tools instead of 'close enough' options. Ultra-fast keyboard automation (10x speed), universal recording, multi-ecosystem debugging support, and compreh

159 lines (157 loc) 7.4 kB
import { BaseToolHandler } from './base-handler.js'; /** * Handler for JavaScript bundle analysis * Analyzes bundle sizes, loading patterns, code coverage, and identifies optimization opportunities */ export class BundleHandler extends BaseToolHandler { localEngine; tools = [ { name: 'analyze_bundles', description: 'Analyze JavaScript bundle sizes, loading patterns, and code coverage. Helps identify performance bottlenecks and unused code.', inputSchema: { type: 'object', properties: { sessionId: { type: 'string', description: 'Debug session ID' } }, required: ['sessionId'] } } ]; constructor(localEngine) { super(); this.localEngine = localEngine; } async handle(toolName, args, sessions) { if (toolName !== 'analyze_bundles') { return this.createErrorResponse(`Unknown tool: ${toolName}`); } const { sessionId } = args; const session = this.getSession(sessionId, sessions); try { const analysis = await this.localEngine.getBundleAnalysis(); // Calculate performance rating const performanceRating = this.getPerformanceRating(analysis.totalSize); // Format bundle report let report = `## Bundle Analysis Results **Total Bundle Size:** **${this.formatSize(analysis.totalSize)}** **Performance:** **${performanceRating.label}** ${performanceRating.emoji} ### Bundle Breakdown:\n\n`; // Sort bundles by size (largest first) const sortedBundles = [...analysis.bundles].sort((a, b) => b.size - a.size); sortedBundles.forEach((bundle, index) => { report += `#### ${index + 1}. \`${bundle.url}\`\n\n`; report += `- **Size:** ${this.formatSize(bundle.size)}`; // Add warnings for large bundles if (bundle.size > 500 * 1024) { report += ' ⚠️ Large bundle'; } report += '\n'; report += `- **Load Time:** ${bundle.loadTime}ms\n`; report += `- **Code Coverage:** ${bundle.coverage}%`; // Add coverage warnings if (bundle.coverage < 70) { report += ' ⚠️ Low coverage'; } report += '\n'; if (bundle.isAsync) { report += `- **Loading:** ✅ Async (not loaded initially)\n`; } else { report += `- **Loading:** Synchronous\n`; } report += '\n'; }); // Add optimization opportunities if present if (analysis.unusedModules && analysis.unusedModules.length > 0) { report += `### Optimization Opportunities:\n\n`; report += `#### Unused Dependencies:\n`; report += `The following modules appear to be imported but never used:\n\n`; analysis.unusedModules.forEach(module => { report += `- \`${module}\`\n`; }); report += '\n'; } if (analysis.duplicates && analysis.duplicates.length > 0) { report += `#### Duplicate Modules:\n`; report += `Multiple versions of the same module detected:\n\n`; analysis.duplicates.forEach(dup => { report += `- **${dup.module}** (${dup.versions.length} versions: ${dup.versions.join(', ')})\n`; }); report += '\n'; } // Add recommendations if (analysis.recommendations && analysis.recommendations.length > 0) { report += `### Recommendations:\n\n`; analysis.recommendations.forEach(rec => { report += `- ${rec}\n`; }); report += '\n'; } else { // Add default recommendations based on analysis report += this.generateRecommendations(analysis); } // Add quick wins section report += `### Quick Wins:\n\n`; report += `1. **Enable gzip/brotli compression** - Can reduce bundle sizes by 60-80%\n`; report += `2. **Use dynamic imports** for code splitting\n`; report += `3. **Remove unused dependencies** with \`npm prune\`\n`; report += `4. **Analyze with source maps** for detailed insights\n\n`; // Add bundle optimization tools report += `### Bundle Optimization Tools:\n\n`; report += `- **webpack-bundle-analyzer**: Visual bundle analysis\n`; report += `- **rollup-plugin-visualizer**: Rollup bundle visualization\n`; report += `- **source-map-explorer**: Analyze bundle composition\n`; report += `- **bundlephobia**: Check package sizes before installing\n\n`; report += `### Modern Bundling Best Practices:\n\n`; report += `- **Tree shaking**: Ensure ES modules for dead code elimination\n`; report += `- **Code splitting**: Split by routes and lazy load\n`; report += `- **Vendor splitting**: Separate third-party code\n`; report += `- **Module federation**: Share code between applications\n`; report += `- **HTTP/2 push**: Leverage server push for critical resources\n`; return this.createTextResponse(report); } catch (error) { return this.createErrorResponse(`Failed to analyze bundles: ${error.message}`); } } formatSize(bytes) { if (bytes < 1024) return `${bytes} B`; if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; } getPerformanceRating(totalSize) { if (totalSize < 300 * 1024) return { label: 'Excellent', emoji: '🚀' }; if (totalSize < 500 * 1024) return { label: 'Good', emoji: '✅' }; if (totalSize < 1024 * 1024) return { label: 'Fair', emoji: '⚡' }; return { label: 'Poor', emoji: '⚠️' }; } generateRecommendations(analysis) { let recommendations = `### Recommendations:\n\n`; // Size-based recommendations if (analysis.totalSize > 1024 * 1024) { recommendations += `- **Bundle too large**: Consider code splitting to reduce initial load\n`; } // Coverage-based recommendations const avgCoverage = analysis.bundles.reduce((sum, b) => sum + b.coverage, 0) / analysis.bundles.length; if (avgCoverage < 70) { recommendations += `- **Low code coverage**: Remove unused code or split into separate bundles\n`; } // Async loading recommendations const syncBundles = analysis.bundles.filter(b => !b.isAsync); if (syncBundles.length > 3) { recommendations += `- **Too many sync bundles**: Use dynamic imports for non-critical code\n`; } return recommendations + '\n'; } } //# sourceMappingURL=bundle-handler.js.map