@dynamicu/chromedebug-mcp 2.7.0 → 2.7.2

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.
@@ -1,6 +1,6 @@
1
1
  // Background script to handle server communication and recording
2
2
  const EXTENSION_VERSION = '2.0.4-BUILD-20250119';
3
- console.log(`[background.js] Loaded version: ${EXTENSION_VERSION}`);
3
+ // console.log(`[background.js] Loaded version: ${EXTENSION_VERSION}`);
4
4
 
5
5
  // Import configuration and libraries
6
6
  importScripts('extension-config.js');
@@ -93,7 +93,7 @@ async function checkUsageBeforeRecording() {
93
93
  async function incrementUsageAfterRecording() {
94
94
  // PRO version: skip tracking
95
95
  if (isProVersion()) {
96
- console.log('[Usage] PRO version - skipping usage tracking');
96
+ // console.log('[Usage] PRO version - skipping usage tracking');
97
97
  return { success: true, count: 0, limit: Infinity, isPro: true };
98
98
  }
99
99
 
@@ -108,7 +108,7 @@ async function incrementUsageAfterRecording() {
108
108
  [USAGE_STORAGE_KEY]: { count: newCount, date: today }
109
109
  });
110
110
 
111
- console.log(`[Usage] Recording tracked: ${newCount}/${FREE_TIER_DAILY_LIMIT} today`);
111
+ // console.log(`[Usage] Recording tracked: ${newCount}/${FREE_TIER_DAILY_LIMIT} today`);
112
112
 
113
113
  return { success: true, count: newCount, limit: FREE_TIER_DAILY_LIMIT };
114
114
  }
@@ -154,7 +154,7 @@ class LogStreamer {
154
154
  async init() {
155
155
  // Skip initialization in browser-only mode
156
156
  if (serverMode === 'browser-only') {
157
- console.log('[LogStreamer] Skipping initialization - browser-only mode');
157
+ // console.log('[LogStreamer] Skipping initialization - browser-only mode');
158
158
  return;
159
159
  }
160
160
 
@@ -164,7 +164,7 @@ class LogStreamer {
164
164
  // Start periodic streaming
165
165
  this.startPeriodicStreaming();
166
166
 
167
- console.log('[LogStreamer] Initialized with server availability:', this.serverAvailable);
167
+ // console.log('[LogStreamer] Initialized with server availability:', this.serverAvailable);
168
168
  }
169
169
 
170
170
  async checkServerAvailability() {
@@ -176,7 +176,7 @@ class LogStreamer {
176
176
  });
177
177
  if (response.ok) {
178
178
  this.serverAvailable = true;
179
- console.log(`[LogStreamer] Server available on port ${port}`);
179
+ // console.log(`[LogStreamer] Server available on port ${port}`);
180
180
  return;
181
181
  }
182
182
  } catch (error) {
@@ -184,7 +184,7 @@ class LogStreamer {
184
184
  }
185
185
  }
186
186
  this.serverAvailable = false;
187
- console.log('[LogStreamer] No server available');
187
+ // console.log('[LogStreamer] No server available');
188
188
  }
189
189
 
190
190
  startPeriodicStreaming() {
@@ -227,7 +227,7 @@ class LogStreamer {
227
227
  // This gives frames time to be processed before logs are associated
228
228
  const timeSinceLastFrame = Date.now() - this.lastFrameCapture;
229
229
  if (this.lastFrameCapture > 0 && timeSinceLastFrame < 100) {
230
- console.log('[LogStreamer] Waiting for frame processing before streaming logs');
230
+ // console.log('[LogStreamer] Waiting for frame processing before streaming logs');
231
231
  return; // Wait for next cycle
232
232
  }
233
233
 
@@ -256,7 +256,7 @@ class LogStreamer {
256
256
  // Method to notify LogStreamer when frame is captured
257
257
  notifyFrameCapture() {
258
258
  this.lastFrameCapture = Date.now();
259
- console.log('[LogStreamer] Frame capture notification received');
259
+ // console.log('[LogStreamer] Frame capture notification received');
260
260
  }
261
261
 
262
262
  async sendToServer(batch) {
@@ -280,7 +280,7 @@ class LogStreamer {
280
280
  const result = await response.json();
281
281
  // Only log if we had to try multiple ports (first port failed)
282
282
  if (port !== this.serverPorts[0]) {
283
- console.log(`[LogStreamer] Connected to server on port ${port}`);
283
+ // console.log(`[LogStreamer] Connected to server on port ${port}`);
284
284
  }
285
285
  return result;
286
286
  }
@@ -331,7 +331,7 @@ class LogStreamer {
331
331
  if (now >= item.nextRetry && item.attempts < 3) {
332
332
  try {
333
333
  await this.sendToServer(item.batch);
334
- console.log(`[LogStreamer] Retry successful for batch with ${item.batch.length} logs`);
334
+ // console.log(`[LogStreamer] Retry successful for batch with ${item.batch.length} logs`);
335
335
  } catch (error) {
336
336
  item.attempts++;
337
337
  item.nextRetry = now + (1000 * Math.pow(2, item.attempts)); // Exponential backoff
@@ -389,7 +389,7 @@ class LogBuffer {
389
389
  // Flush all buffers to Chrome storage
390
390
  async flushAll() {
391
391
  if (this.flushInProgress) {
392
- console.log('[LogBuffer] Flush already in progress, waiting for completion...');
392
+ // console.log('[LogBuffer] Flush already in progress, waiting for completion...');
393
393
  // Wait for current flush to complete instead of skipping
394
394
  while (this.flushInProgress) {
395
395
  await new Promise(resolve => setTimeout(resolve, 10));
@@ -402,7 +402,7 @@ class LogBuffer {
402
402
  const startTime = Date.now();
403
403
 
404
404
  try {
405
- console.log(`[LogBuffer] Starting flushAll for ${this.tabBuffers.size} tabs`);
405
+ // console.log(`[LogBuffer] Starting flushAll for ${this.tabBuffers.size} tabs`);
406
406
 
407
407
  for (const [tabId, tabBuffer] of this.tabBuffers) {
408
408
  flushPromises.push(tabBuffer.flush());
@@ -410,7 +410,7 @@ class LogBuffer {
410
410
 
411
411
  await Promise.all(flushPromises);
412
412
  const duration = Date.now() - startTime;
413
- console.log(`[LogBuffer] Successfully flushed all buffers for ${this.tabBuffers.size} tabs in ${duration}ms`);
413
+ // console.log(`[LogBuffer] Successfully flushed all buffers for ${this.tabBuffers.size} tabs in ${duration}ms`);
414
414
  } catch (error) {
415
415
  console.error('[LogBuffer] Error during flush operation:', error);
416
416
  throw error; // Re-throw to ensure proper error handling upstream
@@ -431,7 +431,7 @@ class LogBuffer {
431
431
  clearTab(tabId) {
432
432
  if (this.tabBuffers.has(tabId)) {
433
433
  this.tabBuffers.delete(tabId);
434
- console.log(`[LogBuffer] Cleared buffer for tab ${tabId}`);
434
+ // console.log(`[LogBuffer] Cleared buffer for tab ${tabId}`);
435
435
  }
436
436
  }
437
437
 
@@ -457,7 +457,7 @@ class LogBuffer {
457
457
  // Debug method to log current buffer state
458
458
  logStats() {
459
459
  const stats = this.getStats();
460
- console.log('[LogBuffer] Current statistics:', stats);
460
+ // console.log('[LogBuffer] Current statistics:', stats);
461
461
  return stats;
462
462
  }
463
463
  }
@@ -572,7 +572,7 @@ class LogTabBuffer {
572
572
  }
573
573
 
574
574
  this.totalLogsFlushed += this.buffer.length;
575
- console.log(`[LogBuffer] Flushed ${this.buffer.length} logs for tab ${this.tabId} (total: ${this.totalLogsFlushed})`);
575
+ // console.log(`[LogBuffer] Flushed ${this.buffer.length} logs for tab ${this.tabId} (total: ${this.totalLogsFlushed})`);
576
576
 
577
577
  // Clear the buffer
578
578
  this.buffer = [];
@@ -715,7 +715,7 @@ class WorkflowLogBuffer {
715
715
  }
716
716
 
717
717
  this.totalLogsFlushed += this.buffer.length;
718
- console.log(`[WorkflowLogBuffer] Flushed ${this.buffer.length} logs for tab ${this.tabId} (total: ${this.totalLogsFlushed})`);
718
+ // console.log(`[WorkflowLogBuffer] Flushed ${this.buffer.length} logs for tab ${this.tabId} (total: ${this.totalLogsFlushed})`);
719
719
 
720
720
  // Clear the buffer
721
721
  this.buffer = [];
@@ -746,7 +746,7 @@ class WorkflowLogBuffer {
746
746
  if (this.buffer.length > 0) {
747
747
  await this.performFlush();
748
748
  }
749
- console.log(`[WorkflowLogBuffer] Cleaned up buffer for tab ${this.tabId}`);
749
+ // console.log(`[WorkflowLogBuffer] Cleaned up buffer for tab ${this.tabId}`);
750
750
  } catch (error) {
751
751
  console.error(`[WorkflowLogBuffer] Error during cleanup for tab ${this.tabId}:`, error);
752
752
  }
@@ -809,10 +809,10 @@ const DATA_PROTECTION_TIERS = {
809
809
  async function initializeServices() {
810
810
  try {
811
811
  // FIRST: Initialize comprehensive error handling system
812
- console.log('[Background] Initializing comprehensive error handling...');
812
+ // console.log('[Background] Initializing comprehensive error handling...');
813
813
  const errorHandlingSuccess = await initializeErrorHandling();
814
814
  if (errorHandlingSuccess) {
815
- console.log('[Background] Comprehensive error handling initialized successfully');
815
+ // console.log('[Background] Comprehensive error handling initialized successfully');
816
816
  } else {
817
817
  console.warn('[Background] Error handling initialization failed - continuing with basic functionality');
818
818
  }
@@ -820,16 +820,16 @@ async function initializeServices() {
820
820
  // Initialize the data buffer
821
821
  dataBuffer = new DataBuffer();
822
822
  await dataBuffer.init();
823
- console.log('[Background] Data buffer initialized');
823
+ // console.log('[Background] Data buffer initialized');
824
824
 
825
825
  // Only create upload manager if data buffer initialized successfully
826
826
  try {
827
827
  uploadManager = new UploadManager(dataBuffer);
828
828
  const serverAvailable = await uploadManager.init();
829
829
  if (serverAvailable) {
830
- console.log('[Background] Upload manager initialized with server');
830
+ // console.log('[Background] Upload manager initialized with server');
831
831
  } else {
832
- console.log('[Background] Upload manager initialized but no server available yet');
832
+ // console.log('[Background] Upload manager initialized but no server available yet');
833
833
  }
834
834
  } catch (uploadErr) {
835
835
  console.error('[Background] Failed to initialize upload manager:', uploadErr);
@@ -841,7 +841,7 @@ async function initializeServices() {
841
841
  try {
842
842
  logStreamer = new LogStreamer();
843
843
  await logStreamer.init();
844
- console.log('[Background] Log streamer initialized');
844
+ // console.log('[Background] Log streamer initialized');
845
845
  } catch (streamErr) {
846
846
  console.error('[Background] Failed to initialize log streamer:', streamErr);
847
847
  logStreamer = null;
@@ -850,7 +850,7 @@ async function initializeServices() {
850
850
  // Initialize log buffer for race-condition-free storage
851
851
  try {
852
852
  logBuffer = new LogBuffer();
853
- console.log('[Background] Log buffer initialized');
853
+ // console.log('[Background] Log buffer initialized');
854
854
  } catch (bufferErr) {
855
855
  console.error('[Background] Failed to initialize log buffer:', bufferErr);
856
856
  logBuffer = null;
@@ -859,7 +859,7 @@ async function initializeServices() {
859
859
  // Initialize browser recording manager for browser-only mode
860
860
  try {
861
861
  browserRecordingManager = new BrowserRecordingManager(dataBuffer);
862
- console.log('[Background] Browser recording manager initialized');
862
+ // console.log('[Background] Browser recording manager initialized');
863
863
  } catch (recordingErr) {
864
864
  console.error('[Background] Failed to initialize browser recording manager:', recordingErr);
865
865
  browserRecordingManager = null;
@@ -869,12 +869,12 @@ async function initializeServices() {
869
869
  try {
870
870
  if (!sessionManager) {
871
871
  sessionManager = new ChromeExtensionSessionManager();
872
- console.log('[Background] Session manager initialized');
872
+ // console.log('[Background] Session manager initialized');
873
873
  }
874
874
 
875
875
  // Recover any stuck sessions on startup
876
876
  await sessionManager.recoverSessions();
877
- console.log('[Background] Session recovery completed');
877
+ // console.log('[Background] Session recovery completed');
878
878
  } catch (sessionErr) {
879
879
  console.error('[Background] Failed to initialize session manager:', sessionErr);
880
880
  // Session manager critical for recording - but don't fail completely
@@ -1012,12 +1012,12 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
1012
1012
  }));
1013
1013
 
1014
1014
  dataBuffer.addBatch(eventsWithRecordingId).then(() => {
1015
- console.log(`[Background] Added ${eventsWithRecordingId.length} events to buffer for recording ${message.recordingId}`);
1015
+ // console.log(`[Background] Added ${eventsWithRecordingId.length} events to buffer for recording ${message.recordingId}`);
1016
1016
  // Create a batch if we have enough events
1017
1017
  return dataBuffer.createBatch(message.recordingId);
1018
1018
  }).then(batch => {
1019
1019
  if (batch) {
1020
- console.log(`[Background] Created batch ${batch.id} with ${batch.events.length} events`);
1020
+ // console.log(`[Background] Created batch ${batch.id} with ${batch.events.length} events`);
1021
1021
  // Process upload queue if upload manager is available
1022
1022
  if (uploadManager) {
1023
1023
  uploadManager.processUploadQueue();
@@ -1086,7 +1086,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
1086
1086
  sessionId: message.sessionId
1087
1087
  }).catch(() => {
1088
1088
  // Content script might not be available
1089
- console.log('[Background] Could not forward start-screen-capture-tracking to content script');
1089
+ // console.log('[Background] Could not forward start-screen-capture-tracking to content script');
1090
1090
  });
1091
1091
  }
1092
1092
  sendResponse({ success: true });
@@ -1098,7 +1098,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
1098
1098
  chrome.tabs.sendMessage(sender.tab.id, {
1099
1099
  type: 'stop-screen-capture-tracking'
1100
1100
  }).catch(() => {
1101
- console.log('[Background] Could not forward stop-screen-capture-tracking to content script');
1101
+ // console.log('[Background] Could not forward stop-screen-capture-tracking to content script');
1102
1102
  });
1103
1103
  }
1104
1104
  sendResponse({ success: true });
@@ -1128,7 +1128,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
1128
1128
  frameIndex: frameIndex
1129
1129
  };
1130
1130
  screenInteractions.push(interaction);
1131
- console.log('[Background] Visual feedback interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
1131
+ // console.log('[Background] Visual feedback interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
1132
1132
  }
1133
1133
  }).catch(error => {
1134
1134
  console.error('Error validating recording state for interaction:', error);
@@ -1141,7 +1141,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
1141
1141
  frameIndex: frameCounter.get(currentRecordingSessionId) || 0
1142
1142
  };
1143
1143
  screenInteractions.push(interaction);
1144
- console.log('[Background] Visual feedback interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
1144
+ // console.log('[Background] Visual feedback interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
1145
1145
  }
1146
1146
  }
1147
1147
  }
@@ -1154,7 +1154,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
1154
1154
  chrome.tabs.sendMessage(sender.tab.id, {
1155
1155
  type: 'screen-capture-frame-captured'
1156
1156
  }).catch(() => {
1157
- console.log('[Background] Could not forward frame flash to content script');
1157
+ // console.log('[Background] Could not forward frame flash to content script');
1158
1158
  });
1159
1159
  }
1160
1160
  // Don't send response to avoid warnings
@@ -1165,7 +1165,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
1165
1165
  if (logBuffer && sender.tab) {
1166
1166
  const tabId = sender.tab.id;
1167
1167
  const testLogsCount = message.count || 1000;
1168
- console.log(`[Background] Starting LogBuffer race condition test with ${testLogsCount} logs for tab ${tabId}`);
1168
+ // console.log(`[Background] Starting LogBuffer race condition test with ${testLogsCount} logs for tab ${tabId}`);
1169
1169
 
1170
1170
  // Simulate rapid log generation like a real high-volume scenario
1171
1171
  const startTime = Date.now();
@@ -1188,8 +1188,8 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
1188
1188
  Promise.all(logPromises).then(() => {
1189
1189
  const endTime = Date.now();
1190
1190
  const stats = logBuffer.getStats();
1191
- console.log(`[Background] LogBuffer test completed in ${endTime - startTime}ms`);
1192
- console.log(`[Background] Test results:`, stats);
1191
+ // console.log(`[Background] LogBuffer test completed in ${endTime - startTime}ms`);
1192
+ // console.log(`[Background] Test results:`, stats);
1193
1193
 
1194
1194
  sendResponse({
1195
1195
  success: true,
@@ -1219,7 +1219,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
1219
1219
  // DEBUG: Get current LogBuffer statistics
1220
1220
  if (logBuffer) {
1221
1221
  const stats = logBuffer.getStats();
1222
- console.log('[Background] LogBuffer stats requested:', stats);
1222
+ // console.log('[Background] LogBuffer stats requested:', stats);
1223
1223
  sendResponse({
1224
1224
  success: true,
1225
1225
  stats: stats
@@ -1234,10 +1234,10 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
1234
1234
 
1235
1235
  case 'getBrowserRecordings':
1236
1236
  // Get all browser-only recordings from IndexedDB
1237
- console.log('[Background] getBrowserRecordings - Manager exists:', !!browserRecordingManager);
1237
+ // console.log('[Background] getBrowserRecordings - Manager exists:', !!browserRecordingManager);
1238
1238
  if (browserRecordingManager) {
1239
1239
  browserRecordingManager.listRecordings().then(recordings => {
1240
- console.log('[Background] Recordings retrieved from manager:', recordings);
1240
+ // console.log('[Background] Recordings retrieved from manager:', recordings);
1241
1241
  sendResponse(recordings);
1242
1242
  }).catch(error => {
1243
1243
  console.error('[Background] Failed to get browser recordings:', error);
@@ -1284,7 +1284,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
1284
1284
  // Get frames for a browser-only recording
1285
1285
  if (dataBuffer && message.sessionId) {
1286
1286
  dataBuffer.getBrowserFrames(message.sessionId).then(frames => {
1287
- console.log(`[DEBUG] getBrowserRecordingFrames: Retrieved ${frames.length} frames from IndexedDB`);
1287
+ // console.log(`[DEBUG] getBrowserRecordingFrames: Retrieved ${frames.length} frames from IndexedDB`);
1288
1288
 
1289
1289
  // Debug first frame to see structure
1290
1290
  if (frames.length > 0) {
@@ -1298,7 +1298,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
1298
1298
  frameIndex: firstFrame.frameIndex,
1299
1299
  allKeys: Object.keys(firstFrame)
1300
1300
  };
1301
- console.log('[DEBUG] First frame structure:', JSON.stringify(debugInfo, null, 2));
1301
+ // console.log('[DEBUG] First frame structure:', JSON.stringify(debugInfo, null, 2));
1302
1302
  }
1303
1303
 
1304
1304
  // Transform frames to match frame editor's expected structure
@@ -1315,7 +1315,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
1315
1315
  logsCount: transformedFrames[0].logs ? transformedFrames[0].logs.length : 0,
1316
1316
  allKeys: Object.keys(transformedFrames[0])
1317
1317
  } : 'No frames';
1318
- console.log('[DEBUG] Transformed first frame:', JSON.stringify(transformDebug, null, 2));
1318
+ // console.log('[DEBUG] Transformed first frame:', JSON.stringify(transformDebug, null, 2));
1319
1319
 
1320
1320
  sendResponse({ success: true, frames: transformedFrames });
1321
1321
  }).catch(error => {
@@ -1341,7 +1341,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
1341
1341
  default:
1342
1342
  // Don't warn or respond for messages that should be handled by other listener (v2.0.6)
1343
1343
  // This prevents intercepting workflow recording messages
1344
- console.log('[Background v2.0.6] Message not handled by this listener:', messageType);
1344
+ // console.log('[Background v2.0.6] Message not handled by this listener:', messageType);
1345
1345
  // Don't send response - let other listener handle it
1346
1346
  return;
1347
1347
  }
@@ -1351,13 +1351,13 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
1351
1351
 
1352
1352
  // Session recovery on startup - handle any stuck recordings from previous session
1353
1353
  chrome.runtime.onStartup.addListener(async () => {
1354
- console.log('[Background] Extension startup detected - checking for stuck sessions');
1354
+ // console.log('[Background] Extension startup detected - checking for stuck sessions');
1355
1355
 
1356
1356
  if (sessionManager) {
1357
1357
  try {
1358
1358
  // Use existing recovery method from session manager
1359
1359
  await sessionManager.recoverSessions();
1360
- console.log('[Background] Startup session recovery completed');
1360
+ // console.log('[Background] Startup session recovery completed');
1361
1361
  } catch (error) {
1362
1362
  console.error('[Background] Failed to recover sessions on startup:', error);
1363
1363
  }
@@ -1368,19 +1368,33 @@ chrome.runtime.onStartup.addListener(async () => {
1368
1368
 
1369
1369
  // Extension install/update
1370
1370
  chrome.runtime.onInstalled.addListener(async (details) => {
1371
- console.log('[Background] Extension installed/updated:', details.reason);
1371
+ // console.log('[Background] Extension installed/updated:', details.reason);
1372
1372
  });
1373
1373
 
1374
1374
  // Listen for tab updates to handle restore points
1375
1375
  chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
1376
1376
  // Inject console logging on navigation during recording
1377
1377
  if (changeInfo.status === 'loading') {
1378
- // Use session manager validation if available
1378
+ // Skip restricted URLs
1379
+ if (!tab.url || tab.url.startsWith('chrome://') || tab.url.startsWith('chrome-extension://')) {
1380
+ return;
1381
+ }
1382
+
1383
+ // Check for WORKFLOW recording first (takes priority)
1384
+ if (workflowRecordingTabs.has(tabId) && workflowIncludeLogs.get(tabId)) {
1385
+ // console.log('[Navigation] Re-injecting workflow console logging for tab:', tabId);
1386
+ self.ConsoleInterceptionLibrary.startConsoleInterception(tabId, WORKFLOW_RECORDING_CONSOLE_CONFIG).catch(err => {
1387
+ console.error('Failed to re-inject workflow console logging:', err);
1388
+ });
1389
+ return; // Don't also inject screen recording logs
1390
+ }
1391
+
1392
+ // Check for SCREEN recording
1379
1393
  if (sessionManager) {
1380
1394
  isCurrentlyRecordingAsync().then(async (recording) => {
1381
1395
  const currentTabId = await getCurrentTabIdAsync();
1382
- if (recording && tabId === currentTabId && tab.url && !tab.url.startsWith('chrome://') && !tab.url.startsWith('chrome-extension://')) {
1383
- console.log('Re-injecting console logging for navigation during recording');
1396
+ if (recording && tabId === currentTabId) {
1397
+ // console.log('[Navigation] Re-injecting screen recording console logging for tab:', tabId);
1384
1398
  startCapturingLogs(tabId).catch(err => {
1385
1399
  console.error('Failed to re-inject console logging:', err);
1386
1400
  });
@@ -1389,9 +1403,9 @@ chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
1389
1403
  console.error('Error checking recording state for navigation:', error);
1390
1404
  });
1391
1405
  } else {
1392
- // Legacy fallback
1393
- if (tabId === recordingTabId && isCurrentlyRecording && tab.url && !tab.url.startsWith('chrome://') && !tab.url.startsWith('chrome-extension://')) {
1394
- console.log('Re-injecting console logging for navigation during recording');
1406
+ // Legacy fallback for screen recording
1407
+ if (tabId === recordingTabId && isCurrentlyRecording) {
1408
+ // console.log('[Navigation] Re-injecting screen recording console logging (legacy) for tab:', tabId);
1395
1409
  startCapturingLogs(tabId).catch(err => {
1396
1410
  console.error('Failed to re-inject console logging:', err);
1397
1411
  });
@@ -1470,7 +1484,7 @@ chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
1470
1484
  chrome.tabs.onRemoved.addListener((tabId, removeInfo) => {
1471
1485
  // Clean up any workflow recording state for closed tabs
1472
1486
  if (workflowRecordingTabs.has(tabId)) {
1473
- console.log(`[Workflow] Tab ${tabId} closed during recording, cleaning up`);
1487
+ // console.log(`[Workflow] Tab ${tabId} closed during recording, cleaning up`);
1474
1488
  workflowRecordingTabs.delete(tabId);
1475
1489
  workflowIncludeLogs.delete(tabId);
1476
1490
  workflowScreenshotSettings.delete(tabId);
@@ -1481,7 +1495,7 @@ chrome.tabs.onRemoved.addListener((tabId, removeInfo) => {
1481
1495
  if (buffer) {
1482
1496
  buffer.cleanup().then(() => {
1483
1497
  workflowLogBuffers.delete(tabId);
1484
- console.log(`[Workflow] Cleaned up WorkflowLogBuffer for closed tab ${tabId}`);
1498
+ // console.log(`[Workflow] Cleaned up WorkflowLogBuffer for closed tab ${tabId}`);
1485
1499
  }).catch(err => {
1486
1500
  console.error(`[Workflow] Error cleaning up buffer for closed tab ${tabId}:`, err);
1487
1501
  workflowLogBuffers.delete(tabId);
@@ -1519,11 +1533,148 @@ let isCurrentlyRecording = false; // DEPRECATED: Use isCurrentlyRecordingAsync()
1519
1533
  let currentRecordingSessionId = null; // DEPRECATED: Use getCurrentSessionIdAsync() instead
1520
1534
  let frameCounter = new Map(); // DEPRECATED: Session manager handles frame counting
1521
1535
 
1536
+ // =============================================================================
1537
+ // INACTIVITY AUTO-STOP - Stop recording if user is inactive
1538
+ // =============================================================================
1539
+ const DEFAULT_INACTIVITY_TIMEOUT_MS = 60 * 1000; // 60 seconds default (1 minute)
1540
+ let lastUserActivityTime = Date.now();
1541
+ let inactivityCheckInterval = null;
1542
+ let currentInactivityTimeout = DEFAULT_INACTIVITY_TIMEOUT_MS;
1543
+ let inactivityMonitoringStarted = false; // Track if monitoring has started
1544
+ let inactivityFallbackTimer = null; // Fallback timer if countdownComplete not received
1545
+ let inactivityDisabled = false; // User can disable for current session
1546
+
1547
+ /**
1548
+ * Start inactivity monitoring for a recording
1549
+ * @param {number} tabId - Tab ID to monitor
1550
+ */
1551
+ async function startInactivityMonitoring(tabId) {
1552
+ // Mark as started (for fallback timer check)
1553
+ inactivityMonitoringStarted = true;
1554
+
1555
+ // Clear fallback timer since we're starting properly
1556
+ if (inactivityFallbackTimer) {
1557
+ clearTimeout(inactivityFallbackTimer);
1558
+ inactivityFallbackTimer = null;
1559
+ }
1560
+
1561
+ // Load user's configured timeout from storage
1562
+ const settings = await chrome.storage.sync.get(['inactivityTimeout']);
1563
+ currentInactivityTimeout = (settings.inactivityTimeout || 60) * 1000; // Convert seconds to ms (default 60s)
1564
+
1565
+ lastUserActivityTime = Date.now();
1566
+
1567
+ // Tell content script to start tracking activity AND send config for countdown display
1568
+ try {
1569
+ await chrome.tabs.sendMessage(tabId, {
1570
+ action: 'startActivityTracking',
1571
+ inactivityTimeoutMs: currentInactivityTimeout,
1572
+ disabled: inactivityDisabled
1573
+ });
1574
+ } catch (error) {
1575
+ console.warn('[Inactivity] Could not start activity tracking in content script:', error.message);
1576
+ }
1577
+
1578
+ // Clear any existing interval
1579
+ if (inactivityCheckInterval) {
1580
+ clearInterval(inactivityCheckInterval);
1581
+ }
1582
+
1583
+ // If disabled, don't start the check interval
1584
+ if (inactivityDisabled) {
1585
+ return;
1586
+ }
1587
+
1588
+ // Check for inactivity every 2 seconds
1589
+ inactivityCheckInterval = setInterval(async () => {
1590
+ // Skip if disabled
1591
+ if (inactivityDisabled) return;
1592
+
1593
+ const timeSinceActivity = Date.now() - lastUserActivityTime;
1594
+ const timeRemaining = Math.max(0, currentInactivityTimeout - timeSinceActivity);
1595
+
1596
+ // Send countdown update to content script
1597
+ try {
1598
+ await chrome.tabs.sendMessage(tabId, {
1599
+ action: 'updateInactivityCountdown',
1600
+ timeRemaining: Math.ceil(timeRemaining / 1000),
1601
+ disabled: inactivityDisabled
1602
+ });
1603
+ } catch (e) {
1604
+ // Tab might be closed, ignore
1605
+ }
1606
+
1607
+ if (timeSinceActivity >= currentInactivityTimeout) {
1608
+ // Stop the recording first
1609
+ await stopRecording();
1610
+
1611
+ // Show notification with link to settings
1612
+ try {
1613
+ await chrome.notifications.create('inactivity-stop', {
1614
+ type: 'basic',
1615
+ iconUrl: 'icon128.png',
1616
+ title: 'Recording Auto-Stopped',
1617
+ message: `Recording stopped after ${Math.round(currentInactivityTimeout / 1000)}s of inactivity. Click to adjust timeout in Settings.`,
1618
+ priority: 2
1619
+ });
1620
+ } catch (e) {
1621
+ console.warn('[Inactivity] Could not show notification:', e.message);
1622
+ }
1623
+ }
1624
+ }, 2000); // Check every 2 seconds
1625
+ }
1626
+
1627
+ /**
1628
+ * Stop inactivity monitoring
1629
+ * @param {number} tabId - Tab ID that was being monitored
1630
+ */
1631
+ async function stopInactivityMonitoring(tabId) {
1632
+ if (inactivityCheckInterval) {
1633
+ clearInterval(inactivityCheckInterval);
1634
+ inactivityCheckInterval = null;
1635
+ }
1636
+
1637
+ // Clear fallback timer
1638
+ if (inactivityFallbackTimer) {
1639
+ clearTimeout(inactivityFallbackTimer);
1640
+ inactivityFallbackTimer = null;
1641
+ }
1642
+
1643
+ // Reset state for next recording
1644
+ inactivityMonitoringStarted = false;
1645
+ inactivityDisabled = false; // Reset disabled state for next session
1646
+
1647
+ // Tell content script to stop tracking
1648
+ if (tabId) {
1649
+ try {
1650
+ await chrome.tabs.sendMessage(tabId, { action: 'stopActivityTracking' });
1651
+ } catch (error) {
1652
+ // Tab might be closed, that's ok
1653
+ }
1654
+ }
1655
+ }
1656
+
1657
+ /**
1658
+ * Handle user activity report from content script
1659
+ * @param {number} timestamp - Activity timestamp
1660
+ */
1661
+ function handleUserActivity(timestamp) {
1662
+ lastUserActivityTime = timestamp || Date.now();
1663
+ }
1664
+
1665
+ // Handle notification clicks - open settings page when inactivity notification is clicked
1666
+ chrome.notifications.onClicked.addListener((notificationId) => {
1667
+ if (notificationId === 'inactivity-stop') {
1668
+ chrome.runtime.openOptionsPage();
1669
+ chrome.notifications.clear(notificationId);
1670
+ }
1671
+ });
1672
+
1522
1673
  // Initialize session manager
1523
1674
  (async function initializeSessionManager() {
1524
1675
  try {
1525
1676
  sessionManager = new ChromeExtensionSessionManager();
1526
- console.log('[ChromeSessionManager] Initialized successfully');
1677
+ // console.log('[ChromeSessionManager] Initialized successfully');
1527
1678
  } catch (error) {
1528
1679
  console.error('[ChromeSessionManager] Failed to initialize:', error);
1529
1680
  }
@@ -1659,7 +1810,7 @@ let workflowLogBuffers = new Map(); // Map of tabId to WorkflowLogBuffer instanc
1659
1810
  */
1660
1811
  async function initializeErrorHandling() {
1661
1812
  try {
1662
- console.log('[ErrorHandling] Initializing comprehensive error handling system...');
1813
+ // console.log('[ErrorHandling] Initializing comprehensive error handling system...');
1663
1814
 
1664
1815
  // Generate session ID if not exists
1665
1816
  if (!errorHandlingState.sessionId) {
@@ -1682,11 +1833,11 @@ async function initializeErrorHandling() {
1682
1833
  errorHandlingState.isInitialized = true;
1683
1834
  errorHandlingState.currentState = 'NORMAL_OPERATION';
1684
1835
 
1685
- console.log('[ErrorHandling] System initialization complete:', {
1686
- sessionId: errorHandlingState.sessionId,
1687
- state: errorHandlingState.currentState,
1688
- circuitBreaker: errorHandlingState.circuitBreakerState
1689
- });
1836
+ // console.log('[ErrorHandling] System initialization complete:', {
1837
+ // sessionId: errorHandlingState.sessionId,
1838
+ // state: errorHandlingState.currentState,
1839
+ // circuitBreaker: errorHandlingState.circuitBreakerState
1840
+ // });
1690
1841
 
1691
1842
  return true;
1692
1843
  } catch (error) {
@@ -1711,7 +1862,7 @@ async function initializeBackupStorage() {
1711
1862
  };
1712
1863
 
1713
1864
  request.onsuccess = () => {
1714
- console.log('[ErrorHandling] IndexedDB initialized successfully');
1865
+ // console.log('[ErrorHandling] IndexedDB initialized successfully');
1715
1866
  resolve(request.result);
1716
1867
  };
1717
1868
 
@@ -1741,7 +1892,7 @@ async function initializeBackupStorage() {
1741
1892
  errorStore.createIndex('timestamp', 'timestamp', { unique: false });
1742
1893
  }
1743
1894
 
1744
- console.log('[ErrorHandling] IndexedDB schema created');
1895
+ // console.log('[ErrorHandling] IndexedDB schema created');
1745
1896
  };
1746
1897
  });
1747
1898
  }
@@ -1752,7 +1903,7 @@ async function initializeBackupStorage() {
1752
1903
  function initializeCircuitBreaker() {
1753
1904
  errorHandlingState.circuitBreakerState = 'CLOSED';
1754
1905
  errorHandlingState.failedSaveCount = 0;
1755
- console.log('[ErrorHandling] Circuit breaker initialized in CLOSED state');
1906
+ // console.log('[ErrorHandling] Circuit breaker initialized in CLOSED state');
1756
1907
  }
1757
1908
 
1758
1909
  /**
@@ -1765,7 +1916,7 @@ async function setupNotificationSystem() {
1765
1916
  await chrome.notifications.clear(notificationId);
1766
1917
  }
1767
1918
 
1768
- console.log('[ErrorHandling] Notification system ready');
1919
+ // console.log('[ErrorHandling] Notification system ready');
1769
1920
  }
1770
1921
 
1771
1922
  /**
@@ -1804,7 +1955,7 @@ async function cleanupOldBackups() {
1804
1955
  }
1805
1956
  };
1806
1957
 
1807
- console.log('[ErrorHandling] Cleanup completed for data older than', ERROR_HANDLING_CONFIG.backupRetentionDays, 'days');
1958
+ // console.log('[ErrorHandling] Cleanup completed for data older than', ERROR_HANDLING_CONFIG.backupRetentionDays, 'days');
1808
1959
  };
1809
1960
  } catch (error) {
1810
1961
  console.error('[ErrorHandling] Failed to cleanup old backups:', error);
@@ -1831,13 +1982,13 @@ async function handleSaveAttempt(saveFunction, data, context = {}) {
1831
1982
  if (errorHandlingState.circuitBreakerState === 'OPEN') {
1832
1983
  const timeSinceLastFailure = Date.now() - (errorHandlingState.lastError?.timestamp || 0);
1833
1984
  if (timeSinceLastFailure < ERROR_HANDLING_CONFIG.resetTimeout) {
1834
- console.log('[ErrorHandling] Circuit breaker OPEN, attempting backup instead');
1985
+ // console.log('[ErrorHandling] Circuit breaker OPEN, attempting backup instead');
1835
1986
  await backupFailedData(data, context);
1836
1987
  return { success: false, circuitBreakerOpen: true };
1837
1988
  } else {
1838
1989
  // Try half-open
1839
1990
  errorHandlingState.circuitBreakerState = 'HALF_OPEN';
1840
- console.log('[ErrorHandling] Circuit breaker moving to HALF_OPEN state');
1991
+ // console.log('[ErrorHandling] Circuit breaker moving to HALF_OPEN state');
1841
1992
  }
1842
1993
  }
1843
1994
 
@@ -1848,7 +1999,7 @@ async function handleSaveAttempt(saveFunction, data, context = {}) {
1848
1999
  if (result && result.success !== false) {
1849
2000
  errorHandlingState.circuitBreakerState = 'CLOSED';
1850
2001
  errorHandlingState.failedSaveCount = 0;
1851
- console.log('[ErrorHandling] Save successful, circuit breaker CLOSED');
2002
+ // console.log('[ErrorHandling] Save successful, circuit breaker CLOSED');
1852
2003
  return { success: true, result };
1853
2004
  } else {
1854
2005
  throw new Error('Save function returned failure');
@@ -1888,7 +2039,7 @@ async function handleSaveFailure(error, data, context, attempt) {
1888
2039
  // Attempt backup
1889
2040
  try {
1890
2041
  await backupFailedData(data, context);
1891
- console.log('[ErrorHandling] Data backed up successfully');
2042
+ // console.log('[ErrorHandling] Data backed up successfully');
1892
2043
  } catch (backupError) {
1893
2044
  console.error('[ErrorHandling] CRITICAL: Backup also failed:', backupError);
1894
2045
  await createUserNotification('CRITICAL', 'Data loss imminent - manual intervention required');
@@ -1984,7 +2135,7 @@ async function backupFailedData(data, context) {
1984
2135
  const store = transaction.objectStore('sessionBackups');
1985
2136
 
1986
2137
  store.add(backupData);
1987
- console.log('[ErrorHandling] Data backed up with session ID:', errorHandlingState.sessionId);
2138
+ // console.log('[ErrorHandling] Data backed up with session ID:', errorHandlingState.sessionId);
1988
2139
  };
1989
2140
 
1990
2141
  // Also add to retained interactions if relevant
@@ -2025,7 +2176,7 @@ async function createUserNotification(priority, message) {
2025
2176
  }
2026
2177
 
2027
2178
  await chrome.notifications.create(notificationId, notificationOptions);
2028
- console.log('[ErrorHandling] User notification created:', notificationId);
2179
+ // console.log('[ErrorHandling] User notification created:', notificationId);
2029
2180
 
2030
2181
  // Set up notification click handlers
2031
2182
  chrome.notifications.onButtonClicked.addListener((notifId, buttonIndex) => {
@@ -2045,16 +2196,16 @@ async function createUserNotification(priority, message) {
2045
2196
  async function handleNotificationAction(buttonIndex, priority) {
2046
2197
  switch (buttonIndex) {
2047
2198
  case 0: // Retry Save
2048
- console.log('[ErrorHandling] User requested retry');
2199
+ // console.log('[ErrorHandling] User requested retry');
2049
2200
  await attemptRecovery();
2050
2201
  break;
2051
2202
  case 1: // View Details
2052
- console.log('[ErrorHandling] User requested error details');
2203
+ // console.log('[ErrorHandling] User requested error details');
2053
2204
  // Could open an options page or log details
2054
2205
  break;
2055
2206
  case 2: // Download Backup (for critical errors)
2056
2207
  if (priority === 'CRITICAL') {
2057
- console.log('[ErrorHandling] User requested backup download');
2208
+ // console.log('[ErrorHandling] User requested backup download');
2058
2209
  await downloadBackupData();
2059
2210
  }
2060
2211
  break;
@@ -2074,14 +2225,14 @@ async function attemptRecovery() {
2074
2225
 
2075
2226
  store.getAll().onsuccess = (event) => {
2076
2227
  const backups = event.target.result;
2077
- console.log('[ErrorHandling] Found', backups.length, 'backup records for recovery');
2228
+ // console.log('[ErrorHandling] Found', backups.length, 'backup records for recovery');
2078
2229
 
2079
2230
  // Process each backup
2080
2231
  backups.forEach(async (backup) => {
2081
2232
  try {
2082
2233
  // Attempt to save the backed up data
2083
2234
  // This would call the original save function with the backed up data
2084
- console.log('[ErrorHandling] Attempting recovery for session:', backup.sessionId);
2235
+ // console.log('[ErrorHandling] Attempting recovery for session:', backup.sessionId);
2085
2236
  } catch (error) {
2086
2237
  console.error('[ErrorHandling] Recovery failed for session:', backup.sessionId, error);
2087
2238
  }
@@ -2124,7 +2275,7 @@ async function downloadBackupData() {
2124
2275
  filename: `chrome-debug-backup-${Date.now()}.json`
2125
2276
  });
2126
2277
 
2127
- console.log('[ErrorHandling] Backup data download initiated');
2278
+ // console.log('[ErrorHandling] Backup data download initiated');
2128
2279
  };
2129
2280
  };
2130
2281
  };
@@ -2140,7 +2291,7 @@ async function createOffscreenDocument() {
2140
2291
  const hasDocument = await chrome.offscreen.hasDocument();
2141
2292
  if (hasDocument) {
2142
2293
  hasOffscreenDocument = true;
2143
- console.log('Offscreen document already exists');
2294
+ // console.log('Offscreen document already exists');
2144
2295
  return;
2145
2296
  }
2146
2297
 
@@ -2151,12 +2302,12 @@ async function createOffscreenDocument() {
2151
2302
  justification: 'Recording tab frames for Chrome Debug'
2152
2303
  });
2153
2304
  hasOffscreenDocument = true;
2154
- console.log('Created new offscreen document');
2305
+ // console.log('Created new offscreen document');
2155
2306
  } catch (error) {
2156
2307
  if (error.message.includes('Only a single offscreen document may be created')) {
2157
2308
  // Document already exists, just mark it as available
2158
2309
  hasOffscreenDocument = true;
2159
- console.log('Offscreen document already exists (caught error)');
2310
+ // console.log('Offscreen document already exists (caught error)');
2160
2311
  } else {
2161
2312
  throw error;
2162
2313
  }
@@ -2174,7 +2325,7 @@ async function closeOffscreenDocument() {
2174
2325
  }
2175
2326
 
2176
2327
  chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2177
- console.log('Received message:', request.action || request.type || 'unknown');
2328
+ // console.log('Received message:', request.action || request.type || 'unknown');
2178
2329
 
2179
2330
  if (request.action === 'sendToServer') {
2180
2331
  // Primary port is 3028 - try it first, then fallback to others if needed
@@ -2182,11 +2333,11 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2182
2333
 
2183
2334
  async function tryPorts() {
2184
2335
  let lastError = null;
2185
- console.log('Trying to connect to server...');
2336
+ // console.log('Trying to connect to server...');
2186
2337
 
2187
2338
  for (const port of ports) {
2188
2339
  try {
2189
- console.log(`Trying port ${port}...`);
2340
+ // console.log(`Trying port ${port}...`);
2190
2341
  const controller = new AbortController();
2191
2342
  const timeoutId = setTimeout(() => controller.abort(), DISCOVERY_TIMEOUT);
2192
2343
 
@@ -2203,7 +2354,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2203
2354
 
2204
2355
  if (response.ok) {
2205
2356
  const result = await response.json();
2206
- console.log(`Success on port ${port}:`, result);
2357
+ // console.log(`Success on port ${port}:`, result);
2207
2358
  sendResponse({ success: true, result, port });
2208
2359
  return;
2209
2360
  } else {
@@ -2211,7 +2362,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2211
2362
  try {
2212
2363
  const errorData = await response.json();
2213
2364
  if (errorData.message || errorData.error) {
2214
- console.log(`Port ${port} error:`, errorData);
2365
+ // console.log(`Port ${port} error:`, errorData);
2215
2366
  sendResponse({
2216
2367
  success: false,
2217
2368
  result: errorData,
@@ -2223,11 +2374,11 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2223
2374
  // Response wasn't JSON
2224
2375
  }
2225
2376
  lastError = `Port ${port}: HTTP ${response.status}`;
2226
- console.log(lastError);
2377
+ // console.log(lastError);
2227
2378
  }
2228
2379
  } catch (e) {
2229
2380
  lastError = `Port ${port}: ${e.message}`;
2230
- console.log(lastError);
2381
+ // console.log(lastError);
2231
2382
  }
2232
2383
  }
2233
2384
 
@@ -2305,7 +2456,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2305
2456
 
2306
2457
  // Session manager lease renewal handler
2307
2458
  if (request.action === 'renewLease') {
2308
- console.log('[Background] RENEW LEASE - Session:', request.sessionId, 'Manager exists:', !!sessionManager);
2459
+ // console.log('[Background] RENEW LEASE - Session:', request.sessionId, 'Manager exists:', !!sessionManager);
2309
2460
 
2310
2461
  if (!sessionManager) {
2311
2462
  console.error('[Background] Session manager not available');
@@ -2321,7 +2472,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2321
2472
  };
2322
2473
 
2323
2474
  sessionManager.renewLease(leaseRequest).then((result) => {
2324
- console.log('[Background] Lease renewed - Success:', result.success);
2475
+ // console.log('[Background] Lease renewed - Success:', result.success);
2325
2476
  sendResponse(result);
2326
2477
  }).catch((error) => {
2327
2478
  console.error('[Background] Error renewing lease:', error);
@@ -2355,6 +2506,45 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2355
2506
  return true;
2356
2507
  }
2357
2508
 
2509
+ // User activity handler for inactivity tracking
2510
+ if (request.action === 'userActivity') {
2511
+ handleUserActivity(request.timestamp);
2512
+ sendResponse({ success: true });
2513
+ return false; // Synchronous response
2514
+ }
2515
+
2516
+ // Countdown complete handler - content script finished 3-2-1 countdown
2517
+ if (request.action === 'countdownComplete') {
2518
+ // Start inactivity monitoring now that countdown is done
2519
+ // Use isCurrentlyRecording (the actual state variable)
2520
+ if (isCurrentlyRecording && recordingTabId && !inactivityMonitoringStarted) {
2521
+ startInactivityMonitoring(recordingTabId);
2522
+ }
2523
+ sendResponse({ success: true });
2524
+ return false;
2525
+ }
2526
+
2527
+ // Toggle inactivity timeout (user clicked disable/enable button)
2528
+ if (request.action === 'toggleInactivityTimeout') {
2529
+ inactivityDisabled = !inactivityDisabled;
2530
+
2531
+ if (inactivityDisabled) {
2532
+ // Stop the check interval but keep tracking activity
2533
+ if (inactivityCheckInterval) {
2534
+ clearInterval(inactivityCheckInterval);
2535
+ inactivityCheckInterval = null;
2536
+ }
2537
+ } else {
2538
+ // Restart monitoring
2539
+ if (recordingTabId && !inactivityCheckInterval) {
2540
+ startInactivityMonitoring(recordingTabId);
2541
+ }
2542
+ }
2543
+
2544
+ sendResponse({ success: true, disabled: inactivityDisabled });
2545
+ return false;
2546
+ }
2547
+
2358
2548
  // Force stop session handler (emergency)
2359
2549
  if (request.action === 'forceStopSession') {
2360
2550
  if (!sessionManager) {
@@ -2408,7 +2598,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2408
2598
  */
2409
2599
  /*
2410
2600
  if (request.action === 'takeStandaloneSnapshot') {
2411
- console.log('Taking standalone snapshot for tab:', request.tabId);
2601
+ // console.log('Taking standalone snapshot for tab:', request.tabId);
2412
2602
  takeStandaloneSnapshot(request.tabId, request.note).then((result) => {
2413
2603
  sendResponse({ success: true, sessionId: result.sessionId });
2414
2604
  }).catch((error) => {
@@ -2456,7 +2646,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2456
2646
  }
2457
2647
 
2458
2648
  if (request.action === 'startRecordingFromContent') {
2459
- console.log('Starting recording from content script');
2649
+ // console.log('Starting recording from content script');
2460
2650
  const tabId = sender.tab.id;
2461
2651
 
2462
2652
  // Store recording state and show notification
@@ -2480,14 +2670,14 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2480
2670
  }
2481
2671
 
2482
2672
  if (request.action === 'deleteRecording') {
2483
- console.log('Deleting recording:', request.recordingId);
2673
+ // console.log('Deleting recording:', request.recordingId);
2484
2674
  deleteRecordingFromServer(request.recordingId, sendResponse);
2485
2675
  return true;
2486
2676
  }
2487
2677
 
2488
2678
  // Workflow recording handlers
2489
2679
  if (request.action === 'startWorkflowRecording') {
2490
- console.log('Starting workflow recording for tab:', request.tabId);
2680
+ // console.log('Starting workflow recording for tab:', request.tabId);
2491
2681
  startWorkflowRecording(
2492
2682
  request.tabId,
2493
2683
  request.includeLogsInExport,
@@ -2504,7 +2694,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2504
2694
 
2505
2695
  if (request.action === 'stopWorkflowRecording') {
2506
2696
  const tabId = request.tabId || sender.tab?.id;
2507
- console.log('Stopping workflow recording for tab:', tabId);
2697
+ // console.log('Stopping workflow recording for tab:', tabId);
2508
2698
  // stopWorkflowRecording already returns { success: true, workflow: {...}, savedToServer: bool }
2509
2699
  // so we pass it through directly - don't double-wrap!
2510
2700
  stopWorkflowRecording(tabId).then(async (result) => {
@@ -2600,7 +2790,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2600
2790
  frameIndex: frameIndex
2601
2791
  };
2602
2792
  screenInteractions.push(interaction);
2603
- console.log('Screen interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
2793
+ // console.log('Screen interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
2604
2794
  }
2605
2795
  }).catch(error => {
2606
2796
  console.error('Error validating recording state for screen interaction:', error);
@@ -2613,7 +2803,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2613
2803
  frameIndex: frameCounter.get(currentRecordingSessionId) || 0
2614
2804
  };
2615
2805
  screenInteractions.push(interaction);
2616
- console.log('Screen interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
2806
+ // console.log('Screen interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
2617
2807
  }
2618
2808
  }
2619
2809
  }
@@ -2729,18 +2919,18 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2729
2919
 
2730
2920
  // Handle workflow screenshot capture
2731
2921
  if (request.action === 'captureWorkflowScreenshot' && sender.tab) {
2732
- console.log('[SCREENSHOT-DEBUG] background.js - Received captureWorkflowScreenshot message');
2922
+ // console.log('[SCREENSHOT-DEBUG] background.js - Received captureWorkflowScreenshot message');
2733
2923
  const tabId = sender.tab.id;
2734
2924
  const settings = request.settings || {};
2735
- console.log('[SCREENSHOT-DEBUG] background.js - tabId:', tabId);
2736
- console.log('[SCREENSHOT-DEBUG] background.js - settings:', JSON.stringify(settings));
2925
+ // console.log('[SCREENSHOT-DEBUG] background.js - tabId:', tabId);
2926
+ // console.log('[SCREENSHOT-DEBUG] background.js - settings:', JSON.stringify(settings));
2737
2927
 
2738
2928
  captureTabScreenshot(tabId, settings).then((screenshotData) => {
2739
- console.log('[SCREENSHOT-DEBUG] background.js - captureTabScreenshot succeeded');
2740
- console.log('[SCREENSHOT-DEBUG] background.js - screenshotData type:', typeof screenshotData);
2741
- console.log('[SCREENSHOT-DEBUG] background.js - screenshotData length:', screenshotData?.length);
2742
- console.log('[SCREENSHOT-DEBUG] background.js - screenshotData preview:', screenshotData?.substring(0, 100));
2743
- console.log('[SCREENSHOT-DEBUG] background.js - Sending response with success: true');
2929
+ // console.log('[SCREENSHOT-DEBUG] background.js - captureTabScreenshot succeeded');
2930
+ // console.log('[SCREENSHOT-DEBUG] background.js - screenshotData type:', typeof screenshotData);
2931
+ // console.log('[SCREENSHOT-DEBUG] background.js - screenshotData length:', screenshotData?.length);
2932
+ // console.log('[SCREENSHOT-DEBUG] background.js - screenshotData preview:', screenshotData?.substring(0, 100));
2933
+ // console.log('[SCREENSHOT-DEBUG] background.js - Sending response with success: true');
2744
2934
  sendResponse({ success: true, screenshotData });
2745
2935
  }).catch((error) => {
2746
2936
  console.error('[SCREENSHOT-DEBUG] background.js - captureTabScreenshot FAILED');
@@ -2774,7 +2964,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2774
2964
  /*
2775
2965
  async function takeStandaloneSnapshot(tabId, note = '') {
2776
2966
  try {
2777
- console.log('Taking standalone snapshot for tab:', tabId);
2967
+ // console.log('Taking standalone snapshot for tab:', tabId);
2778
2968
 
2779
2969
  // Create a unique session ID for the snapshot
2780
2970
  const sessionId = `snapshot_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
@@ -2850,7 +3040,7 @@ async function takeStandaloneSnapshot(tabId, note = '') {
2850
3040
 
2851
3041
  if (response.ok) {
2852
3042
  const result = await response.json();
2853
- console.log('Snapshot uploaded successfully:', sessionId);
3043
+ // console.log('Snapshot uploaded successfully:', sessionId);
2854
3044
  uploadSuccess = true;
2855
3045
  break;
2856
3046
  }
@@ -2874,34 +3064,34 @@ async function takeStandaloneSnapshot(tabId, note = '') {
2874
3064
 
2875
3065
  // Capture screenshot for workflow recording
2876
3066
  async function captureTabScreenshot(tabId, settings) {
2877
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - ENTRY');
2878
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - tabId:', tabId);
2879
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - settings:', JSON.stringify(settings));
3067
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - ENTRY');
3068
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - tabId:', tabId);
3069
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - settings:', JSON.stringify(settings));
2880
3070
 
2881
3071
  try {
2882
3072
  // Get the tab to find its window
2883
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Getting tab info...');
3073
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Getting tab info...');
2884
3074
  const tab = await chrome.tabs.get(tabId);
2885
3075
  const windowId = tab.windowId;
2886
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - windowId:', windowId);
2887
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - tab.url:', tab.url);
3076
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - windowId:', windowId);
3077
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - tab.url:', tab.url);
2888
3078
 
2889
3079
  const captureOptions = {
2890
3080
  format: settings.format || 'jpeg',
2891
3081
  quality: settings.quality || 30
2892
3082
  };
2893
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - captureOptions:', JSON.stringify(captureOptions));
2894
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Calling chrome.tabs.captureVisibleTab...');
3083
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - captureOptions:', JSON.stringify(captureOptions));
3084
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Calling chrome.tabs.captureVisibleTab...');
2895
3085
 
2896
3086
  const dataUrl = await chrome.tabs.captureVisibleTab(windowId, captureOptions);
2897
3087
 
2898
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - captureVisibleTab SUCCESS');
2899
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - dataUrl length:', dataUrl?.length);
2900
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - dataUrl prefix:', dataUrl?.substring(0, 100));
3088
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - captureVisibleTab SUCCESS');
3089
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - dataUrl length:', dataUrl?.length);
3090
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - dataUrl prefix:', dataUrl?.substring(0, 100));
2901
3091
 
2902
3092
  // If resolution is specified, resize the image
2903
3093
  if (settings.maxWidth || settings.maxHeight) {
2904
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Resizing required, maxWidth:', settings.maxWidth, 'maxHeight:', settings.maxHeight);
3094
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Resizing required, maxWidth:', settings.maxWidth, 'maxHeight:', settings.maxHeight);
2905
3095
  // Create an image element to get dimensions
2906
3096
  const img = new Image();
2907
3097
  const canvas = new OffscreenCanvas(1, 1);
@@ -2941,8 +3131,8 @@ async function captureTabScreenshot(tabId, settings) {
2941
3131
  });
2942
3132
  }
2943
3133
 
2944
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - No resize needed, returning dataUrl');
2945
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Final dataUrl length:', dataUrl?.length);
3134
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - No resize needed, returning dataUrl');
3135
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Final dataUrl length:', dataUrl?.length);
2946
3136
  return dataUrl;
2947
3137
  } catch (error) {
2948
3138
  console.error('[SCREENSHOT-DEBUG] captureTabScreenshot - EXCEPTION CAUGHT');
@@ -2956,7 +3146,7 @@ async function captureTabScreenshot(tabId, settings) {
2956
3146
  // Start recording
2957
3147
  // Detect if server is available (server mode vs browser-only mode)
2958
3148
  async function detectServerMode() {
2959
- console.log('[ServerDetection] Checking server availability...');
3149
+ // console.log('[ServerDetection] Checking server availability...');
2960
3150
 
2961
3151
  for (const port of CONFIG_PORTS) {
2962
3152
  try {
@@ -2970,7 +3160,7 @@ async function detectServerMode() {
2970
3160
  ]);
2971
3161
 
2972
3162
  if (response.ok) {
2973
- console.log(`[ServerDetection] Server detected on port ${port}`);
3163
+ // console.log(`[ServerDetection] Server detected on port ${port}`);
2974
3164
  serverMode = 'server';
2975
3165
  return 'server';
2976
3166
  }
@@ -2979,7 +3169,7 @@ async function detectServerMode() {
2979
3169
  }
2980
3170
  }
2981
3171
 
2982
- console.log('[ServerDetection] No server detected - using browser-only mode');
3172
+ // console.log('[ServerDetection] No server detected - using browser-only mode');
2983
3173
  serverMode = 'browser-only';
2984
3174
  return 'browser-only';
2985
3175
  }
@@ -3007,7 +3197,7 @@ async function startRecording(tabId, settings = {}) {
3007
3197
  try {
3008
3198
  // Detect server mode before starting
3009
3199
  await detectServerMode();
3010
- console.log(`[Recording] Mode: ${serverMode}`);
3200
+ // console.log(`[Recording] Mode: ${serverMode}`);
3011
3201
 
3012
3202
  // Check if session manager is available
3013
3203
  if (!sessionManager) {
@@ -3028,12 +3218,12 @@ async function startRecording(tabId, settings = {}) {
3028
3218
 
3029
3219
  // Start capturing console logs FIRST, before any other setup
3030
3220
  const logsStarted = await startCapturingLogs(tabId);
3031
- console.log('Console log capture started:', logsStarted);
3221
+ // console.log('Console log capture started:', logsStarted);
3032
3222
 
3033
3223
  // Give console interception time to settle (increased from 100ms to 500ms for reliability)
3034
3224
  if (logsStarted) {
3035
3225
  await new Promise(resolve => setTimeout(resolve, 500));
3036
- console.log('[Recording] Console interception ready');
3226
+ // console.log('[Recording] Console interception ready');
3037
3227
  } else {
3038
3228
  console.warn('[Recording] Console capture unavailable for this page - recording will proceed without console logs');
3039
3229
  }
@@ -3046,7 +3236,7 @@ async function startRecording(tabId, settings = {}) {
3046
3236
  targetTabId: tabId
3047
3237
  });
3048
3238
 
3049
- console.log('Got stream ID:', streamId);
3239
+ // console.log('Got stream ID:', streamId);
3050
3240
 
3051
3241
  // Create session with session manager
3052
3242
  const sessionConfig = {
@@ -3079,7 +3269,7 @@ async function startRecording(tabId, settings = {}) {
3079
3269
 
3080
3270
  // STEP 4: Initialize browser-only recording if in browser-only mode
3081
3271
  if (serverMode === 'browser-only' && browserRecordingManager) {
3082
- console.log('[Recording] Initializing browser-only recording in IndexedDB');
3272
+ // console.log('[Recording] Initializing browser-only recording in IndexedDB');
3083
3273
  const tab = await chrome.tabs.get(tabId);
3084
3274
  await browserRecordingManager.startRecording(sessionId, {
3085
3275
  tabId: tabId,
@@ -3112,7 +3302,19 @@ async function startRecording(tabId, settings = {}) {
3112
3302
  // Update badge
3113
3303
  chrome.action.setBadgeText({ text: 'REC' });
3114
3304
  chrome.action.setBadgeBackgroundColor({ color: '#FF0000' });
3115
-
3305
+
3306
+ // DON'T start inactivity monitoring here - wait for countdownComplete message
3307
+ // This ensures the 10s timer starts AFTER the 3s visual countdown, not before
3308
+ // Set a fallback timer in case content script doesn't send countdownComplete
3309
+ inactivityMonitoringStarted = false;
3310
+ if (inactivityFallbackTimer) clearTimeout(inactivityFallbackTimer);
3311
+ inactivityFallbackTimer = setTimeout(async () => {
3312
+ // Use isCurrentlyRecording (the actual state variable)
3313
+ if (isCurrentlyRecording && !inactivityMonitoringStarted) {
3314
+ await startInactivityMonitoring(tabId);
3315
+ }
3316
+ }, 5000); // 5s = 3s countdown + 2s buffer
3317
+
3116
3318
  // If on a restricted page, notify user
3117
3319
  const tab = await chrome.tabs.get(tabId);
3118
3320
  if (tab.url && (tab.url.startsWith('chrome://') || tab.url.startsWith('chrome-extension://'))) {
@@ -3133,12 +3335,12 @@ async function startRecording(tabId, settings = {}) {
3133
3335
  sessionId: sessionId
3134
3336
  }).catch(async (error) => {
3135
3337
  // Content script might not be injected, try to inject it
3136
- console.log('Could not notify content script, attempting to inject:', error);
3338
+ // console.log('Could not notify content script, attempting to inject:', error);
3137
3339
 
3138
3340
  // First check if this tab allows content script injection
3139
3341
  const tab = await chrome.tabs.get(tabId);
3140
3342
  if (!tab.url || tab.url.startsWith('chrome://') || tab.url.startsWith('chrome-extension://') || tab.url.startsWith('moz-extension://')) {
3141
- console.log('Cannot inject content script into restricted URL:', tab.url);
3343
+ // console.log('Cannot inject content script into restricted URL:', tab.url);
3142
3344
  return;
3143
3345
  }
3144
3346
 
@@ -3174,7 +3376,7 @@ async function startRecording(tabId, settings = {}) {
3174
3376
  url: tab.url,
3175
3377
  title: tab.title
3176
3378
  });
3177
- console.log('[Recording] Browser recording initialized for session:', sessionId);
3379
+ // console.log('[Recording] Browser recording initialized for session:', sessionId);
3178
3380
  }
3179
3381
 
3180
3382
  // Send stream ID, session info, and settings to offscreen document for frame capture
@@ -3194,7 +3396,7 @@ async function startRecording(tabId, settings = {}) {
3194
3396
  }
3195
3397
  });
3196
3398
 
3197
- console.log('Recording started in', serverMode, 'mode');
3399
+ // console.log('Recording started in', serverMode, 'mode');
3198
3400
  } catch (error) {
3199
3401
  console.error('Error in startRecording:', error);
3200
3402
  throw error;
@@ -3213,13 +3415,16 @@ async function stopRecording() {
3213
3415
  // Check if currently recording via session manager
3214
3416
  const currentlyRecording = await isCurrentlyRecordingAsync();
3215
3417
  if (!currentlyRecording) {
3216
- console.log('No active recording session to stop');
3418
+ // console.log('No active recording session to stop');
3217
3419
  return { success: false, error: 'No active recording' };
3218
3420
  }
3219
3421
 
3220
3422
  // Store sessionId before clearing it
3221
3423
  const stoppedSessionId = currentSession?.sessionId;
3222
3424
 
3425
+ // Stop inactivity monitoring
3426
+ await stopInactivityMonitoring(recordingTabId);
3427
+
3223
3428
  // Capture frame count and duration for the response
3224
3429
  let recordedFrameCount = 0;
3225
3430
  let recordedDuration = 0;
@@ -3233,11 +3438,11 @@ async function stopRecording() {
3233
3438
  } else {
3234
3439
  recordedFrameCount = stopResult.frameCount || 0;
3235
3440
  recordedDuration = stopResult.sessionDuration || 0;
3236
- console.log(`Recording stopped. Duration: ${recordedDuration}ms, Frames: ${recordedFrameCount}`);
3441
+ // console.log(`Recording stopped. Duration: ${recordedDuration}ms, Frames: ${recordedFrameCount}`);
3237
3442
 
3238
3443
  // Finalize browser-only recording if in browser-only mode
3239
3444
  if (serverMode === 'browser-only' && browserRecordingManager) {
3240
- console.log('[Browser-Only] Finalizing browser recording in IndexedDB');
3445
+ // console.log('[Browser-Only] Finalizing browser recording in IndexedDB');
3241
3446
  await browserRecordingManager.stopRecording(currentSession.sessionId);
3242
3447
  }
3243
3448
  }
@@ -3248,10 +3453,10 @@ async function stopRecording() {
3248
3453
  let flushCompleted = false;
3249
3454
  if (logBuffer) {
3250
3455
  try {
3251
- console.log('[Background] Flushing all buffered logs before stop...');
3456
+ // console.log('[Background] Flushing all buffered logs before stop...');
3252
3457
  await logBuffer.flushAll();
3253
3458
  flushCompleted = true;
3254
- console.log('[Background] Successfully flushed all buffered logs');
3459
+ // console.log('[Background] Successfully flushed all buffered logs');
3255
3460
  } catch (flushError) {
3256
3461
  console.error('[Background] Failed to flush logs during stop:', flushError);
3257
3462
  // Continue with stop process even if flush fails
@@ -3271,25 +3476,25 @@ async function stopRecording() {
3271
3476
 
3272
3477
  // CRITICAL: Store recordingTabId BEFORE clearing it (for cleanup)
3273
3478
  const previousRecordingTabId = recordingTabId;
3274
- console.log('[Background] previousRecordingTabId:', previousRecordingTabId, 'stoppedSessionId:', stoppedSessionId);
3479
+ // console.log('[Background] previousRecordingTabId:', previousRecordingTabId, 'stoppedSessionId:', stoppedSessionId);
3275
3480
 
3276
3481
  // CRITICAL FIX: Send stop-screen-capture-tracking message to recording tab WITH sessionId
3277
3482
  // so it can show the completion UI
3278
3483
  if (previousRecordingTabId && stoppedSessionId) {
3279
3484
  try {
3280
- console.log('[Background] Sending recording-complete-show-ui message to tab:', previousRecordingTabId, 'with sessionId:', stoppedSessionId);
3485
+ // console.log('[Background] Sending recording-complete-show-ui message to tab:', previousRecordingTabId, 'with sessionId:', stoppedSessionId);
3281
3486
  await chrome.tabs.sendMessage(previousRecordingTabId, {
3282
3487
  type: 'recording-complete-show-ui',
3283
3488
  sessionId: stoppedSessionId
3284
3489
  }).catch((err) => {
3285
- console.log('[Background] Could not send completion UI message to recording tab:', err);
3490
+ // console.log('[Background] Could not send completion UI message to recording tab:', err);
3286
3491
  });
3287
- console.log('[Background] Successfully sent recording-complete-show-ui message');
3492
+ // console.log('[Background] Successfully sent recording-complete-show-ui message');
3288
3493
  } catch (error) {
3289
3494
  console.error('[Background] Failed to send completion UI message:', error);
3290
3495
  }
3291
3496
  } else {
3292
- console.log('[Background] NOT sending recording-complete-show-ui - missing previousRecordingTabId or stoppedSessionId');
3497
+ // console.log('[Background] NOT sending recording-complete-show-ui - missing previousRecordingTabId or stoppedSessionId');
3293
3498
  }
3294
3499
 
3295
3500
  // CRITICAL FIX: Send stop-screen-capture-tracking message to ALL content scripts
@@ -3301,13 +3506,13 @@ async function stopRecording() {
3301
3506
  type: 'stop-screen-capture-tracking'
3302
3507
  }).catch(() => {
3303
3508
  // Ignore errors for tabs that don't have content scripts
3304
- console.log(`[Background] Could not send cleanup message to tab ${tab.id}`);
3509
+ // console.log(`[Background] Could not send cleanup message to tab ${tab.id}`);
3305
3510
  });
3306
3511
  }
3307
3512
  return Promise.resolve();
3308
3513
  });
3309
3514
  await Promise.all(cleanupPromises);
3310
- console.log('[Background] Cleanup messages sent to all content scripts');
3515
+ // console.log('[Background] Cleanup messages sent to all content scripts');
3311
3516
  } catch (error) {
3312
3517
  console.error('[Background] Failed to send cleanup messages to content scripts:', error);
3313
3518
  }
@@ -3315,7 +3520,7 @@ async function stopRecording() {
3315
3520
  // CRITICAL FIX: Restore original console methods and remove event listeners
3316
3521
  if (previousRecordingTabId) {
3317
3522
  try {
3318
- console.log('[Background] Stopping console log capture for tab:', previousRecordingTabId);
3523
+ // console.log('[Background] Stopping console log capture for tab:', previousRecordingTabId);
3319
3524
  await stopCapturingLogs(previousRecordingTabId);
3320
3525
  } catch (cleanupError) {
3321
3526
  console.error('[Background] Failed to cleanup console interceptor:', cleanupError);
@@ -3339,11 +3544,11 @@ async function stopRecording() {
3339
3544
 
3340
3545
  // CRITICAL: Clear pending frame queue to prevent infinite retry loop
3341
3546
  if (stoppedSessionId && pendingFrameQueue.has(stoppedSessionId)) {
3342
- console.log(`[FrameQueue] Clearing ${pendingFrameQueue.get(stoppedSessionId).length} pending frames for stopped session ${stoppedSessionId}`);
3547
+ // console.log(`[FrameQueue] Clearing ${pendingFrameQueue.get(stoppedSessionId).length} pending frames for stopped session ${stoppedSessionId}`);
3343
3548
  pendingFrameQueue.delete(stoppedSessionId);
3344
3549
  }
3345
3550
 
3346
- console.log('Stop message sent to offscreen document');
3551
+ // console.log('Stop message sent to offscreen document');
3347
3552
 
3348
3553
  // Notify popup to refresh recordings list
3349
3554
  chrome.runtime.sendMessage({
@@ -3351,7 +3556,7 @@ async function stopRecording() {
3351
3556
  sessionId: stoppedSessionId
3352
3557
  }).catch(() => {
3353
3558
  // Popup might not be open, that's okay
3354
- console.log('[Background] Popup not available to notify of recording stop');
3559
+ // console.log('[Background] Popup not available to notify of recording stop');
3355
3560
  });
3356
3561
 
3357
3562
  // Format duration as human-readable string (e.g., "1m 30s" or "45s")
@@ -3380,7 +3585,7 @@ async function stopRecording() {
3380
3585
  // CRITICAL FIX: Clean up console interceptor even on error
3381
3586
  if (errorRecordingTabId) {
3382
3587
  try {
3383
- console.log('[Background] Emergency cleanup of console interceptor for tab:', errorRecordingTabId);
3588
+ // console.log('[Background] Emergency cleanup of console interceptor for tab:', errorRecordingTabId);
3384
3589
  await stopCapturingLogs(errorRecordingTabId);
3385
3590
  } catch (cleanupError) {
3386
3591
  console.error('[Background] Failed to cleanup console interceptor during error handling:', cleanupError);
@@ -3407,25 +3612,25 @@ async function stopRecording() {
3407
3612
  // Capture console logs from the recording tab
3408
3613
  // REFACTORED: Now uses shared console-interception-library.js
3409
3614
  async function startCapturingLogs(tabId) {
3410
- console.log('[Screen Recording] Starting console interception using shared library');
3615
+ // console.log('[Screen Recording] Starting console interception using shared library');
3411
3616
  return await self.ConsoleInterceptionLibrary.startConsoleInterception(tabId, SCREEN_RECORDING_CONSOLE_CONFIG);
3412
3617
  }
3413
3618
 
3414
3619
  // REFACTORED: Now uses shared console-interception-library.js via proper namespace
3415
3620
  async function stopCapturingLogs(tabId) {
3416
- console.log('[Screen Recording] Stopping console interception using shared library');
3621
+ // console.log('[Screen Recording] Stopping console interception using shared library');
3417
3622
  return await self.ConsoleInterceptionLibrary.stopConsoleInterception(tabId, SCREEN_RECORDING_CONSOLE_CONFIG);
3418
3623
  }
3419
3624
 
3420
3625
  // Workflow Recording Functions
3421
3626
  async function startWorkflowRecording(tabId, includeLogsInExport, sessionName = null, screenshotSettings = null) {
3422
3627
  try {
3423
- console.log('Starting workflow recording for tab:', tabId);
3628
+ // console.log('Starting workflow recording for tab:', tabId);
3424
3629
 
3425
3630
  // Check if this tab allows content script injection
3426
3631
  const tab = await chrome.tabs.get(tabId);
3427
3632
  if (!tab.url || tab.url.startsWith('chrome://') || tab.url.startsWith('chrome-extension://') || tab.url.startsWith('moz-extension://')) {
3428
- console.log('Cannot start workflow recording on restricted URL:', tab.url);
3633
+ // console.log('Cannot start workflow recording on restricted URL:', tab.url);
3429
3634
  throw new Error('Cannot record workflows on restricted pages (chrome:// URLs)');
3430
3635
  }
3431
3636
 
@@ -3446,7 +3651,7 @@ async function startWorkflowRecording(tabId, includeLogsInExport, sessionName =
3446
3651
  if (includeLogsInExport) {
3447
3652
  const buffer = new WorkflowLogBuffer(tabId);
3448
3653
  workflowLogBuffers.set(tabId, buffer);
3449
- console.log(`[Workflow] Initialized WorkflowLogBuffer for tab ${tabId}`);
3654
+ // console.log(`[Workflow] Initialized WorkflowLogBuffer for tab ${tabId}`);
3450
3655
  }
3451
3656
 
3452
3657
  // REFACTORED: Use shared console interception library via proper namespace (replaces 150+ lines of duplicate code)
@@ -3464,7 +3669,7 @@ async function startWorkflowRecording(tabId, includeLogsInExport, sessionName =
3464
3669
  });
3465
3670
  } catch (e) {
3466
3671
  // Content script might already be injected
3467
- console.log('Content script injection attempt:', e.message);
3672
+ // console.log('Content script injection attempt:', e.message);
3468
3673
  }
3469
3674
 
3470
3675
  // Tell the content script to start recording
@@ -3475,7 +3680,7 @@ async function startWorkflowRecording(tabId, includeLogsInExport, sessionName =
3475
3680
  tabId: tabId
3476
3681
  });
3477
3682
 
3478
- console.log('Workflow recording started successfully');
3683
+ // console.log('Workflow recording started successfully');
3479
3684
  } catch (error) {
3480
3685
  console.error('Error starting workflow recording:', error);
3481
3686
  throw error;
@@ -3484,7 +3689,7 @@ async function startWorkflowRecording(tabId, includeLogsInExport, sessionName =
3484
3689
 
3485
3690
  async function stopWorkflowRecording(tabId) {
3486
3691
  try {
3487
- console.log('Stopping workflow recording for tab:', tabId);
3692
+ // console.log('Stopping workflow recording for tab:', tabId);
3488
3693
 
3489
3694
  // Check if recording was active
3490
3695
  if (!workflowRecordingTabs.has(tabId)) {
@@ -3503,7 +3708,7 @@ async function stopWorkflowRecording(tabId) {
3503
3708
 
3504
3709
  // CRITICAL FIX: Restore original console methods and remove event listeners
3505
3710
  try {
3506
- console.log('[Workflow] Stopping console log capture for tab:', tabId);
3711
+ // console.log('[Workflow] Stopping console log capture for tab:', tabId);
3507
3712
  await stopCapturingWorkflowLogs(tabId);
3508
3713
  } catch (cleanupError) {
3509
3714
  console.error('[Workflow] Failed to cleanup console interceptor:', cleanupError);
@@ -3515,19 +3720,19 @@ async function stopWorkflowRecording(tabId) {
3515
3720
  let workflow = Array.isArray(workflowData) ? workflowData : (workflowData.actions || []);
3516
3721
  let functionTraces = Array.isArray(workflowData) ? [] : (workflowData.functionTraces || []);
3517
3722
 
3518
- console.log(`[Background] Received ${workflow.length} actions and ${functionTraces.length} function traces`);
3519
- console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Checking actions for screenshot_data');
3723
+ // console.log(`[Background] Received ${workflow.length} actions and ${functionTraces.length} function traces`);
3724
+ // console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Checking actions for screenshot_data');
3520
3725
 
3521
3726
  const actionsWithScreenshots = workflow.filter(a => a.screenshot_data);
3522
- console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Actions WITH screenshot_data:', actionsWithScreenshots.length);
3727
+ // console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Actions WITH screenshot_data:', actionsWithScreenshots.length);
3523
3728
 
3524
3729
  workflow.forEach((action, index) => {
3525
- console.log(`[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Action ${index}:`, {
3526
- type: action.type,
3527
- hasScreenshotData: !!action.screenshot_data,
3528
- screenshotDataLength: action.screenshot_data?.length,
3529
- screenshotPreview: action.screenshot_data?.substring(0, 50)
3530
- });
3730
+ // console.log(`[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Action ${index}:`, {
3731
+ // type: action.type,
3732
+ // hasScreenshotData: !!action.screenshot_data,
3733
+ // screenshotDataLength: action.screenshot_data?.length,
3734
+ // screenshotPreview: action.screenshot_data?.substring(0, 50)
3735
+ // });
3531
3736
  });
3532
3737
 
3533
3738
  // If logs should be included, flush buffer and get them from session storage
@@ -3536,7 +3741,7 @@ async function stopWorkflowRecording(tabId) {
3536
3741
  const buffer = workflowLogBuffers.get(tabId);
3537
3742
  if (buffer) {
3538
3743
  await buffer.flush();
3539
- console.log(`[Workflow] Flushed buffer before retrieval, stats:`, buffer.getStats());
3744
+ // console.log(`[Workflow] Flushed buffer before retrieval, stats:`, buffer.getStats());
3540
3745
  }
3541
3746
 
3542
3747
  const result = await chrome.storage.session.get(`workflow_${tabId}`);
@@ -3585,7 +3790,7 @@ async function stopWorkflowRecording(tabId) {
3585
3790
  if (bufferToCleanup) {
3586
3791
  await bufferToCleanup.cleanup();
3587
3792
  workflowLogBuffers.delete(tabId);
3588
- console.log(`[Workflow] Cleaned up WorkflowLogBuffer for tab ${tabId}`);
3793
+ // console.log(`[Workflow] Cleaned up WorkflowLogBuffer for tab ${tabId}`);
3589
3794
  }
3590
3795
 
3591
3796
  await chrome.storage.session.remove(`workflow_${tabId}`);
@@ -3597,7 +3802,7 @@ async function stopWorkflowRecording(tabId) {
3597
3802
  workflowStartTime: null
3598
3803
  });
3599
3804
 
3600
- console.log('Workflow recording stopped, returning workflow:', workflow);
3805
+ // console.log('Workflow recording stopped, returning workflow:', workflow);
3601
3806
 
3602
3807
  // Try to save to server
3603
3808
  try {
@@ -3610,11 +3815,11 @@ async function stopWorkflowRecording(tabId) {
3610
3815
  // Retrieve the workflow ID that was generated at start
3611
3816
  const storedData = await chrome.storage.local.get(['currentWorkflowId']);
3612
3817
  const sessionId = storedData.currentWorkflowId || `workflow_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
3613
- console.log('[Workflow] Using sessionId for save:', sessionId);
3818
+ // console.log('[Workflow] Using sessionId for save:', sessionId);
3614
3819
 
3615
3820
  for (const port of serverPorts) {
3616
3821
  try {
3617
- console.log(`[Workflow] Attempting to save to server on port ${port}...`);
3822
+ // console.log(`[Workflow] Attempting to save to server on port ${port}...`);
3618
3823
 
3619
3824
  const payloadData = {
3620
3825
  sessionId: sessionId,
@@ -3628,19 +3833,19 @@ async function stopWorkflowRecording(tabId) {
3628
3833
  functionTraces: functionTraces // Include function execution traces
3629
3834
  };
3630
3835
 
3631
- console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - HTTP POST payload being prepared');
3632
- console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Payload actions count:', payloadData.actions.length);
3836
+ // console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - HTTP POST payload being prepared');
3837
+ // console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Payload actions count:', payloadData.actions.length);
3633
3838
 
3634
3839
  const payloadActionsWithScreenshots = payloadData.actions.filter(a => a.screenshot_data);
3635
- console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Payload actions WITH screenshot_data:', payloadActionsWithScreenshots.length);
3840
+ // console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Payload actions WITH screenshot_data:', payloadActionsWithScreenshots.length);
3636
3841
 
3637
3842
  payloadData.actions.forEach((action, index) => {
3638
- console.log(`[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Payload Action ${index}:`, {
3639
- type: action.type,
3640
- hasScreenshotData: !!action.screenshot_data,
3641
- screenshotDataLength: action.screenshot_data?.length,
3642
- screenshotPreview: action.screenshot_data?.substring(0, 50)
3643
- });
3843
+ // console.log(`[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Payload Action ${index}:`, {
3844
+ // type: action.type,
3845
+ // hasScreenshotData: !!action.screenshot_data,
3846
+ // screenshotDataLength: action.screenshot_data?.length,
3847
+ // screenshotPreview: action.screenshot_data?.substring(0, 50)
3848
+ // });
3644
3849
  });
3645
3850
 
3646
3851
  const response = await fetch(`http://localhost:${port}/chromedebug/workflow-recording`, {
@@ -3653,15 +3858,15 @@ async function stopWorkflowRecording(tabId) {
3653
3858
 
3654
3859
  if (response.ok) {
3655
3860
  serverResult = await response.json();
3656
- console.log(`[Workflow] Successfully saved to server on port ${port}`, serverResult);
3861
+ // console.log(`[Workflow] Successfully saved to server on port ${port}`, serverResult);
3657
3862
  break;
3658
3863
  } else {
3659
- console.log(`[Workflow] Failed on port ${port}: ${response.status} ${response.statusText}`);
3864
+ // console.log(`[Workflow] Failed on port ${port}: ${response.status} ${response.statusText}`);
3660
3865
  const errorText = await response.text();
3661
- console.log(`[Workflow] Error response:`, errorText);
3866
+ // console.log(`[Workflow] Error response:`, errorText);
3662
3867
  }
3663
3868
  } catch (error) {
3664
- console.log(`Failed to save to server on port ${port}:`, error.message);
3869
+ // console.log(`Failed to save to server on port ${port}:`, error.message);
3665
3870
  }
3666
3871
  }
3667
3872
 
@@ -3725,7 +3930,7 @@ async function stopWorkflowRecording(tabId) {
3725
3930
  // CRITICAL FIX: Stop workflow console log capture and restore original methods
3726
3931
  // REFACTORED: Now uses shared console-interception-library.js via proper namespace
3727
3932
  async function stopCapturingWorkflowLogs(tabId) {
3728
- console.log('[Workflow Recording] Stopping console interception using shared library');
3933
+ // console.log('[Workflow Recording] Stopping console interception using shared library');
3729
3934
  return await self.ConsoleInterceptionLibrary.stopConsoleInterception(tabId, WORKFLOW_RECORDING_CONSOLE_CONFIG);
3730
3935
  }
3731
3936
 
@@ -3764,7 +3969,7 @@ async function deleteRecordingFromServer(recordingId, sendResponse) {
3764
3969
 
3765
3970
  if (deleteResult.success) {
3766
3971
  deleted = true;
3767
- console.log('Recording deleted successfully');
3972
+ // console.log('Recording deleted successfully');
3768
3973
  sendResponse({ success: true });
3769
3974
  return;
3770
3975
  } else {
@@ -3786,11 +3991,11 @@ async function retryPendingFrames(sessionId) {
3786
3991
  const pending = pendingFrameQueue.get(sessionId);
3787
3992
  if (!pending || pending.length === 0) return;
3788
3993
 
3789
- console.log(`[FrameQueue] Retrying ${pending.length} pending frame batches for session ${sessionId}`);
3994
+ // console.log(`[FrameQueue] Retrying ${pending.length} pending frame batches for session ${sessionId}`);
3790
3995
 
3791
3996
  // Check if this is still the active recording session
3792
3997
  if (currentSession?.sessionId !== sessionId) {
3793
- console.log(`[FrameQueue] Session ${sessionId} is no longer active, clearing pending frames`);
3998
+ // console.log(`[FrameQueue] Session ${sessionId} is no longer active, clearing pending frames`);
3794
3999
  pendingFrameQueue.delete(sessionId);
3795
4000
  return;
3796
4001
  }
@@ -3822,12 +4027,12 @@ async function retryPendingFrames(sessionId) {
3822
4027
  await handleFrameBatch({ sessionId, frames }, true); // skipValidation=true
3823
4028
  }
3824
4029
 
3825
- console.log(`[FrameQueue] Successfully processed ${batches.length} pending batches`);
4030
+ // console.log(`[FrameQueue] Successfully processed ${batches.length} pending batches`);
3826
4031
  }
3827
4032
 
3828
4033
  // Handle frame batches from frame capture
3829
4034
  async function handleFrameBatch(batchData, skipValidation = false) {
3830
- console.log(`Processing frame batch for session ${batchData.sessionId}`);
4035
+ // console.log(`Processing frame batch for session ${batchData.sessionId}`);
3831
4036
 
3832
4037
  try {
3833
4038
  const sessionId = batchData.sessionId;
@@ -3881,7 +4086,7 @@ async function handleFrameBatch(batchData, skipValidation = false) {
3881
4086
  frameCounter.set(sessionId, currentFrameIndex);
3882
4087
  }
3883
4088
 
3884
- console.log(`Assigning frame indices ${frameCounter.get(sessionId) - indexedFrames.length} to ${currentFrameIndex - 1}`);
4089
+ // console.log(`Assigning frame indices ${frameCounter.get(sessionId) - indexedFrames.length} to ${currentFrameIndex - 1}`);
3885
4090
 
3886
4091
  // Find available server port using settings
3887
4092
  const ports = await getServerPorts();
@@ -3907,7 +4112,7 @@ async function handleFrameBatch(batchData, skipValidation = false) {
3907
4112
 
3908
4113
  if (uploadResponse.ok) {
3909
4114
  const result = await uploadResponse.json();
3910
- console.log(`Frame batch uploaded successfully to port ${port}:`, result);
4115
+ // console.log(`Frame batch uploaded successfully to port ${port}:`, result);
3911
4116
  recordingServerPort = port; // Store the successful port
3912
4117
  uploadSuccess = true;
3913
4118
 
@@ -3923,8 +4128,20 @@ async function handleFrameBatch(batchData, skipValidation = false) {
3923
4128
  // Append new frames
3924
4129
  sessionData.frames = sessionData.frames.concat(batchData.frames);
3925
4130
  await chrome.storage.local.set({ [storageKey]: sessionData });
3926
- console.log(`Saved ${batchData.frames.length} frames to local storage, total: ${sessionData.frames.length}`);
3927
-
4131
+ // console.log(`Saved ${batchData.frames.length} frames to local storage, total: ${sessionData.frames.length}`);
4132
+
4133
+ // Send frame count update to content script
4134
+ if (recordingTabId) {
4135
+ try {
4136
+ await chrome.tabs.sendMessage(recordingTabId, {
4137
+ action: 'updateFrameCount',
4138
+ frameCount: sessionData.frames.length
4139
+ });
4140
+ } catch (e) {
4141
+ // Tab might be closed, ignore
4142
+ }
4143
+ }
4144
+
3928
4145
  break;
3929
4146
  } else {
3930
4147
  const errorText = await uploadResponse.text();
@@ -3933,16 +4150,16 @@ async function handleFrameBatch(batchData, skipValidation = false) {
3933
4150
  }
3934
4151
  } catch (e) {
3935
4152
  lastError = e.message;
3936
- console.log(`Failed to upload frame batch to port ${port}:`, e.message);
4153
+ // console.log(`Failed to upload frame batch to port ${port}:`, e.message);
3937
4154
  }
3938
4155
  }
3939
4156
 
3940
4157
  if (!uploadSuccess) {
3941
- console.log(`No server available - checking if browser-only mode`);
4158
+ // console.log(`No server available - checking if browser-only mode`);
3942
4159
 
3943
4160
  // If in browser-only mode, store frames in IndexedDB
3944
4161
  if (serverMode === 'browser-only' && browserRecordingManager) {
3945
- console.log(`[Browser-Only] Storing ${indexedFrames.length} frames in IndexedDB`);
4162
+ // console.log(`[Browser-Only] Storing ${indexedFrames.length} frames in IndexedDB`);
3946
4163
  // Use the browser recording session ID, not the frame capture session ID
3947
4164
  const recordingSessionId = currentRecordingSessionId || batchData.sessionId;
3948
4165
  for (const frame of indexedFrames) {
@@ -3959,7 +4176,7 @@ async function handleFrameBatch(batchData, skipValidation = false) {
3959
4176
  absoluteTimestamp: frame.absoluteTimestamp // Don't use Date.now() fallback - preserve actual capture time
3960
4177
  });
3961
4178
  }
3962
- console.log(`[Browser-Only] Frames stored successfully in IndexedDB for session ${recordingSessionId}`);
4179
+ // console.log(`[Browser-Only] Frames stored successfully in IndexedDB for session ${recordingSessionId}`);
3963
4180
  } else {
3964
4181
  // Server mode but no server available - show error
3965
4182
  console.error(`CRITICAL: Failed to upload frame batch to any Chrome Debug server port. Last error: ${lastError}`);
@@ -3999,7 +4216,7 @@ async function getServerPorts() {
3999
4216
  // Try to discover the active server port
4000
4217
  const discoveredPort = await discoverActiveServerPort();
4001
4218
  if (discoveredPort) {
4002
- console.log(`Discovered Chrome Debug server on port ${discoveredPort}`);
4219
+ // console.log(`Discovered Chrome Debug server on port ${discoveredPort}`);
4003
4220
  return [discoveredPort, ...defaultPorts.filter(p => p !== discoveredPort)];
4004
4221
  }
4005
4222
 
@@ -4037,7 +4254,7 @@ async function discoverActiveServerPort() {
4037
4254
 
4038
4255
  // Handle frame capture session completion
4039
4256
  async function handleFrameCaptureComplete(sessionData) {
4040
- console.log(`Frame capture session ${sessionData.sessionId} completed with ${sessionData.totalFrames} frames`);
4257
+ // console.log(`Frame capture session ${sessionData.sessionId} completed with ${sessionData.totalFrames} frames`);
4041
4258
 
4042
4259
  try {
4043
4260
  // Store the tab ID and session ID before clearing
@@ -4055,7 +4272,7 @@ async function handleFrameCaptureComplete(sessionData) {
4055
4272
  let waitedTime = 0;
4056
4273
  let flushCompleted = false;
4057
4274
 
4058
- console.log('[Background] Waiting for LogBuffer flush completion...');
4275
+ // console.log('[Background] Waiting for LogBuffer flush completion...');
4059
4276
 
4060
4277
  // Poll for flush completion status
4061
4278
  while (waitedTime < maxWaitTime && !flushCompleted) {
@@ -4069,7 +4286,7 @@ async function handleFrameCaptureComplete(sessionData) {
4069
4286
  }
4070
4287
 
4071
4288
  if (flushCompleted) {
4072
- console.log(`[Background] LogBuffer flush completed after ${waitedTime}ms`);
4289
+ // console.log(`[Background] LogBuffer flush completed after ${waitedTime}ms`);
4073
4290
  } else {
4074
4291
  console.warn(`[Background] LogBuffer flush verification timed out after ${waitedTime}ms`);
4075
4292
  }
@@ -4077,9 +4294,9 @@ async function handleFrameCaptureComplete(sessionData) {
4077
4294
  // Retrieve buffered logs for this tab
4078
4295
  const logsResult = await chrome.storage.session.get(String(tabIdToNotify));
4079
4296
  bufferedLogs = logsResult[tabIdToNotify] || [];
4080
- console.log(`Retrieved ${bufferedLogs.length} buffered logs for post-processing`);
4297
+ // console.log(`Retrieved ${bufferedLogs.length} buffered logs for post-processing`);
4081
4298
  if (bufferedLogs.length > 0) {
4082
- console.log('First log:', bufferedLogs[0]);
4299
+ // console.log('First log:', bufferedLogs[0]);
4083
4300
  }
4084
4301
 
4085
4302
  // Clean up flush completion marker
@@ -4090,7 +4307,7 @@ async function handleFrameCaptureComplete(sessionData) {
4090
4307
  // Fallback: Try to read logs anyway
4091
4308
  const logsResult = await chrome.storage.session.get(String(tabIdToNotify));
4092
4309
  bufferedLogs = logsResult[tabIdToNotify] || [];
4093
- console.log(`Fallback: Retrieved ${bufferedLogs.length} buffered logs`);
4310
+ // console.log(`Fallback: Retrieved ${bufferedLogs.length} buffered logs`);
4094
4311
  }
4095
4312
 
4096
4313
  // Clear the buffered logs
@@ -4099,7 +4316,7 @@ async function handleFrameCaptureComplete(sessionData) {
4099
4316
  // Send logs to server for association with frames with retry logic
4100
4317
  // Skip server communication in browser-only mode (logs already in IndexedDB)
4101
4318
  if (bufferedLogs.length > 0 && serverMode !== 'browser-only') {
4102
- console.log(`[Server Mode] Associating ${bufferedLogs.length} logs with server...`);
4319
+ // console.log(`[Server Mode] Associating ${bufferedLogs.length} logs with server...`);
4103
4320
 
4104
4321
  // Retry logic to handle race conditions
4105
4322
  const maxRetries = 3;
@@ -4107,15 +4324,15 @@ async function handleFrameCaptureComplete(sessionData) {
4107
4324
  let success = false;
4108
4325
  let lastErrorDetails = null;
4109
4326
 
4110
- console.log(`[LOG-ASSOC-DEBUG] ========== STARTING LOG ASSOCIATION ==========`);
4111
- console.log(`[LOG-ASSOC-DEBUG] Session ID: ${sessionIdToUse}`);
4112
- console.log(`[LOG-ASSOC-DEBUG] Number of logs to associate: ${bufferedLogs.length}`);
4113
- console.log(`[LOG-ASSOC-DEBUG] Tab ID: ${tabIdToNotify}`);
4327
+ // console.log(`[LOG-ASSOC-DEBUG] ========== STARTING LOG ASSOCIATION ==========`);
4328
+ // console.log(`[LOG-ASSOC-DEBUG] Session ID: ${sessionIdToUse}`);
4329
+ // console.log(`[LOG-ASSOC-DEBUG] Number of logs to associate: ${bufferedLogs.length}`);
4330
+ // console.log(`[LOG-ASSOC-DEBUG] Tab ID: ${tabIdToNotify}`);
4114
4331
 
4115
4332
  // PRE-FLIGHT CHECK: Verify frames exist in database before attempting log association
4116
4333
  try {
4117
4334
  const ports = await getServerPorts();
4118
- console.log(`[LOG-ASSOC-DEBUG] PRE-FLIGHT: Checking if frames exist for session ${sessionIdToUse}...`);
4335
+ // console.log(`[LOG-ASSOC-DEBUG] PRE-FLIGHT: Checking if frames exist for session ${sessionIdToUse}...`);
4119
4336
  for (const port of ports) {
4120
4337
  try {
4121
4338
  const checkResponse = await fetch(`http://localhost:${port}/chromedebug/frame-session/${sessionIdToUse}`, {
@@ -4125,7 +4342,7 @@ async function handleFrameCaptureComplete(sessionData) {
4125
4342
  if (checkResponse.ok) {
4126
4343
  const sessionData = await checkResponse.json();
4127
4344
  const frameCount = sessionData.frames?.length || 0;
4128
- console.log(`[LOG-ASSOC-DEBUG] PRE-FLIGHT: Found ${frameCount} frames on port ${port}`);
4345
+ // console.log(`[LOG-ASSOC-DEBUG] PRE-FLIGHT: Found ${frameCount} frames on port ${port}`);
4129
4346
  if (frameCount === 0) {
4130
4347
  console.warn(`[LOG-ASSOC-DEBUG] ⚠️ WARNING: Session exists but has 0 frames! This will cause log association to fail.`);
4131
4348
  console.warn(`[LOG-ASSOC-DEBUG] Session data:`, sessionData);
@@ -4133,7 +4350,7 @@ async function handleFrameCaptureComplete(sessionData) {
4133
4350
  break;
4134
4351
  }
4135
4352
  } catch (e) {
4136
- console.log(`[LOG-ASSOC-DEBUG] PRE-FLIGHT: Could not check port ${port}:`, e.message);
4353
+ // console.log(`[LOG-ASSOC-DEBUG] PRE-FLIGHT: Could not check port ${port}:`, e.message);
4137
4354
  }
4138
4355
  }
4139
4356
  } catch (preflightError) {
@@ -4143,22 +4360,22 @@ async function handleFrameCaptureComplete(sessionData) {
4143
4360
  while (retryCount < maxRetries && !success) {
4144
4361
  try {
4145
4362
  const ports = await getServerPorts();
4146
- console.log(`[LOG-ASSOC-DEBUG] Attempt ${retryCount + 1}/${maxRetries}: Trying ports:`, ports);
4363
+ // console.log(`[LOG-ASSOC-DEBUG] Attempt ${retryCount + 1}/${maxRetries}: Trying ports:`, ports);
4147
4364
 
4148
4365
  for (const port of ports) {
4149
4366
  try {
4150
- console.log(`[LOG-ASSOC-DEBUG] Attempting port ${port}...`);
4367
+ // console.log(`[LOG-ASSOC-DEBUG] Attempting port ${port}...`);
4151
4368
  const requestBody = {
4152
4369
  sessionId: sessionIdToUse,
4153
4370
  logs: bufferedLogs
4154
4371
  };
4155
- console.log(`[LOG-ASSOC-DEBUG] Request payload: sessionId=${sessionIdToUse}, logs.length=${bufferedLogs.length}`);
4372
+ // console.log(`[LOG-ASSOC-DEBUG] Request payload: sessionId=${sessionIdToUse}, logs.length=${bufferedLogs.length}`);
4156
4373
  if (bufferedLogs.length > 0) {
4157
- console.log(`[LOG-ASSOC-DEBUG] First log sample:`, {
4158
- timestamp: bufferedLogs[0].timestamp,
4159
- level: bufferedLogs[0].level,
4160
- message: bufferedLogs[0].message?.substring(0, 100)
4161
- });
4374
+ // console.log(`[LOG-ASSOC-DEBUG] First log sample:`, {
4375
+ // timestamp: bufferedLogs[0].timestamp,
4376
+ // level: bufferedLogs[0].level,
4377
+ // message: bufferedLogs[0].message?.substring(0, 100)
4378
+ // });
4162
4379
  }
4163
4380
 
4164
4381
  const response = await fetch(`http://localhost:${port}/chromedebug/associate-logs`, {
@@ -4169,12 +4386,12 @@ async function handleFrameCaptureComplete(sessionData) {
4169
4386
  body: JSON.stringify(requestBody)
4170
4387
  });
4171
4388
 
4172
- console.log(`[LOG-ASSOC-DEBUG] Port ${port} response status: ${response.status} ${response.statusText}`);
4389
+ // console.log(`[LOG-ASSOC-DEBUG] Port ${port} response status: ${response.status} ${response.statusText}`);
4173
4390
 
4174
4391
  if (response.ok) {
4175
4392
  const result = await response.json();
4176
- console.log(`[LOG-ASSOC-DEBUG] ✅ SUCCESS on port ${port}:`, result);
4177
- console.log(`Logs associated successfully on port ${port}:`, result);
4393
+ // console.log(`[LOG-ASSOC-DEBUG] ✅ SUCCESS on port ${port}:`, result);
4394
+ // console.log(`Logs associated successfully on port ${port}:`, result);
4178
4395
  success = true;
4179
4396
 
4180
4397
  // Fetch the updated session data with logs from server
@@ -4182,14 +4399,14 @@ async function handleFrameCaptureComplete(sessionData) {
4182
4399
  const sessionResponse = await fetch(`http://localhost:${port}/chromedebug/frame-session/${sessionIdToUse}`);
4183
4400
  if (sessionResponse.ok) {
4184
4401
  const updatedSession = await sessionResponse.json();
4185
- console.log(`[LOG-ASSOC-DEBUG] Fetched updated session: ${updatedSession.frames?.length || 0} frames`);
4186
- console.log(`Fetched updated session with ${updatedSession.frames ? updatedSession.frames.length : 0} frames`);
4402
+ // console.log(`[LOG-ASSOC-DEBUG] Fetched updated session: ${updatedSession.frames?.length || 0} frames`);
4403
+ // console.log(`Fetched updated session with ${updatedSession.frames ? updatedSession.frames.length : 0} frames`);
4187
4404
 
4188
4405
  // Update Chrome local storage with the frames that now have logs
4189
4406
  const storageKey = sessionIdToUse;
4190
4407
  await chrome.storage.local.set({ [storageKey]: updatedSession });
4191
- console.log('[LOG-ASSOC-DEBUG] Updated local storage with frames containing logs');
4192
- console.log('Updated local storage with frames containing logs');
4408
+ // console.log('[LOG-ASSOC-DEBUG] Updated local storage with frames containing logs');
4409
+ // console.log('Updated local storage with frames containing logs');
4193
4410
  } else {
4194
4411
  console.error(`[LOG-ASSOC-DEBUG] Failed to fetch updated session: ${sessionResponse.status}`);
4195
4412
  console.error('Failed to fetch updated session data');
@@ -4225,15 +4442,15 @@ async function handleFrameCaptureComplete(sessionData) {
4225
4442
  attempt: retryCount + 1
4226
4443
  };
4227
4444
  console.error(`[LOG-ASSOC-DEBUG] ❌ Port ${port} exception:`, e);
4228
- console.log(`Failed to associate logs on port ${port}:`, e.message);
4445
+ // console.log(`Failed to associate logs on port ${port}:`, e.message);
4229
4446
  }
4230
4447
  }
4231
4448
 
4232
4449
  if (!success) {
4233
4450
  retryCount++;
4234
4451
  if (retryCount < maxRetries) {
4235
- console.log(`[LOG-ASSOC-DEBUG] Retrying in 1 second (attempt ${retryCount + 1}/${maxRetries})...`);
4236
- console.log(`Retrying log association (attempt ${retryCount + 1}/${maxRetries})...`);
4452
+ // console.log(`[LOG-ASSOC-DEBUG] Retrying in 1 second (attempt ${retryCount + 1}/${maxRetries})...`);
4453
+ // console.log(`Retrying log association (attempt ${retryCount + 1}/${maxRetries})...`);
4237
4454
  await new Promise(resolve => setTimeout(resolve, 1000));
4238
4455
  }
4239
4456
  }
@@ -4247,8 +4464,8 @@ async function handleFrameCaptureComplete(sessionData) {
4247
4464
  }
4248
4465
  }
4249
4466
 
4250
- console.log(`[LOG-ASSOC-DEBUG] ========== LOG ASSOCIATION COMPLETE ==========`);
4251
- console.log(`[LOG-ASSOC-DEBUG] Success: ${success}`);
4467
+ // console.log(`[LOG-ASSOC-DEBUG] ========== LOG ASSOCIATION COMPLETE ==========`);
4468
+ // console.log(`[LOG-ASSOC-DEBUG] Success: ${success}`);
4252
4469
  if (!success && lastErrorDetails) {
4253
4470
  console.error(`[LOG-ASSOC-DEBUG] Last error details:`, lastErrorDetails);
4254
4471
  }
@@ -4279,12 +4496,12 @@ async function handleFrameCaptureComplete(sessionData) {
4279
4496
  }
4280
4497
  } else if (bufferedLogs.length > 0 && serverMode === 'browser-only') {
4281
4498
  // Browser-only mode: Associate logs with frames in IndexedDB
4282
- console.log(`[Browser-Only] Associating ${bufferedLogs.length} logs with frames in IndexedDB...`);
4499
+ // console.log(`[Browser-Only] Associating ${bufferedLogs.length} logs with frames in IndexedDB...`);
4283
4500
 
4284
4501
  try {
4285
4502
  // Get all frames for this session from IndexedDB
4286
4503
  const frames = await dataBuffer.getBrowserFrames(sessionIdToUse);
4287
- console.log(`[Browser-Only] Retrieved ${frames.length} frames from IndexedDB for log association`);
4504
+ // console.log(`[Browser-Only] Retrieved ${frames.length} frames from IndexedDB for log association`);
4288
4505
 
4289
4506
  if (frames.length === 0) {
4290
4507
  console.warn('[Browser-Only] No frames found - logs cannot be associated');
@@ -4328,7 +4545,7 @@ async function handleFrameCaptureComplete(sessionData) {
4328
4545
  }
4329
4546
  }
4330
4547
 
4331
- console.log(`[Browser-Only] ✓ Associated logs with ${updatedCount} frames in IndexedDB`);
4548
+ // console.log(`[Browser-Only] ✓ Associated logs with ${updatedCount} frames in IndexedDB`);
4332
4549
  }
4333
4550
  } catch (error) {
4334
4551
  console.error('[Browser-Only] Failed to associate logs with frames:', error);
@@ -4354,18 +4571,18 @@ async function handleFrameCaptureComplete(sessionData) {
4354
4571
  // Save screen interactions to database
4355
4572
  // Skip server communication in browser-only mode
4356
4573
  if (screenInteractions.length > 0 && serverMode !== 'browser-only') {
4357
- console.log(`[Server Mode] Saving ${screenInteractions.length} screen interactions to database`);
4574
+ // console.log(`[Server Mode] Saving ${screenInteractions.length} screen interactions to database`);
4358
4575
 
4359
4576
  // Use comprehensive error handling for screen interactions save
4360
4577
  const saveScreenInteractions = async (data, context) => {
4361
4578
  // Diagnostic logging for screen interactions save
4362
- console.log('[ScreenInteractions] Preparing to save interactions:', {
4363
- sessionId: context.sessionId,
4364
- dataType: typeof data,
4365
- isArray: Array.isArray(data),
4366
- interactionCount: Array.isArray(data) ? data.length : 'N/A',
4367
- hasComplexData: Array.isArray(data) && data.some(i => i.element_html && i.element_html.length > 100)
4368
- });
4579
+ // console.log('[ScreenInteractions] Preparing to save interactions:', {
4580
+ // sessionId: context.sessionId,
4581
+ // dataType: typeof data,
4582
+ // isArray: Array.isArray(data),
4583
+ // interactionCount: Array.isArray(data) ? data.length : 'N/A',
4584
+ // hasComplexData: Array.isArray(data) && data.some(i => i.element_html && i.element_html.length > 100)
4585
+ // });
4369
4586
 
4370
4587
  let lastError = null;
4371
4588
  for (const port of CONFIG_PORTS) {
@@ -4375,7 +4592,7 @@ async function handleFrameCaptureComplete(sessionData) {
4375
4592
  try {
4376
4593
  // data is already { interactions: screenInteractions } from caller
4377
4594
  serializedBody = JSON.stringify(data);
4378
- console.log('[ScreenInteractions] JSON serialization successful, length:', serializedBody.length);
4595
+ // console.log('[ScreenInteractions] JSON serialization successful, length:', serializedBody.length);
4379
4596
  } catch (serError) {
4380
4597
  console.error('[ScreenInteractions] JSON serialization failed:', serError);
4381
4598
  throw new Error(`JSON serialization failed: ${serError.message}`);
@@ -4392,7 +4609,7 @@ async function handleFrameCaptureComplete(sessionData) {
4392
4609
  if (response.ok) {
4393
4610
  // Only log if we had to try multiple ports
4394
4611
  if (port !== CONFIG_PORTS[0]) {
4395
- console.log(`[ScreenInteractions] Connected to server on port ${port}`);
4612
+ // console.log(`[ScreenInteractions] Connected to server on port ${port}`);
4396
4613
  }
4397
4614
  return { success: true, result: { saved: true } };
4398
4615
  } else {
@@ -4416,13 +4633,13 @@ async function handleFrameCaptureComplete(sessionData) {
4416
4633
  );
4417
4634
 
4418
4635
  if (saveResult.success) {
4419
- console.log('Screen interactions saved successfully with comprehensive error handling');
4636
+ // console.log('Screen interactions saved successfully with comprehensive error handling');
4420
4637
  } else {
4421
4638
  console.error('[ErrorHandling] Failed to save screen interactions after comprehensive error handling');
4422
4639
  }
4423
4640
  } else if (screenInteractions.length > 0 && serverMode === 'browser-only') {
4424
4641
  // Browser-only mode: screen interactions not needed
4425
- console.log(`[Browser-Only] ✓ Skipping screen interactions save (browser-only mode)`);
4642
+ // console.log(`[Browser-Only] ✓ Skipping screen interactions save (browser-only mode)`);
4426
4643
  }
4427
4644
 
4428
4645
  // Stop session via session manager if available
@@ -4430,7 +4647,7 @@ async function handleFrameCaptureComplete(sessionData) {
4430
4647
  try {
4431
4648
  const stopResult = await sessionManager.stopRecording(currentSession.sessionId, currentOwnerId);
4432
4649
  if (stopResult.success) {
4433
- console.log(`Session stopped via session manager. Duration: ${stopResult.sessionDuration}ms, Frames: ${stopResult.frameCount}`);
4650
+ // console.log(`Session stopped via session manager. Duration: ${stopResult.sessionDuration}ms, Frames: ${stopResult.frameCount}`);
4434
4651
  } else {
4435
4652
  console.warn('Failed to stop session via session manager:', stopResult.error?.message);
4436
4653
  }
@@ -4482,7 +4699,7 @@ async function handleFrameCaptureComplete(sessionData) {
4482
4699
  serverPort: recordingServerPort
4483
4700
  }).catch(() => {});
4484
4701
  } else {
4485
- console.log('[Browser-Only] Skipping frameSessionComplete message - recording is in IndexedDB');
4702
+ // console.log('[Browser-Only] Skipping frameSessionComplete message - recording is in IndexedDB');
4486
4703
  }
4487
4704
 
4488
4705
  // Notify content script to hide recording indicator