diff --git a/sentience/extension/content.js b/sentience/extension/content.js index 833ee05..62ae408 100644 --- a/sentience/extension/content.js +++ b/sentience/extension/content.js @@ -25,6 +25,14 @@ window.addEventListener('message', (event) => { handleSnapshotRequest(event.data); break; + case 'SENTIENCE_SHOW_OVERLAY': + handleShowOverlay(event.data); + break; + + case 'SENTIENCE_CLEAR_OVERLAY': + handleClearOverlay(); + break; + default: // Ignore unknown message types break; @@ -135,4 +143,156 @@ function handleSnapshotRequest(data) { } } +// ============================================================================ +// Visual Overlay - Shadow DOM Implementation +// ============================================================================ + +const OVERLAY_HOST_ID = 'sentience-overlay-host'; +let overlayTimeout = null; + +/** + * Show visual overlay highlighting elements using Shadow DOM + * @param {Object} data - Message data with elements and targetElementId + */ +function handleShowOverlay(data) { + const { elements, targetElementId } = data; + + if (!elements || !Array.isArray(elements)) { + console.warn('[Sentience Bridge] showOverlay: elements must be an array'); + return; + } + + removeOverlay(); + + // Create host with Shadow DOM for CSS isolation + const host = document.createElement('div'); + host.id = OVERLAY_HOST_ID; + host.style.cssText = ` + position: fixed !important; + top: 0 !important; + left: 0 !important; + width: 100vw !important; + height: 100vh !important; + pointer-events: none !important; + z-index: 2147483647 !important; + margin: 0 !important; + padding: 0 !important; + `; + document.body.appendChild(host); + + // Attach shadow root (closed mode for security and CSS isolation) + const shadow = host.attachShadow({ mode: 'closed' }); + + // Calculate max importance for scaling + const maxImportance = Math.max(...elements.map(e => e.importance || 0), 1); + + elements.forEach((element) => { + const bbox = element.bbox; + if (!bbox) return; + + const isTarget = element.id === targetElementId; + const isPrimary = element.visual_cues?.is_primary || false; + const importance = element.importance || 0; + + // Color: Red (target), Blue (primary), Green (regular) + let color; + if (isTarget) color = '#FF0000'; + else if (isPrimary) color = '#0066FF'; + else color = '#00FF00'; + + // Scale opacity and border width based on importance + const importanceRatio = maxImportance > 0 ? importance / maxImportance : 0.5; + const borderOpacity = isTarget ? 1.0 : (isPrimary ? 0.9 : Math.max(0.4, 0.5 + importanceRatio * 0.5)); + const fillOpacity = borderOpacity * 0.2; + const borderWidth = isTarget ? 2 : (isPrimary ? 1.5 : Math.max(0.5, Math.round(importanceRatio * 2))); + + // Convert fill opacity to hex for background-color + const hexOpacity = Math.round(fillOpacity * 255).toString(16).padStart(2, '0'); + + // Create box with semi-transparent fill + const box = document.createElement('div'); + box.style.cssText = ` + position: absolute; + left: ${bbox.x}px; + top: ${bbox.y}px; + width: ${bbox.width}px; + height: ${bbox.height}px; + border: ${borderWidth}px solid ${color}; + background-color: ${color}${hexOpacity}; + box-sizing: border-box; + opacity: ${borderOpacity}; + pointer-events: none; + `; + + // Add badge showing importance score + if (importance > 0 || isPrimary) { + const badge = document.createElement('span'); + badge.textContent = isPrimary ? `⭐${importance}` : `${importance}`; + badge.style.cssText = ` + position: absolute; + top: -18px; + left: 0; + background: ${color}; + color: white; + font-size: 11px; + font-weight: bold; + padding: 2px 6px; + font-family: Arial, sans-serif; + border-radius: 3px; + opacity: 0.95; + white-space: nowrap; + pointer-events: none; + `; + box.appendChild(badge); + } + + // Add target emoji for target element + if (isTarget) { + const targetIndicator = document.createElement('span'); + targetIndicator.textContent = '🎯'; + targetIndicator.style.cssText = ` + position: absolute; + top: -18px; + right: 0; + font-size: 16px; + pointer-events: none; + `; + box.appendChild(targetIndicator); + } + + shadow.appendChild(box); + }); + + console.log(`[Sentience Bridge] Overlay shown for ${elements.length} elements`); + + // Auto-remove after 5 seconds + overlayTimeout = setTimeout(() => { + removeOverlay(); + console.log('[Sentience Bridge] Overlay auto-cleared after 5 seconds'); + }, 5000); +} + +/** + * Clear overlay manually + */ +function handleClearOverlay() { + removeOverlay(); + console.log('[Sentience Bridge] Overlay cleared manually'); +} + +/** + * Remove overlay from DOM + */ +function removeOverlay() { + const existing = document.getElementById(OVERLAY_HOST_ID); + if (existing) { + existing.remove(); + } + + if (overlayTimeout) { + clearTimeout(overlayTimeout); + overlayTimeout = null; + } +} + // console.log('[Sentience Bridge] Ready - Extension ID:', chrome.runtime.id); diff --git a/sentience/extension/injected_api.js b/sentience/extension/injected_api.js index dac0f55..712542d 100644 --- a/sentience/extension/injected_api.js +++ b/sentience/extension/injected_api.js @@ -1435,5 +1435,36 @@ } }; + /** + * Show overlay highlighting specific elements with Shadow DOM + * @param {Array} elements - List of elements with bbox, importance, visual_cues + * @param {number} targetElementId - Optional ID of target element (shown in red) + */ + window.sentience.showOverlay = function(elements, targetElementId = null) { + if (!elements || !Array.isArray(elements)) { + console.warn('[Sentience] showOverlay: elements must be an array'); + return; + } + + window.postMessage({ + type: 'SENTIENCE_SHOW_OVERLAY', + elements: elements, + targetElementId: targetElementId, + timestamp: Date.now() + }, '*'); + + console.log(`[Sentience] Overlay requested for ${elements.length} elements`); + }; + + /** + * Clear overlay manually + */ + window.sentience.clearOverlay = function() { + window.postMessage({ + type: 'SENTIENCE_CLEAR_OVERLAY' + }, '*'); + console.log('[Sentience] Overlay cleared'); + }; + console.log('[SentienceAPI] ✓ Ready! (CSP-Resistant - WASM runs in background)'); })(); diff --git a/sentience/extension/manifest.json b/sentience/extension/manifest.json index 2fb7248..00ef666 100644 --- a/sentience/extension/manifest.json +++ b/sentience/extension/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Sentience Semantic Visual Grounding Extractor", - "version": "2.0.5", + "version": "2.0.6", "description": "Extract semantic visual grounding data from web pages", "permissions": ["activeTab", "scripting"], "host_permissions": [""], diff --git a/sentience/extension/pkg/sentience_core_bg.wasm b/sentience/extension/pkg/sentience_core_bg.wasm index 1c6104b..dc0ebba 100644 Binary files a/sentience/extension/pkg/sentience_core_bg.wasm and b/sentience/extension/pkg/sentience_core_bg.wasm differ diff --git a/sentience/extension/release.json b/sentience/extension/release.json index 8f835b6..52303fe 100644 --- a/sentience/extension/release.json +++ b/sentience/extension/release.json @@ -1,9 +1,9 @@ { - "url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/273049720", - "assets_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/273049720/assets", - "upload_url": "https://uploads.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/273049720/assets{?name,label}", - "html_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/tag/v2.0.5", - "id": 273049720, + "url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/273088651", + "assets_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/273088651/assets", + "upload_url": "https://uploads.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/273088651/assets{?name,label}", + "html_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/tag/v2.0.6", + "id": 273088651, "author": { "login": "rcholic", "id": 135060, @@ -25,21 +25,21 @@ "user_view_type": "public", "site_admin": false }, - "node_id": "RE_kwDOQshiJ84QRmh4", - "tag_name": "v2.0.5", + "node_id": "RE_kwDOQshiJ84QRwCL", + "tag_name": "v2.0.6", "target_commitish": "main", - "name": "Release v2.0.5", + "name": "Release v2.0.6", "draft": false, "immutable": false, "prerelease": false, - "created_at": "2025-12-28T06:21:06Z", - "updated_at": "2025-12-28T06:52:14Z", - "published_at": "2025-12-28T06:52:03Z", + "created_at": "2025-12-28T18:16:01Z", + "updated_at": "2025-12-28T18:16:59Z", + "published_at": "2025-12-28T18:16:49Z", "assets": [ { - "url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/assets/333698157", - "id": 333698157, - "node_id": "RA_kwDOQshiJ84T49Rt", + "url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/assets/333817321", + "id": 333817321, + "node_id": "RA_kwDOQshiJ84T5aXp", "name": "extension-files.tar.gz", "label": "", "uploader": { @@ -65,17 +65,17 @@ }, "content_type": "application/gzip", "state": "uploaded", - "size": 76157, - "digest": "sha256:726e388826fc3a5c401250db27ebd663167a96205594608b1bed2c98196cabab", + "size": 78026, + "digest": "sha256:d8ff48cfac38e8a3fe2408f7dacc93fb1c76e4772e7f981545c920aea18998ba", "download_count": 0, - "created_at": "2025-12-28T06:52:13Z", - "updated_at": "2025-12-28T06:52:14Z", - "browser_download_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/download/v2.0.5/extension-files.tar.gz" + "created_at": "2025-12-28T18:16:59Z", + "updated_at": "2025-12-28T18:16:59Z", + "browser_download_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/download/v2.0.6/extension-files.tar.gz" }, { - "url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/assets/333698156", - "id": 333698156, - "node_id": "RA_kwDOQshiJ84T49Rs", + "url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/assets/333817320", + "id": 333817320, + "node_id": "RA_kwDOQshiJ84T5aXo", "name": "extension-package.zip", "label": "", "uploader": { @@ -101,15 +101,15 @@ }, "content_type": "application/zip", "state": "uploaded", - "size": 78281, - "digest": "sha256:311a65065fef9c6d4b02597e4680e9e3f408f0d721a1d7595f6090ad3d794793", + "size": 80099, + "digest": "sha256:4cb46868d668337ea10ae7ea1b9ff07fc87b947bad3f877d3f4250902fe8610f", "download_count": 0, - "created_at": "2025-12-28T06:52:13Z", - "updated_at": "2025-12-28T06:52:13Z", - "browser_download_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/download/v2.0.5/extension-package.zip" + "created_at": "2025-12-28T18:16:59Z", + "updated_at": "2025-12-28T18:16:59Z", + "browser_download_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/download/v2.0.6/extension-package.zip" } ], - "tarball_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/tarball/v2.0.5", - "zipball_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/zipball/v2.0.5", + "tarball_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/tarball/v2.0.6", + "zipball_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/zipball/v2.0.6", "body": "" }