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

237 lines • 8.36 kB
export class TidewaveIntegration { capabilities = new Map(); /** * Detect if a URL has Tidewave enabled and what capabilities it has */ async detectTidewave(url) { try { // Try Phoenix endpoint first const phoenixEndpoint = `${url}/tidewave/mcp`; let response = await this.testEndpoint(phoenixEndpoint); if (response) { const capabilities = { framework: 'phoenix', endpoint: phoenixEndpoint, available_tools: response.tools || [], version: response.version }; this.capabilities.set(url, capabilities); return capabilities; } // Try Rails endpoint const railsEndpoint = `${url}/tidewave`; response = await this.testEndpoint(railsEndpoint); if (response) { const capabilities = { framework: 'rails', endpoint: railsEndpoint, available_tools: response.tools || [], version: response.version }; this.capabilities.set(url, capabilities); return capabilities; } return null; } catch (error) { // console.error('Tidewave detection failed:', error); return null; } } /** * Test if a Tidewave endpoint is accessible */ async testEndpoint(endpoint) { const { AbortSignalManager } = await import('./utils/abort-signal-manager.js'); try { // Use centralized AbortSignalManager to prevent EventTarget memory leaks const { controller, timeoutId } = AbortSignalManager.createWithTimeout(5000); const response = await fetch(`${endpoint}/capabilities`, { method: 'GET', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, signal: controller.signal }); clearTimeout(timeoutId); if (response.ok) { return await response.json(); } return null; } catch { return null; } } /** * Execute a Tidewave tool for enhanced debugging/testing */ async executeTool(url, request) { const capabilities = this.capabilities.get(url); if (!capabilities) { return { success: false, error: 'Tidewave not available for this URL' }; } if (!capabilities.available_tools.includes(request.tool)) { return { success: false, error: `Tool '${request.tool}' not available. Available: ${capabilities.available_tools.join(', ')}` }; } try { const { AbortSignalManager } = await import('./utils/abort-signal-manager.js'); // Use centralized AbortSignalManager to prevent EventTarget memory leaks const { controller, timeoutId } = AbortSignalManager.createWithTimeout(30000); const response = await fetch(`${capabilities.endpoint}/${request.tool}`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, body: JSON.stringify(request.params || {}), signal: controller.signal }); clearTimeout(timeoutId); const data = await response.json(); return { success: response.ok, data: response.ok ? data : undefined, error: response.ok ? undefined : data.error || `HTTP ${response.status}`, metadata: { execution_time: data.execution_time, framework_version: capabilities.version } }; } catch (error) { return { success: false, error: `Tidewave execution failed: ${error instanceof Error ? error.message : String(error)}` }; } } /** * Get application logs through Tidewave */ async getLogs(url, options = {}) { return this.executeTool(url, { tool: 'logs', params: options }); } /** * Execute custom code for testing/debugging */ async evaluateCode(url, code, context) { return this.executeTool(url, { tool: 'eval', params: { code, context } }); } /** * Get application documentation */ async getDocumentation(url, path) { return this.executeTool(url, { tool: 'documentation', params: { path } }); } /** * Execute SQL queries for database testing */ async executeSQL(url, query, params) { return this.executeTool(url, { tool: 'sql', params: { query, params } }); } /** * Trace application processes */ async traceProcesses(url, pattern) { return this.executeTool(url, { tool: 'processes', params: { pattern } }); } /** * Search project dependencies */ async searchDependencies(url, query) { return this.executeTool(url, { tool: 'dependencies', params: { query } }); } /** * Enhanced debugging state with Tidewave data */ async enhanceDebugState(url, debugState) { const capabilities = this.capabilities.get(url); if (!capabilities) { return debugState; } // Add Tidewave-specific information to debug state const tidewaveData = { framework: capabilities.framework, available_tools: capabilities.available_tools, version: capabilities.version }; // Get logs if available if (capabilities.available_tools.includes('logs')) { const logs = await this.getLogs(url, { limit: 50 }); if (logs.success) { tidewaveData.recent_logs = logs.data; } } // Get process information if available if (capabilities.available_tools.includes('processes')) { const processes = await this.traceProcesses(url); if (processes.success) { tidewaveData.processes = processes.data; } } return { ...debugState, tidewave: tidewaveData }; } /** * Generate test assertions using Tidewave application knowledge */ async generateTestAssertions(url, scenario) { const capabilities = this.capabilities.get(url); if (!capabilities) { return []; } const framework = capabilities.framework; const assertions = []; // Framework-specific test generation if (framework === 'phoenix') { assertions.push(`# Phoenix LiveView test assertions for: ${scenario}`); assertions.push('assert has_element?(view, "[data-testid=\\"#{scenario}\\"]")'); assertions.push('refute has_element?(view, ".error")'); } else if (framework === 'rails') { assertions.push(`# Rails system test assertions for: ${scenario}`); assertions.push(`expect(page).to have_content("${scenario}")`); assertions.push('expect(page).not_to have_css(".error")'); } // Use Tidewave documentation to enhance assertions if (capabilities.available_tools.includes('documentation')) { const docs = await this.getDocumentation(url, scenario); if (docs.success && docs.data) { // Parse documentation to generate more specific assertions assertions.push(`# Generated from application documentation`); // Add doc-based assertions here } } return assertions; } } export const tidewave = new TidewaveIntegration(); //# sourceMappingURL=tidewave-integration.js.map