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