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
JavaScript
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