@dynamicu/chromedebug-mcp 2.5.14 → 2.5.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/capture/memory-manager.js +3 -3
- package/src/commands/install-pro.js +37 -37
- package/src/firebase-license-manager.js +4 -4
- package/src/http-server.js +100 -100
- package/src/index-modular.js +1 -1
- package/src/index.js +1 -1
- package/src/mcp/handlers/chrome-tool-handler.js +3 -3
- package/src/mcp/handlers/frame-tool-handler.js +10 -10
- package/src/mcp/handlers/workflow-tool-handler.js +2 -2
- package/src/middleware/security.js +4 -4
- package/src/services/browser-daemon.js +17 -17
- package/src/services/git-safety-service.js +3 -3
- package/src/services/heartbeat-manager.js +7 -7
- package/src/services/process-manager.js +1 -1
- package/src/services/process-tracker.js +22 -22
- package/src/services/profile-manager.js +18 -18
- package/src/services/session-manager.js +21 -21
- package/src/services/session-registry.js +21 -21
- package/src/services/unified-session-manager.js +13 -13
- package/src/standalone-server.js +17 -17
- package/src/utils/extension-path.js +9 -9
- package/src/utils.js +2 -2
- package/src/validation/schemas.js +2 -2
package/src/http-server.js
CHANGED
|
@@ -83,10 +83,10 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
83
83
|
const contentType = req.get('content-type') || 'none';
|
|
84
84
|
const contentLength = req.get('content-length') || '0';
|
|
85
85
|
|
|
86
|
-
console.
|
|
87
|
-
console.
|
|
88
|
-
console.
|
|
89
|
-
console.
|
|
86
|
+
console.error(`[RAW-REQUEST] ${timestamp} - ${req.method} ${req.originalUrl}`);
|
|
87
|
+
console.error(`[RAW-REQUEST] IP: ${ip} | UA: ${userAgent}`);
|
|
88
|
+
console.error(`[RAW-REQUEST] Content-Type: ${contentType} | Length: ${contentLength}bytes`);
|
|
89
|
+
console.error(`[RAW-REQUEST] Headers:`, Object.keys(req.headers).map(h => `${h}=${req.headers[h]}`).join(', '));
|
|
90
90
|
|
|
91
91
|
// Capture body parsing errors
|
|
92
92
|
const originalJson = express.json();
|
|
@@ -96,8 +96,8 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
96
96
|
const originalStatus = res.status;
|
|
97
97
|
res.status = function(code) {
|
|
98
98
|
if (code === 400) {
|
|
99
|
-
console.
|
|
100
|
-
console.
|
|
99
|
+
console.error(`[RAW-REQUEST] HTTP 400 ERROR for ${req.method} ${req.originalUrl}`);
|
|
100
|
+
console.error(`[RAW-REQUEST] This request will be rejected with 400`);
|
|
101
101
|
}
|
|
102
102
|
return originalStatus.call(this, code);
|
|
103
103
|
};
|
|
@@ -108,10 +108,10 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
108
108
|
// ENHANCED BODY PARSING - For debugging body parsing issues (only for screen-interactions)
|
|
109
109
|
app.use('/chromedebug/screen-interactions/*', (req, res, next) => {
|
|
110
110
|
if (req.method === 'POST') {
|
|
111
|
-
console.
|
|
112
|
-
console.
|
|
113
|
-
console.
|
|
114
|
-
console.
|
|
111
|
+
console.error(`[BODY-DEBUG] Processing screen-interactions request for ${req.originalUrl}`);
|
|
112
|
+
console.error(`[BODY-DEBUG] Content-Type: ${req.get('content-type')}`);
|
|
113
|
+
console.error(`[BODY-DEBUG] Content-Length: ${req.get('content-length')}`);
|
|
114
|
+
console.error(`[BODY-DEBUG] User-Agent: ${req.get('user-agent')}`);
|
|
115
115
|
|
|
116
116
|
// Store original data handler to capture raw body
|
|
117
117
|
const originalData = req.on;
|
|
@@ -130,16 +130,16 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
130
130
|
const wrappedHandler = () => {
|
|
131
131
|
if (chunks.length > 0) {
|
|
132
132
|
const rawBody = Buffer.concat(chunks).toString();
|
|
133
|
-
console.
|
|
133
|
+
console.error(`[BODY-DEBUG] Raw body captured (${rawBody.length} chars):`, rawBody);
|
|
134
134
|
req.rawBody = rawBody;
|
|
135
135
|
|
|
136
136
|
// Try to parse manually
|
|
137
137
|
try {
|
|
138
138
|
const parsedBody = JSON.parse(rawBody);
|
|
139
|
-
console.
|
|
140
|
-
console.
|
|
139
|
+
console.error(`[BODY-DEBUG] Manual JSON parse successful`);
|
|
140
|
+
console.error(`[BODY-DEBUG] Parsed data:`, JSON.stringify(parsedBody, null, 2));
|
|
141
141
|
} catch (parseError) {
|
|
142
|
-
console.
|
|
142
|
+
console.error(`[BODY-DEBUG] Manual JSON parse FAILED:`, parseError.message);
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
return originalHandler();
|
|
@@ -155,9 +155,9 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
155
155
|
// JSON PARSING ERROR HANDLER - Catch malformed JSON before it reaches our handlers
|
|
156
156
|
app.use('/chromedebug/screen-interactions/*', (err, req, res, next) => {
|
|
157
157
|
if (err instanceof SyntaxError && err.status === 400 && 'body' in err) {
|
|
158
|
-
console.
|
|
159
|
-
console.
|
|
160
|
-
console.
|
|
158
|
+
console.error(`[JSON-PARSE-ERROR] Malformed JSON in screen-interactions request:`, err.message);
|
|
159
|
+
console.error(`[JSON-PARSE-ERROR] Raw body:`, req.rawBody || 'not captured');
|
|
160
|
+
console.error(`[JSON-PARSE-ERROR] Request body:`, req.body);
|
|
161
161
|
return res.status(400).json({
|
|
162
162
|
error: 'Invalid JSON format',
|
|
163
163
|
details: err.message
|
|
@@ -169,13 +169,13 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
169
169
|
// ENHANCED VALIDATION ERROR HANDLER - Catch and log detailed validation errors
|
|
170
170
|
app.use('/chromedebug/screen-interactions/*', (err, req, res, next) => {
|
|
171
171
|
if (err && err.status === 400 && err.details) {
|
|
172
|
-
console.
|
|
173
|
-
console.
|
|
174
|
-
console.
|
|
175
|
-
console.
|
|
176
|
-
console.
|
|
177
|
-
console.
|
|
178
|
-
console.
|
|
172
|
+
console.error(`[VALIDATION-ERROR] Screen interactions validation failed:`);
|
|
173
|
+
console.error(`[VALIDATION-ERROR] Request path:`, req.originalUrl);
|
|
174
|
+
console.error(`[VALIDATION-ERROR] User agent:`, req.get('user-agent'));
|
|
175
|
+
console.error(`[VALIDATION-ERROR] Content type:`, req.get('content-type'));
|
|
176
|
+
console.error(`[VALIDATION-ERROR] Raw body:`, req.rawBody || 'not captured');
|
|
177
|
+
console.error(`[VALIDATION-ERROR] Parsed body:`, JSON.stringify(req.body, null, 2));
|
|
178
|
+
console.error(`[VALIDATION-ERROR] Validation errors:`, JSON.stringify(err.details, null, 2));
|
|
179
179
|
}
|
|
180
180
|
next(err);
|
|
181
181
|
});
|
|
@@ -288,8 +288,8 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
288
288
|
createValidator(workflowRecordingSchema),
|
|
289
289
|
async (req, res) => {
|
|
290
290
|
const { sessionId, url, title, includeLogs, actions, logs, functionTraces, name, screenshotSettings } = req.body;
|
|
291
|
-
console.
|
|
292
|
-
console.
|
|
291
|
+
console.error('[HTTP Server] Received workflow recording with name:', name);
|
|
292
|
+
console.error('[HTTP Server] Function traces count:', functionTraces ? functionTraces.length : 0);
|
|
293
293
|
if (!sessionId || !actions) {
|
|
294
294
|
return res.status(400).json({ error: 'sessionId and actions are required' });
|
|
295
295
|
}
|
|
@@ -360,18 +360,18 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
360
360
|
return res.status(400).json({ error: 'No data provided' });
|
|
361
361
|
}
|
|
362
362
|
|
|
363
|
-
console.
|
|
363
|
+
console.error(`[Upload] Received batch ${batchId} for recording ${recordingId} with ${events.length} events`);
|
|
364
364
|
|
|
365
365
|
// Ensure recording exists (auto-create if needed)
|
|
366
366
|
try {
|
|
367
367
|
const existingRecording = activeController.database.getRecording(recordingId);
|
|
368
368
|
if (!existingRecording) {
|
|
369
|
-
console.
|
|
369
|
+
console.error(`[Upload] Auto-creating recording ${recordingId} for full data upload`);
|
|
370
370
|
activeController.database.storeRecording(recordingId, 'full_data_recording');
|
|
371
371
|
}
|
|
372
372
|
} catch (error) {
|
|
373
373
|
// Recording doesn't exist, create it
|
|
374
|
-
console.
|
|
374
|
+
console.error(`[Upload] Auto-creating recording ${recordingId} for full data upload (error case)`);
|
|
375
375
|
activeController.database.storeRecording(recordingId, 'full_data_recording');
|
|
376
376
|
}
|
|
377
377
|
|
|
@@ -394,7 +394,7 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
394
394
|
await activeController.database.storePerformanceMetric(recordingId, event);
|
|
395
395
|
break;
|
|
396
396
|
default:
|
|
397
|
-
console.
|
|
397
|
+
console.error(`[Upload] Unknown event type: ${event.type}`);
|
|
398
398
|
}
|
|
399
399
|
}
|
|
400
400
|
|
|
@@ -434,7 +434,7 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
434
434
|
data = typeof req.body === 'string' ? JSON.parse(req.body) : req.body;
|
|
435
435
|
}
|
|
436
436
|
|
|
437
|
-
console.
|
|
437
|
+
console.error(`[Upload] Received ${dataType} data for recording ${recordingId}`);
|
|
438
438
|
|
|
439
439
|
// Store data based on type
|
|
440
440
|
const storeMethod = `store${dataType.charAt(0).toUpperCase() + dataType.slice(1).replace(/-/g, '')}`;
|
|
@@ -461,23 +461,23 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
461
461
|
authorize(PERMISSIONS.FRAME_WRITE),
|
|
462
462
|
upload.none(),
|
|
463
463
|
async (req, res) => {
|
|
464
|
-
console.
|
|
465
|
-
console.
|
|
466
|
-
console.
|
|
467
|
-
console.
|
|
468
|
-
console.
|
|
469
|
-
console.
|
|
470
|
-
console.
|
|
464
|
+
console.error('[FORMDATA-DEBUG] ==========================================');
|
|
465
|
+
console.error('[FORMDATA-DEBUG] Frame batch request received');
|
|
466
|
+
console.error('[FORMDATA-DEBUG] Content-Type:', req.headers['content-type']);
|
|
467
|
+
console.error('[FORMDATA-DEBUG] Request method:', req.method);
|
|
468
|
+
console.error('[FORMDATA-DEBUG] User:', req.user?.name || 'unknown');
|
|
469
|
+
console.error('[FORMDATA-DEBUG] Raw body keys:', Object.keys(req.body || {}));
|
|
470
|
+
console.error('[FORMDATA-DEBUG] Raw body:', req.body);
|
|
471
471
|
|
|
472
472
|
// Handle both JSON and FormData
|
|
473
473
|
let sessionId, frames, sessionName;
|
|
474
474
|
|
|
475
475
|
if (req.headers['content-type']?.includes('application/json')) {
|
|
476
|
-
console.
|
|
476
|
+
console.error('[FORMDATA-DEBUG] Processing as JSON request');
|
|
477
477
|
// JSON request - validate with schema
|
|
478
478
|
const { error, value } = frameBatchSchema.validate(req.body);
|
|
479
479
|
if (error) {
|
|
480
|
-
console.
|
|
480
|
+
console.error('[FORMDATA-DEBUG] JSON validation failed:', error.details);
|
|
481
481
|
return res.status(400).json({
|
|
482
482
|
error: 'Validation failed',
|
|
483
483
|
details: error.details.map(detail => ({
|
|
@@ -490,37 +490,37 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
490
490
|
frames = value.frames;
|
|
491
491
|
sessionName = value.sessionName || null;
|
|
492
492
|
|
|
493
|
-
console.
|
|
493
|
+
console.error('[FORMDATA-DEBUG] JSON parsed successfully:', { sessionId, frameCount: frames?.length, sessionName });
|
|
494
494
|
} else {
|
|
495
|
-
console.
|
|
495
|
+
console.error('[FORMDATA-DEBUG] Processing as FormData request');
|
|
496
496
|
|
|
497
497
|
// FormData request - manual validation
|
|
498
498
|
sessionId = req.body.sessionId;
|
|
499
499
|
sessionName = req.body.sessionName || null;
|
|
500
500
|
|
|
501
|
-
console.
|
|
502
|
-
console.
|
|
503
|
-
console.
|
|
504
|
-
console.
|
|
505
|
-
console.
|
|
501
|
+
console.error('[FORMDATA-DEBUG] SessionId from FormData:', sessionId);
|
|
502
|
+
console.error('[FORMDATA-DEBUG] SessionName from FormData:', sessionName);
|
|
503
|
+
console.error('[FORMDATA-DEBUG] Frames field type:', typeof req.body.frames);
|
|
504
|
+
console.error('[FORMDATA-DEBUG] Frames field length:', req.body.frames?.length);
|
|
505
|
+
console.error('[FORMDATA-DEBUG] Frames field preview:', req.body.frames?.substring(0, 200));
|
|
506
506
|
|
|
507
507
|
try {
|
|
508
508
|
if (!req.body.frames) {
|
|
509
|
-
console.
|
|
509
|
+
console.error('[FORMDATA-DEBUG] ❌ No frames field in FormData');
|
|
510
510
|
frames = null;
|
|
511
511
|
} else {
|
|
512
|
-
console.
|
|
512
|
+
console.error('[FORMDATA-DEBUG] 🔄 Attempting to parse frames JSON...');
|
|
513
513
|
frames = JSON.parse(req.body.frames);
|
|
514
|
-
console.
|
|
515
|
-
console.
|
|
516
|
-
console.
|
|
514
|
+
console.error('[FORMDATA-DEBUG] ✅ Frames JSON parsed successfully');
|
|
515
|
+
console.error('[FORMDATA-DEBUG] Parsed frames count:', frames?.length);
|
|
516
|
+
console.error('[FORMDATA-DEBUG] First frame structure:', frames?.[0] ? Object.keys(frames[0]) : 'no frames');
|
|
517
517
|
}
|
|
518
518
|
|
|
519
|
-
console.
|
|
519
|
+
console.error('[FORMDATA-DEBUG] 🔄 Validating parsed FormData...');
|
|
520
520
|
// Validate the parsed data
|
|
521
521
|
const { error, value } = frameBatchSchema.validate({ sessionId, frames, sessionName });
|
|
522
522
|
if (error) {
|
|
523
|
-
console.
|
|
523
|
+
console.error('[FORMDATA-DEBUG] ❌ FormData validation failed:', error.details);
|
|
524
524
|
return res.status(400).json({
|
|
525
525
|
error: 'Validation failed',
|
|
526
526
|
details: error.details.map(detail => ({
|
|
@@ -533,7 +533,7 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
533
533
|
frames = value.frames;
|
|
534
534
|
sessionName = value.sessionName;
|
|
535
535
|
|
|
536
|
-
console.
|
|
536
|
+
console.error('[FORMDATA-DEBUG] ✅ FormData validation successful');
|
|
537
537
|
} catch (parseError) {
|
|
538
538
|
console.error('[FORMDATA-DEBUG] ❌ Failed to parse frames JSON:', parseError);
|
|
539
539
|
console.error('[FORMDATA-DEBUG] Raw frames data:', req.body.frames);
|
|
@@ -542,38 +542,38 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
542
542
|
}
|
|
543
543
|
|
|
544
544
|
if (!sessionId || !frames) {
|
|
545
|
-
console.
|
|
546
|
-
console.
|
|
547
|
-
console.
|
|
545
|
+
console.error('[FORMDATA-DEBUG] ❌ Missing required data');
|
|
546
|
+
console.error('[FORMDATA-DEBUG] SessionId:', sessionId);
|
|
547
|
+
console.error('[FORMDATA-DEBUG] Frames:', frames ? 'present' : 'null');
|
|
548
548
|
return res.status(400).json({ error: 'sessionId and frames are required' });
|
|
549
549
|
}
|
|
550
550
|
|
|
551
|
-
console.
|
|
552
|
-
console.
|
|
553
|
-
console.
|
|
551
|
+
console.error('[FORMDATA-DEBUG] ✅ All data validated, proceeding to storage');
|
|
552
|
+
console.error('[FORMDATA-DEBUG] Session ID:', sessionId);
|
|
553
|
+
console.error('[FORMDATA-DEBUG] Frame count:', frames?.length);
|
|
554
554
|
|
|
555
555
|
try {
|
|
556
|
-
console.
|
|
556
|
+
console.error('[FORMDATA-DEBUG] 🔄 Calling activeController.storeFrameBatch...');
|
|
557
557
|
if (frames && frames.length > 0) {
|
|
558
|
-
console.
|
|
559
|
-
console.
|
|
560
|
-
console.
|
|
558
|
+
console.error('[FORMDATA-DEBUG] First frame structure:', Object.keys(frames[0]));
|
|
559
|
+
console.error('[FORMDATA-DEBUG] First frame has imageData:', !!frames[0].imageData);
|
|
560
|
+
console.error('[FORMDATA-DEBUG] ImageData length:', frames[0].imageData ? frames[0].imageData.length : 'N/A');
|
|
561
561
|
}
|
|
562
562
|
|
|
563
|
-
console.
|
|
563
|
+
console.error('[FORMDATA-DEBUG] Session name:', sessionName || 'none');
|
|
564
564
|
|
|
565
565
|
const result = await activeController.storeFrameBatch(sessionId, frames, sessionName);
|
|
566
|
-
console.
|
|
566
|
+
console.error('[FORMDATA-DEBUG] ✅ Frame batch storage result:', result);
|
|
567
567
|
|
|
568
|
-
console.
|
|
569
|
-
console.
|
|
570
|
-
console.
|
|
568
|
+
console.error('[FORMDATA-DEBUG] Result recording ID:', result?.id);
|
|
569
|
+
console.error('[FORMDATA-DEBUG] Result frame count:', result?.total_frames);
|
|
570
|
+
console.error('[FORMDATA-DEBUG] ==========================================');
|
|
571
571
|
|
|
572
572
|
res.json(result);
|
|
573
573
|
} catch (error) {
|
|
574
574
|
console.error('[FORMDATA-DEBUG] ❌ Storage error:', error);
|
|
575
575
|
console.error('[FORMDATA-DEBUG] Error stack:', error.stack);
|
|
576
|
-
console.
|
|
576
|
+
console.error('[FORMDATA-DEBUG] ==========================================');
|
|
577
577
|
res.status(500).json({ error: 'Failed to store frame batch', details: error.message });
|
|
578
578
|
}
|
|
579
579
|
});
|
|
@@ -592,7 +592,7 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
592
592
|
|
|
593
593
|
// Debug: Verify logs are properly included and formatted
|
|
594
594
|
if (result.frames?.length > 0 && result.frames[0]?.logs?.length > 0) {
|
|
595
|
-
console.
|
|
595
|
+
console.error(`[INFO] Frame session ${sessionId}: Loaded ${result.frames.length} frames with console logs`);
|
|
596
596
|
}
|
|
597
597
|
|
|
598
598
|
res.json(result);
|
|
@@ -655,7 +655,7 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
655
655
|
if (req.body.logs) {
|
|
656
656
|
const compliance = analyzeLogFieldCompliance(req.body.logs);
|
|
657
657
|
if (!compliance.isCompliant) {
|
|
658
|
-
console.
|
|
658
|
+
console.error('[LogTransform] Applied field filtering:', {
|
|
659
659
|
originalLogs: req.body.logs.length,
|
|
660
660
|
nonSchemaFields: compliance.nonSchemaFields,
|
|
661
661
|
missingFields: compliance.missingRequiredFields
|
|
@@ -690,7 +690,7 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
690
690
|
if (logs) {
|
|
691
691
|
const compliance = analyzeLogFieldCompliance(logs);
|
|
692
692
|
if (!compliance.isCompliant) {
|
|
693
|
-
console.
|
|
693
|
+
console.error('[LogTransform] Applied field filtering (FormData):', {
|
|
694
694
|
originalLogs: logs.length,
|
|
695
695
|
nonSchemaFields: compliance.nonSchemaFields,
|
|
696
696
|
missingFields: compliance.missingRequiredFields
|
|
@@ -1096,27 +1096,27 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
1096
1096
|
const { interactions } = req.body;
|
|
1097
1097
|
|
|
1098
1098
|
// Debug logging to identify validation issues
|
|
1099
|
-
console.
|
|
1100
|
-
console.
|
|
1101
|
-
console.
|
|
1102
|
-
console.
|
|
1103
|
-
console.
|
|
1104
|
-
console.
|
|
1105
|
-
console.
|
|
1106
|
-
console.
|
|
1107
|
-
console.
|
|
1099
|
+
console.error('[SCREEN-INTERACTIONS-DEBUG] ==========================================');
|
|
1100
|
+
console.error('[SCREEN-INTERACTIONS-DEBUG] Request received for session:', sessionId);
|
|
1101
|
+
console.error('[SCREEN-INTERACTIONS-DEBUG] Content-Type:', req.get('content-type'));
|
|
1102
|
+
console.error('[SCREEN-INTERACTIONS-DEBUG] User agent:', req.get('user-agent'));
|
|
1103
|
+
console.error('[SCREEN-INTERACTIONS-DEBUG] Auth user:', req.user?.name || 'unknown');
|
|
1104
|
+
console.error('[SCREEN-INTERACTIONS-DEBUG] Request body keys:', Object.keys(req.body || {}));
|
|
1105
|
+
console.error('[SCREEN-INTERACTIONS-DEBUG] Interactions field present:', !!interactions);
|
|
1106
|
+
console.error('[SCREEN-INTERACTIONS-DEBUG] Interactions type:', typeof interactions);
|
|
1107
|
+
console.error('[SCREEN-INTERACTIONS-DEBUG] Interactions length:', Array.isArray(interactions) ? interactions.length : 'N/A');
|
|
1108
1108
|
if (Array.isArray(interactions) && interactions.length > 0) {
|
|
1109
|
-
console.
|
|
1109
|
+
console.error('[SCREEN-INTERACTIONS-DEBUG] First interaction:', JSON.stringify(interactions[0], null, 2));
|
|
1110
1110
|
}
|
|
1111
|
-
console.
|
|
1112
|
-
console.
|
|
1111
|
+
console.error('[SCREEN-INTERACTIONS-DEBUG] Raw body:', JSON.stringify(req.body, null, 2));
|
|
1112
|
+
console.error('[SCREEN-INTERACTIONS-DEBUG] ==========================================');
|
|
1113
1113
|
|
|
1114
1114
|
try {
|
|
1115
1115
|
const { database } = await import('./database.js');
|
|
1116
1116
|
const result = database.storeScreenInteractions(sessionId, interactions);
|
|
1117
1117
|
|
|
1118
1118
|
if (result.success) {
|
|
1119
|
-
console.
|
|
1119
|
+
console.error(`[HTTP] Stored ${result.count} screen interactions for recording ${sessionId}`);
|
|
1120
1120
|
res.json({ success: true, count: result.count });
|
|
1121
1121
|
} else {
|
|
1122
1122
|
res.status(500).json({ success: false, error: result.error });
|
|
@@ -1131,14 +1131,14 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
1131
1131
|
app.post('/chromedebug/debug-interactions/:sessionId',
|
|
1132
1132
|
authenticate,
|
|
1133
1133
|
(req, res) => {
|
|
1134
|
-
console.
|
|
1135
|
-
console.
|
|
1136
|
-
console.
|
|
1137
|
-
console.
|
|
1138
|
-
console.
|
|
1139
|
-
console.
|
|
1140
|
-
console.
|
|
1141
|
-
console.
|
|
1134
|
+
console.error('[DEBUG-ENDPOINT] ==========================================');
|
|
1135
|
+
console.error('[DEBUG-ENDPOINT] Auth bypass test successful!');
|
|
1136
|
+
console.error('[DEBUG-ENDPOINT] User:', JSON.stringify(req.user, null, 2));
|
|
1137
|
+
console.error('[DEBUG-ENDPOINT] Session ID:', req.params.sessionId);
|
|
1138
|
+
console.error('[DEBUG-ENDPOINT] Content-Type:', req.get('content-type'));
|
|
1139
|
+
console.error('[DEBUG-ENDPOINT] Request headers:', Object.keys(req.headers));
|
|
1140
|
+
console.error('[DEBUG-ENDPOINT] Request body:', JSON.stringify(req.body, null, 2));
|
|
1141
|
+
console.error('[DEBUG-ENDPOINT] ==========================================');
|
|
1142
1142
|
|
|
1143
1143
|
res.json({
|
|
1144
1144
|
debug: true,
|
|
@@ -1316,7 +1316,7 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
1316
1316
|
|
|
1317
1317
|
// Add a catch-all route for debugging
|
|
1318
1318
|
app.use('*', (req, res, next) => {
|
|
1319
|
-
console.
|
|
1319
|
+
console.error(`[HTTP] ${req.method} ${req.originalUrl}`);
|
|
1320
1320
|
next();
|
|
1321
1321
|
});
|
|
1322
1322
|
|
|
@@ -1325,7 +1325,7 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
1325
1325
|
|
|
1326
1326
|
// 404 handler - must be last
|
|
1327
1327
|
app.use((req, res) => {
|
|
1328
|
-
console.
|
|
1328
|
+
console.error(`[HTTP] 404 - Route not found: ${req.method} ${req.originalUrl}`);
|
|
1329
1329
|
res.status(404).json({
|
|
1330
1330
|
success: false,
|
|
1331
1331
|
error: 'Endpoint not found',
|
|
@@ -1353,7 +1353,7 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
1353
1353
|
if (targetPort) {
|
|
1354
1354
|
// Use the target port provided by session manager
|
|
1355
1355
|
portsToTry = [targetPort];
|
|
1356
|
-
console.
|
|
1356
|
+
console.error(`Attempting to start HTTP server on session manager allocated port: ${targetPort}`);
|
|
1357
1357
|
} else {
|
|
1358
1358
|
// Fall back to configured ports
|
|
1359
1359
|
const configuredPorts = configLoader.getHttpServerPorts();
|
|
@@ -1364,7 +1364,7 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
1364
1364
|
? [startPort, ...configuredPorts.filter(p => p !== startPort)]
|
|
1365
1365
|
: configuredPorts;
|
|
1366
1366
|
|
|
1367
|
-
console.
|
|
1367
|
+
console.error('Attempting to start HTTP server on configured ports:', portsToTry);
|
|
1368
1368
|
}
|
|
1369
1369
|
|
|
1370
1370
|
// Try configured ports in order
|
|
@@ -1393,7 +1393,7 @@ async function startHttpServer(chromeController = null, targetPort = null) {
|
|
|
1393
1393
|
throw new Error(`Could not find available port for HTTP server. All ports in use: ${portsToTry.join(', ')}`);
|
|
1394
1394
|
}
|
|
1395
1395
|
|
|
1396
|
-
console.
|
|
1396
|
+
console.error(`HTTP server started on port ${actualPort}`);
|
|
1397
1397
|
|
|
1398
1398
|
// Write port file for discovery
|
|
1399
1399
|
writePortFile(actualPort);
|
package/src/index-modular.js
CHANGED
package/src/index.js
CHANGED
|
@@ -229,7 +229,7 @@ export class ChromeToolHandler {
|
|
|
229
229
|
|
|
230
230
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
231
231
|
try {
|
|
232
|
-
console.
|
|
232
|
+
console.error(`[ChromeToolHandler] Attempt ${attempt}/${maxRetries} for ${name} (Session: ${this.chromeController.sessionId})`);
|
|
233
233
|
|
|
234
234
|
// Execute the operation based on name
|
|
235
235
|
switch (name) {
|
|
@@ -254,7 +254,7 @@ export class ChromeToolHandler {
|
|
|
254
254
|
const isSessionConflict = this.isSessionConflictError(error);
|
|
255
255
|
|
|
256
256
|
if (isSessionConflict && attempt < maxRetries) {
|
|
257
|
-
console.
|
|
257
|
+
console.error(`[ChromeToolHandler] Detected session conflict, attempting recovery...`);
|
|
258
258
|
|
|
259
259
|
try {
|
|
260
260
|
// Force cleanup current session and create new one
|
|
@@ -263,7 +263,7 @@ export class ChromeToolHandler {
|
|
|
263
263
|
// Wait a bit before retrying to let system stabilize
|
|
264
264
|
await new Promise(resolve => setTimeout(resolve, 1000 + (attempt * 500)));
|
|
265
265
|
|
|
266
|
-
console.
|
|
266
|
+
console.error(`[ChromeToolHandler] Session recovery completed, retrying...`);
|
|
267
267
|
} catch (recoveryError) {
|
|
268
268
|
console.error(`[ChromeToolHandler] Session recovery failed:`, recoveryError.message);
|
|
269
269
|
}
|
|
@@ -96,7 +96,7 @@ export class FrameToolHandler {
|
|
|
96
96
|
}
|
|
97
97
|
} catch (error) {
|
|
98
98
|
// Fall back to direct database access if HTTP client fails
|
|
99
|
-
console.
|
|
99
|
+
console.error('[FrameToolHandler] HTTP client failed, falling back to direct access:', error.message);
|
|
100
100
|
sessionInfo = await this.chromeController.getFrameSessionInfo(args.sessionId);
|
|
101
101
|
if (!sessionInfo) {
|
|
102
102
|
availableSessions = await this.chromeController.listFrameSessions();
|
|
@@ -167,7 +167,7 @@ export class FrameToolHandler {
|
|
|
167
167
|
result.note = 'No frame data or interactions found. This may indicate the recording was started but stopped immediately.';
|
|
168
168
|
}
|
|
169
169
|
} catch (error) {
|
|
170
|
-
console.
|
|
170
|
+
console.error('[FrameToolHandler] Failed to check interactions:', error.message);
|
|
171
171
|
result.note = 'No frame data found. Unable to check for interactions.';
|
|
172
172
|
}
|
|
173
173
|
|
|
@@ -285,7 +285,7 @@ export class FrameToolHandler {
|
|
|
285
285
|
frameData.interactionMetadata = { totalFound: 0, displayed: 0, timeWindow: 500 };
|
|
286
286
|
}
|
|
287
287
|
} catch (error) {
|
|
288
|
-
console.
|
|
288
|
+
console.error('[FrameToolHandler] Failed to get frame interactions:', error.message);
|
|
289
289
|
frameData.interactions = [];
|
|
290
290
|
frameData.associatedInteractions = [];
|
|
291
291
|
frameData.interactionMetadata = { totalFound: 0, displayed: 0, timeWindow: 500 };
|
|
@@ -329,7 +329,7 @@ export class FrameToolHandler {
|
|
|
329
329
|
}
|
|
330
330
|
}
|
|
331
331
|
} catch (error) {
|
|
332
|
-
console.
|
|
332
|
+
console.error('[FrameToolHandler] HTTP client failed, falling back to direct access:', error.message);
|
|
333
333
|
info = await this.chromeController.getFrameSessionInfo(args.sessionId);
|
|
334
334
|
if (!info) {
|
|
335
335
|
availableSessions = await this.chromeController.listFrameSessions();
|
|
@@ -386,7 +386,7 @@ export class FrameToolHandler {
|
|
|
386
386
|
interactionSummary.interactionTypes = Object.entries(typeCount).map(([type, count]) => `${type}: ${count}`);
|
|
387
387
|
}
|
|
388
388
|
} catch (error) {
|
|
389
|
-
console.
|
|
389
|
+
console.error('[FrameToolHandler] Failed to get interaction summary:', error.message);
|
|
390
390
|
// Keep default empty summary
|
|
391
391
|
}
|
|
392
392
|
|
|
@@ -424,7 +424,7 @@ export class FrameToolHandler {
|
|
|
424
424
|
frame = await this.chromeController.getFrame(args.sessionId, args.frameIndex);
|
|
425
425
|
}
|
|
426
426
|
} catch (error) {
|
|
427
|
-
console.
|
|
427
|
+
console.error('[FrameToolHandler] HTTP client failed, falling back to direct access:', error.message);
|
|
428
428
|
frame = await this.chromeController.getFrame(args.sessionId, args.frameIndex);
|
|
429
429
|
}
|
|
430
430
|
|
|
@@ -534,7 +534,7 @@ export class FrameToolHandler {
|
|
|
534
534
|
results = await this.chromeController.searchFrameLogs(args.sessionId, args.searchText, logLevel, maxResults);
|
|
535
535
|
}
|
|
536
536
|
} catch (error) {
|
|
537
|
-
console.
|
|
537
|
+
console.error('[FrameToolHandler] HTTP client failed, falling back to direct access:', error.message);
|
|
538
538
|
results = await this.chromeController.searchFrameLogs(args.sessionId, args.searchText, logLevel, maxResults);
|
|
539
539
|
}
|
|
540
540
|
|
|
@@ -577,7 +577,7 @@ export class FrameToolHandler {
|
|
|
577
577
|
results = await this.chromeController.getFrameLogsPaginated(args.sessionId, args.frameIndex, offset, limit, logLevel, searchText);
|
|
578
578
|
}
|
|
579
579
|
} catch (error) {
|
|
580
|
-
console.
|
|
580
|
+
console.error('[FrameToolHandler] HTTP client failed, falling back to direct access:', error.message);
|
|
581
581
|
results = await this.chromeController.getFrameLogsPaginated(args.sessionId, args.frameIndex, offset, limit, logLevel, searchText);
|
|
582
582
|
}
|
|
583
583
|
|
|
@@ -698,7 +698,7 @@ export class FrameToolHandler {
|
|
|
698
698
|
}
|
|
699
699
|
}
|
|
700
700
|
} catch (error) {
|
|
701
|
-
console.
|
|
701
|
+
console.error('[FrameToolHandler] HTTP client failed, falling back to direct access:', error.message);
|
|
702
702
|
if (args.frameIndex !== undefined) {
|
|
703
703
|
interactions = await this.chromeController.getFrameInteractions(args.sessionId, args.frameIndex);
|
|
704
704
|
} else {
|
|
@@ -936,7 +936,7 @@ export class FrameToolHandler {
|
|
|
936
936
|
}
|
|
937
937
|
}
|
|
938
938
|
} catch (error) {
|
|
939
|
-
console.
|
|
939
|
+
console.error(`Error processing snapshot ${snapshot.id}:`, error.message);
|
|
940
940
|
}
|
|
941
941
|
}
|
|
942
942
|
|
|
@@ -77,7 +77,7 @@ export class WorkflowToolHandler {
|
|
|
77
77
|
recording = await this.chromeController.getWorkflowRecording(args.sessionId);
|
|
78
78
|
}
|
|
79
79
|
} catch (error) {
|
|
80
|
-
console.
|
|
80
|
+
console.error('[WorkflowToolHandler] HTTP client failed, falling back to direct access:', error.message);
|
|
81
81
|
recording = await this.chromeController.getWorkflowRecording(args.sessionId);
|
|
82
82
|
}
|
|
83
83
|
|
|
@@ -112,7 +112,7 @@ export class WorkflowToolHandler {
|
|
|
112
112
|
result = await this.chromeController.listWorkflowRecordings();
|
|
113
113
|
}
|
|
114
114
|
} catch (error) {
|
|
115
|
-
console.
|
|
115
|
+
console.error('[WorkflowToolHandler] HTTP client failed, falling back to direct access:', error.message);
|
|
116
116
|
result = await this.chromeController.listWorkflowRecordings();
|
|
117
117
|
}
|
|
118
118
|
|
|
@@ -38,7 +38,7 @@ export const corsOptions = {
|
|
|
38
38
|
if (isAllowed) {
|
|
39
39
|
callback(null, true);
|
|
40
40
|
} else {
|
|
41
|
-
console.
|
|
41
|
+
console.error(`CORS: Blocked origin ${origin}`);
|
|
42
42
|
callback(new Error('Not allowed by CORS policy'));
|
|
43
43
|
}
|
|
44
44
|
},
|
|
@@ -165,14 +165,14 @@ export function securityLogger(req, res, next) {
|
|
|
165
165
|
);
|
|
166
166
|
|
|
167
167
|
if (isSensitive) {
|
|
168
|
-
console.
|
|
168
|
+
console.error(`[Security] ${req.method} ${req.path} - User: ${req.user?.name || 'unauthenticated'} - IP: ${req.ip}`);
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
// Track response time for monitoring
|
|
172
172
|
res.on('finish', () => {
|
|
173
173
|
const duration = Date.now() - start;
|
|
174
174
|
if (duration > 5000) { // Log slow requests
|
|
175
|
-
console.
|
|
175
|
+
console.error(`[Performance] Slow request: ${req.method} ${req.path} - ${duration}ms`);
|
|
176
176
|
}
|
|
177
177
|
});
|
|
178
178
|
|
|
@@ -245,7 +245,7 @@ export function createIPWhitelist(allowedIPs = []) {
|
|
|
245
245
|
const clientIP = req.ip || req.connection.remoteAddress;
|
|
246
246
|
|
|
247
247
|
if (!allowedIPs.includes(clientIP)) {
|
|
248
|
-
console.
|
|
248
|
+
console.error(`[Security] Blocked IP: ${clientIP}`);
|
|
249
249
|
return res.status(403).json({
|
|
250
250
|
error: 'IP not whitelisted'
|
|
251
251
|
});
|