sentienceapi 0.90.6 → 0.90.10
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/README.md +81 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/textSearch.d.ts +64 -0
- package/dist/textSearch.d.ts.map +1 -0
- package/dist/textSearch.js +87 -0
- package/dist/textSearch.js.map +1 -0
- package/dist/tracing/cloud-sink.d.ts +4 -0
- package/dist/tracing/cloud-sink.d.ts.map +1 -1
- package/dist/tracing/cloud-sink.js +15 -0
- package/dist/tracing/cloud-sink.js.map +1 -1
- package/dist/tracing/index-schema.d.ts +182 -0
- package/dist/tracing/index-schema.d.ts.map +1 -0
- package/dist/tracing/index-schema.js +150 -0
- package/dist/tracing/index-schema.js.map +1 -0
- package/dist/tracing/indexer.d.ts +17 -0
- package/dist/tracing/indexer.d.ts.map +1 -0
- package/dist/tracing/indexer.js +282 -0
- package/dist/tracing/indexer.js.map +1 -0
- package/dist/tracing/jsonl-sink.d.ts +4 -0
- package/dist/tracing/jsonl-sink.d.ts.map +1 -1
- package/dist/tracing/jsonl-sink.js +15 -0
- package/dist/tracing/jsonl-sink.js.map +1 -1
- package/dist/tracing/tracer-factory.d.ts +11 -5
- package/dist/tracing/tracer-factory.d.ts.map +1 -1
- package/dist/tracing/tracer-factory.js +16 -7
- package/dist/tracing/tracer-factory.js.map +1 -1
- package/dist/types.d.ts +98 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/extension/background.js +222 -52
- package/src/extension/content.js +285 -9
- package/src/extension/injected_api.js +1224 -189
- package/src/extension/manifest.json +10 -4
- package/src/extension/pkg/README.md +163 -2
- package/src/extension/pkg/sentience_core.d.ts +9 -0
- package/src/extension/pkg/sentience_core.js +16 -0
- package/src/extension/pkg/sentience_core_bg.wasm +0 -0
- package/src/extension/pkg/sentience_core_bg.wasm.d.ts +1 -0
- package/src/extension/release.json +115 -0
- package/src/extension/test-content.js +4 -0
package/src/extension/content.js
CHANGED
|
@@ -1,22 +1,298 @@
|
|
|
1
|
-
// content.js - ISOLATED WORLD
|
|
2
|
-
console.log('[Sentience
|
|
1
|
+
// content.js - ISOLATED WORLD (Bridge between Main World and Background)
|
|
2
|
+
console.log('[Sentience Bridge] Loaded.');
|
|
3
3
|
|
|
4
|
-
//
|
|
4
|
+
// Detect if we're in a child frame (for iframe support)
|
|
5
|
+
const isChildFrame = window !== window.top;
|
|
6
|
+
if (isChildFrame) {
|
|
7
|
+
console.log('[Sentience Bridge] Running in child frame:', window.location.href);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// 1. Pass Extension ID to Main World (So API knows where to find resources)
|
|
5
11
|
document.documentElement.dataset.sentienceExtensionId = chrome.runtime.id;
|
|
6
12
|
|
|
7
|
-
// 2.
|
|
13
|
+
// 2. Message Router - Handles all communication between page and background
|
|
8
14
|
window.addEventListener('message', (event) => {
|
|
9
15
|
// Security check: only accept messages from same window
|
|
10
|
-
if (event.source !== window
|
|
16
|
+
if (event.source !== window) return;
|
|
17
|
+
|
|
18
|
+
// Route different message types
|
|
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);
|
|
26
|
+
break;
|
|
27
|
+
|
|
28
|
+
case 'SENTIENCE_SHOW_OVERLAY':
|
|
29
|
+
handleShowOverlay(event.data);
|
|
30
|
+
break;
|
|
31
|
+
|
|
32
|
+
case 'SENTIENCE_CLEAR_OVERLAY':
|
|
33
|
+
handleClearOverlay();
|
|
34
|
+
break;
|
|
35
|
+
|
|
36
|
+
default:
|
|
37
|
+
// Ignore unknown message types
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
});
|
|
11
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Handle screenshot requests (existing functionality)
|
|
44
|
+
*/
|
|
45
|
+
function handleScreenshotRequest(data) {
|
|
12
46
|
chrome.runtime.sendMessage(
|
|
13
|
-
{ action: 'captureScreenshot', options:
|
|
47
|
+
{ action: 'captureScreenshot', options: data.options },
|
|
14
48
|
(response) => {
|
|
15
49
|
window.postMessage({
|
|
16
50
|
type: 'SENTIENCE_SCREENSHOT_RESULT',
|
|
17
|
-
requestId:
|
|
18
|
-
screenshot: response?.success ? response.screenshot : null
|
|
51
|
+
requestId: data.requestId,
|
|
52
|
+
screenshot: response?.success ? response.screenshot : null,
|
|
53
|
+
error: response?.error
|
|
19
54
|
}, '*');
|
|
20
55
|
}
|
|
21
56
|
);
|
|
22
|
-
}
|
|
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
|
+
|
|
150
|
+
const OVERLAY_HOST_ID = 'sentience-overlay-host';
|
|
151
|
+
let overlayTimeout = null;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Show visual overlay highlighting elements using Shadow DOM
|
|
155
|
+
* @param {Object} data - Message data with elements and targetElementId
|
|
156
|
+
*/
|
|
157
|
+
function handleShowOverlay(data) {
|
|
158
|
+
const { elements, targetElementId } = data;
|
|
159
|
+
|
|
160
|
+
if (!elements || !Array.isArray(elements)) {
|
|
161
|
+
console.warn('[Sentience Bridge] showOverlay: elements must be an array');
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
removeOverlay();
|
|
166
|
+
|
|
167
|
+
// Create host with Shadow DOM for CSS isolation
|
|
168
|
+
const host = document.createElement('div');
|
|
169
|
+
host.id = OVERLAY_HOST_ID;
|
|
170
|
+
host.style.cssText = `
|
|
171
|
+
position: fixed !important;
|
|
172
|
+
top: 0 !important;
|
|
173
|
+
left: 0 !important;
|
|
174
|
+
width: 100vw !important;
|
|
175
|
+
height: 100vh !important;
|
|
176
|
+
pointer-events: none !important;
|
|
177
|
+
z-index: 2147483647 !important;
|
|
178
|
+
margin: 0 !important;
|
|
179
|
+
padding: 0 !important;
|
|
180
|
+
`;
|
|
181
|
+
document.body.appendChild(host);
|
|
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);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
shadow.appendChild(box);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
console.log(`[Sentience Bridge] Overlay shown for ${elements.length} elements`);
|
|
267
|
+
|
|
268
|
+
// Auto-remove after 5 seconds
|
|
269
|
+
overlayTimeout = setTimeout(() => {
|
|
270
|
+
removeOverlay();
|
|
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();
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
if (overlayTimeout) {
|
|
293
|
+
clearTimeout(overlayTimeout);
|
|
294
|
+
overlayTimeout = null;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// console.log('[Sentience Bridge] Ready - Extension ID:', chrome.runtime.id);
|