sentienceapi 0.95.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.

Files changed (82) hide show
  1. sentience/__init__.py +253 -0
  2. sentience/_extension_loader.py +195 -0
  3. sentience/action_executor.py +215 -0
  4. sentience/actions.py +1020 -0
  5. sentience/agent.py +1181 -0
  6. sentience/agent_config.py +46 -0
  7. sentience/agent_runtime.py +424 -0
  8. sentience/asserts/__init__.py +70 -0
  9. sentience/asserts/expect.py +621 -0
  10. sentience/asserts/query.py +383 -0
  11. sentience/async_api.py +108 -0
  12. sentience/backends/__init__.py +137 -0
  13. sentience/backends/actions.py +343 -0
  14. sentience/backends/browser_use_adapter.py +241 -0
  15. sentience/backends/cdp_backend.py +393 -0
  16. sentience/backends/exceptions.py +211 -0
  17. sentience/backends/playwright_backend.py +194 -0
  18. sentience/backends/protocol.py +216 -0
  19. sentience/backends/sentience_context.py +469 -0
  20. sentience/backends/snapshot.py +427 -0
  21. sentience/base_agent.py +196 -0
  22. sentience/browser.py +1215 -0
  23. sentience/browser_evaluator.py +299 -0
  24. sentience/canonicalization.py +207 -0
  25. sentience/cli.py +130 -0
  26. sentience/cloud_tracing.py +807 -0
  27. sentience/constants.py +6 -0
  28. sentience/conversational_agent.py +543 -0
  29. sentience/element_filter.py +136 -0
  30. sentience/expect.py +188 -0
  31. sentience/extension/background.js +104 -0
  32. sentience/extension/content.js +161 -0
  33. sentience/extension/injected_api.js +914 -0
  34. sentience/extension/manifest.json +36 -0
  35. sentience/extension/pkg/sentience_core.d.ts +51 -0
  36. sentience/extension/pkg/sentience_core.js +323 -0
  37. sentience/extension/pkg/sentience_core_bg.wasm +0 -0
  38. sentience/extension/pkg/sentience_core_bg.wasm.d.ts +10 -0
  39. sentience/extension/release.json +115 -0
  40. sentience/formatting.py +15 -0
  41. sentience/generator.py +202 -0
  42. sentience/inspector.py +367 -0
  43. sentience/llm_interaction_handler.py +191 -0
  44. sentience/llm_provider.py +875 -0
  45. sentience/llm_provider_utils.py +120 -0
  46. sentience/llm_response_builder.py +153 -0
  47. sentience/models.py +846 -0
  48. sentience/ordinal.py +280 -0
  49. sentience/overlay.py +222 -0
  50. sentience/protocols.py +228 -0
  51. sentience/query.py +303 -0
  52. sentience/read.py +188 -0
  53. sentience/recorder.py +589 -0
  54. sentience/schemas/trace_v1.json +335 -0
  55. sentience/screenshot.py +100 -0
  56. sentience/sentience_methods.py +86 -0
  57. sentience/snapshot.py +706 -0
  58. sentience/snapshot_diff.py +126 -0
  59. sentience/text_search.py +262 -0
  60. sentience/trace_event_builder.py +148 -0
  61. sentience/trace_file_manager.py +197 -0
  62. sentience/trace_indexing/__init__.py +27 -0
  63. sentience/trace_indexing/index_schema.py +199 -0
  64. sentience/trace_indexing/indexer.py +414 -0
  65. sentience/tracer_factory.py +322 -0
  66. sentience/tracing.py +449 -0
  67. sentience/utils/__init__.py +40 -0
  68. sentience/utils/browser.py +46 -0
  69. sentience/utils/element.py +257 -0
  70. sentience/utils/formatting.py +59 -0
  71. sentience/utils.py +296 -0
  72. sentience/verification.py +380 -0
  73. sentience/visual_agent.py +2058 -0
  74. sentience/wait.py +139 -0
  75. sentienceapi-0.95.0.dist-info/METADATA +984 -0
  76. sentienceapi-0.95.0.dist-info/RECORD +82 -0
  77. sentienceapi-0.95.0.dist-info/WHEEL +5 -0
  78. sentienceapi-0.95.0.dist-info/entry_points.txt +2 -0
  79. sentienceapi-0.95.0.dist-info/licenses/LICENSE +24 -0
  80. sentienceapi-0.95.0.dist-info/licenses/LICENSE-APACHE +201 -0
  81. sentienceapi-0.95.0.dist-info/licenses/LICENSE-MIT +21 -0
  82. sentienceapi-0.95.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,914 @@
1
+ !function() {
2
+ "use strict";
3
+ function getAllElements(root = document) {
4
+ const elements = [], filter = {
5
+ acceptNode: node => [ "SCRIPT", "STYLE", "NOSCRIPT", "META", "LINK", "HEAD" ].includes(node.tagName) || node.parentNode && "SVG" === node.parentNode.tagName && "SVG" !== node.tagName ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT
6
+ }, walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, filter);
7
+ for (;walker.nextNode(); ) {
8
+ const node = walker.currentNode;
9
+ node.isConnected && (elements.push(node), node.shadowRoot && elements.push(...getAllElements(node.shadowRoot)));
10
+ }
11
+ return elements;
12
+ }
13
+ const DEFAULT_INFERENCE_CONFIG = {
14
+ allowedTags: [ "label", "span", "div" ],
15
+ allowedRoles: [],
16
+ allowedClassPatterns: [],
17
+ maxParentDepth: 2,
18
+ maxSiblingDistance: 1,
19
+ requireSameContainer: !0,
20
+ containerTags: [ "form", "fieldset", "div" ],
21
+ methods: {
22
+ explicitLabel: !0,
23
+ ariaLabelledby: !0,
24
+ parentTraversal: !0,
25
+ siblingProximity: !0
26
+ }
27
+ };
28
+ function isInferenceSource(el, config) {
29
+ if (!el || !el.tagName) return !1;
30
+ const tag = el.tagName.toLowerCase(), role = el.getAttribute ? el.getAttribute("role") : "", className = ((el.className || "") + "").toLowerCase();
31
+ if (config.allowedTags.includes(tag)) return !0;
32
+ if (config.allowedRoles.length > 0 && role && config.allowedRoles.includes(role)) return !0;
33
+ if (config.allowedClassPatterns.length > 0) for (const pattern of config.allowedClassPatterns) if (className.includes(pattern.toLowerCase())) return !0;
34
+ return !1;
35
+ }
36
+ function isInSameValidContainer(element, candidate, limits) {
37
+ if (!element || !candidate) return !1;
38
+ if (limits.requireSameContainer) {
39
+ const commonParent = function(el1, el2) {
40
+ if (!el1 || !el2) return null;
41
+ const doc = "undefined" != typeof global && global.document || "undefined" != typeof window && window.document || "undefined" != typeof document && document || null, parents1 = [];
42
+ let current = el1;
43
+ for (;current && (parents1.push(current), current.parentElement) && (!doc || current !== doc.body && current !== doc.documentElement); ) current = current.parentElement;
44
+ for (current = el2; current; ) {
45
+ if (-1 !== parents1.indexOf(current)) return current;
46
+ if (!current.parentElement) break;
47
+ if (doc && (current === doc.body || current === doc.documentElement)) break;
48
+ current = current.parentElement;
49
+ }
50
+ return null;
51
+ }(element, candidate);
52
+ if (!commonParent) return !1;
53
+ if (!function(el, validTags) {
54
+ if (!el || !el.tagName) return !1;
55
+ const tag = el.tagName.toLowerCase();
56
+ let className = "";
57
+ try {
58
+ className = (el.className || "") + "";
59
+ } catch (e) {
60
+ className = "";
61
+ }
62
+ return validTags.includes(tag) || className.toLowerCase().includes("form") || className.toLowerCase().includes("field");
63
+ }(commonParent, limits.containerTags)) return !1;
64
+ }
65
+ return !0;
66
+ }
67
+ function getInferredLabel(el, options = {}) {
68
+ if (!el) return null;
69
+ const {enableInference: enableInference = !0, inferenceConfig: inferenceConfig = {}} = options;
70
+ if (!enableInference) return null;
71
+ const ariaLabel = el.getAttribute ? el.getAttribute("aria-label") : null, hasAriaLabel = ariaLabel && ariaLabel.trim(), hasInputValue = "INPUT" === el.tagName && (el.value || el.placeholder), hasImgAlt = "IMG" === el.tagName && el.alt;
72
+ let innerTextValue = "";
73
+ try {
74
+ innerTextValue = el.innerText || "";
75
+ } catch (e) {
76
+ innerTextValue = "";
77
+ }
78
+ const hasInnerText = "INPUT" !== el.tagName && "IMG" !== el.tagName && innerTextValue && innerTextValue.trim();
79
+ if (hasAriaLabel || hasInputValue || hasImgAlt || hasInnerText) return null;
80
+ const config = function(userConfig = {}) {
81
+ return {
82
+ ...DEFAULT_INFERENCE_CONFIG,
83
+ ...userConfig,
84
+ methods: {
85
+ ...DEFAULT_INFERENCE_CONFIG.methods,
86
+ ...userConfig.methods || {}
87
+ }
88
+ };
89
+ }(inferenceConfig);
90
+ if (config.methods.explicitLabel && el.labels && el.labels.length > 0) {
91
+ const label = el.labels[0];
92
+ if (isInferenceSource(label, config)) {
93
+ const text = (label.innerText || "").trim();
94
+ if (text) return {
95
+ text: text,
96
+ source: "explicit_label"
97
+ };
98
+ }
99
+ }
100
+ if (config.methods.ariaLabelledby && el.hasAttribute && el.hasAttribute("aria-labelledby")) {
101
+ const labelIdsAttr = el.getAttribute("aria-labelledby");
102
+ if (labelIdsAttr) {
103
+ const labelIds = labelIdsAttr.split(/\s+/).filter(id => id.trim()), labelTexts = [], doc = (() => "undefined" != typeof global && global.document ? global.document : "undefined" != typeof window && window.document ? window.document : "undefined" != typeof document ? document : null)();
104
+ if (doc && doc.getElementById) for (const labelId of labelIds) {
105
+ if (!labelId.trim()) continue;
106
+ let labelEl = null;
107
+ try {
108
+ labelEl = doc.getElementById(labelId);
109
+ } catch (e) {
110
+ continue;
111
+ }
112
+ if (labelEl) {
113
+ let text = "";
114
+ try {
115
+ if (text = (labelEl.innerText || "").trim(), !text && labelEl.textContent && (text = labelEl.textContent.trim()),
116
+ !text && labelEl.getAttribute) {
117
+ const ariaLabel = labelEl.getAttribute("aria-label");
118
+ ariaLabel && (text = ariaLabel.trim());
119
+ }
120
+ } catch (e) {
121
+ continue;
122
+ }
123
+ text && labelTexts.push(text);
124
+ }
125
+ } else ;
126
+ if (labelTexts.length > 0) return {
127
+ text: labelTexts.join(" "),
128
+ source: "aria_labelledby"
129
+ };
130
+ }
131
+ }
132
+ if (config.methods.parentTraversal) {
133
+ let parent = el.parentElement, depth = 0;
134
+ for (;parent && depth < config.maxParentDepth; ) {
135
+ if (isInferenceSource(parent, config)) {
136
+ const text = (parent.innerText || "").trim();
137
+ if (text) return {
138
+ text: text,
139
+ source: "parent_label"
140
+ };
141
+ }
142
+ parent = parent.parentElement, depth++;
143
+ }
144
+ }
145
+ if (config.methods.siblingProximity) {
146
+ const prev = el.previousElementSibling;
147
+ if (prev && isInferenceSource(prev, config) && isInSameValidContainer(el, prev, {
148
+ requireSameContainer: config.requireSameContainer,
149
+ containerTags: config.containerTags
150
+ })) {
151
+ const text = (prev.innerText || "").trim();
152
+ if (text) return {
153
+ text: text,
154
+ source: "sibling_label"
155
+ };
156
+ }
157
+ }
158
+ return null;
159
+ }
160
+ function getText(el) {
161
+ return el.getAttribute("aria-label") ? el.getAttribute("aria-label") : "INPUT" === el.tagName ? el.value || el.placeholder || "" : "IMG" === el.tagName ? el.alt || "" : (el.innerText || "").replace(/\s+/g, " ").trim().substring(0, 100);
162
+ }
163
+ function getClassName(el) {
164
+ if (!el || !el.className) return "";
165
+ if ("string" == typeof el.className) return el.className;
166
+ if ("object" == typeof el.className) {
167
+ if ("baseVal" in el.className && "string" == typeof el.className.baseVal) return el.className.baseVal;
168
+ if ("animVal" in el.className && "string" == typeof el.className.animVal) return el.className.animVal;
169
+ try {
170
+ return String(el.className);
171
+ } catch (e) {
172
+ return "";
173
+ }
174
+ }
175
+ return "";
176
+ }
177
+ function toSafeString(value) {
178
+ if (null == value) return null;
179
+ if ("string" == typeof value) return value;
180
+ if ("object" == typeof value) {
181
+ if ("baseVal" in value && "string" == typeof value.baseVal) return value.baseVal;
182
+ if ("animVal" in value && "string" == typeof value.animVal) return value.animVal;
183
+ try {
184
+ return String(value);
185
+ } catch (e) {
186
+ return null;
187
+ }
188
+ }
189
+ try {
190
+ return String(value);
191
+ } catch (e) {
192
+ return null;
193
+ }
194
+ }
195
+ function getSVGColor(el) {
196
+ if (!el || "SVG" !== el.tagName) return null;
197
+ const style = window.getComputedStyle(el), fill = style.fill;
198
+ if (fill && "none" !== fill && "transparent" !== fill && "rgba(0, 0, 0, 0)" !== fill) {
199
+ const rgbaMatch = fill.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);
200
+ if (rgbaMatch) {
201
+ if ((rgbaMatch[4] ? parseFloat(rgbaMatch[4]) : 1) >= .9) return `rgb(${rgbaMatch[1]}, ${rgbaMatch[2]}, ${rgbaMatch[3]})`;
202
+ } else if (fill.startsWith("rgb(")) return fill;
203
+ }
204
+ const stroke = style.stroke;
205
+ if (stroke && "none" !== stroke && "transparent" !== stroke && "rgba(0, 0, 0, 0)" !== stroke) {
206
+ const rgbaMatch = stroke.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);
207
+ if (rgbaMatch) {
208
+ if ((rgbaMatch[4] ? parseFloat(rgbaMatch[4]) : 1) >= .9) return `rgb(${rgbaMatch[1]}, ${rgbaMatch[2]}, ${rgbaMatch[3]})`;
209
+ } else if (stroke.startsWith("rgb(")) return stroke;
210
+ }
211
+ return null;
212
+ }
213
+ function getRawHTML(root) {
214
+ const sourceRoot = root || document.body, clone = sourceRoot.cloneNode(!0);
215
+ [ "nav", "footer", "header", "script", "style", "noscript", "iframe", "svg" ].forEach(tag => {
216
+ clone.querySelectorAll(tag).forEach(el => {
217
+ el.parentNode && el.parentNode.removeChild(el);
218
+ });
219
+ });
220
+ const invisibleSelectors = [], walker = document.createTreeWalker(sourceRoot, NodeFilter.SHOW_ELEMENT, null, !1);
221
+ let node;
222
+ for (;node = walker.nextNode(); ) {
223
+ const tag = node.tagName.toLowerCase();
224
+ if ("head" === tag || "title" === tag) continue;
225
+ const style = window.getComputedStyle(node);
226
+ if ("none" === style.display || "hidden" === style.visibility || 0 === node.offsetWidth && 0 === node.offsetHeight) {
227
+ let selector = tag;
228
+ if (node.id) selector = `#${node.id}`; else if (node.className && "string" == typeof node.className) {
229
+ const classes = node.className.trim().split(/\s+/).filter(c => c);
230
+ classes.length > 0 && (selector = `${tag}.${classes.join(".")}`);
231
+ }
232
+ invisibleSelectors.push(selector);
233
+ }
234
+ }
235
+ invisibleSelectors.forEach(selector => {
236
+ try {
237
+ clone.querySelectorAll(selector).forEach(el => {
238
+ el.parentNode && el.parentNode.removeChild(el);
239
+ });
240
+ } catch (e) {}
241
+ });
242
+ clone.querySelectorAll("a[href]").forEach(link => {
243
+ const href = link.getAttribute("href");
244
+ if (href && !href.startsWith("http://") && !href.startsWith("https://") && !href.startsWith("#")) try {
245
+ link.setAttribute("href", new URL(href, document.baseURI).href);
246
+ } catch (e) {}
247
+ });
248
+ return clone.querySelectorAll("img[src]").forEach(img => {
249
+ const src = img.getAttribute("src");
250
+ if (src && !src.startsWith("http://") && !src.startsWith("https://") && !src.startsWith("data:")) try {
251
+ img.setAttribute("src", new URL(src, document.baseURI).href);
252
+ } catch (e) {}
253
+ }), clone.innerHTML;
254
+ }
255
+ function cleanElement(obj) {
256
+ if (Array.isArray(obj)) return obj.map(cleanElement);
257
+ if (null !== obj && "object" == typeof obj) {
258
+ const cleaned = {};
259
+ for (const [key, value] of Object.entries(obj)) if (null != value) if ("object" == typeof value) {
260
+ const deepClean = cleanElement(value);
261
+ Object.keys(deepClean).length > 0 && (cleaned[key] = deepClean);
262
+ } else cleaned[key] = value;
263
+ return cleaned;
264
+ }
265
+ return obj;
266
+ }
267
+ async function snapshot(options = {}) {
268
+ try {
269
+ !1 !== options.waitForStability && await async function(options = {}) {
270
+ const {minNodeCount: minNodeCount = 500, quietPeriod: quietPeriod = 200, maxWait: maxWait = 5e3} = options, startTime = Date.now();
271
+ return new Promise(resolve => {
272
+ if (document.querySelectorAll("*").length >= minNodeCount) {
273
+ let lastChange = Date.now();
274
+ const observer = new MutationObserver(() => {
275
+ lastChange = Date.now();
276
+ });
277
+ observer.observe(document.body, {
278
+ childList: !0,
279
+ subtree: !0,
280
+ attributes: !1
281
+ });
282
+ const checkStable = () => {
283
+ const timeSinceLastChange = Date.now() - lastChange, totalWait = Date.now() - startTime;
284
+ timeSinceLastChange >= quietPeriod || totalWait >= maxWait ? (observer.disconnect(),
285
+ resolve()) : setTimeout(checkStable, 50);
286
+ };
287
+ checkStable();
288
+ } else {
289
+ const observer = new MutationObserver(() => {
290
+ const currentCount = document.querySelectorAll("*").length, totalWait = Date.now() - startTime;
291
+ if (currentCount >= minNodeCount) {
292
+ observer.disconnect();
293
+ let lastChange = Date.now();
294
+ const quietObserver = new MutationObserver(() => {
295
+ lastChange = Date.now();
296
+ });
297
+ quietObserver.observe(document.body, {
298
+ childList: !0,
299
+ subtree: !0,
300
+ attributes: !1
301
+ });
302
+ const checkQuiet = () => {
303
+ const timeSinceLastChange = Date.now() - lastChange, totalWait = Date.now() - startTime;
304
+ timeSinceLastChange >= quietPeriod || totalWait >= maxWait ? (quietObserver.disconnect(),
305
+ resolve()) : setTimeout(checkQuiet, 50);
306
+ };
307
+ checkQuiet();
308
+ } else totalWait >= maxWait && (observer.disconnect(), resolve());
309
+ });
310
+ observer.observe(document.body, {
311
+ childList: !0,
312
+ subtree: !0,
313
+ attributes: !1
314
+ }), setTimeout(() => {
315
+ observer.disconnect(), resolve();
316
+ }, maxWait);
317
+ }
318
+ });
319
+ }(options.waitForStability || {});
320
+ const rawData = [];
321
+ window.sentience_registry = [];
322
+ getAllElements().forEach((el, idx) => {
323
+ if (!el.getBoundingClientRect) return;
324
+ const rect = el.getBoundingClientRect();
325
+ if (rect.width < 5 || rect.height < 5) return;
326
+ if ("span" === el.tagName.toLowerCase()) {
327
+ if (el.closest("a")) return;
328
+ const childLink = el.querySelector("a[href]");
329
+ if (childLink && childLink.href) return;
330
+ options.debug && el.className && el.className.includes("titleline");
331
+ }
332
+ window.sentience_registry[idx] = el;
333
+ const semanticText = function(el, options = {}) {
334
+ if (!el) return {
335
+ text: "",
336
+ source: null
337
+ };
338
+ const explicitAriaLabel = el.getAttribute ? el.getAttribute("aria-label") : null;
339
+ if (explicitAriaLabel && explicitAriaLabel.trim()) return {
340
+ text: explicitAriaLabel.trim(),
341
+ source: "explicit_aria_label"
342
+ };
343
+ if ("INPUT" === el.tagName) {
344
+ const value = (el.value || el.placeholder || "").trim();
345
+ if (value) return {
346
+ text: value,
347
+ source: "input_value"
348
+ };
349
+ }
350
+ if ("IMG" === el.tagName) {
351
+ const alt = (el.alt || "").trim();
352
+ if (alt) return {
353
+ text: alt,
354
+ source: "img_alt"
355
+ };
356
+ }
357
+ const innerText = (el.innerText || "").trim();
358
+ if (innerText) return {
359
+ text: innerText.substring(0, 100),
360
+ source: "inner_text"
361
+ };
362
+ const inferred = getInferredLabel(el, {
363
+ enableInference: !1 !== options.enableInference,
364
+ inferenceConfig: options.inferenceConfig
365
+ });
366
+ return inferred || {
367
+ text: "",
368
+ source: null
369
+ };
370
+ }(el, {
371
+ enableInference: !1 !== options.enableInference,
372
+ inferenceConfig: options.inferenceConfig
373
+ }), textVal = semanticText.text || getText(el), inferredRole = function(el, options = {}) {
374
+ const {enableInference: enableInference = !0} = options;
375
+ if (!enableInference) return null;
376
+ if (!function(el) {
377
+ if (!el || !el.tagName) return !1;
378
+ const tag = el.tagName.toLowerCase(), role = el.getAttribute ? el.getAttribute("role") : null, hasTabIndex = !!el.hasAttribute && el.hasAttribute("tabindex"), hasHref = "A" === el.tagName && !!el.hasAttribute && el.hasAttribute("href");
379
+ return [ "button", "input", "textarea", "select", "option", "details", "summary", "a" ].includes(tag) ? !("a" === tag && !hasHref) : !(!role || ![ "button", "link", "tab", "menuitem", "checkbox", "radio", "switch", "slider", "combobox", "textbox", "searchbox", "spinbutton" ].includes(role.toLowerCase())) || (!!hasTabIndex || (!!(el.onclick || el.onkeydown || el.onkeypress || el.onkeyup) || !(!el.getAttribute || !(el.getAttribute("onclick") || el.getAttribute("onkeydown") || el.getAttribute("onkeypress") || el.getAttribute("onkeyup")))));
380
+ }(el)) return null;
381
+ const hasAriaLabel = el.getAttribute ? el.getAttribute("aria-label") : null, hasExplicitRole = el.getAttribute ? el.getAttribute("role") : null;
382
+ if (hasAriaLabel || hasExplicitRole) return null;
383
+ const tag = el.tagName.toLowerCase();
384
+ return [ "button", "a", "input", "textarea", "select", "option" ].includes(tag) ? null : el.onclick || el.getAttribute && el.getAttribute("onclick") || el.onkeydown || el.onkeypress || el.onkeyup || el.getAttribute && (el.getAttribute("onkeydown") || el.getAttribute("onkeypress") || el.getAttribute("onkeyup")) || el.hasAttribute && el.hasAttribute("tabindex") && ("div" === tag || "span" === tag) ? "button" : null;
385
+ }(el, {
386
+ enableInference: !1 !== options.enableInference,
387
+ inferenceConfig: options.inferenceConfig
388
+ }), inView = function(rect) {
389
+ return rect.top < window.innerHeight && rect.bottom > 0 && rect.left < window.innerWidth && rect.right > 0;
390
+ }(rect), style = window.getComputedStyle(el), occluded = !!inView && function(el, rect, style) {
391
+ const zIndex = parseInt(style.zIndex, 10);
392
+ if ("static" === style.position && (isNaN(zIndex) || zIndex <= 10)) return !1;
393
+ const cx = rect.x + rect.width / 2, cy = rect.y + rect.height / 2;
394
+ if (cx < 0 || cx > window.innerWidth || cy < 0 || cy > window.innerHeight) return !1;
395
+ const topEl = document.elementFromPoint(cx, cy);
396
+ return !!topEl && !(el === topEl || el.contains(topEl) || topEl.contains(el));
397
+ }(el, rect, style), effectiveBgColor = function(el) {
398
+ if (!el) return null;
399
+ if ("SVG" === el.tagName) {
400
+ const svgColor = getSVGColor(el);
401
+ if (svgColor) return svgColor;
402
+ }
403
+ let current = el, depth = 0;
404
+ for (;current && depth < 10; ) {
405
+ const style = window.getComputedStyle(current);
406
+ if ("SVG" === current.tagName) {
407
+ const svgColor = getSVGColor(current);
408
+ if (svgColor) return svgColor;
409
+ }
410
+ const bgColor = style.backgroundColor;
411
+ if (bgColor && "transparent" !== bgColor && "rgba(0, 0, 0, 0)" !== bgColor) {
412
+ const rgbaMatch = bgColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);
413
+ if (!rgbaMatch) return bgColor.startsWith("rgb("), bgColor;
414
+ if ((rgbaMatch[4] ? parseFloat(rgbaMatch[4]) : 1) >= .9) return `rgb(${rgbaMatch[1]}, ${rgbaMatch[2]}, ${rgbaMatch[3]})`;
415
+ }
416
+ current = current.parentElement, depth++;
417
+ }
418
+ return null;
419
+ }(el);
420
+ rawData.push({
421
+ id: idx,
422
+ tag: el.tagName.toLowerCase(),
423
+ rect: {
424
+ x: rect.x,
425
+ y: rect.y,
426
+ width: rect.width,
427
+ height: rect.height
428
+ },
429
+ styles: {
430
+ display: toSafeString(style.display),
431
+ visibility: toSafeString(style.visibility),
432
+ opacity: toSafeString(style.opacity),
433
+ z_index: toSafeString(style.zIndex || "auto"),
434
+ position: toSafeString(style.position),
435
+ bg_color: toSafeString(effectiveBgColor || style.backgroundColor),
436
+ color: toSafeString(style.color),
437
+ cursor: toSafeString(style.cursor),
438
+ font_weight: toSafeString(style.fontWeight),
439
+ font_size: toSafeString(style.fontSize)
440
+ },
441
+ attributes: {
442
+ role: toSafeString(el.getAttribute("role")),
443
+ type_: toSafeString(el.getAttribute("type")),
444
+ aria_label: "explicit_aria_label" === semanticText?.source ? semanticText.text : toSafeString(el.getAttribute("aria-label")),
445
+ inferred_label: semanticText?.source && ![ "explicit_aria_label", "input_value", "img_alt", "inner_text" ].includes(semanticText.source) ? toSafeString(semanticText.text) : null,
446
+ label_source: semanticText?.source || null,
447
+ inferred_role: inferredRole ? toSafeString(inferredRole) : null,
448
+ href: toSafeString(el.href || el.getAttribute("href") || el.closest && el.closest("a")?.href || null),
449
+ class: toSafeString(getClassName(el)),
450
+ value: void 0 !== el.value ? toSafeString(el.value) : toSafeString(el.getAttribute("value")),
451
+ checked: void 0 !== el.checked ? String(el.checked) : null
452
+ },
453
+ text: toSafeString(textVal),
454
+ in_viewport: inView,
455
+ is_occluded: occluded,
456
+ scroll_y: window.scrollY
457
+ });
458
+ });
459
+ const allRawElements = [ ...rawData ];
460
+ let totalIframeElements = 0;
461
+ if (!1 !== options.collectIframes) try {
462
+ const iframeSnapshots = await async function(options = {}) {
463
+ const iframeData = new Map, iframes = Array.from(document.querySelectorAll("iframe"));
464
+ if (0 === iframes.length) return iframeData;
465
+ const iframePromises = iframes.map((iframe, idx) => {
466
+ const src = iframe.src || "";
467
+ return src.includes("doubleclick") || src.includes("googleadservices") || src.includes("ads system") ? Promise.resolve(null) : new Promise(resolve => {
468
+ const requestId = `iframe-${idx}-${Date.now()}`, timeout = setTimeout(() => {
469
+ resolve(null);
470
+ }, 5e3), listener = event => {
471
+ "SENTIENCE_IFRAME_SNAPSHOT_RESPONSE" === event.data?.type && event.data, "SENTIENCE_IFRAME_SNAPSHOT_RESPONSE" === event.data?.type && event.data?.requestId === requestId && (clearTimeout(timeout),
472
+ window.removeEventListener("message", listener), event.data.error ? resolve(null) : (event.data.snapshot,
473
+ resolve({
474
+ iframe: iframe,
475
+ data: event.data.snapshot,
476
+ error: null
477
+ })));
478
+ };
479
+ window.addEventListener("message", listener);
480
+ try {
481
+ iframe.contentWindow ? iframe.contentWindow.postMessage({
482
+ type: "SENTIENCE_IFRAME_SNAPSHOT_REQUEST",
483
+ requestId: requestId,
484
+ options: {
485
+ ...options,
486
+ collectIframes: !0
487
+ }
488
+ }, "*") : (clearTimeout(timeout), window.removeEventListener("message", listener),
489
+ resolve(null));
490
+ } catch (error) {
491
+ clearTimeout(timeout), window.removeEventListener("message", listener), resolve(null);
492
+ }
493
+ });
494
+ });
495
+ return (await Promise.all(iframePromises)).forEach((result, idx) => {
496
+ result && result.data && !result.error ? iframeData.set(iframes[idx], result.data) : result && result.error;
497
+ }), iframeData;
498
+ }(options);
499
+ iframeSnapshots.size > 0 && iframeSnapshots.forEach((iframeSnapshot, iframeEl) => {
500
+ if (iframeSnapshot && iframeSnapshot.raw_elements) {
501
+ iframeSnapshot.raw_elements.length;
502
+ const iframeRect = iframeEl.getBoundingClientRect(), offset = {
503
+ x: iframeRect.x,
504
+ y: iframeRect.y
505
+ }, iframeSrc = iframeEl.src || iframeEl.getAttribute("src") || "";
506
+ let isSameOrigin = !1;
507
+ try {
508
+ isSameOrigin = null !== iframeEl.contentWindow;
509
+ } catch (e) {
510
+ isSameOrigin = !1;
511
+ }
512
+ const adjustedElements = iframeSnapshot.raw_elements.map(el => {
513
+ const adjusted = {
514
+ ...el
515
+ };
516
+ return adjusted.rect && (adjusted.rect = {
517
+ ...adjusted.rect,
518
+ x: adjusted.rect.x + offset.x,
519
+ y: adjusted.rect.y + offset.y
520
+ }), adjusted.iframe_context = {
521
+ src: iframeSrc,
522
+ is_same_origin: isSameOrigin
523
+ }, adjusted;
524
+ });
525
+ allRawElements.push(...adjustedElements), totalIframeElements += adjustedElements.length;
526
+ }
527
+ });
528
+ } catch (error) {}
529
+ const processed = await function(rawData, options) {
530
+ return new Promise((resolve, reject) => {
531
+ const requestId = Math.random().toString(36).substring(7);
532
+ let resolved = !1;
533
+ const timeout = setTimeout(() => {
534
+ resolved || (resolved = !0, window.removeEventListener("message", listener), reject(new Error("WASM processing timeout - extension may be unresponsive. Try reloading the extension.")));
535
+ }, 25e3), listener = e => {
536
+ if ("SENTIENCE_SNAPSHOT_RESULT" === e.data.type && e.data.requestId === requestId) {
537
+ if (resolved) return;
538
+ resolved = !0, clearTimeout(timeout), window.removeEventListener("message", listener),
539
+ e.data.error ? reject(new Error(e.data.error)) : resolve({
540
+ elements: e.data.elements,
541
+ raw_elements: e.data.raw_elements,
542
+ duration: e.data.duration
543
+ });
544
+ }
545
+ };
546
+ window.addEventListener("message", listener);
547
+ try {
548
+ window.postMessage({
549
+ type: "SENTIENCE_SNAPSHOT_REQUEST",
550
+ requestId: requestId,
551
+ rawData: rawData,
552
+ options: options
553
+ }, "*");
554
+ } catch (error) {
555
+ resolved || (resolved = !0, clearTimeout(timeout), window.removeEventListener("message", listener),
556
+ reject(new Error(`Failed to send snapshot request: ${error.message}`)));
557
+ }
558
+ });
559
+ }(allRawElements, options);
560
+ if (!processed || !processed.elements) throw new Error("WASM processing returned invalid result");
561
+ let screenshot = null;
562
+ options.screenshot && (screenshot = await function(options) {
563
+ return new Promise(resolve => {
564
+ const requestId = Math.random().toString(36).substring(7), listener = e => {
565
+ "SENTIENCE_SCREENSHOT_RESULT" === e.data.type && e.data.requestId === requestId && (window.removeEventListener("message", listener),
566
+ resolve(e.data.screenshot));
567
+ };
568
+ window.addEventListener("message", listener), window.postMessage({
569
+ type: "SENTIENCE_SCREENSHOT_REQUEST",
570
+ requestId: requestId,
571
+ options: options
572
+ }, "*"), setTimeout(() => {
573
+ window.removeEventListener("message", listener), resolve(null);
574
+ }, 1e4);
575
+ });
576
+ }(options.screenshot));
577
+ const cleanedElements = cleanElement(processed.elements), cleanedRawElements = cleanElement(processed.raw_elements);
578
+ cleanedElements.length, cleanedRawElements.length;
579
+ return {
580
+ status: "success",
581
+ url: window.location.href,
582
+ viewport: {
583
+ width: window.innerWidth,
584
+ height: window.innerHeight
585
+ },
586
+ elements: cleanedElements,
587
+ raw_elements: cleanedRawElements,
588
+ screenshot: screenshot
589
+ };
590
+ } catch (error) {
591
+ return {
592
+ status: "error",
593
+ error: error.message || "Unknown error",
594
+ stack: error.stack
595
+ };
596
+ }
597
+ }
598
+ function read(options = {}) {
599
+ const format = options.format || "raw";
600
+ let content;
601
+ return content = "raw" === format ? getRawHTML(document.body) : "markdown" === format ? function(root) {
602
+ const rawHTML = getRawHTML(root), tempDiv = document.createElement("div");
603
+ tempDiv.innerHTML = rawHTML;
604
+ let markdown = "", insideLink = !1;
605
+ return function walk(node) {
606
+ if (node.nodeType === Node.TEXT_NODE) {
607
+ const text = node.textContent.replace(/[\r\n]+/g, " ").replace(/\s+/g, " ");
608
+ return void (text.trim() && (markdown += text));
609
+ }
610
+ if (node.nodeType !== Node.ELEMENT_NODE) return;
611
+ const tag = node.tagName.toLowerCase();
612
+ if ("h1" === tag && (markdown += "\n# "), "h2" === tag && (markdown += "\n## "),
613
+ "h3" === tag && (markdown += "\n### "), "li" === tag && (markdown += "\n- "), insideLink || "p" !== tag && "div" !== tag && "br" !== tag || (markdown += "\n"),
614
+ "strong" !== tag && "b" !== tag || (markdown += "**"), "em" !== tag && "i" !== tag || (markdown += "_"),
615
+ "a" === tag && (markdown += "[", insideLink = !0), node.shadowRoot ? Array.from(node.shadowRoot.childNodes).forEach(walk) : node.childNodes.forEach(walk),
616
+ "a" === tag) {
617
+ const href = node.getAttribute("href");
618
+ markdown += href ? `](${href})` : "]", insideLink = !1;
619
+ }
620
+ "strong" !== tag && "b" !== tag || (markdown += "**"), "em" !== tag && "i" !== tag || (markdown += "_"),
621
+ insideLink || "h1" !== tag && "h2" !== tag && "h3" !== tag && "p" !== tag && "div" !== tag || (markdown += "\n");
622
+ }(tempDiv), markdown.replace(/\n{3,}/g, "\n\n").trim();
623
+ }(document.body) : function(root) {
624
+ let text = "";
625
+ return function walk(node) {
626
+ if (node.nodeType !== Node.TEXT_NODE) {
627
+ if (node.nodeType === Node.ELEMENT_NODE) {
628
+ const tag = node.tagName.toLowerCase();
629
+ if ([ "nav", "footer", "header", "script", "style", "noscript", "iframe", "svg" ].includes(tag)) return;
630
+ const style = window.getComputedStyle(node);
631
+ if ("none" === style.display || "hidden" === style.visibility) return;
632
+ const isBlock = "block" === style.display || "flex" === style.display || "P" === node.tagName || "DIV" === node.tagName;
633
+ isBlock && (text += " "), node.shadowRoot ? Array.from(node.shadowRoot.childNodes).forEach(walk) : node.childNodes.forEach(walk),
634
+ isBlock && (text += "\n");
635
+ }
636
+ } else text += node.textContent;
637
+ }(root || document.body), text.replace(/\n{3,}/g, "\n\n").trim();
638
+ }(document.body), {
639
+ status: "success",
640
+ url: window.location.href,
641
+ format: format,
642
+ content: content,
643
+ length: content.length
644
+ };
645
+ }
646
+ function findTextRect(options = {}) {
647
+ const {text: text, containerElement: containerElement = document.body, caseSensitive: caseSensitive = !1, wholeWord: wholeWord = !1, maxResults: maxResults = 10} = options;
648
+ if (!text || 0 === text.trim().length) return {
649
+ status: "error",
650
+ error: "Text parameter is required"
651
+ };
652
+ const results = [], searchText = caseSensitive ? text : text.toLowerCase();
653
+ function findInTextNode(textNode) {
654
+ const nodeText = textNode.nodeValue, searchableText = caseSensitive ? nodeText : nodeText.toLowerCase();
655
+ let startIndex = 0;
656
+ for (;startIndex < nodeText.length && results.length < maxResults; ) {
657
+ const foundIndex = searchableText.indexOf(searchText, startIndex);
658
+ if (-1 === foundIndex) break;
659
+ if (wholeWord) {
660
+ const before = foundIndex > 0 ? nodeText[foundIndex - 1] : " ", after = foundIndex + text.length < nodeText.length ? nodeText[foundIndex + text.length] : " ";
661
+ if (!/\s/.test(before) || !/\s/.test(after)) {
662
+ startIndex = foundIndex + 1;
663
+ continue;
664
+ }
665
+ }
666
+ try {
667
+ const range = document.createRange();
668
+ range.setStart(textNode, foundIndex), range.setEnd(textNode, foundIndex + text.length);
669
+ const rect = range.getBoundingClientRect();
670
+ rect.width > 0 && rect.height > 0 && results.push({
671
+ text: nodeText.substring(foundIndex, foundIndex + text.length),
672
+ rect: {
673
+ x: rect.left + window.scrollX,
674
+ y: rect.top + window.scrollY,
675
+ width: rect.width,
676
+ height: rect.height,
677
+ left: rect.left + window.scrollX,
678
+ top: rect.top + window.scrollY,
679
+ right: rect.right + window.scrollX,
680
+ bottom: rect.bottom + window.scrollY
681
+ },
682
+ viewport_rect: {
683
+ x: rect.left,
684
+ y: rect.top,
685
+ width: rect.width,
686
+ height: rect.height
687
+ },
688
+ context: {
689
+ before: nodeText.substring(Math.max(0, foundIndex - 20), foundIndex),
690
+ after: nodeText.substring(foundIndex + text.length, Math.min(nodeText.length, foundIndex + text.length + 20))
691
+ },
692
+ in_viewport: rect.top >= 0 && rect.left >= 0 && rect.bottom <= window.innerHeight && rect.right <= window.innerWidth
693
+ });
694
+ } catch (e) {}
695
+ startIndex = foundIndex + 1;
696
+ }
697
+ }
698
+ const walker = document.createTreeWalker(containerElement, NodeFilter.SHOW_TEXT, {
699
+ acceptNode(node) {
700
+ const parent = node.parentElement;
701
+ if (!parent) return NodeFilter.FILTER_REJECT;
702
+ const tagName = parent.tagName.toLowerCase();
703
+ if ("script" === tagName || "style" === tagName || "noscript" === tagName) return NodeFilter.FILTER_REJECT;
704
+ if (!node.nodeValue || 0 === node.nodeValue.trim().length) return NodeFilter.FILTER_REJECT;
705
+ const computedStyle = window.getComputedStyle(parent);
706
+ return "none" === computedStyle.display || "hidden" === computedStyle.visibility || "0" === computedStyle.opacity ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT;
707
+ }
708
+ });
709
+ let currentNode;
710
+ for (;(currentNode = walker.nextNode()) && results.length < maxResults; ) findInTextNode(currentNode);
711
+ return {
712
+ status: "success",
713
+ query: text,
714
+ case_sensitive: caseSensitive,
715
+ whole_word: wholeWord,
716
+ matches: results.length,
717
+ results: results,
718
+ viewport: {
719
+ width: window.innerWidth,
720
+ height: window.innerHeight,
721
+ scroll_x: window.scrollX,
722
+ scroll_y: window.scrollY
723
+ }
724
+ };
725
+ }
726
+ function click(id) {
727
+ const el = window.sentience_registry[id];
728
+ return !!el && (el.click(), el.focus(), !0);
729
+ }
730
+ function startRecording(options = {}) {
731
+ const {highlightColor: highlightColor = "#ff0000", successColor: successColor = "#00ff00", autoDisableTimeout: autoDisableTimeout = 18e5, keyboardShortcut: keyboardShortcut = "Ctrl+Shift+I"} = options;
732
+ if (!window.sentience_registry || 0 === window.sentience_registry.length) return alert("Registry empty. Run `await window.sentience.snapshot()` first!"),
733
+ () => {};
734
+ window.sentience_registry_map = new Map, window.sentience_registry.forEach((el, idx) => {
735
+ el && window.sentience_registry_map.set(el, idx);
736
+ });
737
+ let highlightBox = document.getElementById("sentience-highlight-box");
738
+ highlightBox || (highlightBox = document.createElement("div"), highlightBox.id = "sentience-highlight-box",
739
+ highlightBox.style.cssText = `\n position: fixed;\n pointer-events: none;\n z-index: 2147483647;\n border: 2px solid ${highlightColor};\n background: rgba(255, 0, 0, 0.1);\n display: none;\n transition: all 0.1s ease;\n box-sizing: border-box;\n `,
740
+ document.body.appendChild(highlightBox));
741
+ let recordingIndicator = document.getElementById("sentience-recording-indicator");
742
+ recordingIndicator || (recordingIndicator = document.createElement("div"), recordingIndicator.id = "sentience-recording-indicator",
743
+ recordingIndicator.style.cssText = `\n position: fixed;\n top: 0;\n left: 0;\n right: 0;\n height: 3px;\n background: ${highlightColor};\n z-index: 2147483646;\n pointer-events: none;\n `,
744
+ document.body.appendChild(recordingIndicator)), recordingIndicator.style.display = "block";
745
+ const mouseOverHandler = e => {
746
+ const el = e.target;
747
+ if (!el || el === highlightBox || el === recordingIndicator) return;
748
+ const rect = el.getBoundingClientRect();
749
+ highlightBox.style.display = "block", highlightBox.style.top = rect.top + window.scrollY + "px",
750
+ highlightBox.style.left = rect.left + window.scrollX + "px", highlightBox.style.width = rect.width + "px",
751
+ highlightBox.style.height = rect.height + "px";
752
+ }, clickHandler = e => {
753
+ e.preventDefault(), e.stopPropagation();
754
+ const el = e.target;
755
+ if (!el || el === highlightBox || el === recordingIndicator) return;
756
+ const sentienceId = window.sentience_registry_map.get(el);
757
+ if (void 0 === sentienceId) return void alert("Element not in registry. Run `await window.sentience.snapshot()` first!");
758
+ const rawData = function(el) {
759
+ const style = window.getComputedStyle(el), rect = el.getBoundingClientRect();
760
+ return {
761
+ tag: el.tagName,
762
+ rect: {
763
+ x: Math.round(rect.x),
764
+ y: Math.round(rect.y),
765
+ width: Math.round(rect.width),
766
+ height: Math.round(rect.height)
767
+ },
768
+ styles: {
769
+ cursor: style.cursor || null,
770
+ backgroundColor: style.backgroundColor || null,
771
+ color: style.color || null,
772
+ fontWeight: style.fontWeight || null,
773
+ fontSize: style.fontSize || null,
774
+ display: style.display || null,
775
+ position: style.position || null,
776
+ zIndex: style.zIndex || null,
777
+ opacity: style.opacity || null,
778
+ visibility: style.visibility || null
779
+ },
780
+ attributes: {
781
+ role: el.getAttribute("role") || null,
782
+ type: el.getAttribute("type") || null,
783
+ ariaLabel: el.getAttribute("aria-label") || null,
784
+ id: el.id || null,
785
+ className: el.className || null
786
+ }
787
+ };
788
+ }(el), selector = function(el) {
789
+ if (!el || !el.tagName) return "";
790
+ if (el.id) return `#${el.id}`;
791
+ for (const attr of el.attributes) if (attr.name.startsWith("data-") || "aria-label" === attr.name) {
792
+ const value = attr.value ? attr.value.replace(/"/g, '\\"') : "";
793
+ return `${el.tagName.toLowerCase()}[${attr.name}="${value}"]`;
794
+ }
795
+ const path = [];
796
+ let current = el;
797
+ for (;current && current !== document.body && current !== document.documentElement; ) {
798
+ let selector = current.tagName.toLowerCase();
799
+ if (current.id) {
800
+ selector = `#${current.id}`, path.unshift(selector);
801
+ break;
802
+ }
803
+ if (current.className && "string" == typeof current.className) {
804
+ const classes = current.className.trim().split(/\s+/).filter(c => c);
805
+ classes.length > 0 && (selector += `.${classes[0]}`);
806
+ }
807
+ if (current.parentElement) {
808
+ const sameTagSiblings = Array.from(current.parentElement.children).filter(s => s.tagName === current.tagName), index = sameTagSiblings.indexOf(current);
809
+ (index > 0 || sameTagSiblings.length > 1) && (selector += `:nth-of-type(${index + 1})`);
810
+ }
811
+ path.unshift(selector), current = current.parentElement;
812
+ }
813
+ return path.join(" > ") || el.tagName.toLowerCase();
814
+ }(el), role = el.getAttribute("role") || el.tagName.toLowerCase(), text = getText(el), snippet = {
815
+ task: `Interact with ${text.substring(0, 20)}${text.length > 20 ? "..." : ""}`,
816
+ url: window.location.href,
817
+ timestamp: (new Date).toISOString(),
818
+ target_criteria: {
819
+ id: sentienceId,
820
+ selector: selector,
821
+ role: role,
822
+ text: text.substring(0, 50)
823
+ },
824
+ debug_snapshot: rawData
825
+ }, jsonString = JSON.stringify(snippet, null, 2);
826
+ navigator.clipboard.writeText(jsonString).then(() => {
827
+ highlightBox.style.border = `2px solid ${successColor}`, highlightBox.style.background = "rgba(0, 255, 0, 0.2)",
828
+ setTimeout(() => {
829
+ highlightBox.style.border = `2px solid ${highlightColor}`, highlightBox.style.background = "rgba(255, 0, 0, 0.1)";
830
+ }, 500);
831
+ }).catch(err => {
832
+ alert("Failed to copy to clipboard. Check console for JSON.");
833
+ });
834
+ };
835
+ let timeoutId = null;
836
+ const stopRecording = () => {
837
+ document.removeEventListener("mouseover", mouseOverHandler, !0), document.removeEventListener("click", clickHandler, !0),
838
+ document.removeEventListener("keydown", keyboardHandler, !0), timeoutId && (clearTimeout(timeoutId),
839
+ timeoutId = null), highlightBox && (highlightBox.style.display = "none"), recordingIndicator && (recordingIndicator.style.display = "none"),
840
+ window.sentience_registry_map && window.sentience_registry_map.clear(), window.sentience_stopRecording === stopRecording && delete window.sentience_stopRecording;
841
+ }, keyboardHandler = e => {
842
+ (e.ctrlKey || e.metaKey) && e.shiftKey && "I" === e.key && (e.preventDefault(),
843
+ stopRecording());
844
+ };
845
+ return document.addEventListener("mouseover", mouseOverHandler, !0), document.addEventListener("click", clickHandler, !0),
846
+ document.addEventListener("keydown", keyboardHandler, !0), autoDisableTimeout > 0 && (timeoutId = setTimeout(() => {
847
+ stopRecording();
848
+ }, autoDisableTimeout)), window.sentience_stopRecording = stopRecording, stopRecording;
849
+ }
850
+ function showOverlay(elements, targetElementId = null) {
851
+ elements && Array.isArray(elements) && window.postMessage({
852
+ type: "SENTIENCE_SHOW_OVERLAY",
853
+ elements: elements,
854
+ targetElementId: targetElementId,
855
+ timestamp: Date.now()
856
+ }, "*");
857
+ }
858
+ function showGrid(grids, targetGridId = null) {
859
+ grids && Array.isArray(grids) && window.postMessage({
860
+ type: "SENTIENCE_SHOW_GRID_OVERLAY",
861
+ grids: grids,
862
+ targetGridId: targetGridId,
863
+ timestamp: Date.now()
864
+ }, "*");
865
+ }
866
+ function clearOverlay() {
867
+ window.postMessage({
868
+ type: "SENTIENCE_CLEAR_OVERLAY"
869
+ }, "*");
870
+ }
871
+ (async () => {
872
+ const getExtensionId = () => document.documentElement.dataset.sentienceExtensionId;
873
+ let extId = getExtensionId();
874
+ extId || await new Promise(resolve => {
875
+ const check = setInterval(() => {
876
+ extId = getExtensionId(), extId && (clearInterval(check), resolve());
877
+ }, 50);
878
+ setTimeout(() => resolve(), 5e3);
879
+ }), extId && (window.sentience_registry = [], window.sentience = {
880
+ snapshot: snapshot,
881
+ read: read,
882
+ findTextRect: findTextRect,
883
+ click: click,
884
+ startRecording: startRecording,
885
+ showOverlay: showOverlay,
886
+ showGrid: showGrid,
887
+ clearOverlay: clearOverlay
888
+ }, window.sentience_iframe_handler_setup || (window.addEventListener("message", async event => {
889
+ if ("SENTIENCE_IFRAME_SNAPSHOT_REQUEST" === event.data?.type) {
890
+ const {requestId: requestId, options: options} = event.data;
891
+ try {
892
+ const snapshotOptions = {
893
+ ...options,
894
+ collectIframes: !0,
895
+ waitForStability: (options.waitForStability, !1)
896
+ }, snapshot = await window.sentience.snapshot(snapshotOptions);
897
+ event.source && event.source.postMessage && event.source.postMessage({
898
+ type: "SENTIENCE_IFRAME_SNAPSHOT_RESPONSE",
899
+ requestId: requestId,
900
+ snapshot: snapshot,
901
+ error: null
902
+ }, "*");
903
+ } catch (error) {
904
+ event.source && event.source.postMessage && event.source.postMessage({
905
+ type: "SENTIENCE_IFRAME_SNAPSHOT_RESPONSE",
906
+ requestId: requestId,
907
+ snapshot: null,
908
+ error: error.message
909
+ }, "*");
910
+ }
911
+ }
912
+ }), window.sentience_iframe_handler_setup = !0));
913
+ })();
914
+ }();