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

221 lines 9.66 kB
/** * V2 Framework Detection for Project-Aware Loading * Simplified framework detection optimized for stateless HTTP architecture */ export class V2FrameworkDetector { /** * Detect framework from a Playwright page */ async detectFramework(page) { try { // Run detection scripts in the browser const detectionResult = await page.evaluate(() => { const features = []; let framework = 'unknown'; let confidence = 0; let version; // Check for React if (window.React || document.querySelector('[data-reactroot]') || document.querySelector('[data-react-helmet]')) { features.push('react'); framework = 'react'; confidence = 0.8; // Check for NextJS if (window.__NEXT_DATA__ || document.querySelector('#__next')) { features.push('nextjs'); framework = 'nextjs'; confidence = 0.9; version = window.__NEXT_DATA__?.buildId || 'unknown'; } } // Check for Flutter Web if (window.flutterCanvasKit || document.querySelector('flutter-view') || document.querySelector('[flt-renderer]')) { features.push('flutter'); framework = 'flutter-web'; confidence = 0.95; } // Enhanced Phoenix LiveView detection const liveViewIndicators = { liveSocket: !!window.liveSocket, phoenixLiveView: !!window.Phoenix?.LiveView, phxHooks: !!document.querySelector('[phx-hook]'), phxEvents: !!(document.querySelector('[phx-click]') || document.querySelector('[phx-submit]') || document.querySelector('[phx-change]') || document.querySelector('[phx-keyup]') || document.querySelector('[phx-keydown]')), phxMain: !!document.querySelector('div[data-phx-main]'), phxSession: !!document.querySelector('[data-phx-session]'), phxStatic: !!document.querySelector('[data-phx-static]'), liveViewScript: !!document.querySelector('script[src*="phoenix_live_view"]'), csrfToken: !!document.querySelector('meta[name="csrf-token"]'), phoenixChannel: !!window.Phoenix?.Channel }; const liveViewCount = Object.values(liveViewIndicators).filter(Boolean).length; if (liveViewCount >= 2) { features.push('phoenix', 'liveview'); framework = 'phoenix-liveview'; confidence = Math.min(0.9 + (liveViewCount * 0.01), 0.99); // Check for live_svelte integration const liveSvelteIndicators = { liveSvelte: !!window.LiveSvelte || !!window.live_svelte || !!document.querySelector('[data-live-svelte]'), liveSvelteHook: !!document.querySelector('[phx-hook="LiveSvelte"]') || !!document.querySelector('[phx-hook*="Svelte"]'), liveSvelteContainer: !!document.querySelector('.live-svelte-component') || !!document.querySelector('[data-svelte-component]'), svelteClasses: !!document.querySelector('[class*="svelte-"]'), svelteData: !!document.querySelector('[data-svelte]') }; const liveSvelteCount = Object.values(liveSvelteIndicators).filter(Boolean).length; if (liveSvelteCount >= 1) { features.push('svelte', 'live_svelte'); framework = 'phoenix-liveview-svelte'; confidence = 0.95; } } // Check for standalone Svelte if not already detected with LiveView if (framework !== 'phoenix-liveview-svelte' && (document.querySelector('[data-svelte]') || document.querySelector('[class*="svelte-"]') || window.__svelte)) { features.push('svelte'); framework = 'svelte'; confidence = 0.8; } // Check for Vue.js if (window.Vue || document.querySelector('[data-v-]') || document.querySelector('[v-cloak]')) { features.push('vue'); framework = 'vue'; confidence = 0.8; } // Check for Angular if (window.ng || document.querySelector('[ng-app]') || document.querySelector('[ng-version]')) { features.push('angular'); framework = 'angular'; confidence = 0.8; } // Check for meta-frameworks if (document.querySelector('[data-astro-cid]')) { features.push('astro'); framework = 'astro'; confidence = 0.85; } if (window.__remixContext) { features.push('remix'); framework = 'remix'; confidence = 0.85; } return { framework, confidence, detected_features: features, version }; }); console.error(`🔍 V2 Framework Detection: ${detectionResult.framework} (${Math.round(detectionResult.confidence * 100)}% confidence)`); console.error(`📋 V2 Features detected: ${detectionResult.detected_features.join(', ')}`); // Special handling for hybrid frameworks if (detectionResult.framework === 'phoenix-liveview-svelte') { console.error(`🎯 Special framework detected: Phoenix LiveView + live_svelte integration`); console.error(`💡 This hybrid framework combines server-side LiveView with client-side Svelte components`); } return detectionResult; } catch (error) { console.warn('⚠️ V2 Framework detection failed:', error); return { framework: 'unknown', confidence: 0, detected_features: [], version: undefined }; } } /** * Quick framework detection from URL patterns (for early optimization) */ detectFromUrl(url) { const hostname = new URL(url).hostname.toLowerCase(); // Common hosting patterns if (hostname.includes('vercel') || hostname.includes('netlify')) { return { framework: 'nextjs', // Most common on these platforms confidence: 0.6, detected_features: ['hosting-pattern'], version: undefined }; } if (hostname.includes('flutter') || hostname.includes('dart')) { return { framework: 'flutter-web', confidence: 0.7, detected_features: ['domain-pattern'], version: undefined }; } if (hostname.includes('phoenix') || hostname.includes('elixir')) { return { framework: 'phoenix', confidence: 0.7, detected_features: ['domain-pattern'], version: undefined }; } return { framework: 'unknown', confidence: 0, detected_features: [], version: undefined }; } /** * Merge URL-based detection with page-based detection */ mergeDetectionResults(urlResult, pageResult) { // Page-based detection is more reliable if (pageResult.confidence > 0.5) { return pageResult; } // Fall back to URL-based if page detection failed if (urlResult.confidence > 0.5) { return urlResult; } // Return the one with higher confidence return urlResult.confidence > pageResult.confidence ? urlResult : pageResult; } } /** * Simple framework detection for testing without browser */ export function detectFrameworkFromHeaders(headers) { const serverHeader = headers['server']?.toLowerCase() || ''; const poweredBy = headers['x-powered-by']?.toLowerCase() || ''; if (serverHeader.includes('phoenix') || poweredBy.includes('phoenix')) { return { framework: 'phoenix', confidence: 0.8, detected_features: ['server-header'], version: undefined }; } if (serverHeader.includes('next') || poweredBy.includes('next')) { return { framework: 'nextjs', confidence: 0.7, detected_features: ['server-header'], version: undefined }; } return { framework: 'unknown', confidence: 0, detected_features: [], version: undefined }; } //# sourceMappingURL=framework-detector.js.map