@dynamicu/chromedebug-mcp 2.6.7 → 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.
- package/CLAUDE.md +17 -1
- package/README.md +1 -1
- package/chrome-extension/activation-manager.js +10 -10
- package/chrome-extension/background.js +1045 -736
- package/chrome-extension/browser-recording-manager.js +1 -1
- package/chrome-extension/chrome-debug-logger.js +168 -0
- package/chrome-extension/chrome-session-manager.js +5 -5
- package/chrome-extension/console-interception-library.js +430 -0
- package/chrome-extension/content.css +16 -16
- package/chrome-extension/content.js +739 -221
- package/chrome-extension/data-buffer.js +5 -5
- package/chrome-extension/dom-tracker.js +9 -9
- package/chrome-extension/extension-config.js +1 -1
- package/chrome-extension/firebase-client.js +13 -13
- package/chrome-extension/frame-capture.js +20 -38
- package/chrome-extension/license-helper.js +33 -7
- package/chrome-extension/manifest.free.json +3 -6
- package/chrome-extension/network-tracker.js +9 -9
- package/chrome-extension/options.html +10 -0
- package/chrome-extension/options.js +21 -8
- package/chrome-extension/performance-monitor.js +17 -17
- package/chrome-extension/popup.html +230 -193
- package/chrome-extension/popup.js +146 -458
- package/chrome-extension/pro/enhanced-capture.js +406 -0
- package/chrome-extension/pro/frame-editor.html +433 -0
- package/chrome-extension/pro/frame-editor.js +1567 -0
- package/chrome-extension/pro/function-tracker.js +843 -0
- package/chrome-extension/pro/jszip.min.js +13 -0
- package/chrome-extension/upload-manager.js +7 -7
- package/dist/chromedebug-extension-free.zip +0 -0
- package/package.json +3 -1
- package/scripts/webpack.config.free.cjs +8 -8
- package/scripts/webpack.config.pro.cjs +2 -0
- package/src/cli.js +2 -2
- package/src/database.js +55 -7
- package/src/index.js +9 -6
- package/src/mcp/server.js +2 -2
- package/src/services/process-manager.js +10 -6
- package/src/services/process-tracker.js +10 -5
- package/src/services/profile-manager.js +17 -2
- package/src/validation/schemas.js +12 -11
- package/src/index-direct.js +0 -157
- package/src/index-modular.js +0 -219
- package/src/index-monolithic-backup.js +0 -2230
- package/src/legacy/chrome-controller-old.js +0 -1406
- package/src/legacy/index-express.js +0 -625
- package/src/legacy/index-old.js +0 -977
- package/src/legacy/routes.js +0 -260
- package/src/legacy/shared-storage.js +0 -101
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
// Check if already loaded
|
|
7
7
|
if (window.chromePilotContentScriptLoaded) {
|
|
8
|
-
console.log('[ChromeDebug MCP v2.0] Content script already loaded, skipping re-injection');
|
|
8
|
+
// console.log('[ChromeDebug MCP v2.0] Content script already loaded, skipping re-injection');
|
|
9
9
|
return;
|
|
10
10
|
}
|
|
11
11
|
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
if (shouldBlock) {
|
|
63
|
-
console.log(`[ChromeDebug MCP] Skipping restricted site (${mode} mode):`, hostname);
|
|
63
|
+
// console.log(`[ChromeDebug MCP] Skipping restricted site (${mode} mode):`, hostname);
|
|
64
64
|
return;
|
|
65
65
|
}
|
|
66
66
|
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
window.chromePilotContentScriptLoaded = true;
|
|
73
73
|
|
|
74
74
|
const CHROME_PILOT_VERSION = '2.0.4-BUILD-20250119';
|
|
75
|
-
console.log(`[content.js] Loaded version: ${CHROME_PILOT_VERSION}`);
|
|
75
|
+
// console.log(`[content.js] Loaded version: ${CHROME_PILOT_VERSION}`);
|
|
76
76
|
|
|
77
77
|
let frameFlashIndicator = null;
|
|
78
78
|
|
|
@@ -88,7 +88,7 @@ function isExtensionValid() {
|
|
|
88
88
|
|
|
89
89
|
// Initialize ChromeDebug MCP content script
|
|
90
90
|
setTimeout(() => {
|
|
91
|
-
console.log('[ChromeDebug MCP] 🚀 Content script initializing...');
|
|
91
|
+
// console.log('[ChromeDebug MCP] 🚀 Content script initializing...');
|
|
92
92
|
}, 100);
|
|
93
93
|
|
|
94
94
|
/*
|
|
@@ -119,7 +119,7 @@ let consoleMonitorInjected = false;
|
|
|
119
119
|
|
|
120
120
|
function injectConsoleMonitor() {
|
|
121
121
|
if (consoleMonitorInjected) {
|
|
122
|
-
console.log('[ChromeDebug] Console monitor already injected');
|
|
122
|
+
// console.log('[ChromeDebug] Console monitor already injected');
|
|
123
123
|
return Promise.resolve(true);
|
|
124
124
|
}
|
|
125
125
|
|
|
@@ -128,7 +128,7 @@ function injectConsoleMonitor() {
|
|
|
128
128
|
script.src = chrome.runtime.getURL('console-monitor.js');
|
|
129
129
|
|
|
130
130
|
script.onload = function() {
|
|
131
|
-
console.log('[ChromeDebug] Console monitor loaded successfully');
|
|
131
|
+
// console.log('[ChromeDebug] Console monitor loaded successfully');
|
|
132
132
|
consoleMonitorInjected = true;
|
|
133
133
|
this.remove();
|
|
134
134
|
resolve(true);
|
|
@@ -154,7 +154,7 @@ window.addEventListener('message', (event) => {
|
|
|
154
154
|
}
|
|
155
155
|
});
|
|
156
156
|
|
|
157
|
-
console.log('[ChromeDebug] Console monitoring ready (will inject on demand)');
|
|
157
|
+
// console.log('[ChromeDebug] Console monitoring ready (will inject on demand)');
|
|
158
158
|
*/
|
|
159
159
|
|
|
160
160
|
function getAngularComponentInfo(element) {
|
|
@@ -190,7 +190,7 @@ function getAngularComponentInfo(element) {
|
|
|
190
190
|
};
|
|
191
191
|
}
|
|
192
192
|
} catch (e) {
|
|
193
|
-
console.log('Error detecting Angular component:', e);
|
|
193
|
+
// console.log('Error detecting Angular component:', e);
|
|
194
194
|
}
|
|
195
195
|
|
|
196
196
|
return null;
|
|
@@ -218,8 +218,8 @@ function getReactComponentInfo(element) {
|
|
|
218
218
|
|
|
219
219
|
// Debug: Log the first fiber to see what properties are available
|
|
220
220
|
if (fiber) {
|
|
221
|
-
console.log('React Fiber found:', fiber);
|
|
222
|
-
console.log('Fiber properties:', Object.keys(fiber));
|
|
221
|
+
// console.log('React Fiber found:', fiber);
|
|
222
|
+
// console.log('Fiber properties:', Object.keys(fiber));
|
|
223
223
|
}
|
|
224
224
|
|
|
225
225
|
while (currentFiber) {
|
|
@@ -239,7 +239,7 @@ function getReactComponentInfo(element) {
|
|
|
239
239
|
lineNumber: currentFiber._debugSource.lineNumber,
|
|
240
240
|
columnNumber: currentFiber._debugSource.columnNumber
|
|
241
241
|
};
|
|
242
|
-
console.log('Found _debugSource:', sourceInfo);
|
|
242
|
+
// console.log('Found _debugSource:', sourceInfo);
|
|
243
243
|
}
|
|
244
244
|
|
|
245
245
|
// Method 2: _owner and _source
|
|
@@ -297,7 +297,7 @@ function getSelector(element) {
|
|
|
297
297
|
}
|
|
298
298
|
|
|
299
299
|
if (element.className && typeof element.className === 'string') {
|
|
300
|
-
const classes = element.className.trim().split(/\s+/).filter(c => !c.startsWith('chrome-
|
|
300
|
+
const classes = element.className.trim().split(/\s+/).filter(c => !c.startsWith('chrome-debug'));
|
|
301
301
|
if (classes.length > 0) {
|
|
302
302
|
return `${element.tagName.toLowerCase()}.${classes.join('.')}`;
|
|
303
303
|
}
|
|
@@ -350,8 +350,8 @@ function getComponentInfo(element) {
|
|
|
350
350
|
while (currentElement && depth < maxDepth) {
|
|
351
351
|
// Log for debugging
|
|
352
352
|
if (depth === 0) {
|
|
353
|
-
console.log(`Checking element:`, currentElement);
|
|
354
|
-
console.log(`Element keys:`, Object.keys(currentElement).filter(k => k.includes('react')));
|
|
353
|
+
// console.log(`Checking element:`, currentElement);
|
|
354
|
+
// console.log(`Element keys:`, Object.keys(currentElement).filter(k => k.includes('react')));
|
|
355
355
|
}
|
|
356
356
|
|
|
357
357
|
// Try to find React info on current element
|
|
@@ -388,7 +388,7 @@ function getComponentInfo(element) {
|
|
|
388
388
|
return angularInfo;
|
|
389
389
|
}
|
|
390
390
|
|
|
391
|
-
console.log('No component info found');
|
|
391
|
+
// console.log('No component info found');
|
|
392
392
|
return null;
|
|
393
393
|
}
|
|
394
394
|
|
|
@@ -401,12 +401,12 @@ let cleanupExecuted = false;
|
|
|
401
401
|
async function cleanup() {
|
|
402
402
|
// Idempotent protection - only run cleanup once
|
|
403
403
|
if (cleanupExecuted) {
|
|
404
|
-
console.log('[ChromeDebug MCP] Cleanup already executed, skipping');
|
|
404
|
+
// console.log('[ChromeDebug MCP] Cleanup already executed, skipping');
|
|
405
405
|
return;
|
|
406
406
|
}
|
|
407
407
|
|
|
408
408
|
cleanupExecuted = true;
|
|
409
|
-
console.log('[ChromeDebug MCP] Executing cleanup...');
|
|
409
|
+
// console.log('[ChromeDebug MCP] Executing cleanup...');
|
|
410
410
|
|
|
411
411
|
// Clean up recording indicators and event listeners
|
|
412
412
|
try {
|
|
@@ -414,7 +414,7 @@ async function cleanup() {
|
|
|
414
414
|
|
|
415
415
|
// Stop workflow recording if active
|
|
416
416
|
if (typeof isWorkflowRecording !== 'undefined' && isWorkflowRecording) {
|
|
417
|
-
console.log('[ChromeDebug MCP] Stopping workflow recording during cleanup');
|
|
417
|
+
// console.log('[ChromeDebug MCP] Stopping workflow recording during cleanup');
|
|
418
418
|
if (typeof stopWorkflowRecording === 'function') {
|
|
419
419
|
await stopWorkflowRecording();
|
|
420
420
|
}
|
|
@@ -422,13 +422,13 @@ async function cleanup() {
|
|
|
422
422
|
|
|
423
423
|
// Stop screen interaction tracking if active
|
|
424
424
|
if (typeof isScreenRecording !== 'undefined' && isScreenRecording) {
|
|
425
|
-
console.log('[ChromeDebug MCP] Stopping screen recording during cleanup');
|
|
425
|
+
// console.log('[ChromeDebug MCP] Stopping screen recording during cleanup');
|
|
426
426
|
if (typeof stopScreenInteractionTracking === 'function') {
|
|
427
427
|
stopScreenInteractionTracking();
|
|
428
428
|
}
|
|
429
429
|
}
|
|
430
430
|
|
|
431
|
-
console.log('[ChromeDebug MCP] Cleanup completed successfully');
|
|
431
|
+
// console.log('[ChromeDebug MCP] Cleanup completed successfully');
|
|
432
432
|
} catch (error) {
|
|
433
433
|
console.warn('[ChromeDebug MCP] Error during cleanup:', error);
|
|
434
434
|
}
|
|
@@ -449,7 +449,7 @@ if (isExtensionValid()) {
|
|
|
449
449
|
});
|
|
450
450
|
return true; // Keep channel open for async response
|
|
451
451
|
} else if (request.action === 'showRecordingUI') {
|
|
452
|
-
console.log('Received showRecordingUI message');
|
|
452
|
+
// console.log('Received showRecordingUI message');
|
|
453
453
|
showRecordingInterface();
|
|
454
454
|
sendResponse({ success: true });
|
|
455
455
|
return true; // Keep channel open for async response
|
|
@@ -458,9 +458,9 @@ if (isExtensionValid()) {
|
|
|
458
458
|
sendResponse({ success: true });
|
|
459
459
|
} else if (request.action === 'recordingComplete') {
|
|
460
460
|
// Show the recording ID in the floating UI
|
|
461
|
-
console.log('Recording complete with ID:', request.recordingId);
|
|
461
|
+
// console.log('Recording complete with ID:', request.recordingId);
|
|
462
462
|
if (recordingOverlay) {
|
|
463
|
-
const statusDiv = document.getElementById('chrome-
|
|
463
|
+
const statusDiv = document.getElementById('chrome-debug-recording-status');
|
|
464
464
|
if (statusDiv && request.recordingId) {
|
|
465
465
|
statusDiv.innerHTML = `<strong style="color: #4CAF50;">Recording saved!</strong><br>ID: <code style="background: #f0f0f0; padding: 2px 6px; border-radius: 3px; font-family: monospace;">${request.recordingId}</code>`;
|
|
466
466
|
|
|
@@ -476,32 +476,49 @@ if (isExtensionValid()) {
|
|
|
476
476
|
sendResponse({ success: true });
|
|
477
477
|
} else if (request.action === 'recordingStarted') {
|
|
478
478
|
// Recording indicator now handled by ScreenCaptureVisualFeedback
|
|
479
|
-
console.log('[ChromeDebug MCP] Received recordingStarted message with scheduled start time:', request.scheduledStartTime);
|
|
479
|
+
// console.log('[ChromeDebug MCP] Received recordingStarted message with scheduled start time:', request.scheduledStartTime);
|
|
480
480
|
// Start tracking screen interactions with scheduled timing
|
|
481
481
|
startScreenInteractionTracking(request.scheduledStartTime, request.sessionId);
|
|
482
482
|
sendResponse({ success: true });
|
|
483
483
|
} else if (request.action === 'recordingStopped') {
|
|
484
484
|
// Recording indicator cleanup now handled by ScreenCaptureVisualFeedback
|
|
485
|
-
console.log('[ChromeDebug MCP] Received recordingStopped message');
|
|
485
|
+
// console.log('[ChromeDebug MCP] Received recordingStopped message');
|
|
486
486
|
// Stop tracking screen interactions
|
|
487
487
|
stopScreenInteractionTracking();
|
|
488
488
|
sendResponse({ success: true });
|
|
489
489
|
} else if (request.action === 'recordingSessionComplete') {
|
|
490
490
|
// Recording indicator cleanup now handled by ScreenCaptureVisualFeedback
|
|
491
|
-
console.log('[ChromeDebug MCP] Received recordingSessionComplete message');
|
|
491
|
+
// console.log('[ChromeDebug MCP] Received recordingSessionComplete message');
|
|
492
492
|
// Stop tracking screen interactions
|
|
493
493
|
stopScreenInteractionTracking();
|
|
494
494
|
sendResponse({ success: true });
|
|
495
495
|
} else if (request.action === 'startWorkflowRecording') {
|
|
496
|
-
console.log('[ChromeDebug MCP] Starting workflow recording with settings:', request.screenshotSettings);
|
|
496
|
+
// console.log('[ChromeDebug MCP] Starting workflow recording with settings:', request.screenshotSettings);
|
|
497
|
+
// Store tabId for use when stopping recording from mini-menu
|
|
498
|
+
workflowTabId = request.tabId;
|
|
497
499
|
startWorkflowRecording(request.screenshotSettings);
|
|
498
500
|
sendResponse({ success: true });
|
|
499
|
-
} else if (request.action === '
|
|
500
|
-
|
|
501
|
-
|
|
501
|
+
} else if (request.action === 'getWorkflowData') {
|
|
502
|
+
// Called by background script to retrieve workflow data
|
|
503
|
+
// This happens when popup stops the recording (not mini-menu)
|
|
504
|
+
// console.log('[ChromeDebug MCP] Getting workflow data');
|
|
505
|
+
stopWorkflowRecording().then(async workflow => {
|
|
502
506
|
sendResponse({ success: true, workflow: workflow });
|
|
507
|
+
|
|
508
|
+
// CRITICAL FIX: Show completion UI in mini-menu after data is sent
|
|
509
|
+
// When popup stops recording, the mini-menu needs to show the completion state
|
|
510
|
+
// Get the workflowId from storage (set by background.js when recording started)
|
|
511
|
+
try {
|
|
512
|
+
const storedData = await chrome.storage.local.get(['currentWorkflowId']);
|
|
513
|
+
const workflowId = storedData.currentWorkflowId || 'Recording saved';
|
|
514
|
+
const actionCount = workflow.actions?.length || 0;
|
|
515
|
+
// console.log('[ChromeDebug MCP] Showing completion UI with workflowId:', workflowId, 'actionCount:', actionCount);
|
|
516
|
+
showWorkflowRecordingComplete(workflowId, actionCount);
|
|
517
|
+
} catch (e) {
|
|
518
|
+
// console.log('[ChromeDebug MCP] Could not show completion UI:', e);
|
|
519
|
+
}
|
|
503
520
|
}).catch(error => {
|
|
504
|
-
console.error('[ChromeDebug MCP] Error
|
|
521
|
+
console.error('[ChromeDebug MCP] Error getting workflow data:', error);
|
|
505
522
|
sendResponse({ success: false, error: error.message });
|
|
506
523
|
});
|
|
507
524
|
return true; // Keep channel open for async response
|
|
@@ -531,7 +548,7 @@ if (isExtensionValid()) {
|
|
|
531
548
|
return true; // Keep channel open for async response
|
|
532
549
|
} else if (request.action === 'startFullDataRecording') {
|
|
533
550
|
// Start full data recording with user configuration
|
|
534
|
-
console.log('[ChromeDebug MCP] Starting full data recording with config:', request.config);
|
|
551
|
+
// console.log('[ChromeDebug MCP] Starting full data recording with config:', request.config);
|
|
535
552
|
startFullDataRecording(request.config).then(() => {
|
|
536
553
|
sendResponse({ success: true });
|
|
537
554
|
}).catch(error => {
|
|
@@ -540,7 +557,7 @@ if (isExtensionValid()) {
|
|
|
540
557
|
return true; // Keep channel open for async response
|
|
541
558
|
} else if (request.action === 'stopFullDataRecording') {
|
|
542
559
|
// Stop full data recording
|
|
543
|
-
console.log('[ChromeDebug MCP] Stopping full data recording');
|
|
560
|
+
// console.log('[ChromeDebug MCP] Stopping full data recording');
|
|
544
561
|
stopFullDataRecording().then(() => {
|
|
545
562
|
sendResponse({ success: true });
|
|
546
563
|
}).catch(error => {
|
|
@@ -606,7 +623,7 @@ async function waitForPageLoad(timeout = 10000) {
|
|
|
606
623
|
// Set up timeout
|
|
607
624
|
timeoutId = setTimeout(() => {
|
|
608
625
|
cleanup();
|
|
609
|
-
console.log('[ChromePilot] Page load timeout reached, continuing...');
|
|
626
|
+
// console.log('[ChromePilot] Page load timeout reached, continuing...');
|
|
610
627
|
resolve();
|
|
611
628
|
}, timeout);
|
|
612
629
|
});
|
|
@@ -629,12 +646,12 @@ async function waitForElement(selector, timeout = 5000) {
|
|
|
629
646
|
|
|
630
647
|
// Function to play a workflow recording
|
|
631
648
|
async function playWorkflowRecording(workflow, actions) {
|
|
632
|
-
console.log('[ChromePilot] Starting workflow playback with', actions.length, 'actions');
|
|
649
|
+
// console.log('[ChromePilot] Starting workflow playback with', actions.length, 'actions');
|
|
633
650
|
|
|
634
651
|
try {
|
|
635
652
|
// Show playback indicator
|
|
636
653
|
const playbackIndicator = document.createElement('div');
|
|
637
|
-
playbackIndicator.id = 'chrome-
|
|
654
|
+
playbackIndicator.id = 'chrome-debug-playback-indicator';
|
|
638
655
|
playbackIndicator.style.cssText = `
|
|
639
656
|
position: fixed;
|
|
640
657
|
top: 20px;
|
|
@@ -683,7 +700,7 @@ async function playWorkflowRecording(workflow, actions) {
|
|
|
683
700
|
actionCounter.textContent = i + 1;
|
|
684
701
|
|
|
685
702
|
try {
|
|
686
|
-
console.log(`[ChromePilot] Executing action ${i + 1}/${actions.length}:`, action.type, 'selector:', action.selector);
|
|
703
|
+
// console.log(`[ChromePilot] Executing action ${i + 1}/${actions.length}:`, action.type, 'selector:', action.selector);
|
|
687
704
|
|
|
688
705
|
// Calculate delay based on timestamps
|
|
689
706
|
let delay = 500; // Default delay
|
|
@@ -692,7 +709,7 @@ async function playWorkflowRecording(workflow, actions) {
|
|
|
692
709
|
// Apply reasonable limits
|
|
693
710
|
delay = Math.min(delay, 10000); // Cap at 10 seconds
|
|
694
711
|
delay = Math.max(delay, 100); // Minimum 100ms
|
|
695
|
-
console.log(`[ChromePilot] Calculated delay: ${delay}ms`);
|
|
712
|
+
// console.log(`[ChromePilot] Calculated delay: ${delay}ms`);
|
|
696
713
|
}
|
|
697
714
|
|
|
698
715
|
// Wait between actions
|
|
@@ -710,13 +727,13 @@ async function playWorkflowRecording(workflow, actions) {
|
|
|
710
727
|
let element = document.querySelector(fixedSelector);
|
|
711
728
|
if (!element && action.xpath) {
|
|
712
729
|
// Try XPath as fallback
|
|
713
|
-
console.log('[ChromePilot] Trying XPath fallback:', action.xpath);
|
|
730
|
+
// console.log('[ChromePilot] Trying XPath fallback:', action.xpath);
|
|
714
731
|
const xpathResult = document.evaluate(action.xpath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
|
|
715
732
|
element = xpathResult.singleNodeValue;
|
|
716
733
|
}
|
|
717
734
|
|
|
718
735
|
if (!element) {
|
|
719
|
-
console.log('[ChromePilot] Element not found immediately, waiting...');
|
|
736
|
+
// console.log('[ChromePilot] Element not found immediately, waiting...');
|
|
720
737
|
element = await waitForElement(fixedSelector, 3000);
|
|
721
738
|
}
|
|
722
739
|
|
|
@@ -728,7 +745,7 @@ async function playWorkflowRecording(workflow, actions) {
|
|
|
728
745
|
clickableElement = element.closest('button, a') || element;
|
|
729
746
|
}
|
|
730
747
|
|
|
731
|
-
console.log('[ChromePilot] Found element:', clickableElement.tagName, 'for selector:', fixedSelector);
|
|
748
|
+
// console.log('[ChromePilot] Found element:', clickableElement.tagName, 'for selector:', fixedSelector);
|
|
732
749
|
clickableElement.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
733
750
|
await new Promise(resolve => setTimeout(resolve, 200)); // Wait for scroll
|
|
734
751
|
|
|
@@ -741,7 +758,7 @@ async function playWorkflowRecording(workflow, actions) {
|
|
|
741
758
|
// Try to click
|
|
742
759
|
try {
|
|
743
760
|
clickableElement.click();
|
|
744
|
-
console.log('[ChromePilot] Clicked element successfully');
|
|
761
|
+
// console.log('[ChromePilot] Clicked element successfully');
|
|
745
762
|
} catch (e) {
|
|
746
763
|
console.error('[ChromePilot] Error clicking element:', e);
|
|
747
764
|
// Try alternative click method
|
|
@@ -754,7 +771,7 @@ async function playWorkflowRecording(workflow, actions) {
|
|
|
754
771
|
|
|
755
772
|
// If URL changed, wait for page load
|
|
756
773
|
if (window.location.href !== currentUrl) {
|
|
757
|
-
console.log('[ChromePilot] Navigation detected after click, waiting for page load...');
|
|
774
|
+
// console.log('[ChromePilot] Navigation detected after click, waiting for page load...');
|
|
758
775
|
await waitForPageLoad();
|
|
759
776
|
}
|
|
760
777
|
} else {
|
|
@@ -774,12 +791,12 @@ async function playWorkflowRecording(workflow, actions) {
|
|
|
774
791
|
// Wait for element to appear if it's not immediately available
|
|
775
792
|
let element = document.querySelector(action.selector);
|
|
776
793
|
if (!element) {
|
|
777
|
-
console.log('[ChromePilot] Input element not found immediately, waiting...');
|
|
794
|
+
// console.log('[ChromePilot] Input element not found immediately, waiting...');
|
|
778
795
|
element = await waitForElement(action.selector, 3000);
|
|
779
796
|
}
|
|
780
797
|
|
|
781
798
|
if (element) {
|
|
782
|
-
console.log('[ChromePilot] Found input element:', element.tagName, 'type:', element.type, 'for selector:', action.selector);
|
|
799
|
+
// console.log('[ChromePilot] Found input element:', element.tagName, 'type:', element.type, 'for selector:', action.selector);
|
|
783
800
|
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
784
801
|
await new Promise(resolve => setTimeout(resolve, 200)); // Wait for scroll
|
|
785
802
|
|
|
@@ -791,7 +808,7 @@ async function playWorkflowRecording(workflow, actions) {
|
|
|
791
808
|
|
|
792
809
|
// Set new value
|
|
793
810
|
element.value = action.value || '';
|
|
794
|
-
console.log('[ChromePilot] Set input value to:', action.value);
|
|
811
|
+
// console.log('[ChromePilot] Set input value to:', action.value);
|
|
795
812
|
|
|
796
813
|
// Trigger events in the right order
|
|
797
814
|
element.dispatchEvent(new Event('focus', { bubbles: true }));
|
|
@@ -819,7 +836,7 @@ async function playWorkflowRecording(workflow, actions) {
|
|
|
819
836
|
|
|
820
837
|
case 'navigation':
|
|
821
838
|
// Navigation will be handled by the browser
|
|
822
|
-
console.log('[ChromePilot] Navigation detected');
|
|
839
|
+
// console.log('[ChromePilot] Navigation detected');
|
|
823
840
|
break;
|
|
824
841
|
|
|
825
842
|
default:
|
|
@@ -844,7 +861,7 @@ async function playWorkflowRecording(workflow, actions) {
|
|
|
844
861
|
style.remove();
|
|
845
862
|
}, 3000);
|
|
846
863
|
|
|
847
|
-
console.log('[ChromePilot] Workflow playback completed');
|
|
864
|
+
// console.log('[ChromePilot] Workflow playback completed');
|
|
848
865
|
|
|
849
866
|
} catch (error) {
|
|
850
867
|
console.error('[ChromePilot] Error during workflow playback:', error);
|
|
@@ -857,6 +874,7 @@ let isWorkflowRecording = false;
|
|
|
857
874
|
let workflowActions = [];
|
|
858
875
|
let workflowRecordingIndicator = null;
|
|
859
876
|
let workflowScreenshotSettings = null;
|
|
877
|
+
let workflowTabId = null; // Store tabId for use when stopping recording
|
|
860
878
|
let lastScreenshotTime = 0;
|
|
861
879
|
let pendingScreenshots = []; // Track pending screenshot captures
|
|
862
880
|
|
|
@@ -936,7 +954,7 @@ function getUniqueSelector(element) {
|
|
|
936
954
|
// Try unique class combination
|
|
937
955
|
if (element.className && typeof element.className === 'string') {
|
|
938
956
|
const classes = element.className.trim().split(/\s+/)
|
|
939
|
-
.filter(c => !c.startsWith('chrome-
|
|
957
|
+
.filter(c => !c.startsWith('chrome-debug'))
|
|
940
958
|
.filter(c => !c.includes(':')) // Filter out pseudo-class artifacts
|
|
941
959
|
.map(c => {
|
|
942
960
|
// Escape special characters in class names
|
|
@@ -985,18 +1003,17 @@ function getXPath(element) {
|
|
|
985
1003
|
|
|
986
1004
|
// Create workflow recording indicator
|
|
987
1005
|
function createWorkflowRecordingIndicator() {
|
|
988
|
-
|
|
989
|
-
|
|
1006
|
+
// CRITICAL FIX: If old indicator exists (showing completion), remove it completely
|
|
1007
|
+
// This ensures the old popup closes immediately before showing the new recording indicator
|
|
1008
|
+
if (workflowRecordingIndicator && workflowRecordingIndicator.parentNode) {
|
|
1009
|
+
workflowRecordingIndicator.parentNode.removeChild(workflowRecordingIndicator);
|
|
1010
|
+
workflowRecordingIndicator = null;
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
// Always create fresh element for new recording
|
|
990
1014
|
workflowRecordingIndicator = document.createElement('div');
|
|
991
|
-
workflowRecordingIndicator.id = 'chrome-
|
|
992
|
-
|
|
993
|
-
<div style="display: flex; align-items: center; gap: 8px;">
|
|
994
|
-
<span style="color: #9c27b0; font-size: 20px; animation: pulse 1.5s infinite;">●</span>
|
|
995
|
-
<span>Recording Workflow...</span>
|
|
996
|
-
<span id="workflow-action-count" style="background: rgba(255,255,255,0.2); padding: 2px 8px; border-radius: 12px; font-size: 12px;">0 actions</span>
|
|
997
|
-
</div>
|
|
998
|
-
`;
|
|
999
|
-
|
|
1015
|
+
workflowRecordingIndicator.id = 'chrome-debug-workflow-indicator';
|
|
1016
|
+
|
|
1000
1017
|
Object.assign(workflowRecordingIndicator.style, {
|
|
1001
1018
|
position: 'fixed',
|
|
1002
1019
|
bottom: '20px',
|
|
@@ -1012,11 +1029,77 @@ function createWorkflowRecordingIndicator() {
|
|
|
1012
1029
|
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.3)',
|
|
1013
1030
|
backdropFilter: 'blur(10px)',
|
|
1014
1031
|
WebkitBackdropFilter: 'blur(10px)',
|
|
1015
|
-
pointerEvents: '
|
|
1032
|
+
pointerEvents: 'auto',
|
|
1016
1033
|
userSelect: 'none'
|
|
1017
1034
|
});
|
|
1018
|
-
|
|
1035
|
+
|
|
1036
|
+
workflowRecordingIndicator.innerHTML = `
|
|
1037
|
+
<div style="display: flex; align-items: center; gap: 12px;">
|
|
1038
|
+
<div style="display: flex; align-items: center; gap: 8px; flex: 1;">
|
|
1039
|
+
<span style="color: #9c27b0; font-size: 20px; animation: pulse 1.5s infinite;">●</span>
|
|
1040
|
+
<span>Recording Workflow...</span>
|
|
1041
|
+
<span id="workflow-action-count" style="background: rgba(255,255,255,0.2); padding: 2px 8px; border-radius: 12px; font-size: 12px;">0 actions</span>
|
|
1042
|
+
</div>
|
|
1043
|
+
<button id="workflow-stop-btn" style="background: #f44336; color: white; border: none; padding: 6px 16px; border-radius: 15px; font-size: 12px; font-weight: 500; cursor: pointer; font-family: inherit;">Stop</button>
|
|
1044
|
+
<button id="workflow-close-btn" style="background: transparent; color: white; border: none; padding: 4px 8px; font-size: 16px; cursor: pointer; font-family: inherit; opacity: 0.7;" title="Close notification">×</button>
|
|
1045
|
+
</div>
|
|
1046
|
+
`;
|
|
1047
|
+
|
|
1019
1048
|
document.body.appendChild(workflowRecordingIndicator);
|
|
1049
|
+
|
|
1050
|
+
// Add stop button click handler
|
|
1051
|
+
const stopBtn = document.getElementById('workflow-stop-btn');
|
|
1052
|
+
const closeBtn = document.getElementById('workflow-close-btn');
|
|
1053
|
+
|
|
1054
|
+
if (stopBtn) {
|
|
1055
|
+
stopBtn.addEventListener('click', async (e) => {
|
|
1056
|
+
e.stopPropagation();
|
|
1057
|
+
stopBtn.disabled = true;
|
|
1058
|
+
stopBtn.textContent = 'Stopping...';
|
|
1059
|
+
|
|
1060
|
+
try {
|
|
1061
|
+
// Stop workflow recording via background script (which handles saving automatically)
|
|
1062
|
+
// Include tabId explicitly - sender.tab.id can be undefined in some edge cases
|
|
1063
|
+
chrome.runtime.sendMessage({
|
|
1064
|
+
action: 'stopWorkflowRecording',
|
|
1065
|
+
tabId: workflowTabId
|
|
1066
|
+
}, (response) => {
|
|
1067
|
+
if (chrome.runtime.lastError) {
|
|
1068
|
+
console.error('[WorkflowRecording] Error:', chrome.runtime.lastError.message);
|
|
1069
|
+
stopBtn.textContent = 'Error';
|
|
1070
|
+
stopBtn.style.background = '#666';
|
|
1071
|
+
return;
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
if (response && response.success) {
|
|
1075
|
+
// console.log('[WorkflowRecording] Stop response:', response);
|
|
1076
|
+
const workflowId = response.workflow?.sessionId || 'unknown';
|
|
1077
|
+
const actionCount = response.workflow?.actions?.length || 0;
|
|
1078
|
+
// console.log('[WorkflowRecording] Extracted workflowId:', workflowId, 'actionCount:', actionCount);
|
|
1079
|
+
// Show completion with action buttons
|
|
1080
|
+
showWorkflowRecordingComplete(workflowId, actionCount);
|
|
1081
|
+
} else {
|
|
1082
|
+
console.error('[WorkflowRecording] Failed to save:', response?.error);
|
|
1083
|
+
// Don't remove indicator, just show error
|
|
1084
|
+
stopBtn.textContent = 'Error';
|
|
1085
|
+
stopBtn.style.background = '#666';
|
|
1086
|
+
}
|
|
1087
|
+
});
|
|
1088
|
+
} catch (error) {
|
|
1089
|
+
console.error('[WorkflowRecording] Error stopping:', error);
|
|
1090
|
+
// Don't remove indicator, just show error
|
|
1091
|
+
stopBtn.textContent = 'Error';
|
|
1092
|
+
stopBtn.style.background = '#666';
|
|
1093
|
+
}
|
|
1094
|
+
});
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
if (closeBtn) {
|
|
1098
|
+
closeBtn.addEventListener('click', (e) => {
|
|
1099
|
+
e.stopPropagation();
|
|
1100
|
+
removeWorkflowRecordingIndicator();
|
|
1101
|
+
});
|
|
1102
|
+
}
|
|
1020
1103
|
}
|
|
1021
1104
|
|
|
1022
1105
|
function removeWorkflowRecordingIndicator() {
|
|
@@ -1033,6 +1116,97 @@ function updateWorkflowActionCount() {
|
|
|
1033
1116
|
}
|
|
1034
1117
|
}
|
|
1035
1118
|
|
|
1119
|
+
// Show workflow recording completion with action buttons
|
|
1120
|
+
function showWorkflowRecordingComplete(workflowId, actionCount) {
|
|
1121
|
+
if (!workflowRecordingIndicator) return;
|
|
1122
|
+
|
|
1123
|
+
workflowRecordingIndicator.innerHTML = `
|
|
1124
|
+
<div style="display: flex; flex-direction: column; gap: 10px; position: relative; padding-right: 30px;">
|
|
1125
|
+
<button class="wf-close-complete" style="position: absolute; top: -8px; right: -8px; background: transparent; color: white; border: none; padding: 4px 8px; font-size: 20px; cursor: pointer; font-family: inherit; opacity: 0.7; line-height: 1;" title="Close notification">×</button>
|
|
1126
|
+
|
|
1127
|
+
<div style="display: flex; align-items: center; gap: 8px;">
|
|
1128
|
+
<span style="color: #4CAF50; font-size: 16px;">✓</span>
|
|
1129
|
+
<span style="font-weight: 600; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 400px;" title="${workflowId}">${workflowId}</span>
|
|
1130
|
+
</div>
|
|
1131
|
+
|
|
1132
|
+
<div style="font-size: 11px; color: rgba(255,255,255,0.7); margin-top: -5px;">
|
|
1133
|
+
${actionCount} actions • ${new Date().toLocaleString()}
|
|
1134
|
+
</div>
|
|
1135
|
+
|
|
1136
|
+
<div style="display: flex; gap: 6px; flex-wrap: wrap;">
|
|
1137
|
+
<button class="wf-copy-id" data-id="${workflowId}" style="background: #2196F3; color: white; border: none; padding: 6px 12px; border-radius: 12px; font-size: 11px; cursor: pointer; font-family: inherit; font-weight: 500;">Copy ID</button>
|
|
1138
|
+
<button class="wf-copy-prompt" data-id="${workflowId}" style="background: #4CAF50; color: white; border: none; padding: 6px 12px; border-radius: 12px; font-size: 11px; cursor: pointer; font-family: inherit; font-weight: 500;">Copy Prompt</button>
|
|
1139
|
+
<button class="wf-view" data-id="${workflowId}" style="background: #9C27B0; color: white; border: none; padding: 6px 12px; border-radius: 12px; font-size: 11px; cursor: pointer; font-family: inherit; font-weight: 500;">View</button>
|
|
1140
|
+
<button class="wf-delete" data-id="${workflowId}" style="background: #f44336; color: white; border: none; padding: 6px 12px; border-radius: 12px; font-size: 11px; cursor: pointer; font-family: inherit; font-weight: 500;">Delete</button>
|
|
1141
|
+
</div>
|
|
1142
|
+
</div>
|
|
1143
|
+
`;
|
|
1144
|
+
|
|
1145
|
+
// Add event listeners for action buttons
|
|
1146
|
+
const copyIdBtn = workflowRecordingIndicator.querySelector('.wf-copy-id');
|
|
1147
|
+
const copyPromptBtn = workflowRecordingIndicator.querySelector('.wf-copy-prompt');
|
|
1148
|
+
const viewBtn = workflowRecordingIndicator.querySelector('.wf-view');
|
|
1149
|
+
const deleteBtn = workflowRecordingIndicator.querySelector('.wf-delete');
|
|
1150
|
+
const closeBtn = workflowRecordingIndicator.querySelector('.wf-close-complete');
|
|
1151
|
+
|
|
1152
|
+
if (copyIdBtn) {
|
|
1153
|
+
copyIdBtn.addEventListener('click', async () => {
|
|
1154
|
+
try {
|
|
1155
|
+
await navigator.clipboard.writeText(workflowId);
|
|
1156
|
+
copyIdBtn.textContent = 'Copied!';
|
|
1157
|
+
setTimeout(() => copyIdBtn.textContent = 'Copy ID', 2000);
|
|
1158
|
+
} catch (error) {
|
|
1159
|
+
console.error('[WorkflowRecording] Failed to copy ID:', error);
|
|
1160
|
+
}
|
|
1161
|
+
});
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
if (copyPromptBtn) {
|
|
1165
|
+
copyPromptBtn.addEventListener('click', async () => {
|
|
1166
|
+
const prompt = `Please use the get_workflow_recording function in Chrome Debug to load the workflow recording "${workflowId}".`;
|
|
1167
|
+
try {
|
|
1168
|
+
await navigator.clipboard.writeText(prompt);
|
|
1169
|
+
copyPromptBtn.textContent = 'Copied!';
|
|
1170
|
+
setTimeout(() => copyPromptBtn.textContent = 'Copy Prompt', 2000);
|
|
1171
|
+
} catch (error) {
|
|
1172
|
+
console.error('[WorkflowRecording] Failed to copy prompt:', error);
|
|
1173
|
+
}
|
|
1174
|
+
});
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
if (viewBtn) {
|
|
1178
|
+
viewBtn.addEventListener('click', () => {
|
|
1179
|
+
// Ask background to open frame editor (content scripts can't create tabs)
|
|
1180
|
+
chrome.runtime.sendMessage({
|
|
1181
|
+
action: 'openFrameEditor',
|
|
1182
|
+
sessionId: workflowId,
|
|
1183
|
+
type: 'workflow'
|
|
1184
|
+
});
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
if (deleteBtn) {
|
|
1189
|
+
deleteBtn.addEventListener('click', async () => {
|
|
1190
|
+
if (confirm('Delete this workflow recording?')) {
|
|
1191
|
+
chrome.runtime.sendMessage({
|
|
1192
|
+
action: 'deleteWorkflowRecording',
|
|
1193
|
+
workflowId: workflowId
|
|
1194
|
+
}, (response) => {
|
|
1195
|
+
if (response && response.success) {
|
|
1196
|
+
removeWorkflowRecordingIndicator();
|
|
1197
|
+
}
|
|
1198
|
+
});
|
|
1199
|
+
}
|
|
1200
|
+
});
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
if (closeBtn) {
|
|
1204
|
+
closeBtn.addEventListener('click', () => {
|
|
1205
|
+
removeWorkflowRecordingIndicator();
|
|
1206
|
+
});
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1036
1210
|
// Enhanced click tracking helper functions - Pro Feature
|
|
1037
1211
|
// Try to import enhanced capture module (only exists in pro build)
|
|
1038
1212
|
let enhancedCaptureModule = null;
|
|
@@ -1052,9 +1226,9 @@ let getPerformanceMetrics = null;
|
|
|
1052
1226
|
captureElementState = module.captureElementState;
|
|
1053
1227
|
getEnhancedComponentInfo = module.getEnhancedComponentInfo;
|
|
1054
1228
|
getPerformanceMetrics = module.getPerformanceMetrics;
|
|
1055
|
-
console.log('[ChromePilot Pro] Enhanced capture module loaded');
|
|
1229
|
+
// console.log('[ChromePilot Pro] Enhanced capture module loaded');
|
|
1056
1230
|
} catch (e) {
|
|
1057
|
-
console.log('[ChromePilot Free] Enhanced capture not available - using basic mode');
|
|
1231
|
+
// console.log('[ChromePilot Free] Enhanced capture not available - using basic mode');
|
|
1058
1232
|
// Create stub functions that return empty data for free version
|
|
1059
1233
|
captureElementHTML = () => '';
|
|
1060
1234
|
extractEventHandlers = () => ({});
|
|
@@ -1076,19 +1250,16 @@ async function shouldEnhanceCapture() {
|
|
|
1076
1250
|
// Record click action
|
|
1077
1251
|
function recordClick(event) {
|
|
1078
1252
|
if (!isWorkflowRecording) {
|
|
1079
|
-
console.log('[ChromePilot] Click ignored - not recording');
|
|
1080
1253
|
return;
|
|
1081
1254
|
}
|
|
1082
1255
|
|
|
1083
|
-
console.log('[ChromePilot] Recording click event');
|
|
1084
|
-
|
|
1085
1256
|
let element = event.target;
|
|
1086
1257
|
|
|
1087
1258
|
// If clicking on an SVG element or its children, find the parent button/link
|
|
1088
1259
|
if (element.tagName === 'svg' || element.tagName === 'path' || element.tagName === 'g' || element.tagName === 'circle' || element.tagName === 'rect') {
|
|
1089
1260
|
const clickableParent = element.closest('button, a, [role="button"], [onclick]');
|
|
1090
1261
|
if (clickableParent) {
|
|
1091
|
-
console.log('[ChromePilot] Adjusted click target from', element.tagName, 'to', clickableParent.tagName);
|
|
1262
|
+
// console.log('[ChromePilot] Adjusted click target from', element.tagName, 'to', clickableParent.tagName);
|
|
1092
1263
|
element = clickableParent;
|
|
1093
1264
|
}
|
|
1094
1265
|
}
|
|
@@ -1116,8 +1287,6 @@ function recordClick(event) {
|
|
|
1116
1287
|
shouldEnhanceCapture().then(enhanceCapture => {
|
|
1117
1288
|
if (enhanceCapture) {
|
|
1118
1289
|
try {
|
|
1119
|
-
console.log('[ChromePilot] Capturing enhanced click data asynchronously...');
|
|
1120
|
-
|
|
1121
1290
|
// Capture enhanced element data (only include fields with meaningful values)
|
|
1122
1291
|
const capturedHTML = captureElementHTML(element);
|
|
1123
1292
|
if (capturedHTML) {
|
|
@@ -1168,14 +1337,13 @@ function recordClick(event) {
|
|
|
1168
1337
|
}
|
|
1169
1338
|
}
|
|
1170
1339
|
|
|
1171
|
-
|
|
1340
|
+
// Enhanced click data captured successfully - no need to log
|
|
1172
1341
|
} catch (error) {
|
|
1173
1342
|
console.warn('[ChromePilot] Error capturing enhanced click data:', error);
|
|
1174
1343
|
// Continue with basic click recording if enhanced capture fails
|
|
1175
1344
|
}
|
|
1176
|
-
} else {
|
|
1177
|
-
console.log('[ChromePilot] Enhanced click capture disabled - using basic capture only');
|
|
1178
1345
|
}
|
|
1346
|
+
// Enhanced capture setting checked - no need to log state
|
|
1179
1347
|
}).catch(error => {
|
|
1180
1348
|
console.error('[ChromePilot] Error checking enhanced capture setting:', error);
|
|
1181
1349
|
});
|
|
@@ -1303,12 +1471,12 @@ function startWorkflowRecording(screenshotSettings) {
|
|
|
1303
1471
|
pendingScreenshots = []; // Clear any pending screenshots from previous recording
|
|
1304
1472
|
createWorkflowRecordingIndicator();
|
|
1305
1473
|
|
|
1306
|
-
console.log('[ChromePilot] Workflow recording started with settings:', screenshotSettings);
|
|
1474
|
+
// console.log('[ChromePilot] Workflow recording started with settings:', screenshotSettings);
|
|
1307
1475
|
|
|
1308
1476
|
// Start runtime bridge recording for function traces
|
|
1309
1477
|
if (window.__chromePilot && window.__chromePilot.startRecording) {
|
|
1310
1478
|
window.__chromePilot.startRecording();
|
|
1311
|
-
console.log('[ChromePilot] Started runtime bridge recording for function traces');
|
|
1479
|
+
// console.log('[ChromePilot] Started runtime bridge recording for function traces');
|
|
1312
1480
|
}
|
|
1313
1481
|
|
|
1314
1482
|
// Connect to the existing FunctionTracker for workflow recording
|
|
@@ -1334,17 +1502,19 @@ function startWorkflowRecording(screenshotSettings) {
|
|
|
1334
1502
|
timestamp: event.timestamp,
|
|
1335
1503
|
stack: event.call_stack || null
|
|
1336
1504
|
});
|
|
1337
|
-
|
|
1338
|
-
console.log
|
|
1505
|
+
|
|
1506
|
+
// REMOVED: console.log that logged EVERY function execution (thousands per second)
|
|
1507
|
+
// Function traces are already stored in workflowActions array - no need to log each one
|
|
1339
1508
|
}
|
|
1340
1509
|
});
|
|
1341
1510
|
};
|
|
1342
1511
|
|
|
1343
1512
|
// Enable function tracking via ChromePilotTracker
|
|
1344
1513
|
window.ChromePilotTracker._setRecordingStatus(true);
|
|
1345
|
-
console.log('[ChromePilot] Connected workflow recording to FunctionTracker');
|
|
1514
|
+
// console.log('[ChromePilot] Connected workflow recording to FunctionTracker');
|
|
1346
1515
|
} else {
|
|
1347
|
-
|
|
1516
|
+
// FunctionTracker is a PRO feature - use debug level to avoid confusing FREE users
|
|
1517
|
+
console.debug('[ChromePilot] FunctionTracker not available (PRO feature)');
|
|
1348
1518
|
}
|
|
1349
1519
|
|
|
1350
1520
|
// Add event listeners for recording
|
|
@@ -1373,17 +1543,19 @@ function startWorkflowRecording(screenshotSettings) {
|
|
|
1373
1543
|
// Stop workflow recording
|
|
1374
1544
|
async function stopWorkflowRecording() {
|
|
1375
1545
|
isWorkflowRecording = false;
|
|
1376
|
-
|
|
1546
|
+
workflowTabId = null; // Reset tabId when recording stops
|
|
1547
|
+
// DON'T remove indicator here - let the completion screen handle it
|
|
1548
|
+
// removeWorkflowRecordingIndicator();
|
|
1377
1549
|
|
|
1378
|
-
console.log(`[ChromePilot] Stopping recording. Captured ${workflowActions.length} actions`);
|
|
1550
|
+
// console.log(`[ChromePilot] Stopping recording. Captured ${workflowActions.length} actions`);
|
|
1379
1551
|
|
|
1380
1552
|
// Wait for all pending screenshots to complete
|
|
1381
1553
|
if (pendingScreenshots.length > 0) {
|
|
1382
|
-
console.log(`[SCREENSHOT-DEBUG] Waiting for ${pendingScreenshots.length} pending screenshots to complete...`);
|
|
1554
|
+
// console.log(`[SCREENSHOT-DEBUG] Waiting for ${pendingScreenshots.length} pending screenshots to complete...`);
|
|
1383
1555
|
await Promise.all(pendingScreenshots);
|
|
1384
|
-
console.log('[SCREENSHOT-DEBUG] All pending screenshots completed!');
|
|
1556
|
+
// console.log('[SCREENSHOT-DEBUG] All pending screenshots completed!');
|
|
1385
1557
|
} else {
|
|
1386
|
-
console.log('[SCREENSHOT-DEBUG] No pending screenshots to wait for');
|
|
1558
|
+
// console.log('[SCREENSHOT-DEBUG] No pending screenshots to wait for');
|
|
1387
1559
|
}
|
|
1388
1560
|
|
|
1389
1561
|
// Disconnect from FunctionTracker and disable recording
|
|
@@ -1393,7 +1565,7 @@ async function stopWorkflowRecording() {
|
|
|
1393
1565
|
|
|
1394
1566
|
// Count function traces captured during workflow recording
|
|
1395
1567
|
const functionTraces = workflowActions.filter(action => action.type === 'function-trace');
|
|
1396
|
-
console.log(`[ChromePilot] Function tracking stopped. Captured ${functionTraces.length} function traces`);
|
|
1568
|
+
// console.log(`[ChromePilot] Function tracking stopped. Captured ${functionTraces.length} function traces`);
|
|
1397
1569
|
}
|
|
1398
1570
|
|
|
1399
1571
|
// Remove event listeners
|
|
@@ -1412,7 +1584,7 @@ async function stopWorkflowRecording() {
|
|
|
1412
1584
|
|
|
1413
1585
|
// First, get any function traces from the runtime bridge
|
|
1414
1586
|
if (window.__chromePilot && window.__chromePilot.stopRecording) {
|
|
1415
|
-
console.log('[ChromeDebug MCP] Stopping runtime bridge recording...');
|
|
1587
|
+
// console.log('[ChromeDebug MCP] Stopping runtime bridge recording...');
|
|
1416
1588
|
const bridgeTraces = window.__chromePilot.stopRecording();
|
|
1417
1589
|
if (Array.isArray(bridgeTraces)) {
|
|
1418
1590
|
// Convert bridge traces to workflow action format
|
|
@@ -1430,31 +1602,31 @@ async function stopWorkflowRecording() {
|
|
|
1430
1602
|
placeholder: null,
|
|
1431
1603
|
screenshot_data: null
|
|
1432
1604
|
}));
|
|
1433
|
-
console.log(`[Chrome Debug] Retrieved ${functionTraces.length} function traces from runtime bridge`);
|
|
1605
|
+
// console.log(`[Chrome Debug] Retrieved ${functionTraces.length} function traces from runtime bridge`);
|
|
1434
1606
|
}
|
|
1435
1607
|
}
|
|
1436
1608
|
|
|
1437
1609
|
// Also include any function traces that were added to workflowActions
|
|
1438
1610
|
const embeddedTraces = workflowActions.filter(action => action.type === 'function-trace');
|
|
1439
1611
|
if (embeddedTraces.length > 0) {
|
|
1440
|
-
console.log(`[Chrome Debug] Found ${embeddedTraces.length} embedded function traces`);
|
|
1612
|
+
// console.log(`[Chrome Debug] Found ${embeddedTraces.length} embedded function traces`);
|
|
1441
1613
|
functionTraces = [...functionTraces, ...embeddedTraces];
|
|
1442
1614
|
}
|
|
1443
1615
|
|
|
1444
1616
|
// Log screenshot data before returning
|
|
1445
|
-
console.log('[SCREENSHOT-DEBUG] stopWorkflowRecording - Preparing to return workflow');
|
|
1446
|
-
console.log('[SCREENSHOT-DEBUG] stopWorkflowRecording - Total actions:', workflowActions.length);
|
|
1617
|
+
// console.log('[SCREENSHOT-DEBUG] stopWorkflowRecording - Preparing to return workflow');
|
|
1618
|
+
// console.log('[SCREENSHOT-DEBUG] stopWorkflowRecording - Total actions:', workflowActions.length);
|
|
1447
1619
|
|
|
1448
1620
|
const actionsWithScreenshots = workflowActions.filter(a => a.screenshot_data);
|
|
1449
|
-
console.log('[SCREENSHOT-DEBUG] stopWorkflowRecording - Actions WITH screenshot_data:', actionsWithScreenshots.length);
|
|
1621
|
+
// console.log('[SCREENSHOT-DEBUG] stopWorkflowRecording - Actions WITH screenshot_data:', actionsWithScreenshots.length);
|
|
1450
1622
|
|
|
1451
1623
|
workflowActions.forEach((action, index) => {
|
|
1452
|
-
console.log(`[SCREENSHOT-DEBUG] stopWorkflowRecording - Action ${index}:`, {
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
});
|
|
1624
|
+
// console.log(`[SCREENSHOT-DEBUG] stopWorkflowRecording - Action ${index}:`, {
|
|
1625
|
+
// type: action.type,
|
|
1626
|
+
// hasScreenshotData: !!action.screenshot_data,
|
|
1627
|
+
// screenshotDataLength: action.screenshot_data?.length,
|
|
1628
|
+
// screenshotPreview: action.screenshot_data?.substring(0, 50)
|
|
1629
|
+
// });
|
|
1458
1630
|
});
|
|
1459
1631
|
|
|
1460
1632
|
// Return the recorded workflow with proper functionTraces field
|
|
@@ -1601,7 +1773,7 @@ function captureConsoleLogs() {
|
|
|
1601
1773
|
|
|
1602
1774
|
// Create restore point
|
|
1603
1775
|
async function createRestorePoint(actionIndex) {
|
|
1604
|
-
console.log('[ChromePilot] Creating restore point at action index:', actionIndex);
|
|
1776
|
+
// console.log('[ChromePilot] Creating restore point at action index:', actionIndex);
|
|
1605
1777
|
|
|
1606
1778
|
try {
|
|
1607
1779
|
// Capture all data
|
|
@@ -1630,7 +1802,7 @@ async function createRestorePoint(actionIndex) {
|
|
|
1630
1802
|
});
|
|
1631
1803
|
|
|
1632
1804
|
if (response && response.success) {
|
|
1633
|
-
console.log('[ChromePilot] Restore point saved:', response.restorePointId);
|
|
1805
|
+
// console.log('[ChromePilot] Restore point saved:', response.restorePointId);
|
|
1634
1806
|
// Visual feedback
|
|
1635
1807
|
showRestorePointNotification('Restore point saved!');
|
|
1636
1808
|
return response.restorePointId;
|
|
@@ -1646,7 +1818,7 @@ async function createRestorePoint(actionIndex) {
|
|
|
1646
1818
|
|
|
1647
1819
|
// Restore from a restore point
|
|
1648
1820
|
async function restoreFromPoint(restorePointData) {
|
|
1649
|
-
console.log('[ChromePilot] Restoring from restore point');
|
|
1821
|
+
// console.log('[ChromePilot] Restoring from restore point');
|
|
1650
1822
|
|
|
1651
1823
|
try {
|
|
1652
1824
|
// First check if we need to navigate
|
|
@@ -1802,8 +1974,6 @@ async function recordScreenClick(event) {
|
|
|
1802
1974
|
const enhanceCapture = await shouldEnhanceCapture();
|
|
1803
1975
|
if (enhanceCapture) {
|
|
1804
1976
|
try {
|
|
1805
|
-
console.log('[ChromePilot] Capturing enhanced screen click data...');
|
|
1806
|
-
|
|
1807
1977
|
// Capture enhanced element data (only include fields with meaningful values)
|
|
1808
1978
|
const capturedHTML = captureElementHTML(element);
|
|
1809
1979
|
if (capturedHTML) {
|
|
@@ -1854,14 +2024,13 @@ async function recordScreenClick(event) {
|
|
|
1854
2024
|
}
|
|
1855
2025
|
}
|
|
1856
2026
|
|
|
1857
|
-
|
|
2027
|
+
// Enhanced screen click data captured successfully - no need to log
|
|
1858
2028
|
} catch (error) {
|
|
1859
2029
|
console.warn('[ChromePilot] Error capturing enhanced screen click data:', error);
|
|
1860
2030
|
// Continue with basic click recording if enhanced capture fails
|
|
1861
2031
|
}
|
|
1862
|
-
} else {
|
|
1863
|
-
console.log('[ChromePilot] Enhanced screen click capture disabled - using basic capture only');
|
|
1864
2032
|
}
|
|
2033
|
+
// Enhanced capture setting checked - no need to log state
|
|
1865
2034
|
|
|
1866
2035
|
sendScreenInteraction(interaction);
|
|
1867
2036
|
|
|
@@ -2000,7 +2169,7 @@ function startScreenInteractionTracking(scheduledStartTime, sessionId) {
|
|
|
2000
2169
|
recordingScheduledStartTime = scheduledStartTime;
|
|
2001
2170
|
recordingSessionId = sessionId;
|
|
2002
2171
|
|
|
2003
|
-
console.log('[ChromePilot] Screen interaction tracking scheduled to start at:', new Date(scheduledStartTime));
|
|
2172
|
+
// console.log('[ChromePilot] Screen interaction tracking scheduled to start at:', new Date(scheduledStartTime));
|
|
2004
2173
|
|
|
2005
2174
|
// Trigger visual feedback start
|
|
2006
2175
|
if (window.screenCaptureVisualFeedback) {
|
|
@@ -2021,7 +2190,7 @@ function startScreenInteractionTracking(scheduledStartTime, sessionId) {
|
|
|
2021
2190
|
document.addEventListener('mousedown', recordScreenMouseDown, true);
|
|
2022
2191
|
document.addEventListener('mouseup', recordScreenMouseUp, true);
|
|
2023
2192
|
|
|
2024
|
-
console.log('[ChromePilot] Screen interaction tracking started at scheduled time');
|
|
2193
|
+
// console.log('[ChromePilot] Screen interaction tracking started at scheduled time');
|
|
2025
2194
|
}, waitTime);
|
|
2026
2195
|
}
|
|
2027
2196
|
|
|
@@ -2054,7 +2223,7 @@ function stopScreenInteractionTracking() {
|
|
|
2054
2223
|
screenRecordingDragStartX = 0; // CRITICAL: This was missing
|
|
2055
2224
|
screenRecordingDragStartY = 0; // CRITICAL: This was missing
|
|
2056
2225
|
|
|
2057
|
-
console.log('[ChromePilot] Screen interaction tracking stopped');
|
|
2226
|
+
// console.log('[ChromePilot] Screen interaction tracking stopped');
|
|
2058
2227
|
|
|
2059
2228
|
// Visual feedback stop with error isolation
|
|
2060
2229
|
try {
|
|
@@ -2148,7 +2317,7 @@ let isFullDataRecordingActive = false;
|
|
|
2148
2317
|
|
|
2149
2318
|
// Create floating recording interface
|
|
2150
2319
|
function showRecordingInterface() {
|
|
2151
|
-
console.log('showRecordingInterface called');
|
|
2320
|
+
// console.log('showRecordingInterface called');
|
|
2152
2321
|
|
|
2153
2322
|
// Remove any existing recording overlay
|
|
2154
2323
|
if (recordingOverlay) {
|
|
@@ -2157,7 +2326,7 @@ function showRecordingInterface() {
|
|
|
2157
2326
|
|
|
2158
2327
|
// Create recording overlay
|
|
2159
2328
|
recordingOverlay = document.createElement('div');
|
|
2160
|
-
recordingOverlay.id = 'chrome-
|
|
2329
|
+
recordingOverlay.id = 'chrome-debug-recording-overlay';
|
|
2161
2330
|
recordingOverlay.style.cssText = `
|
|
2162
2331
|
position: fixed;
|
|
2163
2332
|
bottom: 20px;
|
|
@@ -2175,13 +2344,13 @@ function showRecordingInterface() {
|
|
|
2175
2344
|
recordingOverlay.innerHTML = `
|
|
2176
2345
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px;">
|
|
2177
2346
|
<h3 style="margin: 0; font-size: 16px; color: #333;">Screen Recording</h3>
|
|
2178
|
-
<button id="chrome-
|
|
2347
|
+
<button id="chrome-debug-close-recording" style="background: none; border: none; font-size: 20px; cursor: pointer; color: #666;">×</button>
|
|
2179
2348
|
</div>
|
|
2180
2349
|
<p style="margin: 0 0 15px 0; font-size: 13px; color: #666;">
|
|
2181
2350
|
Recording this tab with console logs
|
|
2182
2351
|
</p>
|
|
2183
|
-
<div id="chrome-
|
|
2184
|
-
<button id="chrome-
|
|
2352
|
+
<div id="chrome-debug-recording-status" style="text-align: center; margin-bottom: 15px; font-size: 14px; color: #666;"></div>
|
|
2353
|
+
<button id="chrome-debug-record-btn" style="
|
|
2185
2354
|
width: 100%;
|
|
2186
2355
|
padding: 10px;
|
|
2187
2356
|
background: #f44336;
|
|
@@ -2192,13 +2361,13 @@ function showRecordingInterface() {
|
|
|
2192
2361
|
font-size: 14px;
|
|
2193
2362
|
font-weight: 500;
|
|
2194
2363
|
">Start Recording</button>
|
|
2195
|
-
<div id="chrome-
|
|
2364
|
+
<div id="chrome-debug-recording-result" style="margin-top: 15px; display: none;"></div>
|
|
2196
2365
|
`;
|
|
2197
2366
|
|
|
2198
2367
|
document.body.appendChild(recordingOverlay);
|
|
2199
2368
|
|
|
2200
2369
|
// Add event listeners
|
|
2201
|
-
document.getElementById('chrome-
|
|
2370
|
+
document.getElementById('chrome-debug-close-recording').addEventListener('click', () => {
|
|
2202
2371
|
if (isRecording) {
|
|
2203
2372
|
if (confirm('Stop recording and close?')) {
|
|
2204
2373
|
stopRecording();
|
|
@@ -2211,7 +2380,7 @@ function showRecordingInterface() {
|
|
|
2211
2380
|
}
|
|
2212
2381
|
});
|
|
2213
2382
|
|
|
2214
|
-
document.getElementById('chrome-
|
|
2383
|
+
document.getElementById('chrome-debug-record-btn').addEventListener('click', () => {
|
|
2215
2384
|
if (!isRecording) {
|
|
2216
2385
|
startRecording();
|
|
2217
2386
|
} else {
|
|
@@ -2222,8 +2391,8 @@ function showRecordingInterface() {
|
|
|
2222
2391
|
|
|
2223
2392
|
// Start recording from content script
|
|
2224
2393
|
function startRecording() {
|
|
2225
|
-
const recordBtn = document.getElementById('chrome-
|
|
2226
|
-
const statusDiv = document.getElementById('chrome-
|
|
2394
|
+
const recordBtn = document.getElementById('chrome-debug-record-btn');
|
|
2395
|
+
const statusDiv = document.getElementById('chrome-debug-recording-status');
|
|
2227
2396
|
|
|
2228
2397
|
recordBtn.disabled = true;
|
|
2229
2398
|
recordBtn.textContent = 'Starting...';
|
|
@@ -2250,7 +2419,7 @@ function startRecording() {
|
|
|
2250
2419
|
// Start performance monitoring when recording begins
|
|
2251
2420
|
if (performanceMonitor) {
|
|
2252
2421
|
performanceMonitor.startMonitoring();
|
|
2253
|
-
console.log('[ChromeDebug MCP] Performance monitoring started with recording');
|
|
2422
|
+
// console.log('[ChromeDebug MCP] Performance monitoring started with recording');
|
|
2254
2423
|
}
|
|
2255
2424
|
|
|
2256
2425
|
// Start timer display
|
|
@@ -2270,9 +2439,9 @@ function startRecording() {
|
|
|
2270
2439
|
|
|
2271
2440
|
// Stop recording
|
|
2272
2441
|
function stopRecording() {
|
|
2273
|
-
const recordBtn = document.getElementById('chrome-
|
|
2274
|
-
const statusDiv = document.getElementById('chrome-
|
|
2275
|
-
const resultDiv = document.getElementById('chrome-
|
|
2442
|
+
const recordBtn = document.getElementById('chrome-debug-record-btn');
|
|
2443
|
+
const statusDiv = document.getElementById('chrome-debug-recording-status');
|
|
2444
|
+
const resultDiv = document.getElementById('chrome-debug-recording-result');
|
|
2276
2445
|
|
|
2277
2446
|
recordBtn.disabled = true;
|
|
2278
2447
|
recordBtn.textContent = 'Stopping...';
|
|
@@ -2311,7 +2480,7 @@ function stopRecording() {
|
|
|
2311
2480
|
// Stop performance monitoring when recording ends
|
|
2312
2481
|
if (performanceMonitor) {
|
|
2313
2482
|
performanceMonitor.stopMonitoring();
|
|
2314
|
-
console.log('[ChromeDebug MCP] Performance monitoring stopped with recording');
|
|
2483
|
+
// console.log('[ChromeDebug MCP] Performance monitoring stopped with recording');
|
|
2315
2484
|
}
|
|
2316
2485
|
});
|
|
2317
2486
|
}
|
|
@@ -2350,7 +2519,7 @@ function showFrameFlash() {
|
|
|
2350
2519
|
/*
|
|
2351
2520
|
async function initializeFullDataRecordingSystem() {
|
|
2352
2521
|
try {
|
|
2353
|
-
console.log('[ChromeDebug MCP] Initializing full data recording system...');
|
|
2522
|
+
// console.log('[ChromeDebug MCP] Initializing full data recording system...');
|
|
2354
2523
|
|
|
2355
2524
|
// Initialize core components
|
|
2356
2525
|
if (typeof DataBuffer !== 'undefined') {
|
|
@@ -2397,7 +2566,7 @@ async function initializeFullDataRecordingSystem() {
|
|
|
2397
2566
|
if (dataBuffer) {
|
|
2398
2567
|
try {
|
|
2399
2568
|
await dataBuffer.addBatch(events);
|
|
2400
|
-
console.log(`[Chrome Debug] Persisted ${events.length} function traces`);
|
|
2569
|
+
// console.log(`[Chrome Debug] Persisted ${events.length} function traces`);
|
|
2401
2570
|
} catch (error) {
|
|
2402
2571
|
console.error('[ChromeDebug MCP] Failed to persist function traces:', error);
|
|
2403
2572
|
}
|
|
@@ -2477,10 +2646,10 @@ async function initializeFullDataRecordingSystem() {
|
|
|
2477
2646
|
}
|
|
2478
2647
|
};
|
|
2479
2648
|
|
|
2480
|
-
console.log('[ChromeDebug MCP] ChromePilotTracker API exposed for manual instrumentation');
|
|
2649
|
+
// console.log('[ChromeDebug MCP] ChromePilotTracker API exposed for manual instrumentation');
|
|
2481
2650
|
}
|
|
2482
2651
|
|
|
2483
|
-
console.log('[ChromeDebug MCP] Full data recording system initialized successfully');
|
|
2652
|
+
// console.log('[ChromeDebug MCP] Full data recording system initialized successfully');
|
|
2484
2653
|
return true;
|
|
2485
2654
|
|
|
2486
2655
|
} catch (error) {
|
|
@@ -2497,7 +2666,7 @@ async function startFullDataRecording(config) {
|
|
|
2497
2666
|
return;
|
|
2498
2667
|
}
|
|
2499
2668
|
|
|
2500
|
-
console.log('[ChromeDebug MCP] Starting full data recording with config:', config);
|
|
2669
|
+
// console.log('[ChromeDebug MCP] Starting full data recording with config:', config);
|
|
2501
2670
|
|
|
2502
2671
|
// Initialize system if not already done
|
|
2503
2672
|
if (!dataBuffer) {
|
|
@@ -2527,7 +2696,7 @@ async function startFullDataRecording(config) {
|
|
|
2527
2696
|
// Start performance monitoring (lazy loading - only when recording)
|
|
2528
2697
|
if (performanceMonitor) {
|
|
2529
2698
|
performanceMonitor.startMonitoring();
|
|
2530
|
-
console.log('[ChromeDebug MCP] Performance monitoring started');
|
|
2699
|
+
// console.log('[ChromeDebug MCP] Performance monitoring started');
|
|
2531
2700
|
}
|
|
2532
2701
|
|
|
2533
2702
|
// Configure and start DOM tracking
|
|
@@ -2540,7 +2709,7 @@ async function startFullDataRecording(config) {
|
|
|
2540
2709
|
mutationThrottle: config.instrumentationLevel <= 2 ? 20 : 50 // Throttle for lower levels
|
|
2541
2710
|
});
|
|
2542
2711
|
domTracker.startTracking();
|
|
2543
|
-
console.log('[ChromeDebug MCP] DOM tracking started');
|
|
2712
|
+
// console.log('[ChromeDebug MCP] DOM tracking started');
|
|
2544
2713
|
}
|
|
2545
2714
|
|
|
2546
2715
|
// Configure and start network tracking
|
|
@@ -2555,7 +2724,7 @@ async function startFullDataRecording(config) {
|
|
|
2555
2724
|
maxBodySize: config.instrumentationLevel >= 4 ? 50 * 1024 : 10 * 1024
|
|
2556
2725
|
});
|
|
2557
2726
|
networkTracker.startTracking();
|
|
2558
|
-
console.log('[ChromeDebug MCP] Network tracking started');
|
|
2727
|
+
// console.log('[ChromeDebug MCP] Network tracking started');
|
|
2559
2728
|
}
|
|
2560
2729
|
|
|
2561
2730
|
// Configure and start function tracking
|
|
@@ -2572,7 +2741,7 @@ async function startFullDataRecording(config) {
|
|
|
2572
2741
|
if (chrome.runtime.lastError) {
|
|
2573
2742
|
console.error('[ChromeDebug MCP] Failed to send function traces to background:', chrome.runtime.lastError);
|
|
2574
2743
|
} else {
|
|
2575
|
-
console.log(`[Chrome Debug] Sent ${data.length} function traces to background for upload`);
|
|
2744
|
+
// console.log(`[Chrome Debug] Sent ${data.length} function traces to background for upload`);
|
|
2576
2745
|
}
|
|
2577
2746
|
});
|
|
2578
2747
|
}
|
|
@@ -2601,7 +2770,7 @@ async function startFullDataRecording(config) {
|
|
|
2601
2770
|
window.ChromePilotTracker._functionTracker = functionTracker;
|
|
2602
2771
|
}
|
|
2603
2772
|
|
|
2604
|
-
console.log('[ChromeDebug MCP] Function tracking started');
|
|
2773
|
+
// console.log('[ChromeDebug MCP] Function tracking started');
|
|
2605
2774
|
}
|
|
2606
2775
|
|
|
2607
2776
|
// Start upload manager via background script
|
|
@@ -2611,7 +2780,7 @@ async function startFullDataRecording(config) {
|
|
|
2611
2780
|
if (chrome.runtime.lastError) {
|
|
2612
2781
|
console.error('[ChromeDebug MCP] Error starting upload manager:', chrome.runtime.lastError.message);
|
|
2613
2782
|
} else {
|
|
2614
|
-
console.log('[ChromeDebug MCP] Upload manager started via background script');
|
|
2783
|
+
// console.log('[ChromeDebug MCP] Upload manager started via background script');
|
|
2615
2784
|
}
|
|
2616
2785
|
});
|
|
2617
2786
|
|
|
@@ -2619,7 +2788,7 @@ async function startFullDataRecording(config) {
|
|
|
2619
2788
|
|
|
2620
2789
|
// Full data recording indicator removed - functionality disabled
|
|
2621
2790
|
|
|
2622
|
-
console.log('[ChromeDebug MCP] Full data recording started successfully:', recordingId);
|
|
2791
|
+
// console.log('[ChromeDebug MCP] Full data recording started successfully:', recordingId);
|
|
2623
2792
|
|
|
2624
2793
|
} catch (error) {
|
|
2625
2794
|
console.error('[ChromeDebug MCP] Failed to start full data recording:', error);
|
|
@@ -2635,17 +2804,17 @@ async function stopFullDataRecording() {
|
|
|
2635
2804
|
return;
|
|
2636
2805
|
}
|
|
2637
2806
|
|
|
2638
|
-
console.log('[ChromeDebug MCP] Stopping full data recording...');
|
|
2807
|
+
// console.log('[ChromeDebug MCP] Stopping full data recording...');
|
|
2639
2808
|
|
|
2640
2809
|
// Stop all trackers
|
|
2641
2810
|
if (domTracker) {
|
|
2642
2811
|
domTracker.stopTracking();
|
|
2643
|
-
console.log('[ChromeDebug MCP] DOM tracking stopped');
|
|
2812
|
+
// console.log('[ChromeDebug MCP] DOM tracking stopped');
|
|
2644
2813
|
}
|
|
2645
2814
|
|
|
2646
2815
|
if (networkTracker) {
|
|
2647
2816
|
networkTracker.stopTracking();
|
|
2648
|
-
console.log('[ChromeDebug MCP] Network tracking stopped');
|
|
2817
|
+
// console.log('[ChromeDebug MCP] Network tracking stopped');
|
|
2649
2818
|
}
|
|
2650
2819
|
|
|
2651
2820
|
if (functionTracker) {
|
|
@@ -2656,13 +2825,13 @@ async function stopFullDataRecording() {
|
|
|
2656
2825
|
window.ChromePilotTracker._setRecordingStatus(false);
|
|
2657
2826
|
}
|
|
2658
2827
|
|
|
2659
|
-
console.log('[ChromeDebug MCP] Function tracking stopped');
|
|
2828
|
+
// console.log('[ChromeDebug MCP] Function tracking stopped');
|
|
2660
2829
|
}
|
|
2661
2830
|
|
|
2662
2831
|
// Stop performance monitoring
|
|
2663
2832
|
if (performanceMonitor) {
|
|
2664
2833
|
performanceMonitor.stopMonitoring();
|
|
2665
|
-
console.log('[ChromeDebug MCP] Performance monitoring stopped');
|
|
2834
|
+
// console.log('[ChromeDebug MCP] Performance monitoring stopped');
|
|
2666
2835
|
}
|
|
2667
2836
|
|
|
2668
2837
|
// Create final batch for any remaining events
|
|
@@ -2673,7 +2842,7 @@ async function stopFullDataRecording() {
|
|
|
2673
2842
|
if (result.currentRecordingId) {
|
|
2674
2843
|
// Create a batch with any remaining events
|
|
2675
2844
|
await dataBuffer.createBatch(result.currentRecordingId);
|
|
2676
|
-
console.log('[ChromeDebug MCP] Final batch created for remaining events');
|
|
2845
|
+
// console.log('[ChromeDebug MCP] Final batch created for remaining events');
|
|
2677
2846
|
}
|
|
2678
2847
|
} catch (error) {
|
|
2679
2848
|
console.warn('[ChromeDebug MCP] Could not create final batch:', error);
|
|
@@ -2689,7 +2858,7 @@ async function stopFullDataRecording() {
|
|
|
2689
2858
|
if (chrome.runtime.lastError) {
|
|
2690
2859
|
console.error('[ChromeDebug MCP] Error finalizing uploads:', chrome.runtime.lastError.message);
|
|
2691
2860
|
} else {
|
|
2692
|
-
console.log('[ChromeDebug MCP] Upload manager stopped via background script');
|
|
2861
|
+
// console.log('[ChromeDebug MCP] Upload manager stopped via background script');
|
|
2693
2862
|
}
|
|
2694
2863
|
resolve();
|
|
2695
2864
|
});
|
|
@@ -2700,7 +2869,7 @@ async function stopFullDataRecording() {
|
|
|
2700
2869
|
|
|
2701
2870
|
// Full data recording indicator removed - functionality disabled
|
|
2702
2871
|
|
|
2703
|
-
console.log('[ChromeDebug MCP] Full data recording stopped successfully');
|
|
2872
|
+
// console.log('[ChromeDebug MCP] Full data recording stopped successfully');
|
|
2704
2873
|
|
|
2705
2874
|
} catch (error) {
|
|
2706
2875
|
console.error('[ChromeDebug MCP] Failed to stop full data recording:', error);
|
|
@@ -2734,6 +2903,7 @@ class ScreenCaptureVisualFeedback {
|
|
|
2734
2903
|
init() {
|
|
2735
2904
|
// Listen for screen capture events
|
|
2736
2905
|
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
2906
|
+
// console.log('[ScreenCapture] Received message:', message.type, message);
|
|
2737
2907
|
switch (message.type) {
|
|
2738
2908
|
case 'start-screen-capture-tracking':
|
|
2739
2909
|
this.handleStartScreenCapture(message);
|
|
@@ -2747,11 +2917,27 @@ class ScreenCaptureVisualFeedback {
|
|
|
2747
2917
|
case 'stop-screen-capture-tracking':
|
|
2748
2918
|
this.handleStopScreenCapture(message);
|
|
2749
2919
|
break;
|
|
2920
|
+
case 'recording-complete-show-ui':
|
|
2921
|
+
// Show completion UI when stopped from popup (not from mini menu button)
|
|
2922
|
+
// console.log('[ScreenCapture] Processing recording-complete-show-ui, sessionId:', message.sessionId, 'actionCount:', this.actionCount);
|
|
2923
|
+
if (message.sessionId) {
|
|
2924
|
+
// console.log('[ScreenCapture] Calling showScreenRecordingComplete with sessionId:', message.sessionId);
|
|
2925
|
+
this.showScreenRecordingComplete(message.sessionId, this.actionCount);
|
|
2926
|
+
} else {
|
|
2927
|
+
// console.log('[ScreenCapture] ERROR: No sessionId in recording-complete-show-ui message!');
|
|
2928
|
+
}
|
|
2929
|
+
break;
|
|
2930
|
+
default:
|
|
2931
|
+
// Log unknown message types for debugging
|
|
2932
|
+
if (message.type && message.type.includes('screen-capture') || message.type && message.type.includes('recording')) {
|
|
2933
|
+
// console.log('[ScreenCapture] Unknown screen capture message type:', message.type);
|
|
2934
|
+
}
|
|
2750
2935
|
}
|
|
2751
2936
|
});
|
|
2752
2937
|
}
|
|
2753
2938
|
|
|
2754
2939
|
handleStartScreenCapture(message) {
|
|
2940
|
+
// console.log('[ScreenCapture] Starting new recording, current indicator exists:', !!this.recordingIndicatorElement);
|
|
2755
2941
|
this.isRecording = true;
|
|
2756
2942
|
this.actionCount = 0;
|
|
2757
2943
|
this.showRecordingIndicator();
|
|
@@ -2798,9 +2984,11 @@ class ScreenCaptureVisualFeedback {
|
|
|
2798
2984
|
|
|
2799
2985
|
handleStopScreenCapture(message) {
|
|
2800
2986
|
this.isRecording = false;
|
|
2801
|
-
|
|
2987
|
+
// DON'T hide indicator here - let the completion screen handle it
|
|
2988
|
+
// this.hideRecordingIndicator();
|
|
2802
2989
|
this.hideActionCounter();
|
|
2803
|
-
|
|
2990
|
+
// Don't cleanup yet - we want to keep the indicator visible
|
|
2991
|
+
// this.cleanup();
|
|
2804
2992
|
}
|
|
2805
2993
|
|
|
2806
2994
|
showClickHighlight(x, y) {
|
|
@@ -2836,80 +3024,96 @@ class ScreenCaptureVisualFeedback {
|
|
|
2836
3024
|
}
|
|
2837
3025
|
|
|
2838
3026
|
showRecordingIndicator() {
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
3027
|
+
// CRITICAL FIX: Clear any existing countdown interval FIRST
|
|
3028
|
+
if (this.countdownInterval) {
|
|
3029
|
+
// console.log('[ScreenCapture] Clearing existing countdown interval');
|
|
3030
|
+
clearInterval(this.countdownInterval);
|
|
3031
|
+
this.countdownInterval = null;
|
|
3032
|
+
}
|
|
3033
|
+
|
|
3034
|
+
// CRITICAL FIX: If old indicator exists (showing completion), remove it completely
|
|
3035
|
+
// This ensures the old popup closes immediately before showing the new countdown
|
|
3036
|
+
if (this.recordingIndicatorElement && this.recordingIndicatorElement.parentNode) {
|
|
3037
|
+
// console.log('[ScreenCapture] Removing old indicator element from DOM');
|
|
3038
|
+
this.recordingIndicatorElement.parentNode.removeChild(this.recordingIndicatorElement);
|
|
3039
|
+
this.recordingIndicatorElement = null;
|
|
3040
|
+
// console.log('[ScreenCapture] Old indicator removed successfully');
|
|
3041
|
+
} else {
|
|
3042
|
+
// console.log('[ScreenCapture] No old indicator to remove, creating fresh');
|
|
3043
|
+
}
|
|
3044
|
+
|
|
3045
|
+
// Add required CSS styles if not already added
|
|
3046
|
+
if (!document.getElementById('screen-capture-styles')) {
|
|
3047
|
+
const style = document.createElement('style');
|
|
3048
|
+
style.id = 'screen-capture-styles';
|
|
3049
|
+
style.textContent = `
|
|
3050
|
+
@keyframes pulse {
|
|
3051
|
+
0% { opacity: 1; }
|
|
3052
|
+
50% { opacity: 0.5; }
|
|
3053
|
+
100% { opacity: 1; }
|
|
3054
|
+
}
|
|
3055
|
+
@keyframes screen-capture-pulse {
|
|
3056
|
+
0% { opacity: 1; transform: scale(1); }
|
|
3057
|
+
50% { opacity: 0.7; transform: scale(1.1); }
|
|
3058
|
+
100% { opacity: 1; transform: scale(1); }
|
|
3059
|
+
}
|
|
3060
|
+
.screen-capture-click-highlight {
|
|
3061
|
+
position: fixed;
|
|
3062
|
+
width: 40px;
|
|
3063
|
+
height: 40px;
|
|
3064
|
+
border: 3px solid #4CAF50;
|
|
3065
|
+
border-radius: 50%;
|
|
3066
|
+
background: rgba(76, 175, 80, 0.3);
|
|
3067
|
+
transform: translate(-50%, -50%);
|
|
3068
|
+
pointer-events: none;
|
|
3069
|
+
z-index: 2147483646;
|
|
3070
|
+
animation: screen-capture-ripple 0.5s ease-out;
|
|
3071
|
+
}
|
|
3072
|
+
@keyframes screen-capture-ripple {
|
|
3073
|
+
0% {
|
|
3074
|
+
transform: translate(-50%, -50%) scale(0);
|
|
3075
|
+
opacity: 1;
|
|
2866
3076
|
}
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
opacity: 1;
|
|
2871
|
-
}
|
|
2872
|
-
100% {
|
|
2873
|
-
transform: translate(-50%, -50%) scale(1);
|
|
2874
|
-
opacity: 0;
|
|
2875
|
-
}
|
|
3077
|
+
100% {
|
|
3078
|
+
transform: translate(-50%, -50%) scale(1);
|
|
3079
|
+
opacity: 0;
|
|
2876
3080
|
}
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
3081
|
+
}
|
|
3082
|
+
`;
|
|
3083
|
+
document.head.appendChild(style);
|
|
3084
|
+
}
|
|
3085
|
+
|
|
3086
|
+
// Always create fresh element for new recording
|
|
3087
|
+
this.recordingIndicatorElement = document.createElement('div');
|
|
3088
|
+
this.recordingIndicatorElement.className = 'screen-capture-recording-indicator-unified';
|
|
3089
|
+
|
|
3090
|
+
// Use inline styles to match workflow recording exactly
|
|
3091
|
+
Object.assign(this.recordingIndicatorElement.style, {
|
|
3092
|
+
position: 'fixed',
|
|
3093
|
+
bottom: '80px', // Keep different from workflow to avoid collision
|
|
3094
|
+
left: '20px',
|
|
3095
|
+
background: 'rgba(0, 0, 0, 0.9)',
|
|
3096
|
+
color: 'white',
|
|
3097
|
+
padding: '12px 20px',
|
|
3098
|
+
borderRadius: '25px',
|
|
3099
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif',
|
|
3100
|
+
fontSize: '14px',
|
|
3101
|
+
fontWeight: '500',
|
|
3102
|
+
zIndex: '2147483647',
|
|
3103
|
+
display: 'flex',
|
|
3104
|
+
alignItems: 'center',
|
|
3105
|
+
gap: '8px',
|
|
3106
|
+
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.3)',
|
|
3107
|
+
backdropFilter: 'blur(10px)',
|
|
3108
|
+
WebkitBackdropFilter: 'blur(10px)',
|
|
3109
|
+
pointerEvents: 'none',
|
|
3110
|
+
userSelect: 'none'
|
|
3111
|
+
});
|
|
2906
3112
|
|
|
2907
|
-
|
|
2908
|
-
this.startCountdownSequence();
|
|
2909
|
-
document.body.appendChild(this.recordingIndicatorElement);
|
|
2910
|
-
}
|
|
3113
|
+
document.body.appendChild(this.recordingIndicatorElement);
|
|
2911
3114
|
|
|
2912
|
-
|
|
3115
|
+
// Start countdown sequence
|
|
3116
|
+
this.startCountdownSequence();
|
|
2913
3117
|
}
|
|
2914
3118
|
|
|
2915
3119
|
startCountdownSequence() {
|
|
@@ -2932,18 +3136,223 @@ class ScreenCaptureVisualFeedback {
|
|
|
2932
3136
|
<span class="action-count-badge" style="background: rgba(255,255,255,0.2); padding: 2px 8px; border-radius: 12px; font-size: 12px;">0 actions</span>
|
|
2933
3137
|
`;
|
|
2934
3138
|
} else {
|
|
2935
|
-
//
|
|
3139
|
+
// Countdown complete! Notify background to start inactivity monitoring NOW
|
|
3140
|
+
if (isExtensionValid()) {
|
|
3141
|
+
chrome.runtime.sendMessage({ action: 'countdownComplete' }).catch(err => {
|
|
3142
|
+
console.warn('[ScreenCapture] Could not send countdownComplete:', err);
|
|
3143
|
+
});
|
|
3144
|
+
}
|
|
3145
|
+
|
|
3146
|
+
// Switch to recording display with two-row layout
|
|
3147
|
+
this.recordingIndicatorElement.style.pointerEvents = 'auto'; // Enable clicking
|
|
2936
3148
|
this.recordingIndicatorElement.innerHTML = `
|
|
2937
|
-
<
|
|
2938
|
-
|
|
2939
|
-
|
|
3149
|
+
<div style="display: flex; flex-direction: column; gap: 8px;">
|
|
3150
|
+
<!-- Row 1: Status and primary actions -->
|
|
3151
|
+
<div style="display: flex; align-items: center; gap: 8px;">
|
|
3152
|
+
<span style="color: #4CAF50; font-size: 18px; animation: pulse 1.5s infinite;">●</span>
|
|
3153
|
+
<span style="font-size: 13px; font-weight: 500;">Recording Screen Capture...</span>
|
|
3154
|
+
<span class="action-count-badge" style="background: rgba(255,255,255,0.2); padding: 2px 8px; border-radius: 10px; font-size: 11px;">0 actions</span>
|
|
3155
|
+
<div style="flex: 1;"></div>
|
|
3156
|
+
<button id="screen-stop-btn" style="background: #f44336; color: white; border: none; padding: 6px 14px; border-radius: 15px; font-size: 12px; font-weight: 500; cursor: pointer; font-family: inherit;">Stop</button>
|
|
3157
|
+
<button id="screen-close-btn" style="background: transparent; color: white; border: none; padding: 4px 8px; font-size: 16px; cursor: pointer; font-family: inherit; opacity: 0.7;" title="Close notification">×</button>
|
|
3158
|
+
</div>
|
|
3159
|
+
<!-- Row 2: Frame count, countdown, and disable button -->
|
|
3160
|
+
<div style="display: flex; align-items: center; gap: 10px; font-size: 11px; color: rgba(255,255,255,0.8); padding-left: 26px;">
|
|
3161
|
+
<span class="frame-count-badge">0 frames</span>
|
|
3162
|
+
<span style="opacity: 0.5;">|</span>
|
|
3163
|
+
<span class="inactivity-countdown-badge" style="color: rgba(255,152,0,0.9);">⏱ --</span>
|
|
3164
|
+
<button id="disable-inactivity-btn" style="background: rgba(255,152,0,0.4); color: white; border: none; padding: 4px 10px; border-radius: 10px; font-size: 11px; cursor: pointer; font-family: inherit;" title="Disable auto-stop timeout">Disable</button>
|
|
3165
|
+
</div>
|
|
3166
|
+
</div>
|
|
2940
3167
|
`;
|
|
2941
3168
|
clearInterval(this.countdownInterval);
|
|
2942
3169
|
this.countdownInterval = null;
|
|
3170
|
+
|
|
3171
|
+
// Add stop button click handler
|
|
3172
|
+
const stopBtn = document.getElementById('screen-stop-btn');
|
|
3173
|
+
const closeBtn = document.getElementById('screen-close-btn');
|
|
3174
|
+
|
|
3175
|
+
if (stopBtn) {
|
|
3176
|
+
stopBtn.addEventListener('click', async (e) => {
|
|
3177
|
+
e.stopPropagation();
|
|
3178
|
+
stopBtn.disabled = true;
|
|
3179
|
+
stopBtn.textContent = 'Stopping...';
|
|
3180
|
+
|
|
3181
|
+
// Send message to background to stop recording (correct action name)
|
|
3182
|
+
chrome.runtime.sendMessage({ action: 'stopRecording' }, (response) => {
|
|
3183
|
+
if (response && response.success && response.sessionId) {
|
|
3184
|
+
// Show completion with action buttons
|
|
3185
|
+
this.showScreenRecordingComplete(response.sessionId, this.actionCount);
|
|
3186
|
+
} else {
|
|
3187
|
+
console.error('[ScreenRecording] Failed to stop:', response?.error);
|
|
3188
|
+
// Don't hide indicator, just show error
|
|
3189
|
+
stopBtn.textContent = 'Error';
|
|
3190
|
+
stopBtn.style.background = '#666';
|
|
3191
|
+
}
|
|
3192
|
+
});
|
|
3193
|
+
});
|
|
3194
|
+
}
|
|
3195
|
+
|
|
3196
|
+
if (closeBtn) {
|
|
3197
|
+
closeBtn.addEventListener('click', (e) => {
|
|
3198
|
+
e.stopPropagation();
|
|
3199
|
+
this.hideRecordingIndicator();
|
|
3200
|
+
});
|
|
3201
|
+
}
|
|
3202
|
+
|
|
3203
|
+
// Add disable inactivity timeout button handler
|
|
3204
|
+
const disableBtn = document.getElementById('disable-inactivity-btn');
|
|
3205
|
+
if (disableBtn) {
|
|
3206
|
+
disableBtn.addEventListener('click', async (e) => {
|
|
3207
|
+
e.stopPropagation();
|
|
3208
|
+
try {
|
|
3209
|
+
const response = await chrome.runtime.sendMessage({ action: 'toggleInactivityTimeout' });
|
|
3210
|
+
if (response && response.success) {
|
|
3211
|
+
const countdownBadge = this.recordingIndicatorElement?.querySelector('.inactivity-countdown-badge');
|
|
3212
|
+
if (response.disabled) {
|
|
3213
|
+
// Timeout disabled - show Enable button (green)
|
|
3214
|
+
disableBtn.textContent = 'Enable';
|
|
3215
|
+
disableBtn.title = 'Enable auto-stop timeout';
|
|
3216
|
+
disableBtn.style.background = 'rgba(76, 175, 80, 0.5)';
|
|
3217
|
+
if (countdownBadge) {
|
|
3218
|
+
countdownBadge.textContent = '⏱ OFF';
|
|
3219
|
+
countdownBadge.style.color = 'rgba(76, 175, 80, 0.9)';
|
|
3220
|
+
}
|
|
3221
|
+
} else {
|
|
3222
|
+
// Timeout enabled - show Disable button (orange)
|
|
3223
|
+
disableBtn.textContent = 'Disable';
|
|
3224
|
+
disableBtn.title = 'Disable auto-stop timeout';
|
|
3225
|
+
disableBtn.style.background = 'rgba(255,152,0,0.4)';
|
|
3226
|
+
if (countdownBadge) {
|
|
3227
|
+
countdownBadge.style.color = 'rgba(255,152,0,0.9)';
|
|
3228
|
+
}
|
|
3229
|
+
}
|
|
3230
|
+
}
|
|
3231
|
+
} catch (err) {
|
|
3232
|
+
console.warn('[ScreenCapture] Could not toggle inactivity timeout:', err);
|
|
3233
|
+
}
|
|
3234
|
+
});
|
|
3235
|
+
}
|
|
2943
3236
|
}
|
|
2944
3237
|
}, 1000);
|
|
2945
3238
|
}
|
|
2946
3239
|
|
|
3240
|
+
showScreenRecordingComplete(sessionId, actionCount) {
|
|
3241
|
+
if (!this.recordingIndicatorElement) return;
|
|
3242
|
+
|
|
3243
|
+
this.recordingIndicatorElement.innerHTML = `
|
|
3244
|
+
<div style="display: flex; flex-direction: column; gap: 10px; position: relative; padding-right: 30px;">
|
|
3245
|
+
<button class="sc-close-complete" style="position: absolute; top: -8px; right: -8px; background: transparent; color: white; border: none; padding: 4px 8px; font-size: 20px; cursor: pointer; font-family: inherit; opacity: 0.7; line-height: 1;" title="Close notification">×</button>
|
|
3246
|
+
|
|
3247
|
+
<div style="display: flex; align-items: center; gap: 8px;">
|
|
3248
|
+
<span style="color: #4CAF50; font-size: 16px;">🎬</span>
|
|
3249
|
+
<span style="font-weight: 600; font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 400px;" title="${sessionId}">${sessionId} (frames)</span>
|
|
3250
|
+
</div>
|
|
3251
|
+
|
|
3252
|
+
<div style="font-size: 11px; color: rgba(255,255,255,0.7); margin-top: -5px;">
|
|
3253
|
+
${actionCount} actions • ${new Date().toLocaleString()}
|
|
3254
|
+
</div>
|
|
3255
|
+
|
|
3256
|
+
<div style="display: flex; gap: 6px; flex-wrap: wrap;">
|
|
3257
|
+
<button class="sc-copy-id" data-id="${sessionId}" style="background: #2196F3; color: white; border: none; padding: 6px 12px; border-radius: 12px; font-size: 11px; cursor: pointer; font-family: inherit; font-weight: 500;">Copy ID</button>
|
|
3258
|
+
<button class="sc-copy-prompt" data-id="${sessionId}" style="background: #4CAF50; color: white; border: none; padding: 6px 12px; border-radius: 12px; font-size: 11px; cursor: pointer; font-family: inherit; font-weight: 500;">Copy Prompt</button>
|
|
3259
|
+
<button class="sc-view" data-id="${sessionId}" style="background: #9C27B0; color: white; border: none; padding: 6px 12px; border-radius: 12px; font-size: 11px; cursor: pointer; font-family: inherit; font-weight: 500;">View</button>
|
|
3260
|
+
<button class="sc-delete" data-id="${sessionId}" style="background: #f44336; color: white; border: none; padding: 6px 12px; border-radius: 12px; font-size: 11px; cursor: pointer; font-family: inherit; font-weight: 500;">Delete</button>
|
|
3261
|
+
</div>
|
|
3262
|
+
</div>
|
|
3263
|
+
`;
|
|
3264
|
+
|
|
3265
|
+
// Add event listeners for action buttons
|
|
3266
|
+
const copyIdBtn = this.recordingIndicatorElement.querySelector('.sc-copy-id');
|
|
3267
|
+
const copyPromptBtn = this.recordingIndicatorElement.querySelector('.sc-copy-prompt');
|
|
3268
|
+
const viewBtn = this.recordingIndicatorElement.querySelector('.sc-view');
|
|
3269
|
+
const deleteBtn = this.recordingIndicatorElement.querySelector('.sc-delete');
|
|
3270
|
+
const closeBtn = this.recordingIndicatorElement.querySelector('.sc-close-complete');
|
|
3271
|
+
|
|
3272
|
+
if (copyIdBtn) {
|
|
3273
|
+
copyIdBtn.addEventListener('click', async () => {
|
|
3274
|
+
try {
|
|
3275
|
+
await navigator.clipboard.writeText(sessionId);
|
|
3276
|
+
copyIdBtn.textContent = 'Copied!';
|
|
3277
|
+
setTimeout(() => copyIdBtn.textContent = 'Copy ID', 2000);
|
|
3278
|
+
} catch (error) {
|
|
3279
|
+
console.error('[ScreenRecording] Failed to copy ID:', error);
|
|
3280
|
+
}
|
|
3281
|
+
});
|
|
3282
|
+
}
|
|
3283
|
+
|
|
3284
|
+
if (copyPromptBtn) {
|
|
3285
|
+
copyPromptBtn.addEventListener('click', async () => {
|
|
3286
|
+
const prompt = `Please use the chrome_debug_show_frames function in Chrome Debug to display the screen recording "${sessionId}".`;
|
|
3287
|
+
try {
|
|
3288
|
+
await navigator.clipboard.writeText(prompt);
|
|
3289
|
+
copyPromptBtn.textContent = 'Copied!';
|
|
3290
|
+
setTimeout(() => copyPromptBtn.textContent = 'Copy Prompt', 2000);
|
|
3291
|
+
} catch (error) {
|
|
3292
|
+
console.error('[ScreenRecording] Failed to copy prompt:', error);
|
|
3293
|
+
}
|
|
3294
|
+
});
|
|
3295
|
+
}
|
|
3296
|
+
|
|
3297
|
+
if (viewBtn) {
|
|
3298
|
+
viewBtn.addEventListener('click', () => {
|
|
3299
|
+
// Ask background to open frame editor (content scripts can't create tabs)
|
|
3300
|
+
chrome.runtime.sendMessage({
|
|
3301
|
+
action: 'openFrameEditor',
|
|
3302
|
+
sessionId: sessionId
|
|
3303
|
+
});
|
|
3304
|
+
});
|
|
3305
|
+
}
|
|
3306
|
+
|
|
3307
|
+
if (deleteBtn) {
|
|
3308
|
+
deleteBtn.addEventListener('click', async () => {
|
|
3309
|
+
if (confirm('Delete this screen recording?')) {
|
|
3310
|
+
// Hide immediately for better UX
|
|
3311
|
+
this.hideRecordingIndicator();
|
|
3312
|
+
|
|
3313
|
+
// Show brief "Deleting..." toast
|
|
3314
|
+
const toast = document.createElement('div');
|
|
3315
|
+
Object.assign(toast.style, {
|
|
3316
|
+
position: 'fixed',
|
|
3317
|
+
bottom: '80px',
|
|
3318
|
+
left: '20px',
|
|
3319
|
+
background: 'rgba(0, 0, 0, 0.9)',
|
|
3320
|
+
color: 'white',
|
|
3321
|
+
padding: '12px 20px',
|
|
3322
|
+
borderRadius: '20px',
|
|
3323
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif',
|
|
3324
|
+
fontSize: '13px',
|
|
3325
|
+
zIndex: '2147483646'
|
|
3326
|
+
});
|
|
3327
|
+
toast.textContent = 'Deleting...';
|
|
3328
|
+
document.body.appendChild(toast);
|
|
3329
|
+
|
|
3330
|
+
chrome.runtime.sendMessage({
|
|
3331
|
+
action: 'deleteScreenRecording',
|
|
3332
|
+
sessionId: sessionId
|
|
3333
|
+
}, (response) => {
|
|
3334
|
+
// Update toast with result
|
|
3335
|
+
if (response && response.success) {
|
|
3336
|
+
toast.textContent = '✓ Recording deleted';
|
|
3337
|
+
toast.style.background = 'rgba(76, 175, 80, 0.9)';
|
|
3338
|
+
} else {
|
|
3339
|
+
toast.textContent = '✗ Delete failed';
|
|
3340
|
+
toast.style.background = 'rgba(244, 67, 54, 0.9)';
|
|
3341
|
+
}
|
|
3342
|
+
// Remove toast after 2 seconds
|
|
3343
|
+
setTimeout(() => toast.remove(), 2000);
|
|
3344
|
+
});
|
|
3345
|
+
}
|
|
3346
|
+
});
|
|
3347
|
+
}
|
|
3348
|
+
|
|
3349
|
+
if (closeBtn) {
|
|
3350
|
+
closeBtn.addEventListener('click', () => {
|
|
3351
|
+
this.hideRecordingIndicator();
|
|
3352
|
+
});
|
|
3353
|
+
}
|
|
3354
|
+
}
|
|
3355
|
+
|
|
2947
3356
|
hideRecordingIndicator() {
|
|
2948
3357
|
// Clear countdown interval if running
|
|
2949
3358
|
if (this.countdownInterval) {
|
|
@@ -3077,16 +3486,125 @@ setTimeout(() => {
|
|
|
3077
3486
|
}
|
|
3078
3487
|
};
|
|
3079
3488
|
|
|
3080
|
-
console.log('[ChromeDebug MCP] ChromePilotTracker initialized for workflow recording');
|
|
3489
|
+
// console.log('[ChromeDebug MCP] ChromePilotTracker initialized for workflow recording');
|
|
3081
3490
|
}
|
|
3082
3491
|
|
|
3083
3492
|
// Initialize minimal workflow recording support
|
|
3084
|
-
console.log('[ChromeDebug MCP] Basic workflow recording ready (lightweight mode)');
|
|
3493
|
+
// console.log('[ChromeDebug MCP] Basic workflow recording ready (lightweight mode)');
|
|
3085
3494
|
}
|
|
3086
3495
|
}, 500);
|
|
3087
3496
|
|
|
3088
3497
|
// Full data recording system will be initialized on-demand when recording begins
|
|
3089
3498
|
// This prevents unnecessary resource usage on every page load
|
|
3090
3499
|
|
|
3500
|
+
// =============================================================================
|
|
3501
|
+
// INACTIVITY TRACKER - Auto-stop recording if user is inactive
|
|
3502
|
+
// =============================================================================
|
|
3503
|
+
(function initInactivityTracker() {
|
|
3504
|
+
let lastActivityTime = Date.now();
|
|
3505
|
+
let isTrackingActivity = false;
|
|
3506
|
+
let inactivityCheckInterval = null;
|
|
3507
|
+
|
|
3508
|
+
// Debounce activity updates to avoid flooding background script
|
|
3509
|
+
let activityDebounceTimer = null;
|
|
3510
|
+
const ACTIVITY_DEBOUNCE_MS = 1000; // Report activity at most once per second
|
|
3511
|
+
|
|
3512
|
+
function reportActivity() {
|
|
3513
|
+
if (!isTrackingActivity) return;
|
|
3514
|
+
|
|
3515
|
+
lastActivityTime = Date.now();
|
|
3516
|
+
|
|
3517
|
+
// Debounced report to background
|
|
3518
|
+
if (activityDebounceTimer) return;
|
|
3519
|
+
activityDebounceTimer = setTimeout(() => {
|
|
3520
|
+
activityDebounceTimer = null;
|
|
3521
|
+
if (isExtensionValid()) {
|
|
3522
|
+
chrome.runtime.sendMessage({
|
|
3523
|
+
action: 'userActivity',
|
|
3524
|
+
timestamp: lastActivityTime
|
|
3525
|
+
}).catch(() => {});
|
|
3526
|
+
}
|
|
3527
|
+
}, ACTIVITY_DEBOUNCE_MS);
|
|
3528
|
+
}
|
|
3529
|
+
|
|
3530
|
+
// Activity event listeners (passive for performance)
|
|
3531
|
+
const activityEvents = ['mousedown', 'mousemove', 'keydown', 'scroll', 'touchstart', 'click'];
|
|
3532
|
+
|
|
3533
|
+
function startTracking() {
|
|
3534
|
+
if (isTrackingActivity) return;
|
|
3535
|
+
isTrackingActivity = true;
|
|
3536
|
+
lastActivityTime = Date.now();
|
|
3537
|
+
|
|
3538
|
+
activityEvents.forEach(event => {
|
|
3539
|
+
document.addEventListener(event, reportActivity, { passive: true, capture: true });
|
|
3540
|
+
});
|
|
3541
|
+
|
|
3542
|
+
// Send IMMEDIATE activity report on start to sync with background timer
|
|
3543
|
+
// This prevents premature auto-stop due to setup delay
|
|
3544
|
+
if (isExtensionValid()) {
|
|
3545
|
+
chrome.runtime.sendMessage({
|
|
3546
|
+
action: 'userActivity',
|
|
3547
|
+
timestamp: lastActivityTime
|
|
3548
|
+
}).catch(() => {});
|
|
3549
|
+
}
|
|
3550
|
+
}
|
|
3551
|
+
|
|
3552
|
+
function stopTracking() {
|
|
3553
|
+
if (!isTrackingActivity) return;
|
|
3554
|
+
isTrackingActivity = false;
|
|
3555
|
+
|
|
3556
|
+
activityEvents.forEach(event => {
|
|
3557
|
+
document.removeEventListener(event, reportActivity, { capture: true });
|
|
3558
|
+
});
|
|
3559
|
+
|
|
3560
|
+
if (activityDebounceTimer) {
|
|
3561
|
+
clearTimeout(activityDebounceTimer);
|
|
3562
|
+
activityDebounceTimer = null;
|
|
3563
|
+
}
|
|
3564
|
+
}
|
|
3565
|
+
|
|
3566
|
+
// Listen for start/stop tracking messages from background
|
|
3567
|
+
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
3568
|
+
if (message.action === 'startActivityTracking') {
|
|
3569
|
+
startTracking();
|
|
3570
|
+
sendResponse({ success: true });
|
|
3571
|
+
} else if (message.action === 'stopActivityTracking') {
|
|
3572
|
+
stopTracking();
|
|
3573
|
+
sendResponse({ success: true });
|
|
3574
|
+
} else if (message.action === 'updateInactivityCountdown') {
|
|
3575
|
+
// Update countdown badge in recording indicator
|
|
3576
|
+
const countdownBadge = document.querySelector('.inactivity-countdown-badge');
|
|
3577
|
+
if (countdownBadge) {
|
|
3578
|
+
if (message.disabled) {
|
|
3579
|
+
countdownBadge.textContent = '⏱ OFF';
|
|
3580
|
+
countdownBadge.style.background = 'rgba(76, 175, 80, 0.3)';
|
|
3581
|
+
countdownBadge.style.color = 'rgba(255,255,255,0.9)';
|
|
3582
|
+
} else {
|
|
3583
|
+
countdownBadge.textContent = `⏱ ${message.timeRemaining}s`;
|
|
3584
|
+
// Warning colors
|
|
3585
|
+
if (message.timeRemaining <= 3) {
|
|
3586
|
+
countdownBadge.style.background = 'rgba(244, 67, 54, 0.5)';
|
|
3587
|
+
countdownBadge.style.color = '#fff';
|
|
3588
|
+
} else if (message.timeRemaining <= 5) {
|
|
3589
|
+
countdownBadge.style.background = 'rgba(255, 152, 0, 0.5)';
|
|
3590
|
+
countdownBadge.style.color = '#fff';
|
|
3591
|
+
} else {
|
|
3592
|
+
countdownBadge.style.background = 'rgba(255, 152, 0, 0.3)';
|
|
3593
|
+
countdownBadge.style.color = 'rgba(255,255,255,0.9)';
|
|
3594
|
+
}
|
|
3595
|
+
}
|
|
3596
|
+
}
|
|
3597
|
+
sendResponse({ success: true });
|
|
3598
|
+
} else if (message.action === 'updateFrameCount') {
|
|
3599
|
+
// Update frame count badge in recording indicator
|
|
3600
|
+
const frameBadge = document.querySelector('.frame-count-badge');
|
|
3601
|
+
if (frameBadge) {
|
|
3602
|
+
frameBadge.textContent = `${message.frameCount} frames`;
|
|
3603
|
+
}
|
|
3604
|
+
sendResponse({ success: true });
|
|
3605
|
+
}
|
|
3606
|
+
});
|
|
3607
|
+
})();
|
|
3608
|
+
|
|
3091
3609
|
} // End of initializeChromePilot function
|
|
3092
3610
|
})(); // End of IIFE wrapper
|