diff --git a/sentience/extension/injected_api.js b/sentience/extension/injected_api.js index a47ad55..dac0f55 100644 --- a/sentience/extension/injected_api.js +++ b/sentience/extension/injected_api.js @@ -726,9 +726,15 @@ } console.log(`[SentienceAPI] Found ${iframes.length} iframe(s), requesting snapshots...`); - // Request snapshot from each iframe const iframePromises = iframes.map((iframe, idx) => { + // OPTIMIZATION: Skip common ad domains to save time + const src = iframe.src || ''; + if (src.includes('doubleclick') || src.includes('googleadservices') || src.includes('ads system')) { + console.log(`[SentienceAPI] Skipping ad iframe: ${src.substring(0, 30)}...`); + return Promise.resolve(null); + } + return new Promise((resolve) => { const requestId = `iframe-${idx}-${Date.now()}`; @@ -736,7 +742,7 @@ const timeout = setTimeout(() => { console.warn(`[SentienceAPI] ⚠️ Iframe ${idx} snapshot TIMEOUT (id: ${requestId})`); resolve(null); - }, 10000); // Increased to 10s to handle slow processing + }, 5000); // Increased to 5s to handle slow processing // 2. ROBUST LISTENER with debugging const listener = (event) => { @@ -1036,6 +1042,10 @@ return { status: "success", url: window.location.href, + viewport: { + width: window.innerWidth, + height: window.innerHeight + }, elements: cleanedElements, raw_elements: cleanedRawElements, screenshot: screenshot @@ -1073,6 +1083,154 @@ }; }, + // 2b. Find Text Rectangle - Get exact pixel coordinates of specific text + findTextRect: (options = {}) => { + const { + text, + containerElement = document.body, + caseSensitive = false, + wholeWord = false, + maxResults = 10 + } = options; + + if (!text || text.trim().length === 0) { + return { + status: "error", + error: "Text parameter is required" + }; + } + + const results = []; + const searchText = caseSensitive ? text : text.toLowerCase(); + + // Helper function to find text in a single text node + function findInTextNode(textNode) { + const nodeText = textNode.nodeValue; + const searchableText = caseSensitive ? nodeText : nodeText.toLowerCase(); + + let startIndex = 0; + while (startIndex < nodeText.length && results.length < maxResults) { + const foundIndex = searchableText.indexOf(searchText, startIndex); + + if (foundIndex === -1) break; + + // Check whole word matching if required + if (wholeWord) { + const before = foundIndex > 0 ? nodeText[foundIndex - 1] : ' '; + const after = foundIndex + text.length < nodeText.length + ? nodeText[foundIndex + text.length] + : ' '; + + // Check if surrounded by word boundaries + if (!/\s/.test(before) || !/\s/.test(after)) { + startIndex = foundIndex + 1; + continue; + } + } + + try { + // Create range for this occurrence + const range = document.createRange(); + range.setStart(textNode, foundIndex); + range.setEnd(textNode, foundIndex + text.length); + + const rect = range.getBoundingClientRect(); + + // Only include visible rectangles + if (rect.width > 0 && rect.height > 0) { + results.push({ + text: nodeText.substring(foundIndex, foundIndex + text.length), + rect: { + x: rect.left + window.scrollX, + y: rect.top + window.scrollY, + width: rect.width, + height: rect.height, + left: rect.left + window.scrollX, + top: rect.top + window.scrollY, + right: rect.right + window.scrollX, + bottom: rect.bottom + window.scrollY + }, + viewport_rect: { + x: rect.left, + y: rect.top, + width: rect.width, + height: rect.height + }, + context: { + before: nodeText.substring(Math.max(0, foundIndex - 20), foundIndex), + after: nodeText.substring(foundIndex + text.length, Math.min(nodeText.length, foundIndex + text.length + 20)) + }, + in_viewport: ( + rect.top >= 0 && + rect.left >= 0 && + rect.bottom <= window.innerHeight && + rect.right <= window.innerWidth + ) + }); + } + } catch (e) { + console.warn('[SentienceAPI] Failed to get rect for text:', e); + } + + startIndex = foundIndex + 1; + } + } + + // Tree walker to find all text nodes + const walker = document.createTreeWalker( + containerElement, + NodeFilter.SHOW_TEXT, + { + acceptNode: function(node) { + // Skip script, style, and empty text nodes + const parent = node.parentElement; + if (!parent) return NodeFilter.FILTER_REJECT; + + const tagName = parent.tagName.toLowerCase(); + if (tagName === 'script' || tagName === 'style' || tagName === 'noscript') { + return NodeFilter.FILTER_REJECT; + } + + // Skip whitespace-only nodes + if (!node.nodeValue || node.nodeValue.trim().length === 0) { + return NodeFilter.FILTER_REJECT; + } + + // Check if element is visible + const computedStyle = window.getComputedStyle(parent); + if (computedStyle.display === 'none' || + computedStyle.visibility === 'hidden' || + computedStyle.opacity === '0') { + return NodeFilter.FILTER_REJECT; + } + + return NodeFilter.FILTER_ACCEPT; + } + } + ); + + // Walk through all text nodes + let currentNode; + while ((currentNode = walker.nextNode()) && results.length < maxResults) { + findInTextNode(currentNode); + } + + return { + status: "success", + query: text, + case_sensitive: caseSensitive, + whole_word: wholeWord, + matches: results.length, + results: results, + viewport: { + width: window.innerWidth, + height: window.innerHeight, + scroll_x: window.scrollX, + scroll_y: window.scrollY + } + }; + }, + // 3. Click Action (unchanged) click: (id) => { const el = window.sentience_registry[id]; diff --git a/sentience/extension/manifest.json b/sentience/extension/manifest.json index 7e44a1c..2fb7248 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.2", + "version": "2.0.5", "description": "Extract semantic visual grounding data from web pages", "permissions": ["activeTab", "scripting"], "host_permissions": [""], diff --git a/sentience/extension/release.json b/sentience/extension/release.json index 048c34d..8f835b6 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/273025127", - "assets_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/273025127/assets", - "upload_url": "https://uploads.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/273025127/assets{?name,label}", - "html_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/tag/v2.0.3", - "id": 273025127, + "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, "author": { "login": "rcholic", "id": 135060, @@ -25,21 +25,21 @@ "user_view_type": "public", "site_admin": false }, - "node_id": "RE_kwDOQshiJ84QRghn", - "tag_name": "v2.0.3", + "node_id": "RE_kwDOQshiJ84QRmh4", + "tag_name": "v2.0.5", "target_commitish": "main", - "name": "Release v2.0.3", + "name": "Release v2.0.5", "draft": false, "immutable": false, "prerelease": false, - "created_at": "2025-12-27T01:12:14Z", - "updated_at": "2025-12-27T22:46:31Z", - "published_at": "2025-12-27T22:46:13Z", + "created_at": "2025-12-28T06:21:06Z", + "updated_at": "2025-12-28T06:52:14Z", + "published_at": "2025-12-28T06:52:03Z", "assets": [ { - "url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/assets/333567799", - "id": 333567799, - "node_id": "RA_kwDOQshiJ84T4dc3", + "url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/assets/333698157", + "id": 333698157, + "node_id": "RA_kwDOQshiJ84T49Rt", "name": "extension-files.tar.gz", "label": "", "uploader": { @@ -65,17 +65,17 @@ }, "content_type": "application/gzip", "state": "uploaded", - "size": 73434, - "digest": "sha256:ca93cdaf875792eb22333f7ba5b13dd129552f388900e624422e73959338d8fb", + "size": 76157, + "digest": "sha256:726e388826fc3a5c401250db27ebd663167a96205594608b1bed2c98196cabab", "download_count": 0, - "created_at": "2025-12-27T22:46:31Z", - "updated_at": "2025-12-27T22:46:31Z", - "browser_download_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/download/v2.0.3/extension-files.tar.gz" + "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" }, { - "url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/assets/333567800", - "id": 333567800, - "node_id": "RA_kwDOQshiJ84T4dc4", + "url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/assets/333698156", + "id": 333698156, + "node_id": "RA_kwDOQshiJ84T49Rs", "name": "extension-package.zip", "label": "", "uploader": { @@ -101,15 +101,15 @@ }, "content_type": "application/zip", "state": "uploaded", - "size": 75584, - "digest": "sha256:291750ec174d9aadade298d2a2aa1057d08a138e2650c97cd93d56b6bcbee713", + "size": 78281, + "digest": "sha256:311a65065fef9c6d4b02597e4680e9e3f408f0d721a1d7595f6090ad3d794793", "download_count": 0, - "created_at": "2025-12-27T22:46:31Z", - "updated_at": "2025-12-27T22:46:31Z", - "browser_download_url": "https://github.com/SentienceAPI/Sentience-Geometry-Chrome-Extension/releases/download/v2.0.3/extension-package.zip" + "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" } ], - "tarball_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/tarball/v2.0.3", - "zipball_url": "https://api.github.com/repos/SentienceAPI/Sentience-Geometry-Chrome-Extension/zipball/v2.0.3", + "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", "body": "" }