sentienceapi 0.90.16__py3-none-any.whl → 0.98.0__py3-none-any.whl
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.
Potentially problematic release.
This version of sentienceapi might be problematic. Click here for more details.
- sentience/__init__.py +120 -6
- sentience/_extension_loader.py +156 -1
- sentience/action_executor.py +217 -0
- sentience/actions.py +758 -30
- sentience/agent.py +806 -293
- sentience/agent_config.py +3 -0
- sentience/agent_runtime.py +840 -0
- sentience/asserts/__init__.py +70 -0
- sentience/asserts/expect.py +621 -0
- sentience/asserts/query.py +383 -0
- sentience/async_api.py +89 -1141
- sentience/backends/__init__.py +137 -0
- sentience/backends/actions.py +372 -0
- sentience/backends/browser_use_adapter.py +241 -0
- sentience/backends/cdp_backend.py +393 -0
- sentience/backends/exceptions.py +211 -0
- sentience/backends/playwright_backend.py +194 -0
- sentience/backends/protocol.py +216 -0
- sentience/backends/sentience_context.py +469 -0
- sentience/backends/snapshot.py +483 -0
- sentience/base_agent.py +95 -0
- sentience/browser.py +678 -39
- sentience/browser_evaluator.py +299 -0
- sentience/canonicalization.py +207 -0
- sentience/cloud_tracing.py +507 -42
- sentience/constants.py +6 -0
- sentience/conversational_agent.py +77 -43
- sentience/cursor_policy.py +142 -0
- sentience/element_filter.py +136 -0
- sentience/expect.py +98 -2
- sentience/extension/background.js +56 -185
- sentience/extension/content.js +150 -287
- sentience/extension/injected_api.js +1088 -1368
- sentience/extension/manifest.json +1 -1
- sentience/extension/pkg/sentience_core.d.ts +22 -22
- sentience/extension/pkg/sentience_core.js +275 -433
- sentience/extension/pkg/sentience_core_bg.wasm +0 -0
- sentience/extension/release.json +47 -47
- sentience/failure_artifacts.py +241 -0
- sentience/formatting.py +9 -53
- sentience/inspector.py +183 -1
- sentience/integrations/__init__.py +6 -0
- sentience/integrations/langchain/__init__.py +12 -0
- sentience/integrations/langchain/context.py +18 -0
- sentience/integrations/langchain/core.py +326 -0
- sentience/integrations/langchain/tools.py +180 -0
- sentience/integrations/models.py +46 -0
- sentience/integrations/pydanticai/__init__.py +15 -0
- sentience/integrations/pydanticai/deps.py +20 -0
- sentience/integrations/pydanticai/toolset.py +468 -0
- sentience/llm_interaction_handler.py +191 -0
- sentience/llm_provider.py +765 -66
- sentience/llm_provider_utils.py +120 -0
- sentience/llm_response_builder.py +153 -0
- sentience/models.py +595 -3
- sentience/ordinal.py +280 -0
- sentience/overlay.py +109 -2
- sentience/protocols.py +228 -0
- sentience/query.py +67 -5
- sentience/read.py +95 -3
- sentience/recorder.py +223 -3
- sentience/schemas/trace_v1.json +128 -9
- sentience/screenshot.py +48 -2
- sentience/sentience_methods.py +86 -0
- sentience/snapshot.py +599 -55
- sentience/snapshot_diff.py +126 -0
- sentience/text_search.py +120 -5
- sentience/trace_event_builder.py +148 -0
- sentience/trace_file_manager.py +197 -0
- sentience/trace_indexing/index_schema.py +95 -7
- sentience/trace_indexing/indexer.py +105 -48
- sentience/tracer_factory.py +120 -9
- sentience/tracing.py +172 -8
- sentience/utils/__init__.py +40 -0
- sentience/utils/browser.py +46 -0
- sentience/{utils.py → utils/element.py} +3 -42
- sentience/utils/formatting.py +59 -0
- sentience/verification.py +618 -0
- sentience/visual_agent.py +2058 -0
- sentience/wait.py +68 -2
- {sentienceapi-0.90.16.dist-info → sentienceapi-0.98.0.dist-info}/METADATA +199 -40
- sentienceapi-0.98.0.dist-info/RECORD +92 -0
- sentience/extension/test-content.js +0 -4
- sentienceapi-0.90.16.dist-info/RECORD +0 -50
- {sentienceapi-0.90.16.dist-info → sentienceapi-0.98.0.dist-info}/WHEEL +0 -0
- {sentienceapi-0.90.16.dist-info → sentienceapi-0.98.0.dist-info}/entry_points.txt +0 -0
- {sentienceapi-0.90.16.dist-info → sentienceapi-0.98.0.dist-info}/licenses/LICENSE +0 -0
- {sentienceapi-0.90.16.dist-info → sentienceapi-0.98.0.dist-info}/licenses/LICENSE-APACHE +0 -0
- {sentienceapi-0.90.16.dist-info → sentienceapi-0.98.0.dist-info}/licenses/LICENSE-MIT +0 -0
- {sentienceapi-0.90.16.dist-info → sentienceapi-0.98.0.dist-info}/top_level.txt +0 -0
sentience/extension/content.js
CHANGED
|
@@ -1,298 +1,161 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
if (
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
switch (event.data.type) {
|
|
20
|
-
case 'SENTIENCE_SCREENSHOT_REQUEST':
|
|
21
|
-
handleScreenshotRequest(event.data);
|
|
22
|
-
break;
|
|
23
|
-
|
|
24
|
-
case 'SENTIENCE_SNAPSHOT_REQUEST':
|
|
25
|
-
handleSnapshotRequest(event.data);
|
|
1
|
+
!function() {
|
|
2
|
+
"use strict";
|
|
3
|
+
window, window.top;
|
|
4
|
+
document.documentElement.dataset.sentienceExtensionId = chrome.runtime.id, window.addEventListener("message", event => {
|
|
5
|
+
var data;
|
|
6
|
+
if (event.source === window) switch (event.data.type) {
|
|
7
|
+
case "SENTIENCE_SCREENSHOT_REQUEST":
|
|
8
|
+
data = event.data, chrome.runtime.sendMessage({
|
|
9
|
+
action: "captureScreenshot",
|
|
10
|
+
options: data.options
|
|
11
|
+
}, response => {
|
|
12
|
+
window.postMessage({
|
|
13
|
+
type: "SENTIENCE_SCREENSHOT_RESULT",
|
|
14
|
+
requestId: data.requestId,
|
|
15
|
+
screenshot: response?.success ? response.screenshot : null,
|
|
16
|
+
error: response?.error
|
|
17
|
+
}, "*");
|
|
18
|
+
});
|
|
26
19
|
break;
|
|
27
20
|
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
case "SENTIENCE_SNAPSHOT_REQUEST":
|
|
22
|
+
!function(data) {
|
|
23
|
+
const startTime = performance.now();
|
|
24
|
+
let responded = !1;
|
|
25
|
+
const timeoutId = setTimeout(() => {
|
|
26
|
+
if (!responded) {
|
|
27
|
+
responded = !0;
|
|
28
|
+
const duration = performance.now() - startTime;
|
|
29
|
+
window.postMessage({
|
|
30
|
+
type: "SENTIENCE_SNAPSHOT_RESULT",
|
|
31
|
+
requestId: data.requestId,
|
|
32
|
+
error: "WASM processing timeout - background script may be unresponsive",
|
|
33
|
+
duration: duration
|
|
34
|
+
}, "*");
|
|
35
|
+
}
|
|
36
|
+
}, 2e4);
|
|
37
|
+
try {
|
|
38
|
+
chrome.runtime.sendMessage({
|
|
39
|
+
action: "processSnapshot",
|
|
40
|
+
rawData: data.rawData,
|
|
41
|
+
options: data.options
|
|
42
|
+
}, response => {
|
|
43
|
+
if (responded) return;
|
|
44
|
+
responded = !0, clearTimeout(timeoutId);
|
|
45
|
+
const duration = performance.now() - startTime;
|
|
46
|
+
chrome.runtime.lastError ? window.postMessage({
|
|
47
|
+
type: "SENTIENCE_SNAPSHOT_RESULT",
|
|
48
|
+
requestId: data.requestId,
|
|
49
|
+
error: `Chrome runtime error: ${chrome.runtime.lastError.message}`,
|
|
50
|
+
duration: duration
|
|
51
|
+
}, "*") : response?.success ? window.postMessage({
|
|
52
|
+
type: "SENTIENCE_SNAPSHOT_RESULT",
|
|
53
|
+
requestId: data.requestId,
|
|
54
|
+
elements: response.result.elements,
|
|
55
|
+
raw_elements: response.result.raw_elements,
|
|
56
|
+
duration: duration
|
|
57
|
+
}, "*") : window.postMessage({
|
|
58
|
+
type: "SENTIENCE_SNAPSHOT_RESULT",
|
|
59
|
+
requestId: data.requestId,
|
|
60
|
+
error: response?.error || "Processing failed",
|
|
61
|
+
duration: duration
|
|
62
|
+
}, "*");
|
|
63
|
+
});
|
|
64
|
+
} catch (error) {
|
|
65
|
+
if (!responded) {
|
|
66
|
+
responded = !0, clearTimeout(timeoutId);
|
|
67
|
+
const duration = performance.now() - startTime;
|
|
68
|
+
window.postMessage({
|
|
69
|
+
type: "SENTIENCE_SNAPSHOT_RESULT",
|
|
70
|
+
requestId: data.requestId,
|
|
71
|
+
error: `Failed to send message: ${error.message}`,
|
|
72
|
+
duration: duration
|
|
73
|
+
}, "*");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}(event.data);
|
|
30
77
|
break;
|
|
31
78
|
|
|
32
|
-
|
|
33
|
-
|
|
79
|
+
case "SENTIENCE_SHOW_OVERLAY":
|
|
80
|
+
!function(data) {
|
|
81
|
+
const {elements: elements, targetElementId: targetElementId} = data;
|
|
82
|
+
if (!elements || !Array.isArray(elements)) return;
|
|
83
|
+
removeOverlay();
|
|
84
|
+
const host = document.createElement("div");
|
|
85
|
+
host.id = OVERLAY_HOST_ID, host.style.cssText = "\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n width: 100vw !important;\n height: 100vh !important;\n pointer-events: none !important;\n z-index: 2147483647 !important;\n margin: 0 !important;\n padding: 0 !important;\n ",
|
|
86
|
+
document.body.appendChild(host);
|
|
87
|
+
const shadow = host.attachShadow({
|
|
88
|
+
mode: "closed"
|
|
89
|
+
}), maxImportance = Math.max(...elements.map(e => e.importance || 0), 1);
|
|
90
|
+
elements.forEach(element => {
|
|
91
|
+
const bbox = element.bbox;
|
|
92
|
+
if (!bbox) return;
|
|
93
|
+
const isTarget = element.id === targetElementId, isPrimary = element.visual_cues?.is_primary || !1, importance = element.importance || 0;
|
|
94
|
+
let color;
|
|
95
|
+
color = isTarget ? "#FF0000" : isPrimary ? "#0066FF" : "#00FF00";
|
|
96
|
+
const importanceRatio = maxImportance > 0 ? importance / maxImportance : .5, borderOpacity = isTarget ? 1 : isPrimary ? .9 : Math.max(.4, .5 + .5 * importanceRatio), fillOpacity = .2 * borderOpacity, borderWidth = isTarget ? 2 : isPrimary ? 1.5 : Math.max(.5, Math.round(2 * importanceRatio)), hexOpacity = Math.round(255 * fillOpacity).toString(16).padStart(2, "0"), box = document.createElement("div");
|
|
97
|
+
if (box.style.cssText = `\n position: absolute;\n left: ${bbox.x}px;\n top: ${bbox.y}px;\n width: ${bbox.width}px;\n height: ${bbox.height}px;\n border: ${borderWidth}px solid ${color};\n background-color: ${color}${hexOpacity};\n box-sizing: border-box;\n opacity: ${borderOpacity};\n pointer-events: none;\n `,
|
|
98
|
+
importance > 0 || isPrimary) {
|
|
99
|
+
const badge = document.createElement("span");
|
|
100
|
+
badge.textContent = isPrimary ? `⭐${importance}` : `${importance}`, badge.style.cssText = `\n position: absolute;\n top: -18px;\n left: 0;\n background: ${color};\n color: white;\n font-size: 11px;\n font-weight: bold;\n padding: 2px 6px;\n font-family: Arial, sans-serif;\n border-radius: 3px;\n opacity: 0.95;\n white-space: nowrap;\n pointer-events: none;\n `,
|
|
101
|
+
box.appendChild(badge);
|
|
102
|
+
}
|
|
103
|
+
if (isTarget) {
|
|
104
|
+
const targetIndicator = document.createElement("span");
|
|
105
|
+
targetIndicator.textContent = "🎯", targetIndicator.style.cssText = "\n position: absolute;\n top: -18px;\n right: 0;\n font-size: 16px;\n pointer-events: none;\n ",
|
|
106
|
+
box.appendChild(targetIndicator);
|
|
107
|
+
}
|
|
108
|
+
shadow.appendChild(box);
|
|
109
|
+
}), overlayTimeout = setTimeout(() => {
|
|
110
|
+
removeOverlay();
|
|
111
|
+
}, 5e3);
|
|
112
|
+
}(event.data);
|
|
34
113
|
break;
|
|
35
114
|
|
|
36
|
-
|
|
37
|
-
|
|
115
|
+
case "SENTIENCE_CLEAR_OVERLAY":
|
|
116
|
+
removeOverlay();
|
|
38
117
|
break;
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Handle screenshot requests (existing functionality)
|
|
44
|
-
*/
|
|
45
|
-
function handleScreenshotRequest(data) {
|
|
46
|
-
chrome.runtime.sendMessage(
|
|
47
|
-
{ action: 'captureScreenshot', options: data.options },
|
|
48
|
-
(response) => {
|
|
49
|
-
window.postMessage({
|
|
50
|
-
type: 'SENTIENCE_SCREENSHOT_RESULT',
|
|
51
|
-
requestId: data.requestId,
|
|
52
|
-
screenshot: response?.success ? response.screenshot : null,
|
|
53
|
-
error: response?.error
|
|
54
|
-
}, '*');
|
|
55
|
-
}
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Handle snapshot processing requests (NEW!)
|
|
61
|
-
* Sends raw DOM data to background worker for WASM processing
|
|
62
|
-
* Includes timeout protection to prevent extension crashes
|
|
63
|
-
*/
|
|
64
|
-
function handleSnapshotRequest(data) {
|
|
65
|
-
const startTime = performance.now();
|
|
66
|
-
const TIMEOUT_MS = 20000; // 20 seconds (longer than injected_api timeout)
|
|
67
|
-
let responded = false;
|
|
68
|
-
|
|
69
|
-
// Timeout protection: if background doesn't respond, send error
|
|
70
|
-
const timeoutId = setTimeout(() => {
|
|
71
|
-
if (!responded) {
|
|
72
|
-
responded = true;
|
|
73
|
-
const duration = performance.now() - startTime;
|
|
74
|
-
console.error(`[Sentience Bridge] ⚠️ WASM processing timeout after ${duration.toFixed(1)}ms`);
|
|
75
|
-
window.postMessage({
|
|
76
|
-
type: 'SENTIENCE_SNAPSHOT_RESULT',
|
|
77
|
-
requestId: data.requestId,
|
|
78
|
-
error: 'WASM processing timeout - background script may be unresponsive',
|
|
79
|
-
duration: duration
|
|
80
|
-
}, '*');
|
|
81
|
-
}
|
|
82
|
-
}, TIMEOUT_MS);
|
|
83
|
-
|
|
84
|
-
try {
|
|
85
|
-
chrome.runtime.sendMessage(
|
|
86
|
-
{
|
|
87
|
-
action: 'processSnapshot',
|
|
88
|
-
rawData: data.rawData,
|
|
89
|
-
options: data.options
|
|
90
|
-
},
|
|
91
|
-
(response) => {
|
|
92
|
-
if (responded) return; // Already responded via timeout
|
|
93
|
-
responded = true;
|
|
94
|
-
clearTimeout(timeoutId);
|
|
95
|
-
|
|
96
|
-
const duration = performance.now() - startTime;
|
|
97
|
-
|
|
98
|
-
// Handle Chrome extension errors (e.g., background script crashed)
|
|
99
|
-
if (chrome.runtime.lastError) {
|
|
100
|
-
console.error('[Sentience Bridge] Chrome runtime error:', chrome.runtime.lastError.message);
|
|
101
|
-
window.postMessage({
|
|
102
|
-
type: 'SENTIENCE_SNAPSHOT_RESULT',
|
|
103
|
-
requestId: data.requestId,
|
|
104
|
-
error: `Chrome runtime error: ${chrome.runtime.lastError.message}`,
|
|
105
|
-
duration: duration
|
|
106
|
-
}, '*');
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
if (response?.success) {
|
|
111
|
-
console.log(`[Sentience Bridge] ✓ WASM processing complete in ${duration.toFixed(1)}ms`);
|
|
112
|
-
window.postMessage({
|
|
113
|
-
type: 'SENTIENCE_SNAPSHOT_RESULT',
|
|
114
|
-
requestId: data.requestId,
|
|
115
|
-
elements: response.result.elements,
|
|
116
|
-
raw_elements: response.result.raw_elements,
|
|
117
|
-
duration: duration
|
|
118
|
-
}, '*');
|
|
119
|
-
} else {
|
|
120
|
-
console.error('[Sentience Bridge] WASM processing failed:', response?.error);
|
|
121
|
-
window.postMessage({
|
|
122
|
-
type: 'SENTIENCE_SNAPSHOT_RESULT',
|
|
123
|
-
requestId: data.requestId,
|
|
124
|
-
error: response?.error || 'Processing failed',
|
|
125
|
-
duration: duration
|
|
126
|
-
}, '*');
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
);
|
|
130
|
-
} catch (error) {
|
|
131
|
-
if (!responded) {
|
|
132
|
-
responded = true;
|
|
133
|
-
clearTimeout(timeoutId);
|
|
134
|
-
const duration = performance.now() - startTime;
|
|
135
|
-
console.error('[Sentience Bridge] Exception sending message:', error);
|
|
136
|
-
window.postMessage({
|
|
137
|
-
type: 'SENTIENCE_SNAPSHOT_RESULT',
|
|
138
|
-
requestId: data.requestId,
|
|
139
|
-
error: `Failed to send message: ${error.message}`,
|
|
140
|
-
duration: duration
|
|
141
|
-
}, '*');
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
// ============================================================================
|
|
147
|
-
// Visual Overlay - Shadow DOM Implementation
|
|
148
|
-
// ============================================================================
|
|
149
118
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
// Attach shadow root (closed mode for security and CSS isolation)
|
|
184
|
-
const shadow = host.attachShadow({ mode: 'closed' });
|
|
185
|
-
|
|
186
|
-
// Calculate max importance for scaling
|
|
187
|
-
const maxImportance = Math.max(...elements.map(e => e.importance || 0), 1);
|
|
188
|
-
|
|
189
|
-
elements.forEach((element) => {
|
|
190
|
-
const bbox = element.bbox;
|
|
191
|
-
if (!bbox) return;
|
|
192
|
-
|
|
193
|
-
const isTarget = element.id === targetElementId;
|
|
194
|
-
const isPrimary = element.visual_cues?.is_primary || false;
|
|
195
|
-
const importance = element.importance || 0;
|
|
196
|
-
|
|
197
|
-
// Color: Red (target), Blue (primary), Green (regular)
|
|
198
|
-
let color;
|
|
199
|
-
if (isTarget) color = '#FF0000';
|
|
200
|
-
else if (isPrimary) color = '#0066FF';
|
|
201
|
-
else color = '#00FF00';
|
|
202
|
-
|
|
203
|
-
// Scale opacity and border width based on importance
|
|
204
|
-
const importanceRatio = maxImportance > 0 ? importance / maxImportance : 0.5;
|
|
205
|
-
const borderOpacity = isTarget ? 1.0 : (isPrimary ? 0.9 : Math.max(0.4, 0.5 + importanceRatio * 0.5));
|
|
206
|
-
const fillOpacity = borderOpacity * 0.2;
|
|
207
|
-
const borderWidth = isTarget ? 2 : (isPrimary ? 1.5 : Math.max(0.5, Math.round(importanceRatio * 2)));
|
|
208
|
-
|
|
209
|
-
// Convert fill opacity to hex for background-color
|
|
210
|
-
const hexOpacity = Math.round(fillOpacity * 255).toString(16).padStart(2, '0');
|
|
211
|
-
|
|
212
|
-
// Create box with semi-transparent fill
|
|
213
|
-
const box = document.createElement('div');
|
|
214
|
-
box.style.cssText = `
|
|
215
|
-
position: absolute;
|
|
216
|
-
left: ${bbox.x}px;
|
|
217
|
-
top: ${bbox.y}px;
|
|
218
|
-
width: ${bbox.width}px;
|
|
219
|
-
height: ${bbox.height}px;
|
|
220
|
-
border: ${borderWidth}px solid ${color};
|
|
221
|
-
background-color: ${color}${hexOpacity};
|
|
222
|
-
box-sizing: border-box;
|
|
223
|
-
opacity: ${borderOpacity};
|
|
224
|
-
pointer-events: none;
|
|
225
|
-
`;
|
|
226
|
-
|
|
227
|
-
// Add badge showing importance score
|
|
228
|
-
if (importance > 0 || isPrimary) {
|
|
229
|
-
const badge = document.createElement('span');
|
|
230
|
-
badge.textContent = isPrimary ? `⭐${importance}` : `${importance}`;
|
|
231
|
-
badge.style.cssText = `
|
|
232
|
-
position: absolute;
|
|
233
|
-
top: -18px;
|
|
234
|
-
left: 0;
|
|
235
|
-
background: ${color};
|
|
236
|
-
color: white;
|
|
237
|
-
font-size: 11px;
|
|
238
|
-
font-weight: bold;
|
|
239
|
-
padding: 2px 6px;
|
|
240
|
-
font-family: Arial, sans-serif;
|
|
241
|
-
border-radius: 3px;
|
|
242
|
-
opacity: 0.95;
|
|
243
|
-
white-space: nowrap;
|
|
244
|
-
pointer-events: none;
|
|
245
|
-
`;
|
|
246
|
-
box.appendChild(badge);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// Add target emoji for target element
|
|
250
|
-
if (isTarget) {
|
|
251
|
-
const targetIndicator = document.createElement('span');
|
|
252
|
-
targetIndicator.textContent = '🎯';
|
|
253
|
-
targetIndicator.style.cssText = `
|
|
254
|
-
position: absolute;
|
|
255
|
-
top: -18px;
|
|
256
|
-
right: 0;
|
|
257
|
-
font-size: 16px;
|
|
258
|
-
pointer-events: none;
|
|
259
|
-
`;
|
|
260
|
-
box.appendChild(targetIndicator);
|
|
119
|
+
case "SENTIENCE_SHOW_GRID_OVERLAY":
|
|
120
|
+
!function(data) {
|
|
121
|
+
const {grids: grids, targetGridId: targetGridId} = data;
|
|
122
|
+
if (!grids || !Array.isArray(grids)) return;
|
|
123
|
+
removeOverlay();
|
|
124
|
+
const host = document.createElement("div");
|
|
125
|
+
host.id = OVERLAY_HOST_ID, host.style.cssText = "\n position: fixed !important;\n top: 0 !important;\n left: 0 !important;\n width: 100vw !important;\n height: 100vh !important;\n pointer-events: none !important;\n z-index: 2147483647 !important;\n margin: 0 !important;\n padding: 0 !important;\n ",
|
|
126
|
+
document.body.appendChild(host);
|
|
127
|
+
const shadow = host.attachShadow({
|
|
128
|
+
mode: "closed"
|
|
129
|
+
});
|
|
130
|
+
grids.forEach(grid => {
|
|
131
|
+
const bbox = grid.bbox;
|
|
132
|
+
if (!bbox) return;
|
|
133
|
+
const isTarget = grid.grid_id === targetGridId, isDominant = !0 === grid.is_dominant;
|
|
134
|
+
let color = "#9B59B6";
|
|
135
|
+
isTarget ? color = "#FF0000" : isDominant && (color = "#FF8C00");
|
|
136
|
+
const borderStyle = isTarget ? "solid" : "dashed", borderWidth = isTarget ? 3 : isDominant ? 2.5 : 2, opacity = isTarget ? 1 : isDominant ? .9 : .8, fillOpacity = .1 * opacity, hexOpacity = Math.round(255 * fillOpacity).toString(16).padStart(2, "0"), box = document.createElement("div");
|
|
137
|
+
box.style.cssText = `\n position: absolute;\n left: ${bbox.x}px;\n top: ${bbox.y}px;\n width: ${bbox.width}px;\n height: ${bbox.height}px;\n border: ${borderWidth}px ${borderStyle} ${color};\n background-color: ${color}${hexOpacity};\n box-sizing: border-box;\n opacity: ${opacity};\n pointer-events: none;\n `;
|
|
138
|
+
let labelText = grid.label ? `Grid ${grid.grid_id}: ${grid.label}` : `Grid ${grid.grid_id}`;
|
|
139
|
+
grid.is_dominant && (labelText = `⭐ ${labelText} (dominant)`);
|
|
140
|
+
const badge = document.createElement("span");
|
|
141
|
+
if (badge.textContent = labelText, badge.style.cssText = `\n position: absolute;\n top: -18px;\n left: 0;\n background: ${color};\n color: white;\n font-size: 11px;\n font-weight: bold;\n padding: 2px 6px;\n font-family: Arial, sans-serif;\n border-radius: 3px;\n opacity: 0.95;\n white-space: nowrap;\n pointer-events: none;\n `,
|
|
142
|
+
box.appendChild(badge), isTarget) {
|
|
143
|
+
const targetIndicator = document.createElement("span");
|
|
144
|
+
targetIndicator.textContent = "🎯", targetIndicator.style.cssText = "\n position: absolute;\n top: -18px;\n right: 0;\n font-size: 16px;\n pointer-events: none;\n ",
|
|
145
|
+
box.appendChild(targetIndicator);
|
|
146
|
+
}
|
|
147
|
+
shadow.appendChild(box);
|
|
148
|
+
}), overlayTimeout = setTimeout(() => {
|
|
149
|
+
removeOverlay();
|
|
150
|
+
}, 5e3);
|
|
151
|
+
}(event.data);
|
|
261
152
|
}
|
|
262
|
-
|
|
263
|
-
shadow.appendChild(box);
|
|
264
153
|
});
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
console.log('[Sentience Bridge] Overlay auto-cleared after 5 seconds');
|
|
272
|
-
}, 5000);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Clear overlay manually
|
|
277
|
-
*/
|
|
278
|
-
function handleClearOverlay() {
|
|
279
|
-
removeOverlay();
|
|
280
|
-
console.log('[Sentience Bridge] Overlay cleared manually');
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Remove overlay from DOM
|
|
285
|
-
*/
|
|
286
|
-
function removeOverlay() {
|
|
287
|
-
const existing = document.getElementById(OVERLAY_HOST_ID);
|
|
288
|
-
if (existing) {
|
|
289
|
-
existing.remove();
|
|
154
|
+
const OVERLAY_HOST_ID = "sentience-overlay-host";
|
|
155
|
+
let overlayTimeout = null;
|
|
156
|
+
function removeOverlay() {
|
|
157
|
+
const existing = document.getElementById(OVERLAY_HOST_ID);
|
|
158
|
+
existing && existing.remove(), overlayTimeout && (clearTimeout(overlayTimeout),
|
|
159
|
+
overlayTimeout = null);
|
|
290
160
|
}
|
|
291
|
-
|
|
292
|
-
if (overlayTimeout) {
|
|
293
|
-
clearTimeout(overlayTimeout);
|
|
294
|
-
overlayTimeout = null;
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// console.log('[Sentience Bridge] Ready - Extension ID:', chrome.runtime.id);
|
|
161
|
+
}();
|