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

275 lines • 12.6 kB
import { BaseToolHandler } from '../base-handler.js'; export class FlutterQuantumHandler extends BaseToolHandler { localEngine; quantumDebugger; constructor(localEngine, quantumDebugger) { super(); this.localEngine = localEngine; this.quantumDebugger = quantumDebugger; } get tools() { return [ { name: 'flutter_quantum_interact', description: 'Advanced natural language Flutter interaction. Works with ANY Flutter web app without hardcoded coordinates. Examples: "click Submit Report button", "type John Doe in name field", "select California from state dropdown"', inputSchema: { type: 'object', properties: { sessionId: { type: 'string', description: 'Debug session ID' }, command: { type: 'string', description: 'Natural language command like "click Submit button" or "type hello in search field"' } }, required: ['sessionId', 'command'] } }, { name: 'flutter_quantum_analyze', description: 'Analyze Flutter semantic tree and UI structure. Returns detailed information about all interactable elements, forms, and navigation.', inputSchema: { type: 'object', properties: { sessionId: { type: 'string', description: 'Debug session ID' } }, required: ['sessionId'] } }, { name: 'flutter_quantum_find', description: 'Find Flutter elements by text or label. Returns coordinates and properties of matching elements.', inputSchema: { type: 'object', properties: { sessionId: { type: 'string', description: 'Debug session ID' }, searchText: { type: 'string', description: 'Text to search for in Flutter UI' } }, required: ['sessionId', 'searchText'] } }, { name: 'flutter_enable_accessibility', description: 'Enable Flutter accessibility tree for better element detection. This is required for most Flutter web apps to expose their UI elements for testing.', inputSchema: { type: 'object', properties: { sessionId: { type: 'string', description: 'Debug session ID' } }, required: ['sessionId'] } } ]; } async handle(toolName, args, sessions) { const session = sessions.get(args.sessionId); if (!session) { throw new Error('Session not found'); } if (session.framework !== 'flutter' && session.framework !== 'flutter-web') { throw new Error('This tool only works with Flutter Web applications'); } switch (toolName) { case 'flutter_quantum_interact': return this.quantumInteract(session, args.command); case 'flutter_quantum_analyze': return this.quantumAnalyze(session); case 'flutter_quantum_find': return this.quantumFind(session, args.searchText); case 'flutter_enable_accessibility': return this.enableAccessibility(session); default: throw new Error(`Unknown tool: ${toolName}`); } } async quantumInteract(session, command) { try { const result = await this.quantumDebugger.interact(session.id, command); if (!result.success) { return { content: [{ type: 'text', text: `āŒ **Interaction Failed**\n\nError: ${result.error || 'Unknown error'}\n\nšŸ’” **Tip:** Try \`flutter_quantum_analyze\` to see available elements.` }] }; } let details = `āœ… **Interaction Successful**\n\n`; details += `**Command:** ${command}\n`; // Parse command to extract action details const lowerCommand = command.toLowerCase(); if (lowerCommand.includes('click')) { const target = command.replace(/^click\s+/i, ''); details += `**Clicked on:** ${target}\n`; } else if (lowerCommand.includes('type')) { const match = command.match(/type\s+(.+?)\s+in\s+(.+)/i); if (match) { details += `**Typed:** ${match[1]}\n`; details += `**Into:** ${match[2]}\n`; } } if (result.method) { details += `**Method:** ${result.method}\n`; } return { content: [{ type: 'text', text: details }] }; } catch (error) { throw new Error(`Failed to interact with Flutter app: ${error.message}`); } } async quantumAnalyze(session) { try { const quantumSession = await this.quantumDebugger.getSession(session.id); if (!quantumSession) { throw new Error('Quantum debugging session not initialized. Please run flutter_quantum_interact first.'); } const structure = quantumSession.structure; let analysis = `šŸ” **Flutter UI Analysis**\n\n`; // Navigation elements if (structure.navigation?.navigationElements?.length > 0) { analysis += `**šŸ“± Navigation Elements:**\n`; structure.navigation.navigationElements.forEach((nav) => { analysis += ` • ${nav.label}\n`; }); analysis += '\n'; } // Forms if (structure.forms?.length > 0) { analysis += `**šŸ“ Forms Detected:**\n`; structure.forms.forEach((form) => { analysis += ` • ${form.name}:\n`; form.fields.forEach((field) => { analysis += ` - ${field.label}\n`; }); }); analysis += '\n'; } // Detected elements count const elementCount = quantumSession.detectedElements?.length || 0; analysis += `**šŸŽÆ Total Elements:** ${elementCount} interactive elements detected\n\n`; analysis += `šŸ’” **Usage Tips:**\n`; analysis += `• Use \`flutter_quantum_find "text"\` to search for specific elements\n`; analysis += `• Use \`flutter_quantum_interact "action"\` to interact with elements\n`; analysis += `• Natural language commands work best (e.g., "click Submit button")`; return { content: [{ type: 'text', text: analysis }] }; } catch (error) { throw new Error(`Failed to analyze Flutter UI: ${error.message}`); } } async quantumFind(session, searchText) { try { const quantumSession = await this.quantumDebugger.getSession(session.id); if (!quantumSession) { throw new Error('Quantum debugging session not initialized. Please run flutter_quantum_interact first.'); } // Search through detected elements const matchingElements = quantumSession.detectedElements?.filter((element) => { const label = element.label?.toLowerCase() || ''; const search = searchText.toLowerCase(); return label.includes(search); }) || []; let result = `šŸ” **Flutter Element Search**\n\n`; result += `**Search Term:** "${searchText}"\n`; result += `**Found:** ${matchingElements.length} element(s)\n\n`; if (matchingElements.length === 0) { result += `No elements found matching "${searchText}".\n\n`; result += `šŸ’” **Tips:**\n`; result += `• Try a partial search term\n`; result += `• Use \`flutter_quantum_analyze\` to see all available elements\n`; result += `• Ensure accessibility is enabled with \`flutter_enable_accessibility\``; } else { result += `**šŸ“ Matching Elements:**\n`; matchingElements.slice(0, 5).forEach((element) => { result += `\n• **${element.label}**\n`; result += ` Type: ${element.type || 'Unknown'}\n`; if (element.bounds) { result += ` Location: (${element.bounds.left}, ${element.bounds.top})\n`; result += ` Size: ${element.bounds.width}x${element.bounds.height}\n`; } result += ` Interaction: flutter_quantum_interact "${element.interactionHint || 'click ' + element.label}"\n`; }); if (matchingElements.length > 5) { result += `\n... and ${matchingElements.length - 5} more results`; } } return { content: [{ type: 'text', text: result }] }; } catch (error) { throw new Error(`Failed to find Flutter elements: ${error.message}`); } } async enableAccessibility(session) { try { // Check if we already have a quantum session let quantumSession = await this.quantumDebugger.getSession(session.id); // If no session exists, initialize one if (!quantumSession) { quantumSession = await this.quantumDebugger.initialize(session.page, session.id); } let response = `♿ **Flutter Accessibility**\n\n`; if (quantumSession) { response += `āœ… **Accessibility Enabled Successfully**\n\n`; const elementsFound = quantumSession.detectedElements?.length || 0; response += `**Elements Found:** ${elementsFound}\n`; if (quantumSession.structure) { const nodeCount = quantumSession.structure.forms?.length || 0 + quantumSession.structure.navigation?.navigationElements?.length || 0; response += `**Semantic nodes created:** ${nodeCount}\n\n`; } response += `**Improvements:**\n`; response += `- Better element detection for natural language interactions\n`; response += `- More accurate click targets\n`; response += `- Improved form field identification\n\n`; } else { response += `āš ļø **Failed to Enable Accessibility**\n\n`; response += `Could not initialize Flutter debugging session.\n\n`; } response += `šŸ’” **Next Steps:**\n`; response += `- Use \`flutter_quantum_analyze\` to see all available elements\n`; response += `- Use \`flutter_quantum_find\` to search for specific elements\n`; response += `- Use \`flutter_quantum_interact\` to interact with elements`; return { content: [{ type: 'text', text: response }] }; } catch (error) { throw new Error(`Failed to enable Flutter accessibility: ${error.message}`); } } } //# sourceMappingURL=flutter-quantum-handler.js.map