@dynamicu/chromedebug-mcp 2.7.0 → 2.7.1

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,7 +1368,7 @@ 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
@@ -1380,7 +1380,7 @@ chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
1380
1380
  isCurrentlyRecordingAsync().then(async (recording) => {
1381
1381
  const currentTabId = await getCurrentTabIdAsync();
1382
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');
1383
+ // console.log('Re-injecting console logging for navigation during recording');
1384
1384
  startCapturingLogs(tabId).catch(err => {
1385
1385
  console.error('Failed to re-inject console logging:', err);
1386
1386
  });
@@ -1391,7 +1391,7 @@ chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
1391
1391
  } else {
1392
1392
  // Legacy fallback
1393
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');
1394
+ // console.log('Re-injecting console logging for navigation during recording');
1395
1395
  startCapturingLogs(tabId).catch(err => {
1396
1396
  console.error('Failed to re-inject console logging:', err);
1397
1397
  });
@@ -1470,7 +1470,7 @@ chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
1470
1470
  chrome.tabs.onRemoved.addListener((tabId, removeInfo) => {
1471
1471
  // Clean up any workflow recording state for closed tabs
1472
1472
  if (workflowRecordingTabs.has(tabId)) {
1473
- console.log(`[Workflow] Tab ${tabId} closed during recording, cleaning up`);
1473
+ // console.log(`[Workflow] Tab ${tabId} closed during recording, cleaning up`);
1474
1474
  workflowRecordingTabs.delete(tabId);
1475
1475
  workflowIncludeLogs.delete(tabId);
1476
1476
  workflowScreenshotSettings.delete(tabId);
@@ -1481,7 +1481,7 @@ chrome.tabs.onRemoved.addListener((tabId, removeInfo) => {
1481
1481
  if (buffer) {
1482
1482
  buffer.cleanup().then(() => {
1483
1483
  workflowLogBuffers.delete(tabId);
1484
- console.log(`[Workflow] Cleaned up WorkflowLogBuffer for closed tab ${tabId}`);
1484
+ // console.log(`[Workflow] Cleaned up WorkflowLogBuffer for closed tab ${tabId}`);
1485
1485
  }).catch(err => {
1486
1486
  console.error(`[Workflow] Error cleaning up buffer for closed tab ${tabId}:`, err);
1487
1487
  workflowLogBuffers.delete(tabId);
@@ -1519,11 +1519,148 @@ let isCurrentlyRecording = false; // DEPRECATED: Use isCurrentlyRecordingAsync()
1519
1519
  let currentRecordingSessionId = null; // DEPRECATED: Use getCurrentSessionIdAsync() instead
1520
1520
  let frameCounter = new Map(); // DEPRECATED: Session manager handles frame counting
1521
1521
 
1522
+ // =============================================================================
1523
+ // INACTIVITY AUTO-STOP - Stop recording if user is inactive
1524
+ // =============================================================================
1525
+ const DEFAULT_INACTIVITY_TIMEOUT_MS = 10 * 1000; // 10 seconds default
1526
+ let lastUserActivityTime = Date.now();
1527
+ let inactivityCheckInterval = null;
1528
+ let currentInactivityTimeout = DEFAULT_INACTIVITY_TIMEOUT_MS;
1529
+ let inactivityMonitoringStarted = false; // Track if monitoring has started
1530
+ let inactivityFallbackTimer = null; // Fallback timer if countdownComplete not received
1531
+ let inactivityDisabled = false; // User can disable for current session
1532
+
1533
+ /**
1534
+ * Start inactivity monitoring for a recording
1535
+ * @param {number} tabId - Tab ID to monitor
1536
+ */
1537
+ async function startInactivityMonitoring(tabId) {
1538
+ // Mark as started (for fallback timer check)
1539
+ inactivityMonitoringStarted = true;
1540
+
1541
+ // Clear fallback timer since we're starting properly
1542
+ if (inactivityFallbackTimer) {
1543
+ clearTimeout(inactivityFallbackTimer);
1544
+ inactivityFallbackTimer = null;
1545
+ }
1546
+
1547
+ // Load user's configured timeout from storage
1548
+ const settings = await chrome.storage.sync.get(['inactivityTimeout']);
1549
+ currentInactivityTimeout = (settings.inactivityTimeout || 10) * 1000; // Convert seconds to ms (default 10s)
1550
+
1551
+ lastUserActivityTime = Date.now();
1552
+
1553
+ // Tell content script to start tracking activity AND send config for countdown display
1554
+ try {
1555
+ await chrome.tabs.sendMessage(tabId, {
1556
+ action: 'startActivityTracking',
1557
+ inactivityTimeoutMs: currentInactivityTimeout,
1558
+ disabled: inactivityDisabled
1559
+ });
1560
+ } catch (error) {
1561
+ console.warn('[Inactivity] Could not start activity tracking in content script:', error.message);
1562
+ }
1563
+
1564
+ // Clear any existing interval
1565
+ if (inactivityCheckInterval) {
1566
+ clearInterval(inactivityCheckInterval);
1567
+ }
1568
+
1569
+ // If disabled, don't start the check interval
1570
+ if (inactivityDisabled) {
1571
+ return;
1572
+ }
1573
+
1574
+ // Check for inactivity every 2 seconds
1575
+ inactivityCheckInterval = setInterval(async () => {
1576
+ // Skip if disabled
1577
+ if (inactivityDisabled) return;
1578
+
1579
+ const timeSinceActivity = Date.now() - lastUserActivityTime;
1580
+ const timeRemaining = Math.max(0, currentInactivityTimeout - timeSinceActivity);
1581
+
1582
+ // Send countdown update to content script
1583
+ try {
1584
+ await chrome.tabs.sendMessage(tabId, {
1585
+ action: 'updateInactivityCountdown',
1586
+ timeRemaining: Math.ceil(timeRemaining / 1000),
1587
+ disabled: inactivityDisabled
1588
+ });
1589
+ } catch (e) {
1590
+ // Tab might be closed, ignore
1591
+ }
1592
+
1593
+ if (timeSinceActivity >= currentInactivityTimeout) {
1594
+ // Stop the recording first
1595
+ await stopRecording();
1596
+
1597
+ // Show notification with link to settings
1598
+ try {
1599
+ await chrome.notifications.create('inactivity-stop', {
1600
+ type: 'basic',
1601
+ iconUrl: 'icon128.png',
1602
+ title: 'Recording Auto-Stopped',
1603
+ message: `Recording stopped after ${Math.round(currentInactivityTimeout / 1000)}s of inactivity. Click to adjust timeout in Settings.`,
1604
+ priority: 2
1605
+ });
1606
+ } catch (e) {
1607
+ console.warn('[Inactivity] Could not show notification:', e.message);
1608
+ }
1609
+ }
1610
+ }, 2000); // Check every 2 seconds
1611
+ }
1612
+
1613
+ /**
1614
+ * Stop inactivity monitoring
1615
+ * @param {number} tabId - Tab ID that was being monitored
1616
+ */
1617
+ async function stopInactivityMonitoring(tabId) {
1618
+ if (inactivityCheckInterval) {
1619
+ clearInterval(inactivityCheckInterval);
1620
+ inactivityCheckInterval = null;
1621
+ }
1622
+
1623
+ // Clear fallback timer
1624
+ if (inactivityFallbackTimer) {
1625
+ clearTimeout(inactivityFallbackTimer);
1626
+ inactivityFallbackTimer = null;
1627
+ }
1628
+
1629
+ // Reset state for next recording
1630
+ inactivityMonitoringStarted = false;
1631
+ inactivityDisabled = false; // Reset disabled state for next session
1632
+
1633
+ // Tell content script to stop tracking
1634
+ if (tabId) {
1635
+ try {
1636
+ await chrome.tabs.sendMessage(tabId, { action: 'stopActivityTracking' });
1637
+ } catch (error) {
1638
+ // Tab might be closed, that's ok
1639
+ }
1640
+ }
1641
+ }
1642
+
1643
+ /**
1644
+ * Handle user activity report from content script
1645
+ * @param {number} timestamp - Activity timestamp
1646
+ */
1647
+ function handleUserActivity(timestamp) {
1648
+ lastUserActivityTime = timestamp || Date.now();
1649
+ }
1650
+
1651
+ // Handle notification clicks - open settings page when inactivity notification is clicked
1652
+ chrome.notifications.onClicked.addListener((notificationId) => {
1653
+ if (notificationId === 'inactivity-stop') {
1654
+ chrome.runtime.openOptionsPage();
1655
+ chrome.notifications.clear(notificationId);
1656
+ }
1657
+ });
1658
+
1522
1659
  // Initialize session manager
1523
1660
  (async function initializeSessionManager() {
1524
1661
  try {
1525
1662
  sessionManager = new ChromeExtensionSessionManager();
1526
- console.log('[ChromeSessionManager] Initialized successfully');
1663
+ // console.log('[ChromeSessionManager] Initialized successfully');
1527
1664
  } catch (error) {
1528
1665
  console.error('[ChromeSessionManager] Failed to initialize:', error);
1529
1666
  }
@@ -1659,7 +1796,7 @@ let workflowLogBuffers = new Map(); // Map of tabId to WorkflowLogBuffer instanc
1659
1796
  */
1660
1797
  async function initializeErrorHandling() {
1661
1798
  try {
1662
- console.log('[ErrorHandling] Initializing comprehensive error handling system...');
1799
+ // console.log('[ErrorHandling] Initializing comprehensive error handling system...');
1663
1800
 
1664
1801
  // Generate session ID if not exists
1665
1802
  if (!errorHandlingState.sessionId) {
@@ -1682,11 +1819,11 @@ async function initializeErrorHandling() {
1682
1819
  errorHandlingState.isInitialized = true;
1683
1820
  errorHandlingState.currentState = 'NORMAL_OPERATION';
1684
1821
 
1685
- console.log('[ErrorHandling] System initialization complete:', {
1686
- sessionId: errorHandlingState.sessionId,
1687
- state: errorHandlingState.currentState,
1688
- circuitBreaker: errorHandlingState.circuitBreakerState
1689
- });
1822
+ // console.log('[ErrorHandling] System initialization complete:', {
1823
+ // sessionId: errorHandlingState.sessionId,
1824
+ // state: errorHandlingState.currentState,
1825
+ // circuitBreaker: errorHandlingState.circuitBreakerState
1826
+ // });
1690
1827
 
1691
1828
  return true;
1692
1829
  } catch (error) {
@@ -1711,7 +1848,7 @@ async function initializeBackupStorage() {
1711
1848
  };
1712
1849
 
1713
1850
  request.onsuccess = () => {
1714
- console.log('[ErrorHandling] IndexedDB initialized successfully');
1851
+ // console.log('[ErrorHandling] IndexedDB initialized successfully');
1715
1852
  resolve(request.result);
1716
1853
  };
1717
1854
 
@@ -1741,7 +1878,7 @@ async function initializeBackupStorage() {
1741
1878
  errorStore.createIndex('timestamp', 'timestamp', { unique: false });
1742
1879
  }
1743
1880
 
1744
- console.log('[ErrorHandling] IndexedDB schema created');
1881
+ // console.log('[ErrorHandling] IndexedDB schema created');
1745
1882
  };
1746
1883
  });
1747
1884
  }
@@ -1752,7 +1889,7 @@ async function initializeBackupStorage() {
1752
1889
  function initializeCircuitBreaker() {
1753
1890
  errorHandlingState.circuitBreakerState = 'CLOSED';
1754
1891
  errorHandlingState.failedSaveCount = 0;
1755
- console.log('[ErrorHandling] Circuit breaker initialized in CLOSED state');
1892
+ // console.log('[ErrorHandling] Circuit breaker initialized in CLOSED state');
1756
1893
  }
1757
1894
 
1758
1895
  /**
@@ -1765,7 +1902,7 @@ async function setupNotificationSystem() {
1765
1902
  await chrome.notifications.clear(notificationId);
1766
1903
  }
1767
1904
 
1768
- console.log('[ErrorHandling] Notification system ready');
1905
+ // console.log('[ErrorHandling] Notification system ready');
1769
1906
  }
1770
1907
 
1771
1908
  /**
@@ -1804,7 +1941,7 @@ async function cleanupOldBackups() {
1804
1941
  }
1805
1942
  };
1806
1943
 
1807
- console.log('[ErrorHandling] Cleanup completed for data older than', ERROR_HANDLING_CONFIG.backupRetentionDays, 'days');
1944
+ // console.log('[ErrorHandling] Cleanup completed for data older than', ERROR_HANDLING_CONFIG.backupRetentionDays, 'days');
1808
1945
  };
1809
1946
  } catch (error) {
1810
1947
  console.error('[ErrorHandling] Failed to cleanup old backups:', error);
@@ -1831,13 +1968,13 @@ async function handleSaveAttempt(saveFunction, data, context = {}) {
1831
1968
  if (errorHandlingState.circuitBreakerState === 'OPEN') {
1832
1969
  const timeSinceLastFailure = Date.now() - (errorHandlingState.lastError?.timestamp || 0);
1833
1970
  if (timeSinceLastFailure < ERROR_HANDLING_CONFIG.resetTimeout) {
1834
- console.log('[ErrorHandling] Circuit breaker OPEN, attempting backup instead');
1971
+ // console.log('[ErrorHandling] Circuit breaker OPEN, attempting backup instead');
1835
1972
  await backupFailedData(data, context);
1836
1973
  return { success: false, circuitBreakerOpen: true };
1837
1974
  } else {
1838
1975
  // Try half-open
1839
1976
  errorHandlingState.circuitBreakerState = 'HALF_OPEN';
1840
- console.log('[ErrorHandling] Circuit breaker moving to HALF_OPEN state');
1977
+ // console.log('[ErrorHandling] Circuit breaker moving to HALF_OPEN state');
1841
1978
  }
1842
1979
  }
1843
1980
 
@@ -1848,7 +1985,7 @@ async function handleSaveAttempt(saveFunction, data, context = {}) {
1848
1985
  if (result && result.success !== false) {
1849
1986
  errorHandlingState.circuitBreakerState = 'CLOSED';
1850
1987
  errorHandlingState.failedSaveCount = 0;
1851
- console.log('[ErrorHandling] Save successful, circuit breaker CLOSED');
1988
+ // console.log('[ErrorHandling] Save successful, circuit breaker CLOSED');
1852
1989
  return { success: true, result };
1853
1990
  } else {
1854
1991
  throw new Error('Save function returned failure');
@@ -1888,7 +2025,7 @@ async function handleSaveFailure(error, data, context, attempt) {
1888
2025
  // Attempt backup
1889
2026
  try {
1890
2027
  await backupFailedData(data, context);
1891
- console.log('[ErrorHandling] Data backed up successfully');
2028
+ // console.log('[ErrorHandling] Data backed up successfully');
1892
2029
  } catch (backupError) {
1893
2030
  console.error('[ErrorHandling] CRITICAL: Backup also failed:', backupError);
1894
2031
  await createUserNotification('CRITICAL', 'Data loss imminent - manual intervention required');
@@ -1984,7 +2121,7 @@ async function backupFailedData(data, context) {
1984
2121
  const store = transaction.objectStore('sessionBackups');
1985
2122
 
1986
2123
  store.add(backupData);
1987
- console.log('[ErrorHandling] Data backed up with session ID:', errorHandlingState.sessionId);
2124
+ // console.log('[ErrorHandling] Data backed up with session ID:', errorHandlingState.sessionId);
1988
2125
  };
1989
2126
 
1990
2127
  // Also add to retained interactions if relevant
@@ -2025,7 +2162,7 @@ async function createUserNotification(priority, message) {
2025
2162
  }
2026
2163
 
2027
2164
  await chrome.notifications.create(notificationId, notificationOptions);
2028
- console.log('[ErrorHandling] User notification created:', notificationId);
2165
+ // console.log('[ErrorHandling] User notification created:', notificationId);
2029
2166
 
2030
2167
  // Set up notification click handlers
2031
2168
  chrome.notifications.onButtonClicked.addListener((notifId, buttonIndex) => {
@@ -2045,16 +2182,16 @@ async function createUserNotification(priority, message) {
2045
2182
  async function handleNotificationAction(buttonIndex, priority) {
2046
2183
  switch (buttonIndex) {
2047
2184
  case 0: // Retry Save
2048
- console.log('[ErrorHandling] User requested retry');
2185
+ // console.log('[ErrorHandling] User requested retry');
2049
2186
  await attemptRecovery();
2050
2187
  break;
2051
2188
  case 1: // View Details
2052
- console.log('[ErrorHandling] User requested error details');
2189
+ // console.log('[ErrorHandling] User requested error details');
2053
2190
  // Could open an options page or log details
2054
2191
  break;
2055
2192
  case 2: // Download Backup (for critical errors)
2056
2193
  if (priority === 'CRITICAL') {
2057
- console.log('[ErrorHandling] User requested backup download');
2194
+ // console.log('[ErrorHandling] User requested backup download');
2058
2195
  await downloadBackupData();
2059
2196
  }
2060
2197
  break;
@@ -2074,14 +2211,14 @@ async function attemptRecovery() {
2074
2211
 
2075
2212
  store.getAll().onsuccess = (event) => {
2076
2213
  const backups = event.target.result;
2077
- console.log('[ErrorHandling] Found', backups.length, 'backup records for recovery');
2214
+ // console.log('[ErrorHandling] Found', backups.length, 'backup records for recovery');
2078
2215
 
2079
2216
  // Process each backup
2080
2217
  backups.forEach(async (backup) => {
2081
2218
  try {
2082
2219
  // Attempt to save the backed up data
2083
2220
  // This would call the original save function with the backed up data
2084
- console.log('[ErrorHandling] Attempting recovery for session:', backup.sessionId);
2221
+ // console.log('[ErrorHandling] Attempting recovery for session:', backup.sessionId);
2085
2222
  } catch (error) {
2086
2223
  console.error('[ErrorHandling] Recovery failed for session:', backup.sessionId, error);
2087
2224
  }
@@ -2124,7 +2261,7 @@ async function downloadBackupData() {
2124
2261
  filename: `chrome-debug-backup-${Date.now()}.json`
2125
2262
  });
2126
2263
 
2127
- console.log('[ErrorHandling] Backup data download initiated');
2264
+ // console.log('[ErrorHandling] Backup data download initiated');
2128
2265
  };
2129
2266
  };
2130
2267
  };
@@ -2140,7 +2277,7 @@ async function createOffscreenDocument() {
2140
2277
  const hasDocument = await chrome.offscreen.hasDocument();
2141
2278
  if (hasDocument) {
2142
2279
  hasOffscreenDocument = true;
2143
- console.log('Offscreen document already exists');
2280
+ // console.log('Offscreen document already exists');
2144
2281
  return;
2145
2282
  }
2146
2283
 
@@ -2151,12 +2288,12 @@ async function createOffscreenDocument() {
2151
2288
  justification: 'Recording tab frames for Chrome Debug'
2152
2289
  });
2153
2290
  hasOffscreenDocument = true;
2154
- console.log('Created new offscreen document');
2291
+ // console.log('Created new offscreen document');
2155
2292
  } catch (error) {
2156
2293
  if (error.message.includes('Only a single offscreen document may be created')) {
2157
2294
  // Document already exists, just mark it as available
2158
2295
  hasOffscreenDocument = true;
2159
- console.log('Offscreen document already exists (caught error)');
2296
+ // console.log('Offscreen document already exists (caught error)');
2160
2297
  } else {
2161
2298
  throw error;
2162
2299
  }
@@ -2174,7 +2311,7 @@ async function closeOffscreenDocument() {
2174
2311
  }
2175
2312
 
2176
2313
  chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2177
- console.log('Received message:', request.action || request.type || 'unknown');
2314
+ // console.log('Received message:', request.action || request.type || 'unknown');
2178
2315
 
2179
2316
  if (request.action === 'sendToServer') {
2180
2317
  // Primary port is 3028 - try it first, then fallback to others if needed
@@ -2182,11 +2319,11 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2182
2319
 
2183
2320
  async function tryPorts() {
2184
2321
  let lastError = null;
2185
- console.log('Trying to connect to server...');
2322
+ // console.log('Trying to connect to server...');
2186
2323
 
2187
2324
  for (const port of ports) {
2188
2325
  try {
2189
- console.log(`Trying port ${port}...`);
2326
+ // console.log(`Trying port ${port}...`);
2190
2327
  const controller = new AbortController();
2191
2328
  const timeoutId = setTimeout(() => controller.abort(), DISCOVERY_TIMEOUT);
2192
2329
 
@@ -2203,7 +2340,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2203
2340
 
2204
2341
  if (response.ok) {
2205
2342
  const result = await response.json();
2206
- console.log(`Success on port ${port}:`, result);
2343
+ // console.log(`Success on port ${port}:`, result);
2207
2344
  sendResponse({ success: true, result, port });
2208
2345
  return;
2209
2346
  } else {
@@ -2211,7 +2348,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2211
2348
  try {
2212
2349
  const errorData = await response.json();
2213
2350
  if (errorData.message || errorData.error) {
2214
- console.log(`Port ${port} error:`, errorData);
2351
+ // console.log(`Port ${port} error:`, errorData);
2215
2352
  sendResponse({
2216
2353
  success: false,
2217
2354
  result: errorData,
@@ -2223,11 +2360,11 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2223
2360
  // Response wasn't JSON
2224
2361
  }
2225
2362
  lastError = `Port ${port}: HTTP ${response.status}`;
2226
- console.log(lastError);
2363
+ // console.log(lastError);
2227
2364
  }
2228
2365
  } catch (e) {
2229
2366
  lastError = `Port ${port}: ${e.message}`;
2230
- console.log(lastError);
2367
+ // console.log(lastError);
2231
2368
  }
2232
2369
  }
2233
2370
 
@@ -2305,7 +2442,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2305
2442
 
2306
2443
  // Session manager lease renewal handler
2307
2444
  if (request.action === 'renewLease') {
2308
- console.log('[Background] RENEW LEASE - Session:', request.sessionId, 'Manager exists:', !!sessionManager);
2445
+ // console.log('[Background] RENEW LEASE - Session:', request.sessionId, 'Manager exists:', !!sessionManager);
2309
2446
 
2310
2447
  if (!sessionManager) {
2311
2448
  console.error('[Background] Session manager not available');
@@ -2321,7 +2458,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2321
2458
  };
2322
2459
 
2323
2460
  sessionManager.renewLease(leaseRequest).then((result) => {
2324
- console.log('[Background] Lease renewed - Success:', result.success);
2461
+ // console.log('[Background] Lease renewed - Success:', result.success);
2325
2462
  sendResponse(result);
2326
2463
  }).catch((error) => {
2327
2464
  console.error('[Background] Error renewing lease:', error);
@@ -2355,6 +2492,45 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2355
2492
  return true;
2356
2493
  }
2357
2494
 
2495
+ // User activity handler for inactivity tracking
2496
+ if (request.action === 'userActivity') {
2497
+ handleUserActivity(request.timestamp);
2498
+ sendResponse({ success: true });
2499
+ return false; // Synchronous response
2500
+ }
2501
+
2502
+ // Countdown complete handler - content script finished 3-2-1 countdown
2503
+ if (request.action === 'countdownComplete') {
2504
+ // Start inactivity monitoring now that countdown is done
2505
+ // Use isCurrentlyRecording (the actual state variable)
2506
+ if (isCurrentlyRecording && recordingTabId && !inactivityMonitoringStarted) {
2507
+ startInactivityMonitoring(recordingTabId);
2508
+ }
2509
+ sendResponse({ success: true });
2510
+ return false;
2511
+ }
2512
+
2513
+ // Toggle inactivity timeout (user clicked disable/enable button)
2514
+ if (request.action === 'toggleInactivityTimeout') {
2515
+ inactivityDisabled = !inactivityDisabled;
2516
+
2517
+ if (inactivityDisabled) {
2518
+ // Stop the check interval but keep tracking activity
2519
+ if (inactivityCheckInterval) {
2520
+ clearInterval(inactivityCheckInterval);
2521
+ inactivityCheckInterval = null;
2522
+ }
2523
+ } else {
2524
+ // Restart monitoring
2525
+ if (recordingTabId && !inactivityCheckInterval) {
2526
+ startInactivityMonitoring(recordingTabId);
2527
+ }
2528
+ }
2529
+
2530
+ sendResponse({ success: true, disabled: inactivityDisabled });
2531
+ return false;
2532
+ }
2533
+
2358
2534
  // Force stop session handler (emergency)
2359
2535
  if (request.action === 'forceStopSession') {
2360
2536
  if (!sessionManager) {
@@ -2408,7 +2584,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2408
2584
  */
2409
2585
  /*
2410
2586
  if (request.action === 'takeStandaloneSnapshot') {
2411
- console.log('Taking standalone snapshot for tab:', request.tabId);
2587
+ // console.log('Taking standalone snapshot for tab:', request.tabId);
2412
2588
  takeStandaloneSnapshot(request.tabId, request.note).then((result) => {
2413
2589
  sendResponse({ success: true, sessionId: result.sessionId });
2414
2590
  }).catch((error) => {
@@ -2456,7 +2632,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2456
2632
  }
2457
2633
 
2458
2634
  if (request.action === 'startRecordingFromContent') {
2459
- console.log('Starting recording from content script');
2635
+ // console.log('Starting recording from content script');
2460
2636
  const tabId = sender.tab.id;
2461
2637
 
2462
2638
  // Store recording state and show notification
@@ -2480,14 +2656,14 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2480
2656
  }
2481
2657
 
2482
2658
  if (request.action === 'deleteRecording') {
2483
- console.log('Deleting recording:', request.recordingId);
2659
+ // console.log('Deleting recording:', request.recordingId);
2484
2660
  deleteRecordingFromServer(request.recordingId, sendResponse);
2485
2661
  return true;
2486
2662
  }
2487
2663
 
2488
2664
  // Workflow recording handlers
2489
2665
  if (request.action === 'startWorkflowRecording') {
2490
- console.log('Starting workflow recording for tab:', request.tabId);
2666
+ // console.log('Starting workflow recording for tab:', request.tabId);
2491
2667
  startWorkflowRecording(
2492
2668
  request.tabId,
2493
2669
  request.includeLogsInExport,
@@ -2504,7 +2680,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2504
2680
 
2505
2681
  if (request.action === 'stopWorkflowRecording') {
2506
2682
  const tabId = request.tabId || sender.tab?.id;
2507
- console.log('Stopping workflow recording for tab:', tabId);
2683
+ // console.log('Stopping workflow recording for tab:', tabId);
2508
2684
  // stopWorkflowRecording already returns { success: true, workflow: {...}, savedToServer: bool }
2509
2685
  // so we pass it through directly - don't double-wrap!
2510
2686
  stopWorkflowRecording(tabId).then(async (result) => {
@@ -2600,7 +2776,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2600
2776
  frameIndex: frameIndex
2601
2777
  };
2602
2778
  screenInteractions.push(interaction);
2603
- console.log('Screen interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
2779
+ // console.log('Screen interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
2604
2780
  }
2605
2781
  }).catch(error => {
2606
2782
  console.error('Error validating recording state for screen interaction:', error);
@@ -2613,7 +2789,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2613
2789
  frameIndex: frameCounter.get(currentRecordingSessionId) || 0
2614
2790
  };
2615
2791
  screenInteractions.push(interaction);
2616
- console.log('Screen interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
2792
+ // console.log('Screen interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
2617
2793
  }
2618
2794
  }
2619
2795
  }
@@ -2729,18 +2905,18 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2729
2905
 
2730
2906
  // Handle workflow screenshot capture
2731
2907
  if (request.action === 'captureWorkflowScreenshot' && sender.tab) {
2732
- console.log('[SCREENSHOT-DEBUG] background.js - Received captureWorkflowScreenshot message');
2908
+ // console.log('[SCREENSHOT-DEBUG] background.js - Received captureWorkflowScreenshot message');
2733
2909
  const tabId = sender.tab.id;
2734
2910
  const settings = request.settings || {};
2735
- console.log('[SCREENSHOT-DEBUG] background.js - tabId:', tabId);
2736
- console.log('[SCREENSHOT-DEBUG] background.js - settings:', JSON.stringify(settings));
2911
+ // console.log('[SCREENSHOT-DEBUG] background.js - tabId:', tabId);
2912
+ // console.log('[SCREENSHOT-DEBUG] background.js - settings:', JSON.stringify(settings));
2737
2913
 
2738
2914
  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');
2915
+ // console.log('[SCREENSHOT-DEBUG] background.js - captureTabScreenshot succeeded');
2916
+ // console.log('[SCREENSHOT-DEBUG] background.js - screenshotData type:', typeof screenshotData);
2917
+ // console.log('[SCREENSHOT-DEBUG] background.js - screenshotData length:', screenshotData?.length);
2918
+ // console.log('[SCREENSHOT-DEBUG] background.js - screenshotData preview:', screenshotData?.substring(0, 100));
2919
+ // console.log('[SCREENSHOT-DEBUG] background.js - Sending response with success: true');
2744
2920
  sendResponse({ success: true, screenshotData });
2745
2921
  }).catch((error) => {
2746
2922
  console.error('[SCREENSHOT-DEBUG] background.js - captureTabScreenshot FAILED');
@@ -2774,7 +2950,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
2774
2950
  /*
2775
2951
  async function takeStandaloneSnapshot(tabId, note = '') {
2776
2952
  try {
2777
- console.log('Taking standalone snapshot for tab:', tabId);
2953
+ // console.log('Taking standalone snapshot for tab:', tabId);
2778
2954
 
2779
2955
  // Create a unique session ID for the snapshot
2780
2956
  const sessionId = `snapshot_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
@@ -2850,7 +3026,7 @@ async function takeStandaloneSnapshot(tabId, note = '') {
2850
3026
 
2851
3027
  if (response.ok) {
2852
3028
  const result = await response.json();
2853
- console.log('Snapshot uploaded successfully:', sessionId);
3029
+ // console.log('Snapshot uploaded successfully:', sessionId);
2854
3030
  uploadSuccess = true;
2855
3031
  break;
2856
3032
  }
@@ -2874,34 +3050,34 @@ async function takeStandaloneSnapshot(tabId, note = '') {
2874
3050
 
2875
3051
  // Capture screenshot for workflow recording
2876
3052
  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));
3053
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - ENTRY');
3054
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - tabId:', tabId);
3055
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - settings:', JSON.stringify(settings));
2880
3056
 
2881
3057
  try {
2882
3058
  // Get the tab to find its window
2883
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Getting tab info...');
3059
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Getting tab info...');
2884
3060
  const tab = await chrome.tabs.get(tabId);
2885
3061
  const windowId = tab.windowId;
2886
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - windowId:', windowId);
2887
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - tab.url:', tab.url);
3062
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - windowId:', windowId);
3063
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - tab.url:', tab.url);
2888
3064
 
2889
3065
  const captureOptions = {
2890
3066
  format: settings.format || 'jpeg',
2891
3067
  quality: settings.quality || 30
2892
3068
  };
2893
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - captureOptions:', JSON.stringify(captureOptions));
2894
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Calling chrome.tabs.captureVisibleTab...');
3069
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - captureOptions:', JSON.stringify(captureOptions));
3070
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Calling chrome.tabs.captureVisibleTab...');
2895
3071
 
2896
3072
  const dataUrl = await chrome.tabs.captureVisibleTab(windowId, captureOptions);
2897
3073
 
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));
3074
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - captureVisibleTab SUCCESS');
3075
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - dataUrl length:', dataUrl?.length);
3076
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - dataUrl prefix:', dataUrl?.substring(0, 100));
2901
3077
 
2902
3078
  // If resolution is specified, resize the image
2903
3079
  if (settings.maxWidth || settings.maxHeight) {
2904
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Resizing required, maxWidth:', settings.maxWidth, 'maxHeight:', settings.maxHeight);
3080
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Resizing required, maxWidth:', settings.maxWidth, 'maxHeight:', settings.maxHeight);
2905
3081
  // Create an image element to get dimensions
2906
3082
  const img = new Image();
2907
3083
  const canvas = new OffscreenCanvas(1, 1);
@@ -2941,8 +3117,8 @@ async function captureTabScreenshot(tabId, settings) {
2941
3117
  });
2942
3118
  }
2943
3119
 
2944
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - No resize needed, returning dataUrl');
2945
- console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Final dataUrl length:', dataUrl?.length);
3120
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - No resize needed, returning dataUrl');
3121
+ // console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Final dataUrl length:', dataUrl?.length);
2946
3122
  return dataUrl;
2947
3123
  } catch (error) {
2948
3124
  console.error('[SCREENSHOT-DEBUG] captureTabScreenshot - EXCEPTION CAUGHT');
@@ -2956,7 +3132,7 @@ async function captureTabScreenshot(tabId, settings) {
2956
3132
  // Start recording
2957
3133
  // Detect if server is available (server mode vs browser-only mode)
2958
3134
  async function detectServerMode() {
2959
- console.log('[ServerDetection] Checking server availability...');
3135
+ // console.log('[ServerDetection] Checking server availability...');
2960
3136
 
2961
3137
  for (const port of CONFIG_PORTS) {
2962
3138
  try {
@@ -2970,7 +3146,7 @@ async function detectServerMode() {
2970
3146
  ]);
2971
3147
 
2972
3148
  if (response.ok) {
2973
- console.log(`[ServerDetection] Server detected on port ${port}`);
3149
+ // console.log(`[ServerDetection] Server detected on port ${port}`);
2974
3150
  serverMode = 'server';
2975
3151
  return 'server';
2976
3152
  }
@@ -2979,7 +3155,7 @@ async function detectServerMode() {
2979
3155
  }
2980
3156
  }
2981
3157
 
2982
- console.log('[ServerDetection] No server detected - using browser-only mode');
3158
+ // console.log('[ServerDetection] No server detected - using browser-only mode');
2983
3159
  serverMode = 'browser-only';
2984
3160
  return 'browser-only';
2985
3161
  }
@@ -3007,7 +3183,7 @@ async function startRecording(tabId, settings = {}) {
3007
3183
  try {
3008
3184
  // Detect server mode before starting
3009
3185
  await detectServerMode();
3010
- console.log(`[Recording] Mode: ${serverMode}`);
3186
+ // console.log(`[Recording] Mode: ${serverMode}`);
3011
3187
 
3012
3188
  // Check if session manager is available
3013
3189
  if (!sessionManager) {
@@ -3028,12 +3204,12 @@ async function startRecording(tabId, settings = {}) {
3028
3204
 
3029
3205
  // Start capturing console logs FIRST, before any other setup
3030
3206
  const logsStarted = await startCapturingLogs(tabId);
3031
- console.log('Console log capture started:', logsStarted);
3207
+ // console.log('Console log capture started:', logsStarted);
3032
3208
 
3033
3209
  // Give console interception time to settle (increased from 100ms to 500ms for reliability)
3034
3210
  if (logsStarted) {
3035
3211
  await new Promise(resolve => setTimeout(resolve, 500));
3036
- console.log('[Recording] Console interception ready');
3212
+ // console.log('[Recording] Console interception ready');
3037
3213
  } else {
3038
3214
  console.warn('[Recording] Console capture unavailable for this page - recording will proceed without console logs');
3039
3215
  }
@@ -3046,7 +3222,7 @@ async function startRecording(tabId, settings = {}) {
3046
3222
  targetTabId: tabId
3047
3223
  });
3048
3224
 
3049
- console.log('Got stream ID:', streamId);
3225
+ // console.log('Got stream ID:', streamId);
3050
3226
 
3051
3227
  // Create session with session manager
3052
3228
  const sessionConfig = {
@@ -3079,7 +3255,7 @@ async function startRecording(tabId, settings = {}) {
3079
3255
 
3080
3256
  // STEP 4: Initialize browser-only recording if in browser-only mode
3081
3257
  if (serverMode === 'browser-only' && browserRecordingManager) {
3082
- console.log('[Recording] Initializing browser-only recording in IndexedDB');
3258
+ // console.log('[Recording] Initializing browser-only recording in IndexedDB');
3083
3259
  const tab = await chrome.tabs.get(tabId);
3084
3260
  await browserRecordingManager.startRecording(sessionId, {
3085
3261
  tabId: tabId,
@@ -3112,7 +3288,19 @@ async function startRecording(tabId, settings = {}) {
3112
3288
  // Update badge
3113
3289
  chrome.action.setBadgeText({ text: 'REC' });
3114
3290
  chrome.action.setBadgeBackgroundColor({ color: '#FF0000' });
3115
-
3291
+
3292
+ // DON'T start inactivity monitoring here - wait for countdownComplete message
3293
+ // This ensures the 10s timer starts AFTER the 3s visual countdown, not before
3294
+ // Set a fallback timer in case content script doesn't send countdownComplete
3295
+ inactivityMonitoringStarted = false;
3296
+ if (inactivityFallbackTimer) clearTimeout(inactivityFallbackTimer);
3297
+ inactivityFallbackTimer = setTimeout(async () => {
3298
+ // Use isCurrentlyRecording (the actual state variable)
3299
+ if (isCurrentlyRecording && !inactivityMonitoringStarted) {
3300
+ await startInactivityMonitoring(tabId);
3301
+ }
3302
+ }, 5000); // 5s = 3s countdown + 2s buffer
3303
+
3116
3304
  // If on a restricted page, notify user
3117
3305
  const tab = await chrome.tabs.get(tabId);
3118
3306
  if (tab.url && (tab.url.startsWith('chrome://') || tab.url.startsWith('chrome-extension://'))) {
@@ -3133,12 +3321,12 @@ async function startRecording(tabId, settings = {}) {
3133
3321
  sessionId: sessionId
3134
3322
  }).catch(async (error) => {
3135
3323
  // Content script might not be injected, try to inject it
3136
- console.log('Could not notify content script, attempting to inject:', error);
3324
+ // console.log('Could not notify content script, attempting to inject:', error);
3137
3325
 
3138
3326
  // First check if this tab allows content script injection
3139
3327
  const tab = await chrome.tabs.get(tabId);
3140
3328
  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);
3329
+ // console.log('Cannot inject content script into restricted URL:', tab.url);
3142
3330
  return;
3143
3331
  }
3144
3332
 
@@ -3174,7 +3362,7 @@ async function startRecording(tabId, settings = {}) {
3174
3362
  url: tab.url,
3175
3363
  title: tab.title
3176
3364
  });
3177
- console.log('[Recording] Browser recording initialized for session:', sessionId);
3365
+ // console.log('[Recording] Browser recording initialized for session:', sessionId);
3178
3366
  }
3179
3367
 
3180
3368
  // Send stream ID, session info, and settings to offscreen document for frame capture
@@ -3194,7 +3382,7 @@ async function startRecording(tabId, settings = {}) {
3194
3382
  }
3195
3383
  });
3196
3384
 
3197
- console.log('Recording started in', serverMode, 'mode');
3385
+ // console.log('Recording started in', serverMode, 'mode');
3198
3386
  } catch (error) {
3199
3387
  console.error('Error in startRecording:', error);
3200
3388
  throw error;
@@ -3213,13 +3401,16 @@ async function stopRecording() {
3213
3401
  // Check if currently recording via session manager
3214
3402
  const currentlyRecording = await isCurrentlyRecordingAsync();
3215
3403
  if (!currentlyRecording) {
3216
- console.log('No active recording session to stop');
3404
+ // console.log('No active recording session to stop');
3217
3405
  return { success: false, error: 'No active recording' };
3218
3406
  }
3219
3407
 
3220
3408
  // Store sessionId before clearing it
3221
3409
  const stoppedSessionId = currentSession?.sessionId;
3222
3410
 
3411
+ // Stop inactivity monitoring
3412
+ await stopInactivityMonitoring(recordingTabId);
3413
+
3223
3414
  // Capture frame count and duration for the response
3224
3415
  let recordedFrameCount = 0;
3225
3416
  let recordedDuration = 0;
@@ -3233,11 +3424,11 @@ async function stopRecording() {
3233
3424
  } else {
3234
3425
  recordedFrameCount = stopResult.frameCount || 0;
3235
3426
  recordedDuration = stopResult.sessionDuration || 0;
3236
- console.log(`Recording stopped. Duration: ${recordedDuration}ms, Frames: ${recordedFrameCount}`);
3427
+ // console.log(`Recording stopped. Duration: ${recordedDuration}ms, Frames: ${recordedFrameCount}`);
3237
3428
 
3238
3429
  // Finalize browser-only recording if in browser-only mode
3239
3430
  if (serverMode === 'browser-only' && browserRecordingManager) {
3240
- console.log('[Browser-Only] Finalizing browser recording in IndexedDB');
3431
+ // console.log('[Browser-Only] Finalizing browser recording in IndexedDB');
3241
3432
  await browserRecordingManager.stopRecording(currentSession.sessionId);
3242
3433
  }
3243
3434
  }
@@ -3248,10 +3439,10 @@ async function stopRecording() {
3248
3439
  let flushCompleted = false;
3249
3440
  if (logBuffer) {
3250
3441
  try {
3251
- console.log('[Background] Flushing all buffered logs before stop...');
3442
+ // console.log('[Background] Flushing all buffered logs before stop...');
3252
3443
  await logBuffer.flushAll();
3253
3444
  flushCompleted = true;
3254
- console.log('[Background] Successfully flushed all buffered logs');
3445
+ // console.log('[Background] Successfully flushed all buffered logs');
3255
3446
  } catch (flushError) {
3256
3447
  console.error('[Background] Failed to flush logs during stop:', flushError);
3257
3448
  // Continue with stop process even if flush fails
@@ -3271,25 +3462,25 @@ async function stopRecording() {
3271
3462
 
3272
3463
  // CRITICAL: Store recordingTabId BEFORE clearing it (for cleanup)
3273
3464
  const previousRecordingTabId = recordingTabId;
3274
- console.log('[Background] previousRecordingTabId:', previousRecordingTabId, 'stoppedSessionId:', stoppedSessionId);
3465
+ // console.log('[Background] previousRecordingTabId:', previousRecordingTabId, 'stoppedSessionId:', stoppedSessionId);
3275
3466
 
3276
3467
  // CRITICAL FIX: Send stop-screen-capture-tracking message to recording tab WITH sessionId
3277
3468
  // so it can show the completion UI
3278
3469
  if (previousRecordingTabId && stoppedSessionId) {
3279
3470
  try {
3280
- console.log('[Background] Sending recording-complete-show-ui message to tab:', previousRecordingTabId, 'with sessionId:', stoppedSessionId);
3471
+ // console.log('[Background] Sending recording-complete-show-ui message to tab:', previousRecordingTabId, 'with sessionId:', stoppedSessionId);
3281
3472
  await chrome.tabs.sendMessage(previousRecordingTabId, {
3282
3473
  type: 'recording-complete-show-ui',
3283
3474
  sessionId: stoppedSessionId
3284
3475
  }).catch((err) => {
3285
- console.log('[Background] Could not send completion UI message to recording tab:', err);
3476
+ // console.log('[Background] Could not send completion UI message to recording tab:', err);
3286
3477
  });
3287
- console.log('[Background] Successfully sent recording-complete-show-ui message');
3478
+ // console.log('[Background] Successfully sent recording-complete-show-ui message');
3288
3479
  } catch (error) {
3289
3480
  console.error('[Background] Failed to send completion UI message:', error);
3290
3481
  }
3291
3482
  } else {
3292
- console.log('[Background] NOT sending recording-complete-show-ui - missing previousRecordingTabId or stoppedSessionId');
3483
+ // console.log('[Background] NOT sending recording-complete-show-ui - missing previousRecordingTabId or stoppedSessionId');
3293
3484
  }
3294
3485
 
3295
3486
  // CRITICAL FIX: Send stop-screen-capture-tracking message to ALL content scripts
@@ -3301,13 +3492,13 @@ async function stopRecording() {
3301
3492
  type: 'stop-screen-capture-tracking'
3302
3493
  }).catch(() => {
3303
3494
  // Ignore errors for tabs that don't have content scripts
3304
- console.log(`[Background] Could not send cleanup message to tab ${tab.id}`);
3495
+ // console.log(`[Background] Could not send cleanup message to tab ${tab.id}`);
3305
3496
  });
3306
3497
  }
3307
3498
  return Promise.resolve();
3308
3499
  });
3309
3500
  await Promise.all(cleanupPromises);
3310
- console.log('[Background] Cleanup messages sent to all content scripts');
3501
+ // console.log('[Background] Cleanup messages sent to all content scripts');
3311
3502
  } catch (error) {
3312
3503
  console.error('[Background] Failed to send cleanup messages to content scripts:', error);
3313
3504
  }
@@ -3315,7 +3506,7 @@ async function stopRecording() {
3315
3506
  // CRITICAL FIX: Restore original console methods and remove event listeners
3316
3507
  if (previousRecordingTabId) {
3317
3508
  try {
3318
- console.log('[Background] Stopping console log capture for tab:', previousRecordingTabId);
3509
+ // console.log('[Background] Stopping console log capture for tab:', previousRecordingTabId);
3319
3510
  await stopCapturingLogs(previousRecordingTabId);
3320
3511
  } catch (cleanupError) {
3321
3512
  console.error('[Background] Failed to cleanup console interceptor:', cleanupError);
@@ -3339,11 +3530,11 @@ async function stopRecording() {
3339
3530
 
3340
3531
  // CRITICAL: Clear pending frame queue to prevent infinite retry loop
3341
3532
  if (stoppedSessionId && pendingFrameQueue.has(stoppedSessionId)) {
3342
- console.log(`[FrameQueue] Clearing ${pendingFrameQueue.get(stoppedSessionId).length} pending frames for stopped session ${stoppedSessionId}`);
3533
+ // console.log(`[FrameQueue] Clearing ${pendingFrameQueue.get(stoppedSessionId).length} pending frames for stopped session ${stoppedSessionId}`);
3343
3534
  pendingFrameQueue.delete(stoppedSessionId);
3344
3535
  }
3345
3536
 
3346
- console.log('Stop message sent to offscreen document');
3537
+ // console.log('Stop message sent to offscreen document');
3347
3538
 
3348
3539
  // Notify popup to refresh recordings list
3349
3540
  chrome.runtime.sendMessage({
@@ -3351,7 +3542,7 @@ async function stopRecording() {
3351
3542
  sessionId: stoppedSessionId
3352
3543
  }).catch(() => {
3353
3544
  // Popup might not be open, that's okay
3354
- console.log('[Background] Popup not available to notify of recording stop');
3545
+ // console.log('[Background] Popup not available to notify of recording stop');
3355
3546
  });
3356
3547
 
3357
3548
  // Format duration as human-readable string (e.g., "1m 30s" or "45s")
@@ -3380,7 +3571,7 @@ async function stopRecording() {
3380
3571
  // CRITICAL FIX: Clean up console interceptor even on error
3381
3572
  if (errorRecordingTabId) {
3382
3573
  try {
3383
- console.log('[Background] Emergency cleanup of console interceptor for tab:', errorRecordingTabId);
3574
+ // console.log('[Background] Emergency cleanup of console interceptor for tab:', errorRecordingTabId);
3384
3575
  await stopCapturingLogs(errorRecordingTabId);
3385
3576
  } catch (cleanupError) {
3386
3577
  console.error('[Background] Failed to cleanup console interceptor during error handling:', cleanupError);
@@ -3407,25 +3598,25 @@ async function stopRecording() {
3407
3598
  // Capture console logs from the recording tab
3408
3599
  // REFACTORED: Now uses shared console-interception-library.js
3409
3600
  async function startCapturingLogs(tabId) {
3410
- console.log('[Screen Recording] Starting console interception using shared library');
3601
+ // console.log('[Screen Recording] Starting console interception using shared library');
3411
3602
  return await self.ConsoleInterceptionLibrary.startConsoleInterception(tabId, SCREEN_RECORDING_CONSOLE_CONFIG);
3412
3603
  }
3413
3604
 
3414
3605
  // REFACTORED: Now uses shared console-interception-library.js via proper namespace
3415
3606
  async function stopCapturingLogs(tabId) {
3416
- console.log('[Screen Recording] Stopping console interception using shared library');
3607
+ // console.log('[Screen Recording] Stopping console interception using shared library');
3417
3608
  return await self.ConsoleInterceptionLibrary.stopConsoleInterception(tabId, SCREEN_RECORDING_CONSOLE_CONFIG);
3418
3609
  }
3419
3610
 
3420
3611
  // Workflow Recording Functions
3421
3612
  async function startWorkflowRecording(tabId, includeLogsInExport, sessionName = null, screenshotSettings = null) {
3422
3613
  try {
3423
- console.log('Starting workflow recording for tab:', tabId);
3614
+ // console.log('Starting workflow recording for tab:', tabId);
3424
3615
 
3425
3616
  // Check if this tab allows content script injection
3426
3617
  const tab = await chrome.tabs.get(tabId);
3427
3618
  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);
3619
+ // console.log('Cannot start workflow recording on restricted URL:', tab.url);
3429
3620
  throw new Error('Cannot record workflows on restricted pages (chrome:// URLs)');
3430
3621
  }
3431
3622
 
@@ -3446,7 +3637,7 @@ async function startWorkflowRecording(tabId, includeLogsInExport, sessionName =
3446
3637
  if (includeLogsInExport) {
3447
3638
  const buffer = new WorkflowLogBuffer(tabId);
3448
3639
  workflowLogBuffers.set(tabId, buffer);
3449
- console.log(`[Workflow] Initialized WorkflowLogBuffer for tab ${tabId}`);
3640
+ // console.log(`[Workflow] Initialized WorkflowLogBuffer for tab ${tabId}`);
3450
3641
  }
3451
3642
 
3452
3643
  // REFACTORED: Use shared console interception library via proper namespace (replaces 150+ lines of duplicate code)
@@ -3464,7 +3655,7 @@ async function startWorkflowRecording(tabId, includeLogsInExport, sessionName =
3464
3655
  });
3465
3656
  } catch (e) {
3466
3657
  // Content script might already be injected
3467
- console.log('Content script injection attempt:', e.message);
3658
+ // console.log('Content script injection attempt:', e.message);
3468
3659
  }
3469
3660
 
3470
3661
  // Tell the content script to start recording
@@ -3475,7 +3666,7 @@ async function startWorkflowRecording(tabId, includeLogsInExport, sessionName =
3475
3666
  tabId: tabId
3476
3667
  });
3477
3668
 
3478
- console.log('Workflow recording started successfully');
3669
+ // console.log('Workflow recording started successfully');
3479
3670
  } catch (error) {
3480
3671
  console.error('Error starting workflow recording:', error);
3481
3672
  throw error;
@@ -3484,7 +3675,7 @@ async function startWorkflowRecording(tabId, includeLogsInExport, sessionName =
3484
3675
 
3485
3676
  async function stopWorkflowRecording(tabId) {
3486
3677
  try {
3487
- console.log('Stopping workflow recording for tab:', tabId);
3678
+ // console.log('Stopping workflow recording for tab:', tabId);
3488
3679
 
3489
3680
  // Check if recording was active
3490
3681
  if (!workflowRecordingTabs.has(tabId)) {
@@ -3503,7 +3694,7 @@ async function stopWorkflowRecording(tabId) {
3503
3694
 
3504
3695
  // CRITICAL FIX: Restore original console methods and remove event listeners
3505
3696
  try {
3506
- console.log('[Workflow] Stopping console log capture for tab:', tabId);
3697
+ // console.log('[Workflow] Stopping console log capture for tab:', tabId);
3507
3698
  await stopCapturingWorkflowLogs(tabId);
3508
3699
  } catch (cleanupError) {
3509
3700
  console.error('[Workflow] Failed to cleanup console interceptor:', cleanupError);
@@ -3515,19 +3706,19 @@ async function stopWorkflowRecording(tabId) {
3515
3706
  let workflow = Array.isArray(workflowData) ? workflowData : (workflowData.actions || []);
3516
3707
  let functionTraces = Array.isArray(workflowData) ? [] : (workflowData.functionTraces || []);
3517
3708
 
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');
3709
+ // console.log(`[Background] Received ${workflow.length} actions and ${functionTraces.length} function traces`);
3710
+ // console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Checking actions for screenshot_data');
3520
3711
 
3521
3712
  const actionsWithScreenshots = workflow.filter(a => a.screenshot_data);
3522
- console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Actions WITH screenshot_data:', actionsWithScreenshots.length);
3713
+ // console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Actions WITH screenshot_data:', actionsWithScreenshots.length);
3523
3714
 
3524
3715
  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
- });
3716
+ // console.log(`[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Action ${index}:`, {
3717
+ // type: action.type,
3718
+ // hasScreenshotData: !!action.screenshot_data,
3719
+ // screenshotDataLength: action.screenshot_data?.length,
3720
+ // screenshotPreview: action.screenshot_data?.substring(0, 50)
3721
+ // });
3531
3722
  });
3532
3723
 
3533
3724
  // If logs should be included, flush buffer and get them from session storage
@@ -3536,7 +3727,7 @@ async function stopWorkflowRecording(tabId) {
3536
3727
  const buffer = workflowLogBuffers.get(tabId);
3537
3728
  if (buffer) {
3538
3729
  await buffer.flush();
3539
- console.log(`[Workflow] Flushed buffer before retrieval, stats:`, buffer.getStats());
3730
+ // console.log(`[Workflow] Flushed buffer before retrieval, stats:`, buffer.getStats());
3540
3731
  }
3541
3732
 
3542
3733
  const result = await chrome.storage.session.get(`workflow_${tabId}`);
@@ -3585,7 +3776,7 @@ async function stopWorkflowRecording(tabId) {
3585
3776
  if (bufferToCleanup) {
3586
3777
  await bufferToCleanup.cleanup();
3587
3778
  workflowLogBuffers.delete(tabId);
3588
- console.log(`[Workflow] Cleaned up WorkflowLogBuffer for tab ${tabId}`);
3779
+ // console.log(`[Workflow] Cleaned up WorkflowLogBuffer for tab ${tabId}`);
3589
3780
  }
3590
3781
 
3591
3782
  await chrome.storage.session.remove(`workflow_${tabId}`);
@@ -3597,7 +3788,7 @@ async function stopWorkflowRecording(tabId) {
3597
3788
  workflowStartTime: null
3598
3789
  });
3599
3790
 
3600
- console.log('Workflow recording stopped, returning workflow:', workflow);
3791
+ // console.log('Workflow recording stopped, returning workflow:', workflow);
3601
3792
 
3602
3793
  // Try to save to server
3603
3794
  try {
@@ -3610,11 +3801,11 @@ async function stopWorkflowRecording(tabId) {
3610
3801
  // Retrieve the workflow ID that was generated at start
3611
3802
  const storedData = await chrome.storage.local.get(['currentWorkflowId']);
3612
3803
  const sessionId = storedData.currentWorkflowId || `workflow_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
3613
- console.log('[Workflow] Using sessionId for save:', sessionId);
3804
+ // console.log('[Workflow] Using sessionId for save:', sessionId);
3614
3805
 
3615
3806
  for (const port of serverPorts) {
3616
3807
  try {
3617
- console.log(`[Workflow] Attempting to save to server on port ${port}...`);
3808
+ // console.log(`[Workflow] Attempting to save to server on port ${port}...`);
3618
3809
 
3619
3810
  const payloadData = {
3620
3811
  sessionId: sessionId,
@@ -3628,19 +3819,19 @@ async function stopWorkflowRecording(tabId) {
3628
3819
  functionTraces: functionTraces // Include function execution traces
3629
3820
  };
3630
3821
 
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);
3822
+ // console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - HTTP POST payload being prepared');
3823
+ // console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Payload actions count:', payloadData.actions.length);
3633
3824
 
3634
3825
  const payloadActionsWithScreenshots = payloadData.actions.filter(a => a.screenshot_data);
3635
- console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Payload actions WITH screenshot_data:', payloadActionsWithScreenshots.length);
3826
+ // console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Payload actions WITH screenshot_data:', payloadActionsWithScreenshots.length);
3636
3827
 
3637
3828
  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
- });
3829
+ // console.log(`[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Payload Action ${index}:`, {
3830
+ // type: action.type,
3831
+ // hasScreenshotData: !!action.screenshot_data,
3832
+ // screenshotDataLength: action.screenshot_data?.length,
3833
+ // screenshotPreview: action.screenshot_data?.substring(0, 50)
3834
+ // });
3644
3835
  });
3645
3836
 
3646
3837
  const response = await fetch(`http://localhost:${port}/chromedebug/workflow-recording`, {
@@ -3653,15 +3844,15 @@ async function stopWorkflowRecording(tabId) {
3653
3844
 
3654
3845
  if (response.ok) {
3655
3846
  serverResult = await response.json();
3656
- console.log(`[Workflow] Successfully saved to server on port ${port}`, serverResult);
3847
+ // console.log(`[Workflow] Successfully saved to server on port ${port}`, serverResult);
3657
3848
  break;
3658
3849
  } else {
3659
- console.log(`[Workflow] Failed on port ${port}: ${response.status} ${response.statusText}`);
3850
+ // console.log(`[Workflow] Failed on port ${port}: ${response.status} ${response.statusText}`);
3660
3851
  const errorText = await response.text();
3661
- console.log(`[Workflow] Error response:`, errorText);
3852
+ // console.log(`[Workflow] Error response:`, errorText);
3662
3853
  }
3663
3854
  } catch (error) {
3664
- console.log(`Failed to save to server on port ${port}:`, error.message);
3855
+ // console.log(`Failed to save to server on port ${port}:`, error.message);
3665
3856
  }
3666
3857
  }
3667
3858
 
@@ -3725,7 +3916,7 @@ async function stopWorkflowRecording(tabId) {
3725
3916
  // CRITICAL FIX: Stop workflow console log capture and restore original methods
3726
3917
  // REFACTORED: Now uses shared console-interception-library.js via proper namespace
3727
3918
  async function stopCapturingWorkflowLogs(tabId) {
3728
- console.log('[Workflow Recording] Stopping console interception using shared library');
3919
+ // console.log('[Workflow Recording] Stopping console interception using shared library');
3729
3920
  return await self.ConsoleInterceptionLibrary.stopConsoleInterception(tabId, WORKFLOW_RECORDING_CONSOLE_CONFIG);
3730
3921
  }
3731
3922
 
@@ -3764,7 +3955,7 @@ async function deleteRecordingFromServer(recordingId, sendResponse) {
3764
3955
 
3765
3956
  if (deleteResult.success) {
3766
3957
  deleted = true;
3767
- console.log('Recording deleted successfully');
3958
+ // console.log('Recording deleted successfully');
3768
3959
  sendResponse({ success: true });
3769
3960
  return;
3770
3961
  } else {
@@ -3786,11 +3977,11 @@ async function retryPendingFrames(sessionId) {
3786
3977
  const pending = pendingFrameQueue.get(sessionId);
3787
3978
  if (!pending || pending.length === 0) return;
3788
3979
 
3789
- console.log(`[FrameQueue] Retrying ${pending.length} pending frame batches for session ${sessionId}`);
3980
+ // console.log(`[FrameQueue] Retrying ${pending.length} pending frame batches for session ${sessionId}`);
3790
3981
 
3791
3982
  // Check if this is still the active recording session
3792
3983
  if (currentSession?.sessionId !== sessionId) {
3793
- console.log(`[FrameQueue] Session ${sessionId} is no longer active, clearing pending frames`);
3984
+ // console.log(`[FrameQueue] Session ${sessionId} is no longer active, clearing pending frames`);
3794
3985
  pendingFrameQueue.delete(sessionId);
3795
3986
  return;
3796
3987
  }
@@ -3822,12 +4013,12 @@ async function retryPendingFrames(sessionId) {
3822
4013
  await handleFrameBatch({ sessionId, frames }, true); // skipValidation=true
3823
4014
  }
3824
4015
 
3825
- console.log(`[FrameQueue] Successfully processed ${batches.length} pending batches`);
4016
+ // console.log(`[FrameQueue] Successfully processed ${batches.length} pending batches`);
3826
4017
  }
3827
4018
 
3828
4019
  // Handle frame batches from frame capture
3829
4020
  async function handleFrameBatch(batchData, skipValidation = false) {
3830
- console.log(`Processing frame batch for session ${batchData.sessionId}`);
4021
+ // console.log(`Processing frame batch for session ${batchData.sessionId}`);
3831
4022
 
3832
4023
  try {
3833
4024
  const sessionId = batchData.sessionId;
@@ -3881,7 +4072,7 @@ async function handleFrameBatch(batchData, skipValidation = false) {
3881
4072
  frameCounter.set(sessionId, currentFrameIndex);
3882
4073
  }
3883
4074
 
3884
- console.log(`Assigning frame indices ${frameCounter.get(sessionId) - indexedFrames.length} to ${currentFrameIndex - 1}`);
4075
+ // console.log(`Assigning frame indices ${frameCounter.get(sessionId) - indexedFrames.length} to ${currentFrameIndex - 1}`);
3885
4076
 
3886
4077
  // Find available server port using settings
3887
4078
  const ports = await getServerPorts();
@@ -3907,7 +4098,7 @@ async function handleFrameBatch(batchData, skipValidation = false) {
3907
4098
 
3908
4099
  if (uploadResponse.ok) {
3909
4100
  const result = await uploadResponse.json();
3910
- console.log(`Frame batch uploaded successfully to port ${port}:`, result);
4101
+ // console.log(`Frame batch uploaded successfully to port ${port}:`, result);
3911
4102
  recordingServerPort = port; // Store the successful port
3912
4103
  uploadSuccess = true;
3913
4104
 
@@ -3923,8 +4114,20 @@ async function handleFrameBatch(batchData, skipValidation = false) {
3923
4114
  // Append new frames
3924
4115
  sessionData.frames = sessionData.frames.concat(batchData.frames);
3925
4116
  await chrome.storage.local.set({ [storageKey]: sessionData });
3926
- console.log(`Saved ${batchData.frames.length} frames to local storage, total: ${sessionData.frames.length}`);
3927
-
4117
+ // console.log(`Saved ${batchData.frames.length} frames to local storage, total: ${sessionData.frames.length}`);
4118
+
4119
+ // Send frame count update to content script
4120
+ if (recordingTabId) {
4121
+ try {
4122
+ await chrome.tabs.sendMessage(recordingTabId, {
4123
+ action: 'updateFrameCount',
4124
+ frameCount: sessionData.frames.length
4125
+ });
4126
+ } catch (e) {
4127
+ // Tab might be closed, ignore
4128
+ }
4129
+ }
4130
+
3928
4131
  break;
3929
4132
  } else {
3930
4133
  const errorText = await uploadResponse.text();
@@ -3933,16 +4136,16 @@ async function handleFrameBatch(batchData, skipValidation = false) {
3933
4136
  }
3934
4137
  } catch (e) {
3935
4138
  lastError = e.message;
3936
- console.log(`Failed to upload frame batch to port ${port}:`, e.message);
4139
+ // console.log(`Failed to upload frame batch to port ${port}:`, e.message);
3937
4140
  }
3938
4141
  }
3939
4142
 
3940
4143
  if (!uploadSuccess) {
3941
- console.log(`No server available - checking if browser-only mode`);
4144
+ // console.log(`No server available - checking if browser-only mode`);
3942
4145
 
3943
4146
  // If in browser-only mode, store frames in IndexedDB
3944
4147
  if (serverMode === 'browser-only' && browserRecordingManager) {
3945
- console.log(`[Browser-Only] Storing ${indexedFrames.length} frames in IndexedDB`);
4148
+ // console.log(`[Browser-Only] Storing ${indexedFrames.length} frames in IndexedDB`);
3946
4149
  // Use the browser recording session ID, not the frame capture session ID
3947
4150
  const recordingSessionId = currentRecordingSessionId || batchData.sessionId;
3948
4151
  for (const frame of indexedFrames) {
@@ -3959,7 +4162,7 @@ async function handleFrameBatch(batchData, skipValidation = false) {
3959
4162
  absoluteTimestamp: frame.absoluteTimestamp // Don't use Date.now() fallback - preserve actual capture time
3960
4163
  });
3961
4164
  }
3962
- console.log(`[Browser-Only] Frames stored successfully in IndexedDB for session ${recordingSessionId}`);
4165
+ // console.log(`[Browser-Only] Frames stored successfully in IndexedDB for session ${recordingSessionId}`);
3963
4166
  } else {
3964
4167
  // Server mode but no server available - show error
3965
4168
  console.error(`CRITICAL: Failed to upload frame batch to any Chrome Debug server port. Last error: ${lastError}`);
@@ -3999,7 +4202,7 @@ async function getServerPorts() {
3999
4202
  // Try to discover the active server port
4000
4203
  const discoveredPort = await discoverActiveServerPort();
4001
4204
  if (discoveredPort) {
4002
- console.log(`Discovered Chrome Debug server on port ${discoveredPort}`);
4205
+ // console.log(`Discovered Chrome Debug server on port ${discoveredPort}`);
4003
4206
  return [discoveredPort, ...defaultPorts.filter(p => p !== discoveredPort)];
4004
4207
  }
4005
4208
 
@@ -4037,7 +4240,7 @@ async function discoverActiveServerPort() {
4037
4240
 
4038
4241
  // Handle frame capture session completion
4039
4242
  async function handleFrameCaptureComplete(sessionData) {
4040
- console.log(`Frame capture session ${sessionData.sessionId} completed with ${sessionData.totalFrames} frames`);
4243
+ // console.log(`Frame capture session ${sessionData.sessionId} completed with ${sessionData.totalFrames} frames`);
4041
4244
 
4042
4245
  try {
4043
4246
  // Store the tab ID and session ID before clearing
@@ -4055,7 +4258,7 @@ async function handleFrameCaptureComplete(sessionData) {
4055
4258
  let waitedTime = 0;
4056
4259
  let flushCompleted = false;
4057
4260
 
4058
- console.log('[Background] Waiting for LogBuffer flush completion...');
4261
+ // console.log('[Background] Waiting for LogBuffer flush completion...');
4059
4262
 
4060
4263
  // Poll for flush completion status
4061
4264
  while (waitedTime < maxWaitTime && !flushCompleted) {
@@ -4069,7 +4272,7 @@ async function handleFrameCaptureComplete(sessionData) {
4069
4272
  }
4070
4273
 
4071
4274
  if (flushCompleted) {
4072
- console.log(`[Background] LogBuffer flush completed after ${waitedTime}ms`);
4275
+ // console.log(`[Background] LogBuffer flush completed after ${waitedTime}ms`);
4073
4276
  } else {
4074
4277
  console.warn(`[Background] LogBuffer flush verification timed out after ${waitedTime}ms`);
4075
4278
  }
@@ -4077,9 +4280,9 @@ async function handleFrameCaptureComplete(sessionData) {
4077
4280
  // Retrieve buffered logs for this tab
4078
4281
  const logsResult = await chrome.storage.session.get(String(tabIdToNotify));
4079
4282
  bufferedLogs = logsResult[tabIdToNotify] || [];
4080
- console.log(`Retrieved ${bufferedLogs.length} buffered logs for post-processing`);
4283
+ // console.log(`Retrieved ${bufferedLogs.length} buffered logs for post-processing`);
4081
4284
  if (bufferedLogs.length > 0) {
4082
- console.log('First log:', bufferedLogs[0]);
4285
+ // console.log('First log:', bufferedLogs[0]);
4083
4286
  }
4084
4287
 
4085
4288
  // Clean up flush completion marker
@@ -4090,7 +4293,7 @@ async function handleFrameCaptureComplete(sessionData) {
4090
4293
  // Fallback: Try to read logs anyway
4091
4294
  const logsResult = await chrome.storage.session.get(String(tabIdToNotify));
4092
4295
  bufferedLogs = logsResult[tabIdToNotify] || [];
4093
- console.log(`Fallback: Retrieved ${bufferedLogs.length} buffered logs`);
4296
+ // console.log(`Fallback: Retrieved ${bufferedLogs.length} buffered logs`);
4094
4297
  }
4095
4298
 
4096
4299
  // Clear the buffered logs
@@ -4099,7 +4302,7 @@ async function handleFrameCaptureComplete(sessionData) {
4099
4302
  // Send logs to server for association with frames with retry logic
4100
4303
  // Skip server communication in browser-only mode (logs already in IndexedDB)
4101
4304
  if (bufferedLogs.length > 0 && serverMode !== 'browser-only') {
4102
- console.log(`[Server Mode] Associating ${bufferedLogs.length} logs with server...`);
4305
+ // console.log(`[Server Mode] Associating ${bufferedLogs.length} logs with server...`);
4103
4306
 
4104
4307
  // Retry logic to handle race conditions
4105
4308
  const maxRetries = 3;
@@ -4107,15 +4310,15 @@ async function handleFrameCaptureComplete(sessionData) {
4107
4310
  let success = false;
4108
4311
  let lastErrorDetails = null;
4109
4312
 
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}`);
4313
+ // console.log(`[LOG-ASSOC-DEBUG] ========== STARTING LOG ASSOCIATION ==========`);
4314
+ // console.log(`[LOG-ASSOC-DEBUG] Session ID: ${sessionIdToUse}`);
4315
+ // console.log(`[LOG-ASSOC-DEBUG] Number of logs to associate: ${bufferedLogs.length}`);
4316
+ // console.log(`[LOG-ASSOC-DEBUG] Tab ID: ${tabIdToNotify}`);
4114
4317
 
4115
4318
  // PRE-FLIGHT CHECK: Verify frames exist in database before attempting log association
4116
4319
  try {
4117
4320
  const ports = await getServerPorts();
4118
- console.log(`[LOG-ASSOC-DEBUG] PRE-FLIGHT: Checking if frames exist for session ${sessionIdToUse}...`);
4321
+ // console.log(`[LOG-ASSOC-DEBUG] PRE-FLIGHT: Checking if frames exist for session ${sessionIdToUse}...`);
4119
4322
  for (const port of ports) {
4120
4323
  try {
4121
4324
  const checkResponse = await fetch(`http://localhost:${port}/chromedebug/frame-session/${sessionIdToUse}`, {
@@ -4125,7 +4328,7 @@ async function handleFrameCaptureComplete(sessionData) {
4125
4328
  if (checkResponse.ok) {
4126
4329
  const sessionData = await checkResponse.json();
4127
4330
  const frameCount = sessionData.frames?.length || 0;
4128
- console.log(`[LOG-ASSOC-DEBUG] PRE-FLIGHT: Found ${frameCount} frames on port ${port}`);
4331
+ // console.log(`[LOG-ASSOC-DEBUG] PRE-FLIGHT: Found ${frameCount} frames on port ${port}`);
4129
4332
  if (frameCount === 0) {
4130
4333
  console.warn(`[LOG-ASSOC-DEBUG] ⚠️ WARNING: Session exists but has 0 frames! This will cause log association to fail.`);
4131
4334
  console.warn(`[LOG-ASSOC-DEBUG] Session data:`, sessionData);
@@ -4133,7 +4336,7 @@ async function handleFrameCaptureComplete(sessionData) {
4133
4336
  break;
4134
4337
  }
4135
4338
  } catch (e) {
4136
- console.log(`[LOG-ASSOC-DEBUG] PRE-FLIGHT: Could not check port ${port}:`, e.message);
4339
+ // console.log(`[LOG-ASSOC-DEBUG] PRE-FLIGHT: Could not check port ${port}:`, e.message);
4137
4340
  }
4138
4341
  }
4139
4342
  } catch (preflightError) {
@@ -4143,22 +4346,22 @@ async function handleFrameCaptureComplete(sessionData) {
4143
4346
  while (retryCount < maxRetries && !success) {
4144
4347
  try {
4145
4348
  const ports = await getServerPorts();
4146
- console.log(`[LOG-ASSOC-DEBUG] Attempt ${retryCount + 1}/${maxRetries}: Trying ports:`, ports);
4349
+ // console.log(`[LOG-ASSOC-DEBUG] Attempt ${retryCount + 1}/${maxRetries}: Trying ports:`, ports);
4147
4350
 
4148
4351
  for (const port of ports) {
4149
4352
  try {
4150
- console.log(`[LOG-ASSOC-DEBUG] Attempting port ${port}...`);
4353
+ // console.log(`[LOG-ASSOC-DEBUG] Attempting port ${port}...`);
4151
4354
  const requestBody = {
4152
4355
  sessionId: sessionIdToUse,
4153
4356
  logs: bufferedLogs
4154
4357
  };
4155
- console.log(`[LOG-ASSOC-DEBUG] Request payload: sessionId=${sessionIdToUse}, logs.length=${bufferedLogs.length}`);
4358
+ // console.log(`[LOG-ASSOC-DEBUG] Request payload: sessionId=${sessionIdToUse}, logs.length=${bufferedLogs.length}`);
4156
4359
  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
- });
4360
+ // console.log(`[LOG-ASSOC-DEBUG] First log sample:`, {
4361
+ // timestamp: bufferedLogs[0].timestamp,
4362
+ // level: bufferedLogs[0].level,
4363
+ // message: bufferedLogs[0].message?.substring(0, 100)
4364
+ // });
4162
4365
  }
4163
4366
 
4164
4367
  const response = await fetch(`http://localhost:${port}/chromedebug/associate-logs`, {
@@ -4169,12 +4372,12 @@ async function handleFrameCaptureComplete(sessionData) {
4169
4372
  body: JSON.stringify(requestBody)
4170
4373
  });
4171
4374
 
4172
- console.log(`[LOG-ASSOC-DEBUG] Port ${port} response status: ${response.status} ${response.statusText}`);
4375
+ // console.log(`[LOG-ASSOC-DEBUG] Port ${port} response status: ${response.status} ${response.statusText}`);
4173
4376
 
4174
4377
  if (response.ok) {
4175
4378
  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);
4379
+ // console.log(`[LOG-ASSOC-DEBUG] ✅ SUCCESS on port ${port}:`, result);
4380
+ // console.log(`Logs associated successfully on port ${port}:`, result);
4178
4381
  success = true;
4179
4382
 
4180
4383
  // Fetch the updated session data with logs from server
@@ -4182,14 +4385,14 @@ async function handleFrameCaptureComplete(sessionData) {
4182
4385
  const sessionResponse = await fetch(`http://localhost:${port}/chromedebug/frame-session/${sessionIdToUse}`);
4183
4386
  if (sessionResponse.ok) {
4184
4387
  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`);
4388
+ // console.log(`[LOG-ASSOC-DEBUG] Fetched updated session: ${updatedSession.frames?.length || 0} frames`);
4389
+ // console.log(`Fetched updated session with ${updatedSession.frames ? updatedSession.frames.length : 0} frames`);
4187
4390
 
4188
4391
  // Update Chrome local storage with the frames that now have logs
4189
4392
  const storageKey = sessionIdToUse;
4190
4393
  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');
4394
+ // console.log('[LOG-ASSOC-DEBUG] Updated local storage with frames containing logs');
4395
+ // console.log('Updated local storage with frames containing logs');
4193
4396
  } else {
4194
4397
  console.error(`[LOG-ASSOC-DEBUG] Failed to fetch updated session: ${sessionResponse.status}`);
4195
4398
  console.error('Failed to fetch updated session data');
@@ -4225,15 +4428,15 @@ async function handleFrameCaptureComplete(sessionData) {
4225
4428
  attempt: retryCount + 1
4226
4429
  };
4227
4430
  console.error(`[LOG-ASSOC-DEBUG] ❌ Port ${port} exception:`, e);
4228
- console.log(`Failed to associate logs on port ${port}:`, e.message);
4431
+ // console.log(`Failed to associate logs on port ${port}:`, e.message);
4229
4432
  }
4230
4433
  }
4231
4434
 
4232
4435
  if (!success) {
4233
4436
  retryCount++;
4234
4437
  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})...`);
4438
+ // console.log(`[LOG-ASSOC-DEBUG] Retrying in 1 second (attempt ${retryCount + 1}/${maxRetries})...`);
4439
+ // console.log(`Retrying log association (attempt ${retryCount + 1}/${maxRetries})...`);
4237
4440
  await new Promise(resolve => setTimeout(resolve, 1000));
4238
4441
  }
4239
4442
  }
@@ -4247,8 +4450,8 @@ async function handleFrameCaptureComplete(sessionData) {
4247
4450
  }
4248
4451
  }
4249
4452
 
4250
- console.log(`[LOG-ASSOC-DEBUG] ========== LOG ASSOCIATION COMPLETE ==========`);
4251
- console.log(`[LOG-ASSOC-DEBUG] Success: ${success}`);
4453
+ // console.log(`[LOG-ASSOC-DEBUG] ========== LOG ASSOCIATION COMPLETE ==========`);
4454
+ // console.log(`[LOG-ASSOC-DEBUG] Success: ${success}`);
4252
4455
  if (!success && lastErrorDetails) {
4253
4456
  console.error(`[LOG-ASSOC-DEBUG] Last error details:`, lastErrorDetails);
4254
4457
  }
@@ -4279,12 +4482,12 @@ async function handleFrameCaptureComplete(sessionData) {
4279
4482
  }
4280
4483
  } else if (bufferedLogs.length > 0 && serverMode === 'browser-only') {
4281
4484
  // Browser-only mode: Associate logs with frames in IndexedDB
4282
- console.log(`[Browser-Only] Associating ${bufferedLogs.length} logs with frames in IndexedDB...`);
4485
+ // console.log(`[Browser-Only] Associating ${bufferedLogs.length} logs with frames in IndexedDB...`);
4283
4486
 
4284
4487
  try {
4285
4488
  // Get all frames for this session from IndexedDB
4286
4489
  const frames = await dataBuffer.getBrowserFrames(sessionIdToUse);
4287
- console.log(`[Browser-Only] Retrieved ${frames.length} frames from IndexedDB for log association`);
4490
+ // console.log(`[Browser-Only] Retrieved ${frames.length} frames from IndexedDB for log association`);
4288
4491
 
4289
4492
  if (frames.length === 0) {
4290
4493
  console.warn('[Browser-Only] No frames found - logs cannot be associated');
@@ -4328,7 +4531,7 @@ async function handleFrameCaptureComplete(sessionData) {
4328
4531
  }
4329
4532
  }
4330
4533
 
4331
- console.log(`[Browser-Only] ✓ Associated logs with ${updatedCount} frames in IndexedDB`);
4534
+ // console.log(`[Browser-Only] ✓ Associated logs with ${updatedCount} frames in IndexedDB`);
4332
4535
  }
4333
4536
  } catch (error) {
4334
4537
  console.error('[Browser-Only] Failed to associate logs with frames:', error);
@@ -4354,18 +4557,18 @@ async function handleFrameCaptureComplete(sessionData) {
4354
4557
  // Save screen interactions to database
4355
4558
  // Skip server communication in browser-only mode
4356
4559
  if (screenInteractions.length > 0 && serverMode !== 'browser-only') {
4357
- console.log(`[Server Mode] Saving ${screenInteractions.length} screen interactions to database`);
4560
+ // console.log(`[Server Mode] Saving ${screenInteractions.length} screen interactions to database`);
4358
4561
 
4359
4562
  // Use comprehensive error handling for screen interactions save
4360
4563
  const saveScreenInteractions = async (data, context) => {
4361
4564
  // 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
- });
4565
+ // console.log('[ScreenInteractions] Preparing to save interactions:', {
4566
+ // sessionId: context.sessionId,
4567
+ // dataType: typeof data,
4568
+ // isArray: Array.isArray(data),
4569
+ // interactionCount: Array.isArray(data) ? data.length : 'N/A',
4570
+ // hasComplexData: Array.isArray(data) && data.some(i => i.element_html && i.element_html.length > 100)
4571
+ // });
4369
4572
 
4370
4573
  let lastError = null;
4371
4574
  for (const port of CONFIG_PORTS) {
@@ -4375,7 +4578,7 @@ async function handleFrameCaptureComplete(sessionData) {
4375
4578
  try {
4376
4579
  // data is already { interactions: screenInteractions } from caller
4377
4580
  serializedBody = JSON.stringify(data);
4378
- console.log('[ScreenInteractions] JSON serialization successful, length:', serializedBody.length);
4581
+ // console.log('[ScreenInteractions] JSON serialization successful, length:', serializedBody.length);
4379
4582
  } catch (serError) {
4380
4583
  console.error('[ScreenInteractions] JSON serialization failed:', serError);
4381
4584
  throw new Error(`JSON serialization failed: ${serError.message}`);
@@ -4392,7 +4595,7 @@ async function handleFrameCaptureComplete(sessionData) {
4392
4595
  if (response.ok) {
4393
4596
  // Only log if we had to try multiple ports
4394
4597
  if (port !== CONFIG_PORTS[0]) {
4395
- console.log(`[ScreenInteractions] Connected to server on port ${port}`);
4598
+ // console.log(`[ScreenInteractions] Connected to server on port ${port}`);
4396
4599
  }
4397
4600
  return { success: true, result: { saved: true } };
4398
4601
  } else {
@@ -4416,13 +4619,13 @@ async function handleFrameCaptureComplete(sessionData) {
4416
4619
  );
4417
4620
 
4418
4621
  if (saveResult.success) {
4419
- console.log('Screen interactions saved successfully with comprehensive error handling');
4622
+ // console.log('Screen interactions saved successfully with comprehensive error handling');
4420
4623
  } else {
4421
4624
  console.error('[ErrorHandling] Failed to save screen interactions after comprehensive error handling');
4422
4625
  }
4423
4626
  } else if (screenInteractions.length > 0 && serverMode === 'browser-only') {
4424
4627
  // Browser-only mode: screen interactions not needed
4425
- console.log(`[Browser-Only] ✓ Skipping screen interactions save (browser-only mode)`);
4628
+ // console.log(`[Browser-Only] ✓ Skipping screen interactions save (browser-only mode)`);
4426
4629
  }
4427
4630
 
4428
4631
  // Stop session via session manager if available
@@ -4430,7 +4633,7 @@ async function handleFrameCaptureComplete(sessionData) {
4430
4633
  try {
4431
4634
  const stopResult = await sessionManager.stopRecording(currentSession.sessionId, currentOwnerId);
4432
4635
  if (stopResult.success) {
4433
- console.log(`Session stopped via session manager. Duration: ${stopResult.sessionDuration}ms, Frames: ${stopResult.frameCount}`);
4636
+ // console.log(`Session stopped via session manager. Duration: ${stopResult.sessionDuration}ms, Frames: ${stopResult.frameCount}`);
4434
4637
  } else {
4435
4638
  console.warn('Failed to stop session via session manager:', stopResult.error?.message);
4436
4639
  }
@@ -4482,7 +4685,7 @@ async function handleFrameCaptureComplete(sessionData) {
4482
4685
  serverPort: recordingServerPort
4483
4686
  }).catch(() => {});
4484
4687
  } else {
4485
- console.log('[Browser-Only] Skipping frameSessionComplete message - recording is in IndexedDB');
4688
+ // console.log('[Browser-Only] Skipping frameSessionComplete message - recording is in IndexedDB');
4486
4689
  }
4487
4690
 
4488
4691
  // Notify content script to hide recording indicator