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

252 lines • 9.16 kB
/** * NetworkCoordinator - Consolidates network request/response debugging functionality * * Provides unified interface for: * - Network request interception and monitoring * - Response capture and analysis * - Performance metrics tracking * - Error detection and reporting * - Network debugging report generation */ export class NetworkCoordinator { isMonitoring = false; capturedRequests = []; capturedResponses = []; networkErrors = []; requestTimings = new Map(); currentPage; routeHandler; responseHandler; constructor() { this.routeHandler = this.handleRequest.bind(this); this.responseHandler = this.handleResponse.bind(this); } /** * Setup network monitoring on the given page */ async setupNetworkMonitoring(page) { if (this.isMonitoring) { return; // Already monitoring } try { this.currentPage = page; // Intercept all network requests await page.route('**/*', this.routeHandler); // Listen for responses page.context().on('response', this.responseHandler); this.isMonitoring = true; } catch (error) { throw new Error(`Failed to setup network monitoring: ${error instanceof Error ? error.message : 'Unknown error'}`); } } /** * Handle intercepted network requests */ async handleRequest(route, request) { try { const requestId = this.generateRequestId(); // Capture request details const networkRequest = { requestId, url: request.url(), method: request.method(), headers: request.headers(), postData: request.postData(), timestamp: Date.now(), frameUrl: request.frame()?.url(), }; this.capturedRequests.push(networkRequest); this.requestTimings.set(requestId, Date.now()); // Continue with the request await route.continue(); } catch (error) { // Handle connection errors this.networkErrors.push({ type: 'connection_error', url: route.request().url(), message: error instanceof Error ? error.message : 'Connection failed', timestamp: Date.now(), }); } } /** * Handle network responses */ async handleResponse(response) { try { const requestId = this.findRequestId(response.url()); const responseTime = Date.now(); const requestTime = this.requestTimings.get(requestId || '') || responseTime; let bodySize = 0; try { const body = await response.body(); bodySize = body.length; } catch (error) { // Body read failed, continue without size } const networkResponse = { requestId: requestId || this.generateRequestId(), url: response.url(), status: response.status(), statusText: response.statusText(), headers: response.headers(), bodySize, responseTime: responseTime - requestTime, timestamp: responseTime, }; this.capturedResponses.push(networkResponse); // Check for HTTP errors if (response.status() >= 400) { this.networkErrors.push({ type: 'http_error', url: response.url(), status: response.status(), statusText: response.statusText(), message: `HTTP ${response.status()}: ${response.statusText()}`, timestamp: responseTime, requestId, }); } } catch (error) { // Handle response processing errors gracefully console.warn('NetworkCoordinator: Response processing error:', error); } } /** * Get captured network requests */ getCapturedRequests() { return [...this.capturedRequests]; } /** * Get API requests (alias for getCapturedRequests for consistency with LocalDebugEngine) * Returns requests in the legacy format expected by ReactStateCoordinator */ getApiRequests() { // Convert NetworkCoordinator format to LocalDebugEngine format const requests = this.getCapturedRequests(); const responses = this.getCapturedResponses(); return requests.map(request => { const response = responses.find(r => r.requestId === request.requestId); return { url: request.url, method: request.method, headers: request.headers, timestamp: new Date(request.timestamp), status: response ? 'complete' : 'pending', responseStatus: response?.status, responseStatusText: response?.statusText, responseHeaders: response?.headers, requestBody: request.postData, responseBody: response?.responseBody, responseSize: response?.bodySize, duration: response ? response.responseTime : undefined, resourceType: undefined, queryParams: undefined }; }); } /** * Get captured network responses */ getCapturedResponses() { return [...this.capturedResponses]; } /** * Get detected network errors */ getNetworkErrors() { return [...this.networkErrors]; } /** * Get network performance metrics */ getNetworkMetrics() { const totalRequests = this.capturedRequests.length; const successfulRequests = this.capturedResponses.filter(r => r.status < 400).length; const failedRequests = this.capturedResponses.filter(r => r.status >= 400).length; const responseTimes = this.capturedResponses.map(r => r.responseTime); const averageResponseTime = responseTimes.length > 0 ? responseTimes.reduce((sum, time) => sum + time, 0) / responseTimes.length : 0; const totalDataTransferred = this.capturedResponses.reduce((sum, r) => sum + r.bodySize, 0); return { totalRequests, successfulRequests, failedRequests, averageResponseTime, totalDataTransferred, }; } /** * Generate comprehensive network debugging report */ generateNetworkReport() { const metrics = this.getNetworkMetrics(); const insights = []; // Generate performance insights if (metrics.averageResponseTime > 2000) { insights.push('High average response time detected (>2s) - consider optimizing API calls'); } if (metrics.failedRequests > 0) { insights.push(`${metrics.failedRequests} failed requests detected - check error responses`); } if (metrics.totalDataTransferred > 1024 * 1024) { insights.push(`Large data transfer detected (${Math.round(metrics.totalDataTransferred / 1024 / 1024)}MB) - consider response compression`); } const summary = `Network Activity Summary: - Total Requests: ${metrics.totalRequests} - Successful: ${metrics.successfulRequests} - Failed: ${metrics.failedRequests} - Average Response Time: ${Math.round(metrics.averageResponseTime)}ms - Data Transferred: ${Math.round(metrics.totalDataTransferred / 1024)}KB`; return { metrics, requests: this.getCapturedRequests(), responses: this.getCapturedResponses(), errors: this.getNetworkErrors(), summary, insights, }; } /** * Cleanup network monitoring and reset state */ cleanup() { if (this.currentPage && this.isMonitoring) { try { this.currentPage.unroute('**/*'); this.currentPage.context().off('response', this.responseHandler); } catch (error) { // Cleanup errors are non-fatal console.warn('NetworkCoordinator: Cleanup warning:', error); } } // Reset state this.isMonitoring = false; this.capturedRequests = []; this.capturedResponses = []; this.networkErrors = []; this.requestTimings.clear(); this.currentPage = undefined; } /** * Generate unique request ID */ generateRequestId() { return `req_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; } /** * Find request ID by URL (best effort matching) */ findRequestId(url) { const request = this.capturedRequests.find(req => req.url === url); return request?.requestId; } } //# sourceMappingURL=network-coordinator.js.map