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
270 lines (262 loc) • 11 kB
JavaScript
import { BaseToolHandler } from '../base-handler.js';
/**
* Handler for Flutter core information and configuration tools
*/
export class FlutterCoreInfoHandler extends BaseToolHandler {
localEngine;
quantumDebugger;
constructor(localEngine, quantumDebugger) {
super();
this.localEngine = localEngine;
this.quantumDebugger = quantumDebugger;
}
tools = [
{
name: 'flutter_config',
description: 'Get comprehensive Flutter configuration including version, renderer type, build mode, and web config.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'flutter_diagnostics',
description: 'Get Flutter-specific diagnostics including renderer info, platform channels, fonts, gesture handling, and text input.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'flutter_browser_compatibility',
description: 'Check browser compatibility and get specific warnings and recommendations.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'flutter_health_check',
description: 'Run comprehensive Flutter web health check with score, status, and recommendations.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
}
];
async handle(toolName, args, sessions) {
// Validate session
const session = sessions.get(args.sessionId);
if (!session) {
throw new Error(`Session not found: ${args.sessionId}`);
}
if (session.framework !== 'flutter' && session.framework !== 'flutter-web') {
throw new Error('Not a Flutter session');
}
switch (toolName) {
case 'flutter_config':
return await this.getFlutterConfig(session);
case 'flutter_diagnostics':
return await this.getFlutterDiagnostics(session);
case 'flutter_browser_compatibility':
return await this.getFlutterBrowserCompatibility(session);
case 'flutter_health_check':
return await this.getFlutterHealthCheck(session);
default:
throw new Error(`Unknown tool: ${toolName}`);
}
}
async getFlutterConfig(session) {
const config = await session.page.evaluate(() => {
const flutterConfig = window.flutter_internalWebConfiguration || {};
const flutterVersion = window.flutterVersion || 'Unknown';
return {
version: flutterVersion,
channel: flutterConfig.channel || 'Unknown',
renderer: flutterConfig.renderer || 'auto',
buildMode: flutterConfig.buildMode || 'release',
engineRevision: flutterConfig.engineRevision || 'Unknown',
frameworkRevision: flutterConfig.frameworkRevision || 'Unknown',
canvasKitBaseUrl: flutterConfig.canvasKitBaseUrl || null,
useColorEmoji: flutterConfig.useColorEmoji || false
};
});
return {
content: [{
type: 'text',
text: `🔧 Flutter Configuration:
Version: ${config.version} | Channel: ${config.channel}
Renderer: ${config.renderer} | Build Mode: ${config.buildMode}
Engine: ${config.engineRevision}
Framework: ${config.frameworkRevision}`
}]
};
}
async getFlutterDiagnostics(session) {
const diagnostics = await session.page.evaluate(() => {
const config = window.flutter_internalWebConfiguration || {};
return {
renderer: {
type: config.renderer || 'auto',
canvasKit: !!config.canvasKitBaseUrl
},
platformChannels: Object.keys(window._flutter?.platformChannels || {}),
fonts: {
loaded: document.fonts?.size || 0,
ready: 'Yes'
},
gestureHandling: {
enabled: !!window._flutter?.gestureArena,
touchSupported: 'ontouchstart' in window
},
textInput: {
active: !!window._flutter?.textInput,
inputElement: !!document.querySelector('input[data-flutter-input]')
}
};
});
return {
content: [{
type: 'text',
text: `🔍 Flutter Diagnostics:
Renderer: ${diagnostics.renderer.type} (CanvasKit: ${diagnostics.renderer.canvasKit ? 'Yes' : 'No'})
Platform Channels: ${diagnostics.platformChannels.length || 'None'}
Fonts: ${diagnostics.fonts.loaded} loaded
Gesture: ${diagnostics.gestureHandling.enabled ? 'Enabled' : 'Disabled'}
Text Input: ${diagnostics.textInput.active ? 'Active' : 'Inactive'}`
}]
};
}
async getFlutterBrowserCompatibility(session) {
const compatibility = await session.page.evaluate(() => {
const ua = navigator.userAgent;
let browser = 'Unknown';
let version = '0';
if (ua.includes('Chrome')) {
browser = 'Chrome';
version = ua.match(/Chrome\/(\d+)/)?.[1] || '0';
}
else if (ua.includes('Firefox')) {
browser = 'Firefox';
version = ua.match(/Firefox\/(\d+)/)?.[1] || '0';
}
else if (ua.includes('Safari') && !ua.includes('Chrome')) {
browser = 'Safari';
version = ua.match(/Version\/(\d+)/)?.[1] || '0';
}
const warnings = [];
const canvas = document.createElement('canvas');
const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
if (!gl)
warnings.push('WebGL not supported - Flutter performance will be degraded');
const minVersions = { Chrome: 88, Firefox: 78, Safari: 14 };
const currentVer = parseInt(version);
const minVer = minVersions[browser] || 0;
if (minVer && currentVer < minVer) {
warnings.push(`${browser} ${version} is below minimum version ${minVer}`);
}
return {
browser,
version,
compatible: warnings.length === 0,
warnings,
features: {
webGL: !!gl,
webAssembly: typeof WebAssembly !== 'undefined',
serviceWorker: 'serviceWorker' in navigator,
indexedDB: 'indexedDB' in window
}
};
});
const features = Object.entries(compatibility.features)
.map(([k, v]) => ` ${k}: ${v ? '✅' : '❌'}`)
.join('\n');
return {
content: [{
type: 'text',
text: `🌐 Browser Compatibility:
Browser: ${compatibility.browser} ${compatibility.version}
Compatible: ${compatibility.compatible ? '✅ Yes' : '⚠️ No'}
Features:
${features}
${compatibility.warnings.length > 0 ? `⚠️ Warnings:\n${compatibility.warnings.map((w) => ` - ${w}`).join('\n')}` : ''}`
}]
};
}
async getFlutterHealthCheck(session) {
const healthCheck = await session.page.evaluate(() => {
const issues = [];
const recommendations = [];
let score = 100;
if (!window._flutter) {
issues.push('Flutter not initialized');
score -= 50;
}
const config = window.flutter_internalWebConfiguration || {};
if (config.renderer === 'html') {
recommendations.push('Consider using CanvasKit renderer for better performance');
score -= 5;
}
const errorLogs = window.__flutterErrors || [];
if (errorLogs.length > 0) {
issues.push(`${errorLogs.length} Flutter errors detected`);
score -= errorLogs.length * 2;
}
const perfEntry = performance.getEntriesByType('navigation')[0];
const loadTime = perfEntry?.loadEventEnd - perfEntry?.fetchStart || 0;
if (loadTime > 3000) {
issues.push('Slow initial load time detected');
recommendations.push('Optimize bundle size and lazy load assets');
score -= 10;
}
return {
status: score < 50 ? 'critical' : score < 80 ? 'warning' : 'healthy',
score: Math.max(0, score),
issues,
recommendations,
metrics: {
initTime: loadTime,
memoryUsage: performance.memory?.usedJSHeapSize || 0,
errorCount: errorLogs.length
}
};
});
const statusIcon = healthCheck.status === 'healthy' ? '✅' :
healthCheck.status === 'warning' ? '⚠️' : '❌';
return {
content: [{
type: 'text',
text: `🏥 Flutter Health Check:
Status: ${healthCheck.status.toUpperCase()} ${statusIcon} | Score: ${healthCheck.score}/100
Init: ${healthCheck.metrics.initTime}ms | Memory: ${(healthCheck.metrics.memoryUsage / 1024 / 1024).toFixed(1)}MB | Errors: ${healthCheck.metrics.errorCount}
${healthCheck.issues.length > 0 ? `❌ Issues:\n${healthCheck.issues.map((i) => ` - ${i}`).join('\n')}` : '✅ No issues detected'}
${healthCheck.recommendations.length > 0 ? `💡 Recommendations:\n${healthCheck.recommendations.map((r) => ` - ${r}`).join('\n')}` : ''}`
}]
};
}
}
//# sourceMappingURL=flutter-core-info-handler.js.map