@predicatelabs/sdk 0.99.9

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.
Files changed (302) hide show
  1. package/LICENSE +24 -0
  2. package/README.md +252 -0
  3. package/dist/actions.d.ts +185 -0
  4. package/dist/actions.d.ts.map +1 -0
  5. package/dist/actions.js +1120 -0
  6. package/dist/actions.js.map +1 -0
  7. package/dist/agent-runtime.d.ts +352 -0
  8. package/dist/agent-runtime.d.ts.map +1 -0
  9. package/dist/agent-runtime.js +1170 -0
  10. package/dist/agent-runtime.js.map +1 -0
  11. package/dist/agent.d.ts +164 -0
  12. package/dist/agent.d.ts.map +1 -0
  13. package/dist/agent.js +408 -0
  14. package/dist/agent.js.map +1 -0
  15. package/dist/asserts/expect.d.ts +159 -0
  16. package/dist/asserts/expect.d.ts.map +1 -0
  17. package/dist/asserts/expect.js +547 -0
  18. package/dist/asserts/expect.js.map +1 -0
  19. package/dist/asserts/index.d.ts +58 -0
  20. package/dist/asserts/index.d.ts.map +1 -0
  21. package/dist/asserts/index.js +70 -0
  22. package/dist/asserts/index.js.map +1 -0
  23. package/dist/asserts/query.d.ts +199 -0
  24. package/dist/asserts/query.d.ts.map +1 -0
  25. package/dist/asserts/query.js +288 -0
  26. package/dist/asserts/query.js.map +1 -0
  27. package/dist/backends/actions.d.ts +119 -0
  28. package/dist/backends/actions.d.ts.map +1 -0
  29. package/dist/backends/actions.js +291 -0
  30. package/dist/backends/actions.js.map +1 -0
  31. package/dist/backends/browser-use-adapter.d.ts +131 -0
  32. package/dist/backends/browser-use-adapter.d.ts.map +1 -0
  33. package/dist/backends/browser-use-adapter.js +219 -0
  34. package/dist/backends/browser-use-adapter.js.map +1 -0
  35. package/dist/backends/cdp-backend.d.ts +66 -0
  36. package/dist/backends/cdp-backend.d.ts.map +1 -0
  37. package/dist/backends/cdp-backend.js +273 -0
  38. package/dist/backends/cdp-backend.js.map +1 -0
  39. package/dist/backends/index.d.ts +80 -0
  40. package/dist/backends/index.d.ts.map +1 -0
  41. package/dist/backends/index.js +101 -0
  42. package/dist/backends/index.js.map +1 -0
  43. package/dist/backends/protocol.d.ts +156 -0
  44. package/dist/backends/protocol.d.ts.map +1 -0
  45. package/dist/backends/protocol.js +16 -0
  46. package/dist/backends/protocol.js.map +1 -0
  47. package/dist/backends/sentience-context.d.ts +143 -0
  48. package/dist/backends/sentience-context.d.ts.map +1 -0
  49. package/dist/backends/sentience-context.js +359 -0
  50. package/dist/backends/sentience-context.js.map +1 -0
  51. package/dist/backends/snapshot.d.ts +188 -0
  52. package/dist/backends/snapshot.d.ts.map +1 -0
  53. package/dist/backends/snapshot.js +360 -0
  54. package/dist/backends/snapshot.js.map +1 -0
  55. package/dist/browser.d.ts +154 -0
  56. package/dist/browser.d.ts.map +1 -0
  57. package/dist/browser.js +920 -0
  58. package/dist/browser.js.map +1 -0
  59. package/dist/canonicalization.d.ts +126 -0
  60. package/dist/canonicalization.d.ts.map +1 -0
  61. package/dist/canonicalization.js +161 -0
  62. package/dist/canonicalization.js.map +1 -0
  63. package/dist/captcha/strategies.d.ts +12 -0
  64. package/dist/captcha/strategies.d.ts.map +1 -0
  65. package/dist/captcha/strategies.js +43 -0
  66. package/dist/captcha/strategies.js.map +1 -0
  67. package/dist/captcha/types.d.ts +45 -0
  68. package/dist/captcha/types.d.ts.map +1 -0
  69. package/dist/captcha/types.js +12 -0
  70. package/dist/captcha/types.js.map +1 -0
  71. package/dist/cli.d.ts +5 -0
  72. package/dist/cli.d.ts.map +1 -0
  73. package/dist/cli.js +422 -0
  74. package/dist/cli.js.map +1 -0
  75. package/dist/conversational-agent.d.ts +123 -0
  76. package/dist/conversational-agent.d.ts.map +1 -0
  77. package/dist/conversational-agent.js +341 -0
  78. package/dist/conversational-agent.js.map +1 -0
  79. package/dist/cursor-policy.d.ts +41 -0
  80. package/dist/cursor-policy.d.ts.map +1 -0
  81. package/dist/cursor-policy.js +81 -0
  82. package/dist/cursor-policy.js.map +1 -0
  83. package/dist/debugger.d.ts +28 -0
  84. package/dist/debugger.d.ts.map +1 -0
  85. package/dist/debugger.js +107 -0
  86. package/dist/debugger.js.map +1 -0
  87. package/dist/expect.d.ts +16 -0
  88. package/dist/expect.d.ts.map +1 -0
  89. package/dist/expect.js +67 -0
  90. package/dist/expect.js.map +1 -0
  91. package/dist/failure-artifacts.d.ts +95 -0
  92. package/dist/failure-artifacts.d.ts.map +1 -0
  93. package/dist/failure-artifacts.js +805 -0
  94. package/dist/failure-artifacts.js.map +1 -0
  95. package/dist/generator.d.ts +16 -0
  96. package/dist/generator.d.ts.map +1 -0
  97. package/dist/generator.js +205 -0
  98. package/dist/generator.js.map +1 -0
  99. package/dist/index.d.ts +37 -0
  100. package/dist/index.d.ts.map +1 -0
  101. package/dist/index.js +160 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/inspector.d.ts +13 -0
  104. package/dist/inspector.d.ts.map +1 -0
  105. package/dist/inspector.js +153 -0
  106. package/dist/inspector.js.map +1 -0
  107. package/dist/llm-provider.d.ts +144 -0
  108. package/dist/llm-provider.d.ts.map +1 -0
  109. package/dist/llm-provider.js +460 -0
  110. package/dist/llm-provider.js.map +1 -0
  111. package/dist/ordinal.d.ts +90 -0
  112. package/dist/ordinal.d.ts.map +1 -0
  113. package/dist/ordinal.js +249 -0
  114. package/dist/ordinal.js.map +1 -0
  115. package/dist/overlay.d.ts +63 -0
  116. package/dist/overlay.d.ts.map +1 -0
  117. package/dist/overlay.js +102 -0
  118. package/dist/overlay.js.map +1 -0
  119. package/dist/protocols/browser-protocol.d.ts +79 -0
  120. package/dist/protocols/browser-protocol.d.ts.map +1 -0
  121. package/dist/protocols/browser-protocol.js +9 -0
  122. package/dist/protocols/browser-protocol.js.map +1 -0
  123. package/dist/query.d.ts +66 -0
  124. package/dist/query.d.ts.map +1 -0
  125. package/dist/query.js +482 -0
  126. package/dist/query.js.map +1 -0
  127. package/dist/read.d.ts +47 -0
  128. package/dist/read.d.ts.map +1 -0
  129. package/dist/read.js +128 -0
  130. package/dist/read.js.map +1 -0
  131. package/dist/recorder.d.ts +44 -0
  132. package/dist/recorder.d.ts.map +1 -0
  133. package/dist/recorder.js +262 -0
  134. package/dist/recorder.js.map +1 -0
  135. package/dist/runtime-agent.d.ts +72 -0
  136. package/dist/runtime-agent.d.ts.map +1 -0
  137. package/dist/runtime-agent.js +357 -0
  138. package/dist/runtime-agent.js.map +1 -0
  139. package/dist/screenshot.d.ts +17 -0
  140. package/dist/screenshot.d.ts.map +1 -0
  141. package/dist/screenshot.js +40 -0
  142. package/dist/screenshot.js.map +1 -0
  143. package/dist/snapshot-diff.d.ts +23 -0
  144. package/dist/snapshot-diff.d.ts.map +1 -0
  145. package/dist/snapshot-diff.js +119 -0
  146. package/dist/snapshot-diff.js.map +1 -0
  147. package/dist/snapshot.d.ts +47 -0
  148. package/dist/snapshot.d.ts.map +1 -0
  149. package/dist/snapshot.js +358 -0
  150. package/dist/snapshot.js.map +1 -0
  151. package/dist/textSearch.d.ts +64 -0
  152. package/dist/textSearch.d.ts.map +1 -0
  153. package/dist/textSearch.js +113 -0
  154. package/dist/textSearch.js.map +1 -0
  155. package/dist/tools/context.d.ts +18 -0
  156. package/dist/tools/context.d.ts.map +1 -0
  157. package/dist/tools/context.js +40 -0
  158. package/dist/tools/context.js.map +1 -0
  159. package/dist/tools/defaults.d.ts +5 -0
  160. package/dist/tools/defaults.d.ts.map +1 -0
  161. package/dist/tools/defaults.js +368 -0
  162. package/dist/tools/defaults.js.map +1 -0
  163. package/dist/tools/filesystem.d.ts +12 -0
  164. package/dist/tools/filesystem.d.ts.map +1 -0
  165. package/dist/tools/filesystem.js +137 -0
  166. package/dist/tools/filesystem.js.map +1 -0
  167. package/dist/tools/index.d.ts +5 -0
  168. package/dist/tools/index.d.ts.map +1 -0
  169. package/dist/tools/index.js +15 -0
  170. package/dist/tools/index.js.map +1 -0
  171. package/dist/tools/registry.d.ts +38 -0
  172. package/dist/tools/registry.d.ts.map +1 -0
  173. package/dist/tools/registry.js +100 -0
  174. package/dist/tools/registry.js.map +1 -0
  175. package/dist/tracing/cloud-sink.d.ts +189 -0
  176. package/dist/tracing/cloud-sink.d.ts.map +1 -0
  177. package/dist/tracing/cloud-sink.js +1067 -0
  178. package/dist/tracing/cloud-sink.js.map +1 -0
  179. package/dist/tracing/index-schema.d.ts +231 -0
  180. package/dist/tracing/index-schema.d.ts.map +1 -0
  181. package/dist/tracing/index-schema.js +235 -0
  182. package/dist/tracing/index-schema.js.map +1 -0
  183. package/dist/tracing/index.d.ts +12 -0
  184. package/dist/tracing/index.d.ts.map +1 -0
  185. package/dist/tracing/index.js +28 -0
  186. package/dist/tracing/index.js.map +1 -0
  187. package/dist/tracing/indexer.d.ts +20 -0
  188. package/dist/tracing/indexer.d.ts.map +1 -0
  189. package/dist/tracing/indexer.js +347 -0
  190. package/dist/tracing/indexer.js.map +1 -0
  191. package/dist/tracing/jsonl-sink.d.ts +51 -0
  192. package/dist/tracing/jsonl-sink.d.ts.map +1 -0
  193. package/dist/tracing/jsonl-sink.js +329 -0
  194. package/dist/tracing/jsonl-sink.js.map +1 -0
  195. package/dist/tracing/sink.d.ts +25 -0
  196. package/dist/tracing/sink.d.ts.map +1 -0
  197. package/dist/tracing/sink.js +15 -0
  198. package/dist/tracing/sink.js.map +1 -0
  199. package/dist/tracing/tracer-factory.d.ts +102 -0
  200. package/dist/tracing/tracer-factory.d.ts.map +1 -0
  201. package/dist/tracing/tracer-factory.js +375 -0
  202. package/dist/tracing/tracer-factory.js.map +1 -0
  203. package/dist/tracing/tracer.d.ts +140 -0
  204. package/dist/tracing/tracer.d.ts.map +1 -0
  205. package/dist/tracing/tracer.js +336 -0
  206. package/dist/tracing/tracer.js.map +1 -0
  207. package/dist/tracing/types.d.ts +203 -0
  208. package/dist/tracing/types.d.ts.map +1 -0
  209. package/dist/tracing/types.js +8 -0
  210. package/dist/tracing/types.js.map +1 -0
  211. package/dist/types.d.ts +422 -0
  212. package/dist/types.d.ts.map +1 -0
  213. package/dist/types.js +6 -0
  214. package/dist/types.js.map +1 -0
  215. package/dist/utils/action-executor.d.ts +25 -0
  216. package/dist/utils/action-executor.d.ts.map +1 -0
  217. package/dist/utils/action-executor.js +121 -0
  218. package/dist/utils/action-executor.js.map +1 -0
  219. package/dist/utils/browser-evaluator.d.ts +76 -0
  220. package/dist/utils/browser-evaluator.d.ts.map +1 -0
  221. package/dist/utils/browser-evaluator.js +130 -0
  222. package/dist/utils/browser-evaluator.js.map +1 -0
  223. package/dist/utils/browser.d.ts +30 -0
  224. package/dist/utils/browser.d.ts.map +1 -0
  225. package/dist/utils/browser.js +75 -0
  226. package/dist/utils/browser.js.map +1 -0
  227. package/dist/utils/element-filter.d.ts +76 -0
  228. package/dist/utils/element-filter.d.ts.map +1 -0
  229. package/dist/utils/element-filter.js +195 -0
  230. package/dist/utils/element-filter.js.map +1 -0
  231. package/dist/utils/grid-utils.d.ts +37 -0
  232. package/dist/utils/grid-utils.d.ts.map +1 -0
  233. package/dist/utils/grid-utils.js +283 -0
  234. package/dist/utils/grid-utils.js.map +1 -0
  235. package/dist/utils/llm-interaction-handler.d.ts +41 -0
  236. package/dist/utils/llm-interaction-handler.d.ts.map +1 -0
  237. package/dist/utils/llm-interaction-handler.js +171 -0
  238. package/dist/utils/llm-interaction-handler.js.map +1 -0
  239. package/dist/utils/llm-response-builder.d.ts +56 -0
  240. package/dist/utils/llm-response-builder.d.ts.map +1 -0
  241. package/dist/utils/llm-response-builder.js +130 -0
  242. package/dist/utils/llm-response-builder.js.map +1 -0
  243. package/dist/utils/selector-utils.d.ts +12 -0
  244. package/dist/utils/selector-utils.d.ts.map +1 -0
  245. package/dist/utils/selector-utils.js +32 -0
  246. package/dist/utils/selector-utils.js.map +1 -0
  247. package/dist/utils/snapshot-event-builder.d.ts +28 -0
  248. package/dist/utils/snapshot-event-builder.d.ts.map +1 -0
  249. package/dist/utils/snapshot-event-builder.js +88 -0
  250. package/dist/utils/snapshot-event-builder.js.map +1 -0
  251. package/dist/utils/snapshot-processor.d.ts +27 -0
  252. package/dist/utils/snapshot-processor.d.ts.map +1 -0
  253. package/dist/utils/snapshot-processor.js +47 -0
  254. package/dist/utils/snapshot-processor.js.map +1 -0
  255. package/dist/utils/trace-event-builder.d.ts +122 -0
  256. package/dist/utils/trace-event-builder.d.ts.map +1 -0
  257. package/dist/utils/trace-event-builder.js +365 -0
  258. package/dist/utils/trace-event-builder.js.map +1 -0
  259. package/dist/utils/trace-file-manager.d.ts +70 -0
  260. package/dist/utils/trace-file-manager.d.ts.map +1 -0
  261. package/dist/utils/trace-file-manager.js +194 -0
  262. package/dist/utils/trace-file-manager.js.map +1 -0
  263. package/dist/utils/zod.d.ts +5 -0
  264. package/dist/utils/zod.d.ts.map +1 -0
  265. package/dist/utils/zod.js +80 -0
  266. package/dist/utils/zod.js.map +1 -0
  267. package/dist/utils.d.ts +8 -0
  268. package/dist/utils.d.ts.map +1 -0
  269. package/dist/utils.js +13 -0
  270. package/dist/utils.js.map +1 -0
  271. package/dist/verification.d.ts +194 -0
  272. package/dist/verification.d.ts.map +1 -0
  273. package/dist/verification.js +530 -0
  274. package/dist/verification.js.map +1 -0
  275. package/dist/vision-executor.d.ts +18 -0
  276. package/dist/vision-executor.d.ts.map +1 -0
  277. package/dist/vision-executor.js +60 -0
  278. package/dist/vision-executor.js.map +1 -0
  279. package/dist/visual-agent.d.ts +120 -0
  280. package/dist/visual-agent.d.ts.map +1 -0
  281. package/dist/visual-agent.js +796 -0
  282. package/dist/visual-agent.js.map +1 -0
  283. package/dist/wait.d.ts +35 -0
  284. package/dist/wait.d.ts.map +1 -0
  285. package/dist/wait.js +76 -0
  286. package/dist/wait.js.map +1 -0
  287. package/package.json +94 -0
  288. package/spec/README.md +72 -0
  289. package/spec/SNAPSHOT_V1.md +208 -0
  290. package/spec/sdk-types.md +259 -0
  291. package/spec/snapshot.schema.json +148 -0
  292. package/src/extension/background.js +104 -0
  293. package/src/extension/content.js +162 -0
  294. package/src/extension/injected_api.js +1399 -0
  295. package/src/extension/manifest.json +36 -0
  296. package/src/extension/pkg/README.md +1340 -0
  297. package/src/extension/pkg/package.json +15 -0
  298. package/src/extension/pkg/sentience_core.d.ts +51 -0
  299. package/src/extension/pkg/sentience_core.js +371 -0
  300. package/src/extension/pkg/sentience_core_bg.wasm +0 -0
  301. package/src/extension/pkg/sentience_core_bg.wasm.d.ts +10 -0
  302. package/src/extension/release.json +116 -0
@@ -0,0 +1,1399 @@
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 CAPTCHA_TEXT_KEYWORDS = [ "verify you are human", "captcha", "human verification", "unusual traffic", "are you a robot", "security check", "prove you are human", "bot detection", "automated access" ], CAPTCHA_URL_HINTS = [ "captcha", "challenge", "verify" ], CAPTCHA_IFRAME_HINTS = {
14
+ recaptcha: [ "recaptcha", "google.com/recaptcha" ],
15
+ hcaptcha: [ "hcaptcha.com" ],
16
+ turnstile: [ "challenges.cloudflare.com", "turnstile" ],
17
+ arkose: [ "arkoselabs.com", "funcaptcha.com", "client-api.arkoselabs.com" ],
18
+ awswaf: [ "amazonaws.com/captcha", "awswaf.com" ]
19
+ }, CAPTCHA_SCRIPT_HINTS = {
20
+ recaptcha: [ "recaptcha" ],
21
+ hcaptcha: [ "hcaptcha" ],
22
+ turnstile: [ "turnstile", "challenges.cloudflare.com" ],
23
+ arkose: [ "arkoselabs", "funcaptcha" ],
24
+ awswaf: [ "captcha.awswaf", "awswaf-captcha" ]
25
+ }, CAPTCHA_CONTAINER_SELECTORS = [ {
26
+ selector: ".g-recaptcha",
27
+ provider: "recaptcha"
28
+ }, {
29
+ selector: "#g-recaptcha",
30
+ provider: "recaptcha"
31
+ }, {
32
+ selector: ".recaptcha-checkbox-border",
33
+ provider: "recaptcha"
34
+ }, {
35
+ selector: "#recaptcha-anchor-label",
36
+ provider: "recaptcha"
37
+ }, {
38
+ selector: '[class*="recaptcha" i]',
39
+ provider: "recaptcha"
40
+ }, {
41
+ selector: '[id*="recaptcha" i]',
42
+ provider: "recaptcha"
43
+ }, {
44
+ selector: "[data-sitekey]",
45
+ provider: "unknown"
46
+ }, {
47
+ selector: 'iframe[title*="recaptcha" i]',
48
+ provider: "recaptcha"
49
+ }, {
50
+ selector: ".h-captcha",
51
+ provider: "hcaptcha"
52
+ }, {
53
+ selector: "#h-captcha",
54
+ provider: "hcaptcha"
55
+ }, {
56
+ selector: 'iframe[title*="hcaptcha" i]',
57
+ provider: "hcaptcha"
58
+ }, {
59
+ selector: ".cf-turnstile",
60
+ provider: "turnstile"
61
+ }, {
62
+ selector: "[data-cf-turnstile-sitekey]",
63
+ provider: "turnstile"
64
+ }, {
65
+ selector: 'iframe[src*="challenges.cloudflare.com"]',
66
+ provider: "turnstile"
67
+ }, {
68
+ selector: "#FunCaptcha",
69
+ provider: "arkose"
70
+ }, {
71
+ selector: ".funcaptcha",
72
+ provider: "arkose"
73
+ }, {
74
+ selector: "[data-arkose-public-key]",
75
+ provider: "arkose"
76
+ }, {
77
+ selector: 'iframe[src*="arkoselabs"]',
78
+ provider: "arkose"
79
+ }, {
80
+ selector: "#captcha-container",
81
+ provider: "awswaf"
82
+ }, {
83
+ selector: "[data-awswaf-captcha]",
84
+ provider: "awswaf"
85
+ }, {
86
+ selector: 'iframe[title*="captcha" i]',
87
+ provider: "unknown"
88
+ }, {
89
+ selector: '[class*="captcha" i]',
90
+ provider: "unknown"
91
+ }, {
92
+ selector: '[id*="captcha" i]',
93
+ provider: "unknown"
94
+ } ];
95
+ function addEvidence(list, value) {
96
+ value && (list.length >= 5 || list.push(value));
97
+ }
98
+ function truncateText(text, maxLen) {
99
+ return text ? text.length <= maxLen ? text : text.slice(0, maxLen) : "";
100
+ }
101
+ function matchHints(value, hints) {
102
+ const lower = String(value || "").toLowerCase();
103
+ return !!lower && hints.some(hint => lower.includes(hint));
104
+ }
105
+ function detectCaptcha() {
106
+ function isVisibleElement(el) {
107
+ try {
108
+ if (!el) return !1;
109
+ const style = window.getComputedStyle(el);
110
+ if ("none" === style.display || "hidden" === style.visibility) return !1;
111
+ const opacity = parseFloat(style.opacity || "1");
112
+ if (!Number.isNaN(opacity) && opacity <= .01) return !1;
113
+ if (!el.getClientRects || 0 === el.getClientRects().length) return !1;
114
+ const rect = el.getBoundingClientRect();
115
+ if (rect.width < 8 || rect.height < 8) return !1;
116
+ const vw = window.innerWidth || document.documentElement.clientWidth || 0, vh = window.innerHeight || document.documentElement.clientHeight || 0;
117
+ return !(vw && vh && (rect.bottom <= 0 || rect.right <= 0 || rect.top >= vh || rect.left >= vw));
118
+ } catch (e) {
119
+ return !1;
120
+ }
121
+ }
122
+ const evidence = {
123
+ text_hits: [],
124
+ selector_hits: [],
125
+ iframe_src_hits: [],
126
+ url_hits: []
127
+ };
128
+ let hasIframeHit = !1, hasContainerHit = !1, hasScriptHit = !1, hasKeywordHit = !1, hasUrlHit = !1;
129
+ const providerSignals = {
130
+ recaptcha: 0,
131
+ hcaptcha: 0,
132
+ turnstile: 0,
133
+ arkose: 0,
134
+ awswaf: 0
135
+ };
136
+ try {
137
+ const iframes = document.querySelectorAll("iframe");
138
+ for (const iframe of iframes) {
139
+ const src = iframe.getAttribute("src") || "", title = iframe.getAttribute("title") || "";
140
+ if (src) for (const [provider, hints] of Object.entries(CAPTCHA_IFRAME_HINTS)) matchHints(src, hints) && (addEvidence(evidence.iframe_src_hits, truncateText(src, 120)),
141
+ isVisibleElement(iframe) && (hasIframeHit = !0, providerSignals[provider] += 1));
142
+ if (title && matchHints(title, [ "captcha", "recaptcha" ]) && (addEvidence(evidence.selector_hits, 'iframe[title*="captcha"]'),
143
+ isVisibleElement(iframe) && (hasContainerHit = !0)), evidence.iframe_src_hits.length >= 5) break;
144
+ }
145
+ } catch (e) {}
146
+ try {
147
+ const scripts = document.querySelectorAll("script[src]");
148
+ for (const script of scripts) {
149
+ const src = script.getAttribute("src") || "";
150
+ if (src) {
151
+ for (const [provider, hints] of Object.entries(CAPTCHA_SCRIPT_HINTS)) matchHints(src, hints) && (hasScriptHit = !0,
152
+ providerSignals[provider] += 1, addEvidence(evidence.selector_hits, `script[src*="${hints[0]}"]`));
153
+ if (evidence.selector_hits.length >= 5) break;
154
+ }
155
+ }
156
+ } catch (e) {}
157
+ for (const {selector: selector, provider: provider} of CAPTCHA_CONTAINER_SELECTORS) try {
158
+ const hit = document.querySelector(selector);
159
+ hit && (addEvidence(evidence.selector_hits, selector), isVisibleElement(hit) && (hasContainerHit = !0,
160
+ "unknown" !== provider && (providerSignals[provider] += 1)));
161
+ } catch (e) {}
162
+ const textSnippet = function() {
163
+ try {
164
+ const candidates = document.querySelectorAll("h1, h2, h3, h4, p, label, button, form, div, span");
165
+ let combined = "", count = 0;
166
+ for (const node of candidates) {
167
+ if (count >= 30 || combined.length >= 2e3) break;
168
+ if (!node || "string" != typeof node.innerText) continue;
169
+ if (!node.offsetWidth && !node.offsetHeight && !node.getClientRects().length) continue;
170
+ const text = node.innerText.replace(/\s+/g, " ").trim();
171
+ text && (combined += `${text} `, count += 1);
172
+ }
173
+ if (combined = combined.trim(), combined) return truncateText(combined, 2e3);
174
+ } catch (e) {}
175
+ try {
176
+ let bodyText = document.body?.innerText || "";
177
+ return !bodyText && document.body?.textContent && (bodyText = document.body.textContent),
178
+ truncateText(bodyText.replace(/\s+/g, " ").trim(), 2e3);
179
+ } catch (e) {
180
+ return "";
181
+ }
182
+ }();
183
+ if (textSnippet) {
184
+ const lowerText = textSnippet.toLowerCase();
185
+ for (const keyword of CAPTCHA_TEXT_KEYWORDS) lowerText.includes(keyword) && (hasKeywordHit = !0,
186
+ addEvidence(evidence.text_hits, keyword));
187
+ }
188
+ try {
189
+ const lowerUrl = (window.location?.href || "").toLowerCase();
190
+ for (const hint of CAPTCHA_URL_HINTS) lowerUrl.includes(hint) && (hasUrlHit = !0,
191
+ addEvidence(evidence.url_hits, hint));
192
+ } catch (e) {}
193
+ let confidence = 0;
194
+ hasIframeHit && (confidence += .7), hasContainerHit && (confidence += .5), hasScriptHit && (confidence += .5),
195
+ hasKeywordHit && (confidence += .3), hasUrlHit && (confidence += .2), confidence = Math.min(1, confidence),
196
+ hasIframeHit && (confidence = Math.max(confidence, .8)), !hasKeywordHit || hasIframeHit || hasContainerHit || hasScriptHit || hasUrlHit || (confidence = Math.min(confidence, .4));
197
+ const detected = confidence >= .7;
198
+ let providerHint = null;
199
+ return providerSignals.recaptcha > 0 ? providerHint = "recaptcha" : providerSignals.hcaptcha > 0 ? providerHint = "hcaptcha" : providerSignals.turnstile > 0 ? providerHint = "turnstile" : providerSignals.arkose > 0 ? providerHint = "arkose" : providerSignals.awswaf > 0 ? providerHint = "awswaf" : detected && (providerHint = "unknown"),
200
+ {
201
+ detected: detected,
202
+ provider_hint: providerHint,
203
+ confidence: confidence,
204
+ evidence: evidence
205
+ };
206
+ }
207
+ const DEFAULT_INFERENCE_CONFIG = {
208
+ allowedTags: [ "label", "span", "div" ],
209
+ allowedRoles: [],
210
+ allowedClassPatterns: [],
211
+ maxParentDepth: 2,
212
+ maxSiblingDistance: 1,
213
+ requireSameContainer: !0,
214
+ containerTags: [ "form", "fieldset", "div" ],
215
+ methods: {
216
+ explicitLabel: !0,
217
+ ariaLabelledby: !0,
218
+ parentTraversal: !0,
219
+ siblingProximity: !0
220
+ }
221
+ };
222
+ function isInferenceSource(el, config) {
223
+ if (!el || !el.tagName) return !1;
224
+ const tag = el.tagName.toLowerCase(), role = el.getAttribute ? el.getAttribute("role") : "", className = ((el.className || "") + "").toLowerCase();
225
+ if (config.allowedTags.includes(tag)) return !0;
226
+ if (config.allowedRoles.length > 0 && role && config.allowedRoles.includes(role)) return !0;
227
+ if (config.allowedClassPatterns.length > 0) for (const pattern of config.allowedClassPatterns) if (className.includes(pattern.toLowerCase())) return !0;
228
+ return !1;
229
+ }
230
+ function isInSameValidContainer(element, candidate, limits) {
231
+ if (!element || !candidate) return !1;
232
+ if (limits.requireSameContainer) {
233
+ const commonParent = function(el1, el2) {
234
+ if (!el1 || !el2) return null;
235
+ const doc = "undefined" != typeof global && global.document || "undefined" != typeof window && window.document || "undefined" != typeof document && document || null, parents1 = [];
236
+ let current = el1;
237
+ for (;current && (parents1.push(current), current.parentElement) && (!doc || current !== doc.body && current !== doc.documentElement); ) current = current.parentElement;
238
+ for (current = el2; current; ) {
239
+ if (-1 !== parents1.indexOf(current)) return current;
240
+ if (!current.parentElement) break;
241
+ if (doc && (current === doc.body || current === doc.documentElement)) break;
242
+ current = current.parentElement;
243
+ }
244
+ return null;
245
+ }(element, candidate);
246
+ if (!commonParent) return !1;
247
+ if (!function(el, validTags) {
248
+ if (!el || !el.tagName) return !1;
249
+ const tag = el.tagName.toLowerCase();
250
+ let className = "";
251
+ try {
252
+ className = (el.className || "") + "";
253
+ } catch (e) {
254
+ className = "";
255
+ }
256
+ return validTags.includes(tag) || className.toLowerCase().includes("form") || className.toLowerCase().includes("field");
257
+ }(commonParent, limits.containerTags)) return !1;
258
+ }
259
+ return !0;
260
+ }
261
+ function getInferredLabel(el, options = {}) {
262
+ if (!el) return null;
263
+ const {enableInference: enableInference = !0, inferenceConfig: inferenceConfig = {}} = options;
264
+ if (!enableInference) return null;
265
+ 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;
266
+ let innerTextValue = "";
267
+ try {
268
+ innerTextValue = el.innerText || "";
269
+ } catch (e) {
270
+ innerTextValue = "";
271
+ }
272
+ const hasInnerText = "INPUT" !== el.tagName && "IMG" !== el.tagName && innerTextValue && innerTextValue.trim();
273
+ if (hasAriaLabel || hasInputValue || hasImgAlt || hasInnerText) return null;
274
+ const config = function(userConfig = {}) {
275
+ return {
276
+ ...DEFAULT_INFERENCE_CONFIG,
277
+ ...userConfig,
278
+ methods: {
279
+ ...DEFAULT_INFERENCE_CONFIG.methods,
280
+ ...userConfig.methods || {}
281
+ }
282
+ };
283
+ }(inferenceConfig);
284
+ if (config.methods.explicitLabel && el.labels && el.labels.length > 0) {
285
+ const label = el.labels[0];
286
+ if (isInferenceSource(label, config)) {
287
+ const text = (label.innerText || "").trim();
288
+ if (text) return {
289
+ text: text,
290
+ source: "explicit_label"
291
+ };
292
+ }
293
+ }
294
+ if (config.methods.ariaLabelledby && el.hasAttribute && el.hasAttribute("aria-labelledby")) {
295
+ const labelIdsAttr = el.getAttribute("aria-labelledby");
296
+ if (labelIdsAttr) {
297
+ 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)();
298
+ if (doc && doc.getElementById) for (const labelId of labelIds) {
299
+ if (!labelId.trim()) continue;
300
+ let labelEl = null;
301
+ try {
302
+ labelEl = doc.getElementById(labelId);
303
+ } catch (e) {
304
+ continue;
305
+ }
306
+ if (labelEl) {
307
+ let text = "";
308
+ try {
309
+ if (text = (labelEl.innerText || "").trim(), !text && labelEl.textContent && (text = labelEl.textContent.trim()),
310
+ !text && labelEl.getAttribute) {
311
+ const ariaLabel = labelEl.getAttribute("aria-label");
312
+ ariaLabel && (text = ariaLabel.trim());
313
+ }
314
+ } catch (e) {
315
+ continue;
316
+ }
317
+ text && labelTexts.push(text);
318
+ }
319
+ } else ;
320
+ if (labelTexts.length > 0) return {
321
+ text: labelTexts.join(" "),
322
+ source: "aria_labelledby"
323
+ };
324
+ }
325
+ }
326
+ if (config.methods.parentTraversal) {
327
+ let parent = el.parentElement, depth = 0;
328
+ for (;parent && depth < config.maxParentDepth; ) {
329
+ if (isInferenceSource(parent, config)) {
330
+ const text = (parent.innerText || "").trim();
331
+ if (text) return {
332
+ text: text,
333
+ source: "parent_label"
334
+ };
335
+ }
336
+ parent = parent.parentElement, depth++;
337
+ }
338
+ }
339
+ if (config.methods.siblingProximity) {
340
+ const prev = el.previousElementSibling;
341
+ if (prev && isInferenceSource(prev, config) && isInSameValidContainer(el, prev, {
342
+ requireSameContainer: config.requireSameContainer,
343
+ containerTags: config.containerTags
344
+ })) {
345
+ const text = (prev.innerText || "").trim();
346
+ if (text) return {
347
+ text: text,
348
+ source: "sibling_label"
349
+ };
350
+ }
351
+ }
352
+ return null;
353
+ }
354
+ function normalizeNearbyText(text) {
355
+ return text ? text.replace(/\s+/g, " ").trim() : "";
356
+ }
357
+ function isInteractableElement(el) {
358
+ if (!el || !el.tagName) return !1;
359
+ 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");
360
+ if ([ "button", "input", "textarea", "select", "option", "details", "summary", "a" ].includes(tag)) return !("a" === tag && !hasHref);
361
+ if (role && [ "button", "link", "tab", "menuitem", "checkbox", "radio", "switch", "slider", "combobox", "textbox", "searchbox", "spinbutton" ].includes(role.toLowerCase())) return !0;
362
+ if (hasTabIndex) return !0;
363
+ if (el.onclick || el.onkeydown || el.onkeypress || el.onkeyup) return !0;
364
+ if (el.getAttribute) {
365
+ if (el.getAttribute("onclick") || el.getAttribute("onkeydown") || el.getAttribute("onkeypress") || el.getAttribute("onkeyup")) return !0;
366
+ }
367
+ return !1;
368
+ }
369
+ function getText(el) {
370
+ if (el.getAttribute("aria-label")) return el.getAttribute("aria-label");
371
+ if ("INPUT" === el.tagName) {
372
+ const t = el.getAttribute && el.getAttribute("type") || el.type || "";
373
+ return "password" === String(t).toLowerCase() ? el.placeholder || "" : el.value || el.placeholder || "";
374
+ }
375
+ return "IMG" === el.tagName ? el.alt || "" : (el.innerText || "").replace(/\s+/g, " ").trim().substring(0, 100);
376
+ }
377
+ function getClassName(el) {
378
+ if (!el || !el.className) return "";
379
+ if ("string" == typeof el.className) return el.className;
380
+ if ("object" == typeof el.className) {
381
+ if ("baseVal" in el.className && "string" == typeof el.className.baseVal) return el.className.baseVal;
382
+ if ("animVal" in el.className && "string" == typeof el.className.animVal) return el.className.animVal;
383
+ try {
384
+ return String(el.className);
385
+ } catch (e) {
386
+ return "";
387
+ }
388
+ }
389
+ return "";
390
+ }
391
+ function toSafeString(value) {
392
+ if (null == value) return null;
393
+ if ("string" == typeof value) return value;
394
+ if ("object" == typeof value) {
395
+ if ("baseVal" in value && "string" == typeof value.baseVal) return value.baseVal;
396
+ if ("animVal" in value && "string" == typeof value.animVal) return value.animVal;
397
+ try {
398
+ return String(value);
399
+ } catch (e) {
400
+ return null;
401
+ }
402
+ }
403
+ try {
404
+ return String(value);
405
+ } catch (e) {
406
+ return null;
407
+ }
408
+ }
409
+ function getSVGColor(el) {
410
+ if (!el || "SVG" !== el.tagName) return null;
411
+ const style = window.getComputedStyle(el), fill = style.fill;
412
+ if (fill && "none" !== fill && "transparent" !== fill && "rgba(0, 0, 0, 0)" !== fill) {
413
+ const rgbaMatch = fill.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);
414
+ if (rgbaMatch) {
415
+ if ((rgbaMatch[4] ? parseFloat(rgbaMatch[4]) : 1) >= .9) return `rgb(${rgbaMatch[1]}, ${rgbaMatch[2]}, ${rgbaMatch[3]})`;
416
+ } else if (fill.startsWith("rgb(")) return fill;
417
+ }
418
+ const stroke = style.stroke;
419
+ if (stroke && "none" !== stroke && "transparent" !== stroke && "rgba(0, 0, 0, 0)" !== stroke) {
420
+ const rgbaMatch = stroke.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);
421
+ if (rgbaMatch) {
422
+ if ((rgbaMatch[4] ? parseFloat(rgbaMatch[4]) : 1) >= .9) return `rgb(${rgbaMatch[1]}, ${rgbaMatch[2]}, ${rgbaMatch[3]})`;
423
+ } else if (stroke.startsWith("rgb(")) return stroke;
424
+ }
425
+ return null;
426
+ }
427
+ function getRawHTML(root) {
428
+ const sourceRoot = root || document.body, clone = sourceRoot.cloneNode(!0), unwantedTags = [ "script", "style", "noscript", "iframe", "svg" ], unwantedTagSet = new Set(unwantedTags);
429
+ function getChildIndex(node) {
430
+ let index = 0, sibling = node;
431
+ for (;sibling = sibling.previousElementSibling; ) index++;
432
+ return index;
433
+ }
434
+ function getElementPath(node, root) {
435
+ const path = [];
436
+ let current = node;
437
+ for (;current && current !== root && current.parentElement; ) path.unshift(getChildIndex(current)),
438
+ current = current.parentElement;
439
+ return path;
440
+ }
441
+ const invisiblePaths = [], walker = document.createTreeWalker(sourceRoot, NodeFilter.SHOW_ELEMENT, null, !1);
442
+ let node;
443
+ for (;node = walker.nextNode(); ) {
444
+ const tag = node.tagName.toLowerCase();
445
+ if ("head" === tag || "title" === tag) continue;
446
+ if (unwantedTagSet.has(tag)) continue;
447
+ const style = window.getComputedStyle(node);
448
+ "none" !== style.display && "hidden" !== style.visibility || invisiblePaths.push(getElementPath(node, sourceRoot));
449
+ }
450
+ invisiblePaths.sort((a, b) => {
451
+ if (a.length !== b.length) return b.length - a.length;
452
+ for (let i = a.length - 1; i >= 0; i--) if (a[i] !== b[i]) return b[i] - a[i];
453
+ return 0;
454
+ }), invisiblePaths.forEach(path => {
455
+ const el = function(root, path) {
456
+ let current = root;
457
+ for (const index of path) {
458
+ if (!current || !current.children || index >= current.children.length) return null;
459
+ current = current.children[index];
460
+ }
461
+ return current;
462
+ }(clone, path);
463
+ el && el.parentNode && el.parentNode.removeChild(el);
464
+ }), unwantedTags.forEach(tag => {
465
+ clone.querySelectorAll(tag).forEach(el => {
466
+ el.parentNode && el.parentNode.removeChild(el);
467
+ });
468
+ });
469
+ clone.querySelectorAll("a[href]").forEach(link => {
470
+ const href = link.getAttribute("href");
471
+ if (href && !href.startsWith("http://") && !href.startsWith("https://") && !href.startsWith("#")) try {
472
+ link.setAttribute("href", new URL(href, document.baseURI).href);
473
+ } catch (e) {}
474
+ });
475
+ return clone.querySelectorAll("img[src]").forEach(img => {
476
+ const src = img.getAttribute("src");
477
+ if (src && !src.startsWith("http://") && !src.startsWith("https://") && !src.startsWith("data:")) try {
478
+ img.setAttribute("src", new URL(src, document.baseURI).href);
479
+ } catch (e) {}
480
+ }), clone.innerHTML;
481
+ }
482
+ function cleanElement(obj) {
483
+ if (Array.isArray(obj)) return obj.map(cleanElement);
484
+ if (null !== obj && "object" == typeof obj) {
485
+ const cleaned = {};
486
+ for (const [key, value] of Object.entries(obj)) if (null != value) if ("object" == typeof value) {
487
+ const deepClean = cleanElement(value);
488
+ Object.keys(deepClean).length > 0 && (cleaned[key] = deepClean);
489
+ } else cleaned[key] = value;
490
+ return cleaned;
491
+ }
492
+ return obj;
493
+ }
494
+ async function snapshot(options = {}) {
495
+ try {
496
+ !1 !== options.waitForStability && await async function(options = {}) {
497
+ const {minNodeCount: minNodeCount = 500, quietPeriod: quietPeriod = 200, maxWait: maxWait = 5e3} = options, startTime = Date.now();
498
+ try {
499
+ window.__sentience_lastMutationTs = performance.now();
500
+ } catch (e) {}
501
+ return new Promise(resolve => {
502
+ if (document.querySelectorAll("*").length >= minNodeCount) {
503
+ let lastChange = Date.now();
504
+ const observer = new MutationObserver(() => {
505
+ lastChange = Date.now();
506
+ try {
507
+ window.__sentience_lastMutationTs = performance.now();
508
+ } catch (e) {}
509
+ });
510
+ observer.observe(document.body, {
511
+ childList: !0,
512
+ subtree: !0,
513
+ attributes: !1
514
+ });
515
+ const checkStable = () => {
516
+ const timeSinceLastChange = Date.now() - lastChange, totalWait = Date.now() - startTime;
517
+ timeSinceLastChange >= quietPeriod || totalWait >= maxWait ? (observer.disconnect(),
518
+ resolve()) : setTimeout(checkStable, 50);
519
+ };
520
+ checkStable();
521
+ } else {
522
+ const observer = new MutationObserver(() => {
523
+ const currentCount = document.querySelectorAll("*").length, totalWait = Date.now() - startTime;
524
+ try {
525
+ window.__sentience_lastMutationTs = performance.now();
526
+ } catch (e) {}
527
+ if (currentCount >= minNodeCount) {
528
+ observer.disconnect();
529
+ let lastChange = Date.now();
530
+ const quietObserver = new MutationObserver(() => {
531
+ lastChange = Date.now();
532
+ try {
533
+ window.__sentience_lastMutationTs = performance.now();
534
+ } catch (e) {}
535
+ });
536
+ quietObserver.observe(document.body, {
537
+ childList: !0,
538
+ subtree: !0,
539
+ attributes: !1
540
+ });
541
+ const checkQuiet = () => {
542
+ const timeSinceLastChange = Date.now() - lastChange, totalWait = Date.now() - startTime;
543
+ timeSinceLastChange >= quietPeriod || totalWait >= maxWait ? (quietObserver.disconnect(),
544
+ resolve()) : setTimeout(checkQuiet, 50);
545
+ };
546
+ checkQuiet();
547
+ } else totalWait >= maxWait && (observer.disconnect(), resolve());
548
+ });
549
+ observer.observe(document.body, {
550
+ childList: !0,
551
+ subtree: !0,
552
+ attributes: !1
553
+ }), setTimeout(() => {
554
+ observer.disconnect(), resolve();
555
+ }, maxWait);
556
+ }
557
+ });
558
+ }(options.waitForStability || {});
559
+ const rawData = [];
560
+ window.sentience_registry = [];
561
+ const nodes = getAllElements(), parseAriaInt = (el, attr) => {
562
+ try {
563
+ const raw = el.getAttribute ? el.getAttribute(attr) : null;
564
+ if (!raw) return null;
565
+ const n = parseInt(String(raw), 10);
566
+ return Number.isFinite(n) ? n : null;
567
+ } catch (e) {
568
+ return null;
569
+ }
570
+ }, safeKeyPart = (s, maxLen = 48) => String(s || "").replace(/\s+/g, " ").trim().slice(0, maxLen) || null, buildContainerKey = container => {
571
+ try {
572
+ const tag = container.tagName ? container.tagName.toLowerCase() : "div", role = container.getAttribute ? container.getAttribute("role") : null, id = container.id ? `#${safeKeyPart(container.id, 32)}` : null, cls = (() => {
573
+ if (!container.className) return null;
574
+ const parts = String(container.className).split(/\s+/).filter(Boolean).slice(0, 2);
575
+ return parts.length ? `.${safeKeyPart(parts.join("."), 48)}` : null;
576
+ })(), ariaLabel = container.getAttribute && container.getAttribute("aria-label") ? `aria=${safeKeyPart(container.getAttribute("aria-label"), 40)}` : null, parts = [ safeKeyPart(tag, 16), role ? `role=${safeKeyPart(role, 24)}` : null, id, cls, ariaLabel ].filter(Boolean);
577
+ return parts.length ? parts.join("|") : null;
578
+ } catch (e) {
579
+ return null;
580
+ }
581
+ }, computeContainerInfo = el => {
582
+ try {
583
+ if (!("A" === el.tagName && (el.getAttribute("href") || el.href) || "BUTTON" === el.tagName || el.getAttribute && ("link" === el.getAttribute("role") || "button" === el.getAttribute("role")) || isInteractableElement(el))) return null;
584
+ const candidates = [];
585
+ let node = el;
586
+ for (let depth = 0; depth < 6 && node && node.parentElement; depth++) {
587
+ const p = node.parentElement, tag = p.tagName ? p.tagName.toLowerCase() : "", role = p.getAttribute ? p.getAttribute("role") : null, isExplicit = "ul" === tag || "ol" === tag || "table" === tag || "tbody" === tag || "list" === role || "feed" === role || "grid" === role || "table" === role, childCount = p.children ? p.children.length : 0;
588
+ (isExplicit || childCount >= 6) && candidates.push({
589
+ p: p,
590
+ depth: depth,
591
+ tag: tag,
592
+ role: role,
593
+ childCount: childCount
594
+ }), node = p;
595
+ }
596
+ if (!candidates.length) return null;
597
+ const pickItemNodes = (container, tag, role) => {
598
+ if ("ul" === tag || "ol" === tag || "list" === role) {
599
+ const lis = Array.from(container.children || []).filter(c => c && "LI" === c.tagName), filtered = lis.filter(li => {
600
+ if (!li || !li.querySelector) return !1;
601
+ const a = li.querySelector("a[href]");
602
+ if (!a) return !1;
603
+ return (a.textContent || "").replace(/\s+/g, " ").trim().length >= 8;
604
+ });
605
+ return filtered.length ? filtered : lis;
606
+ }
607
+ if ("table" === tag || "tbody" === tag || "table" === role || "grid" === role) {
608
+ const rows = Array.from(container.children || []).filter(c => c && "TR" === c.tagName), allRows = rows.length ? rows : Array.from(container.querySelectorAll("tr")), filtered = allRows.filter(tr => {
609
+ if (!tr || !tr.querySelector) return !1;
610
+ const links = Array.from(tr.querySelectorAll("a[href]"));
611
+ let bestLen = 0;
612
+ for (const a of links) {
613
+ const t = (a.textContent || "").replace(/\s+/g, " ").trim();
614
+ t.length > bestLen && (bestLen = t.length);
615
+ }
616
+ return bestLen >= 12;
617
+ });
618
+ return filtered.length ? filtered : allRows;
619
+ }
620
+ const kids = Array.from(container.children || []), items = kids.filter(c => {
621
+ if (!c || !c.querySelector) return !1;
622
+ if (!c.querySelector('a[href],button,[role="link"],[role="button"]')) return !1;
623
+ return (c.textContent || "").replace(/\s+/g, " ").trim().length >= 8;
624
+ });
625
+ return items.length ? items : kids;
626
+ };
627
+ let best = null;
628
+ for (const c of candidates) {
629
+ const items = pickItemNodes(c.p, c.tag, c.role), size = items.length || 0;
630
+ if (size < 4) continue;
631
+ let itemIndex = null;
632
+ for (let i = 0; i < items.length; i++) {
633
+ const it = items[i];
634
+ if (it && (it === el || it.contains(el))) {
635
+ itemIndex = i;
636
+ break;
637
+ }
638
+ }
639
+ if (null === itemIndex) continue;
640
+ const score = size + ("ul" === c.tag || "ol" === c.tag || "table" === c.tag || c.role ? 2 : 0) - .4 * c.depth;
641
+ (!best || score > best.score) && (best = {
642
+ key: buildContainerKey(c.p),
643
+ index: itemIndex,
644
+ size: size,
645
+ score: score
646
+ });
647
+ }
648
+ return best && best.key ? {
649
+ container_key: best.key,
650
+ index_in_container: best.index,
651
+ container_item_count: best.size
652
+ } : null;
653
+ } catch (e) {
654
+ return null;
655
+ }
656
+ };
657
+ nodes.forEach((el, idx) => {
658
+ if (!el.getBoundingClientRect) return;
659
+ const rect = el.getBoundingClientRect();
660
+ if (rect.width < 5 || rect.height < 5) return;
661
+ const tagName = el.tagName.toLowerCase();
662
+ if ("span" === tagName) {
663
+ if (el.closest("a")) return;
664
+ const childLink = el.querySelector("a[href]");
665
+ if (childLink && childLink.href) return;
666
+ options.debug && el.className && el.className.includes("titleline");
667
+ }
668
+ window.sentience_registry[idx] = el;
669
+ const inputType = "input" === tagName ? toSafeString(el.getAttribute && el.getAttribute("type") || el.type || null) : null, isPasswordInput = inputType && "password" === inputType.toLowerCase(), semanticText = function(el, options = {}) {
670
+ if (!el) return {
671
+ text: "",
672
+ source: null
673
+ };
674
+ const explicitAriaLabel = el.getAttribute ? el.getAttribute("aria-label") : null;
675
+ if (explicitAriaLabel && explicitAriaLabel.trim()) return {
676
+ text: explicitAriaLabel.trim(),
677
+ source: "explicit_aria_label"
678
+ };
679
+ if ("INPUT" === el.tagName) {
680
+ const t = el.getAttribute && el.getAttribute("type") || el.type || "", isPassword = "password" === String(t).toLowerCase(), value = (isPassword ? el.placeholder || "" : el.value || el.placeholder || "").trim();
681
+ if (value) return {
682
+ text: value,
683
+ source: isPassword ? "input_placeholder" : "input_value"
684
+ };
685
+ }
686
+ if ("IMG" === el.tagName) {
687
+ const alt = (el.alt || "").trim();
688
+ if (alt) return {
689
+ text: alt,
690
+ source: "img_alt"
691
+ };
692
+ }
693
+ const innerText = (el.innerText || "").trim();
694
+ if (innerText) return {
695
+ text: innerText.substring(0, 100),
696
+ source: "inner_text"
697
+ };
698
+ const inferred = getInferredLabel(el, {
699
+ enableInference: !1 !== options.enableInference,
700
+ inferenceConfig: options.inferenceConfig
701
+ });
702
+ return inferred || {
703
+ text: "",
704
+ source: null
705
+ };
706
+ }(el, {
707
+ enableInference: !1 !== options.enableInference,
708
+ inferenceConfig: options.inferenceConfig
709
+ }), textVal = semanticText.text || getText(el), inferredRole = function(el, options = {}) {
710
+ const {enableInference: enableInference = !0} = options;
711
+ if (!enableInference) return null;
712
+ if (!isInteractableElement(el)) return null;
713
+ const hasAriaLabel = el.getAttribute ? el.getAttribute("aria-label") : null, hasExplicitRole = el.getAttribute ? el.getAttribute("role") : null;
714
+ if (hasAriaLabel || hasExplicitRole) return null;
715
+ const tag = el.tagName.toLowerCase();
716
+ 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;
717
+ }(el, {
718
+ enableInference: !1 !== options.enableInference,
719
+ inferenceConfig: options.inferenceConfig
720
+ }), inView = function(rect) {
721
+ return rect.top < window.innerHeight && rect.bottom > 0 && rect.left < window.innerWidth && rect.right > 0;
722
+ }(rect), style = window.getComputedStyle(el), occluded = !!inView && function(el, rect, style) {
723
+ const zIndex = parseInt(style.zIndex, 10);
724
+ if ("static" === style.position && (isNaN(zIndex) || zIndex <= 10)) return !1;
725
+ const cx = rect.x + rect.width / 2, cy = rect.y + rect.height / 2;
726
+ if (cx < 0 || cx > window.innerWidth || cy < 0 || cy > window.innerHeight) return !1;
727
+ const topEl = document.elementFromPoint(cx, cy);
728
+ return !!topEl && !(el === topEl || el.contains(topEl) || topEl.contains(el));
729
+ }(el, rect, style), effectiveBgColor = function(el) {
730
+ if (!el) return null;
731
+ if ("SVG" === el.tagName) {
732
+ const svgColor = getSVGColor(el);
733
+ if (svgColor) return svgColor;
734
+ }
735
+ let current = el, depth = 0;
736
+ for (;current && depth < 10; ) {
737
+ const style = window.getComputedStyle(current);
738
+ if ("SVG" === current.tagName) {
739
+ const svgColor = getSVGColor(current);
740
+ if (svgColor) return svgColor;
741
+ }
742
+ const bgColor = style.backgroundColor;
743
+ if (bgColor && "transparent" !== bgColor && "rgba(0, 0, 0, 0)" !== bgColor) {
744
+ const rgbaMatch = bgColor.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);
745
+ if (!rgbaMatch) return bgColor.startsWith("rgb("), bgColor;
746
+ if ((rgbaMatch[4] ? parseFloat(rgbaMatch[4]) : 1) >= .9) return `rgb(${rgbaMatch[1]}, ${rgbaMatch[2]}, ${rgbaMatch[3]})`;
747
+ }
748
+ current = current.parentElement, depth++;
749
+ }
750
+ return null;
751
+ }(el);
752
+ let safeValue = null, valueRedacted = null;
753
+ try {
754
+ if (void 0 !== el.value || el.getAttribute && null !== el.getAttribute("value")) if (isPasswordInput) safeValue = null,
755
+ valueRedacted = "true"; else {
756
+ const rawValue = void 0 !== el.value ? String(el.value) : String(el.getAttribute("value"));
757
+ safeValue = rawValue.length > 200 ? rawValue.substring(0, 200) : rawValue, valueRedacted = "false";
758
+ }
759
+ } catch (e) {}
760
+ const accessibleName = toSafeString(function(el) {
761
+ if (!el || !el.getAttribute) return "";
762
+ const ariaLabel = el.getAttribute("aria-label");
763
+ if (ariaLabel && ariaLabel.trim()) return ariaLabel.trim().substring(0, 200);
764
+ const labelledBy = el.getAttribute("aria-labelledby");
765
+ if (labelledBy && labelledBy.trim()) {
766
+ const ids = labelledBy.split(/\s+/).filter(id => id.trim()), texts = [];
767
+ for (const id of ids) try {
768
+ const ref = document.getElementById(id);
769
+ if (!ref) continue;
770
+ const txt = (ref.innerText || ref.textContent || ref.getAttribute?.("aria-label") || "").toString().trim();
771
+ txt && texts.push(txt);
772
+ } catch (e) {}
773
+ if (texts.length > 0) return texts.join(" ").substring(0, 200);
774
+ }
775
+ try {
776
+ if (el.labels && el.labels.length > 0) {
777
+ const t = (el.labels[0].innerText || el.labels[0].textContent || "").toString().trim();
778
+ if (t) return t.substring(0, 200);
779
+ }
780
+ } catch (e) {}
781
+ try {
782
+ const parentLabel = el.closest && el.closest("label");
783
+ if (parentLabel) {
784
+ const t = (parentLabel.innerText || parentLabel.textContent || "").toString().trim();
785
+ if (t) return t.substring(0, 200);
786
+ }
787
+ } catch (e) {}
788
+ const tag = (el.tagName || "").toUpperCase();
789
+ if ("INPUT" === tag || "TEXTAREA" === tag) {
790
+ const ph = (el.getAttribute("placeholder") || "").toString().trim();
791
+ if (ph) return ph.substring(0, 200);
792
+ }
793
+ const title = el.getAttribute("title");
794
+ return title && title.trim() ? title.trim().substring(0, 200) : "";
795
+ }(el) || null), nearbyText = isInteractableElement(el) ? function(el, options = {}) {
796
+ if (!el) return null;
797
+ const maxLen = "number" == typeof options.maxLen ? options.maxLen : 80, ownText = normalizeNearbyText(el.innerText || ""), candidates = [], collect = node => {
798
+ if (!node) return;
799
+ let text = "";
800
+ try {
801
+ text = normalizeNearbyText(node.innerText || node.textContent || "");
802
+ } catch (e) {
803
+ text = "";
804
+ }
805
+ text && text !== ownText && candidates.push(text);
806
+ };
807
+ if (collect(el.previousElementSibling), collect(el.nextElementSibling), 0 === candidates.length && el.parentElement) {
808
+ let parentText = "";
809
+ try {
810
+ parentText = normalizeNearbyText(el.parentElement.innerText || "");
811
+ } catch (e) {
812
+ parentText = "";
813
+ }
814
+ parentText && parentText !== ownText && parentText.length <= 120 && candidates.push(parentText);
815
+ }
816
+ if (0 === candidates.length) return null;
817
+ let text = candidates[0];
818
+ return text.length > maxLen && (text = text.slice(0, maxLen).trim()), text || null;
819
+ }(el, {
820
+ maxLen: 80
821
+ }) : null, containerInfo = computeContainerInfo(el);
822
+ rawData.push({
823
+ id: idx,
824
+ tag: tagName,
825
+ rect: {
826
+ x: rect.x,
827
+ y: rect.y,
828
+ width: rect.width,
829
+ height: rect.height
830
+ },
831
+ styles: {
832
+ display: toSafeString(style.display),
833
+ visibility: toSafeString(style.visibility),
834
+ opacity: toSafeString(style.opacity),
835
+ z_index: toSafeString(style.zIndex || "auto"),
836
+ position: toSafeString(style.position),
837
+ bg_color: toSafeString(effectiveBgColor || style.backgroundColor),
838
+ color: toSafeString(style.color),
839
+ cursor: toSafeString(style.cursor),
840
+ font_weight: toSafeString(style.fontWeight),
841
+ font_size: toSafeString(style.fontSize)
842
+ },
843
+ attributes: {
844
+ role: toSafeString(el.getAttribute("role")),
845
+ type_: toSafeString(el.getAttribute("type")),
846
+ input_type: inputType,
847
+ aria_label: "explicit_aria_label" === semanticText?.source ? semanticText.text : toSafeString(el.getAttribute("aria-label")),
848
+ name: accessibleName,
849
+ inferred_label: semanticText?.source && ![ "explicit_aria_label", "input_value", "img_alt", "inner_text" ].includes(semanticText.source) ? toSafeString(semanticText.text) : null,
850
+ label_source: semanticText?.source || null,
851
+ inferred_role: inferredRole ? toSafeString(inferredRole) : null,
852
+ nearby_text: toSafeString(nearbyText),
853
+ href: toSafeString(el.href || el.getAttribute("href") || el.closest && el.closest("a")?.href || null),
854
+ class: toSafeString(getClassName(el)),
855
+ value: null !== safeValue ? toSafeString(safeValue) : null,
856
+ value_redacted: valueRedacted,
857
+ checked: void 0 !== el.checked ? String(el.checked) : null,
858
+ disabled: void 0 !== el.disabled ? String(el.disabled) : null,
859
+ aria_checked: toSafeString(el.getAttribute("aria-checked")),
860
+ aria_disabled: toSafeString(el.getAttribute("aria-disabled")),
861
+ aria_expanded: toSafeString(el.getAttribute("aria-expanded")),
862
+ aria_posinset: parseAriaInt(el, "aria-posinset"),
863
+ aria_setsize: parseAriaInt(el, "aria-setsize"),
864
+ aria_rowindex: parseAriaInt(el, "aria-rowindex"),
865
+ aria_colindex: parseAriaInt(el, "aria-colindex")
866
+ },
867
+ container_key: containerInfo ? containerInfo.container_key : null,
868
+ index_in_container: containerInfo ? containerInfo.index_in_container : null,
869
+ container_item_count: containerInfo ? containerInfo.container_item_count : null,
870
+ text: toSafeString(textVal),
871
+ in_viewport: inView,
872
+ is_occluded: occluded,
873
+ scroll_y: window.scrollY
874
+ });
875
+ });
876
+ const allRawElements = [ ...rawData ];
877
+ let totalIframeElements = 0;
878
+ if (!1 !== options.collectIframes) try {
879
+ const iframeSnapshots = await async function(options = {}) {
880
+ const iframeData = new Map, iframes = Array.from(document.querySelectorAll("iframe"));
881
+ if (0 === iframes.length) return iframeData;
882
+ const iframePromises = iframes.map((iframe, idx) => {
883
+ const src = iframe.src || "";
884
+ return src.includes("doubleclick") || src.includes("googleadservices") || src.includes("ads system") ? Promise.resolve(null) : new Promise(resolve => {
885
+ const requestId = `iframe-${idx}-${Date.now()}`, timeout = setTimeout(() => {
886
+ resolve(null);
887
+ }, 5e3), listener = event => {
888
+ "SENTIENCE_IFRAME_SNAPSHOT_RESPONSE" === event.data?.type && event.data, "SENTIENCE_IFRAME_SNAPSHOT_RESPONSE" === event.data?.type && event.data?.requestId === requestId && (clearTimeout(timeout),
889
+ window.removeEventListener("message", listener), event.data.error ? resolve(null) : (event.data.snapshot,
890
+ resolve({
891
+ iframe: iframe,
892
+ data: event.data.snapshot,
893
+ error: null
894
+ })));
895
+ };
896
+ window.addEventListener("message", listener);
897
+ try {
898
+ iframe.contentWindow ? iframe.contentWindow.postMessage({
899
+ type: "SENTIENCE_IFRAME_SNAPSHOT_REQUEST",
900
+ requestId: requestId,
901
+ options: {
902
+ ...options,
903
+ collectIframes: !0
904
+ }
905
+ }, "*") : (clearTimeout(timeout), window.removeEventListener("message", listener),
906
+ resolve(null));
907
+ } catch (error) {
908
+ clearTimeout(timeout), window.removeEventListener("message", listener), resolve(null);
909
+ }
910
+ });
911
+ });
912
+ return (await Promise.all(iframePromises)).forEach((result, idx) => {
913
+ result && result.data && !result.error ? iframeData.set(iframes[idx], result.data) : result && result.error;
914
+ }), iframeData;
915
+ }(options);
916
+ iframeSnapshots.size > 0 && iframeSnapshots.forEach((iframeSnapshot, iframeEl) => {
917
+ if (iframeSnapshot && iframeSnapshot.raw_elements) {
918
+ iframeSnapshot.raw_elements.length;
919
+ const iframeRect = iframeEl.getBoundingClientRect(), offset = {
920
+ x: iframeRect.x,
921
+ y: iframeRect.y
922
+ }, iframeSrc = iframeEl.src || iframeEl.getAttribute("src") || "";
923
+ let isSameOrigin = !1;
924
+ try {
925
+ isSameOrigin = null !== iframeEl.contentWindow;
926
+ } catch (e) {
927
+ isSameOrigin = !1;
928
+ }
929
+ const adjustedElements = iframeSnapshot.raw_elements.map(el => {
930
+ const adjusted = {
931
+ ...el
932
+ };
933
+ return adjusted.rect && (adjusted.rect = {
934
+ ...adjusted.rect,
935
+ x: adjusted.rect.x + offset.x,
936
+ y: adjusted.rect.y + offset.y
937
+ }), adjusted.iframe_context = {
938
+ src: iframeSrc,
939
+ is_same_origin: isSameOrigin
940
+ }, adjusted;
941
+ });
942
+ allRawElements.push(...adjustedElements), totalIframeElements += adjustedElements.length;
943
+ }
944
+ });
945
+ } catch (error) {}
946
+ const fallbackElementsFromRaw = raw => (raw || []).map(r => {
947
+ const rect = r && r.rect || {
948
+ x: 0,
949
+ y: 0,
950
+ width: 0,
951
+ height: 0
952
+ }, attrs = r && r.attributes || {}, role = attrs.role || r && (r.inferred_role || r.inferredRole) || (r && "a" === r.tag ? "link" : "generic"), href = attrs.href || r && r.href || null, isClickable = "link" === role || "button" === role || "textbox" === role || "checkbox" === role || "radio" === role || "combobox" === role || !!href;
953
+ return {
954
+ id: Number(r && r.id || 0),
955
+ role: String(role || "generic"),
956
+ text: r && (r.text || r.semantic_text || r.semanticText) || null,
957
+ importance: 1,
958
+ bbox: {
959
+ x: Number(rect.x || 0),
960
+ y: Number(rect.y || 0),
961
+ width: Number(rect.width || 0),
962
+ height: Number(rect.height || 0)
963
+ },
964
+ visual_cues: {
965
+ is_primary: !1,
966
+ is_clickable: !!isClickable
967
+ },
968
+ in_viewport: !0,
969
+ is_occluded: !(!r || !r.occluded && !r.is_occluded),
970
+ z_index: 0,
971
+ name: attrs.aria_label || attrs.ariaLabel || null,
972
+ value: r && r.value || null,
973
+ input_type: attrs.type_ || attrs.type || null,
974
+ checked: "boolean" == typeof (r && r.checked) ? r.checked : null,
975
+ disabled: "boolean" == typeof (r && r.disabled) ? r.disabled : null,
976
+ expanded: "boolean" == typeof (r && r.expanded) ? r.expanded : null
977
+ };
978
+ });
979
+ let processed = null;
980
+ try {
981
+ processed = await function(rawData, options) {
982
+ return new Promise((resolve, reject) => {
983
+ const requestId = Math.random().toString(36).substring(7);
984
+ let resolved = !1;
985
+ const timeout = setTimeout(() => {
986
+ resolved || (resolved = !0, window.removeEventListener("message", listener), reject(new Error("WASM processing timeout - extension may be unresponsive. Try reloading the extension.")));
987
+ }, 25e3), listener = e => {
988
+ if ("SENTIENCE_SNAPSHOT_RESULT" === e.data.type && e.data.requestId === requestId) {
989
+ if (resolved) return;
990
+ resolved = !0, clearTimeout(timeout), window.removeEventListener("message", listener),
991
+ e.data.error ? reject(new Error(e.data.error)) : resolve({
992
+ elements: e.data.elements,
993
+ raw_elements: e.data.raw_elements,
994
+ duration: e.data.duration
995
+ });
996
+ }
997
+ };
998
+ window.addEventListener("message", listener);
999
+ try {
1000
+ window.postMessage({
1001
+ type: "SENTIENCE_SNAPSHOT_REQUEST",
1002
+ requestId: requestId,
1003
+ rawData: rawData,
1004
+ options: options
1005
+ }, "*");
1006
+ } catch (error) {
1007
+ resolved || (resolved = !0, clearTimeout(timeout), window.removeEventListener("message", listener),
1008
+ reject(new Error(`Failed to send snapshot request: ${error.message}`)));
1009
+ }
1010
+ });
1011
+ }(allRawElements, options);
1012
+ } catch (error) {
1013
+ processed = {
1014
+ elements: fallbackElementsFromRaw(allRawElements),
1015
+ raw_elements: allRawElements,
1016
+ duration: null
1017
+ };
1018
+ }
1019
+ processed && processed.elements || (processed = {
1020
+ elements: fallbackElementsFromRaw(allRawElements),
1021
+ raw_elements: allRawElements,
1022
+ duration: null
1023
+ });
1024
+ let screenshot = null;
1025
+ options.screenshot && (screenshot = await function(options) {
1026
+ return new Promise(resolve => {
1027
+ const requestId = Math.random().toString(36).substring(7), listener = e => {
1028
+ "SENTIENCE_SCREENSHOT_RESULT" === e.data.type && e.data.requestId === requestId && (window.removeEventListener("message", listener),
1029
+ resolve(e.data.screenshot));
1030
+ };
1031
+ window.addEventListener("message", listener), window.postMessage({
1032
+ type: "SENTIENCE_SCREENSHOT_REQUEST",
1033
+ requestId: requestId,
1034
+ options: options
1035
+ }, "*"), setTimeout(() => {
1036
+ window.removeEventListener("message", listener), resolve(null);
1037
+ }, 1e4);
1038
+ });
1039
+ }(options.screenshot));
1040
+ const cleanedElements = cleanElement(processed.elements), cleanedRawElements = cleanElement(processed.raw_elements);
1041
+ cleanedElements.length, cleanedRawElements.length;
1042
+ let diagnostics;
1043
+ try {
1044
+ const lastMutationTs = window.__sentience_lastMutationTs, now = performance.now(), quietMs = "number" == typeof lastMutationTs && Number.isFinite(lastMutationTs) ? Math.max(0, now - lastMutationTs) : null, nodeCount = document.querySelectorAll("*").length;
1045
+ let requiresVision = !1, requiresVisionReason = null;
1046
+ const canvasCount = document.getElementsByTagName("canvas").length;
1047
+ canvasCount > 0 && (requiresVision = !0, requiresVisionReason = `canvas:${canvasCount}`),
1048
+ diagnostics = {
1049
+ metrics: {
1050
+ ready_state: document.readyState || null,
1051
+ quiet_ms: quietMs,
1052
+ node_count: nodeCount
1053
+ },
1054
+ captcha: detectCaptcha(),
1055
+ requires_vision: requiresVision,
1056
+ requires_vision_reason: requiresVisionReason
1057
+ };
1058
+ } catch (e) {}
1059
+ return {
1060
+ status: "success",
1061
+ url: window.location.href,
1062
+ viewport: {
1063
+ width: window.innerWidth,
1064
+ height: window.innerHeight
1065
+ },
1066
+ elements: cleanedElements,
1067
+ raw_elements: cleanedRawElements,
1068
+ screenshot: screenshot,
1069
+ diagnostics: diagnostics
1070
+ };
1071
+ } catch (error) {
1072
+ return {
1073
+ status: "error",
1074
+ error: error.message || "Unknown error",
1075
+ stack: error.stack
1076
+ };
1077
+ }
1078
+ }
1079
+ function read(options = {}) {
1080
+ const format = options.format || "raw";
1081
+ let content;
1082
+ return content = "raw" === format ? getRawHTML(document.body) : "markdown" === format ? function(root) {
1083
+ const rawHTML = getRawHTML(root), tempDiv = document.createElement("div");
1084
+ tempDiv.innerHTML = rawHTML;
1085
+ let markdown = "", insideLink = !1;
1086
+ return function walk(node) {
1087
+ if (node.nodeType === Node.TEXT_NODE) {
1088
+ const text = node.textContent.replace(/[\r\n]+/g, " ").replace(/\s+/g, " ");
1089
+ return void (text.trim() && (markdown += text));
1090
+ }
1091
+ if (node.nodeType !== Node.ELEMENT_NODE) return;
1092
+ const tag = node.tagName.toLowerCase();
1093
+ if ("h1" === tag && (markdown += "\n# "), "h2" === tag && (markdown += "\n## "),
1094
+ "h3" === tag && (markdown += "\n### "), "li" === tag && (markdown += "\n- "), insideLink || "p" !== tag && "div" !== tag && "br" !== tag || (markdown += "\n"),
1095
+ "strong" !== tag && "b" !== tag || (markdown += "**"), "em" !== tag && "i" !== tag || (markdown += "_"),
1096
+ "a" === tag && (markdown += "[", insideLink = !0), node.shadowRoot ? Array.from(node.shadowRoot.childNodes).forEach(walk) : node.childNodes.forEach(walk),
1097
+ "a" === tag) {
1098
+ const href = node.getAttribute("href");
1099
+ markdown += href ? `](${href})` : "]", insideLink = !1;
1100
+ }
1101
+ "strong" !== tag && "b" !== tag || (markdown += "**"), "em" !== tag && "i" !== tag || (markdown += "_"),
1102
+ insideLink || "h1" !== tag && "h2" !== tag && "h3" !== tag && "p" !== tag && "div" !== tag || (markdown += "\n");
1103
+ }(tempDiv), markdown.replace(/\n{3,}/g, "\n\n").trim();
1104
+ }(document.body) : function(root) {
1105
+ let text = "";
1106
+ return function walk(node) {
1107
+ if (node.nodeType !== Node.TEXT_NODE) {
1108
+ if (node.nodeType === Node.ELEMENT_NODE) {
1109
+ const tag = node.tagName.toLowerCase();
1110
+ if ([ "nav", "footer", "header", "script", "style", "noscript", "iframe", "svg" ].includes(tag)) return;
1111
+ const style = window.getComputedStyle(node);
1112
+ if ("none" === style.display || "hidden" === style.visibility) return;
1113
+ const isBlock = "block" === style.display || "flex" === style.display || "P" === node.tagName || "DIV" === node.tagName;
1114
+ isBlock && (text += " "), node.shadowRoot ? Array.from(node.shadowRoot.childNodes).forEach(walk) : node.childNodes.forEach(walk),
1115
+ isBlock && (text += "\n");
1116
+ }
1117
+ } else text += node.textContent;
1118
+ }(root || document.body), text.replace(/\n{3,}/g, "\n\n").trim();
1119
+ }(document.body), {
1120
+ status: "success",
1121
+ url: window.location.href,
1122
+ format: format,
1123
+ content: content,
1124
+ length: content.length
1125
+ };
1126
+ }
1127
+ function findTextRect(options = {}) {
1128
+ const {text: text, containerElement: containerElement = document.body, caseSensitive: caseSensitive = !1, wholeWord: wholeWord = !1, maxResults: maxResults = 10} = options;
1129
+ if (!text || 0 === text.trim().length) return {
1130
+ status: "error",
1131
+ error: "Text parameter is required"
1132
+ };
1133
+ const results = [], searchText = caseSensitive ? text : text.toLowerCase();
1134
+ function findInTextNode(textNode) {
1135
+ const nodeText = textNode.nodeValue, searchableText = caseSensitive ? nodeText : nodeText.toLowerCase();
1136
+ let startIndex = 0;
1137
+ for (;startIndex < nodeText.length && results.length < maxResults; ) {
1138
+ const foundIndex = searchableText.indexOf(searchText, startIndex);
1139
+ if (-1 === foundIndex) break;
1140
+ if (wholeWord) {
1141
+ const before = foundIndex > 0 ? nodeText[foundIndex - 1] : " ", after = foundIndex + text.length < nodeText.length ? nodeText[foundIndex + text.length] : " ";
1142
+ if (!/\s/.test(before) || !/\s/.test(after)) {
1143
+ startIndex = foundIndex + 1;
1144
+ continue;
1145
+ }
1146
+ }
1147
+ try {
1148
+ const range = document.createRange();
1149
+ range.setStart(textNode, foundIndex), range.setEnd(textNode, foundIndex + text.length);
1150
+ const rect = range.getBoundingClientRect();
1151
+ rect.width > 0 && rect.height > 0 && results.push({
1152
+ text: nodeText.substring(foundIndex, foundIndex + text.length),
1153
+ rect: {
1154
+ x: rect.left + window.scrollX,
1155
+ y: rect.top + window.scrollY,
1156
+ width: rect.width,
1157
+ height: rect.height,
1158
+ left: rect.left + window.scrollX,
1159
+ top: rect.top + window.scrollY,
1160
+ right: rect.right + window.scrollX,
1161
+ bottom: rect.bottom + window.scrollY
1162
+ },
1163
+ viewport_rect: {
1164
+ x: rect.left,
1165
+ y: rect.top,
1166
+ width: rect.width,
1167
+ height: rect.height
1168
+ },
1169
+ context: {
1170
+ before: nodeText.substring(Math.max(0, foundIndex - 20), foundIndex),
1171
+ after: nodeText.substring(foundIndex + text.length, Math.min(nodeText.length, foundIndex + text.length + 20))
1172
+ },
1173
+ in_viewport: rect.top >= 0 && rect.left >= 0 && rect.bottom <= window.innerHeight && rect.right <= window.innerWidth
1174
+ });
1175
+ } catch (e) {}
1176
+ startIndex = foundIndex + 1;
1177
+ }
1178
+ }
1179
+ const walker = document.createTreeWalker(containerElement, NodeFilter.SHOW_TEXT, {
1180
+ acceptNode(node) {
1181
+ const parent = node.parentElement;
1182
+ if (!parent) return NodeFilter.FILTER_REJECT;
1183
+ const tagName = parent.tagName.toLowerCase();
1184
+ if ("script" === tagName || "style" === tagName || "noscript" === tagName) return NodeFilter.FILTER_REJECT;
1185
+ if (!node.nodeValue || 0 === node.nodeValue.trim().length) return NodeFilter.FILTER_REJECT;
1186
+ const computedStyle = window.getComputedStyle(parent);
1187
+ return "none" === computedStyle.display || "hidden" === computedStyle.visibility || "0" === computedStyle.opacity ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT;
1188
+ }
1189
+ });
1190
+ let currentNode;
1191
+ for (;(currentNode = walker.nextNode()) && results.length < maxResults; ) findInTextNode(currentNode);
1192
+ return {
1193
+ status: "success",
1194
+ query: text,
1195
+ case_sensitive: caseSensitive,
1196
+ whole_word: wholeWord,
1197
+ matches: results.length,
1198
+ results: results,
1199
+ viewport: {
1200
+ width: window.innerWidth,
1201
+ height: window.innerHeight,
1202
+ scroll_x: window.scrollX,
1203
+ scroll_y: window.scrollY
1204
+ }
1205
+ };
1206
+ }
1207
+ function click(id) {
1208
+ const el = window.sentience_registry[id];
1209
+ return !!el && (el.click(), el.focus(), !0);
1210
+ }
1211
+ function startRecording(options = {}) {
1212
+ const {highlightColor: highlightColor = "#ff0000", successColor: successColor = "#00ff00", autoDisableTimeout: autoDisableTimeout = 18e5, keyboardShortcut: keyboardShortcut = "Ctrl+Shift+I"} = options;
1213
+ if (!window.sentience_registry || 0 === window.sentience_registry.length) return alert("Registry empty. Run `await window.sentience.snapshot()` first!"),
1214
+ () => {};
1215
+ window.sentience_registry_map = new Map, window.sentience_registry.forEach((el, idx) => {
1216
+ el && window.sentience_registry_map.set(el, idx);
1217
+ });
1218
+ let highlightBox = document.getElementById("sentience-highlight-box");
1219
+ highlightBox || (highlightBox = document.createElement("div"), highlightBox.id = "sentience-highlight-box",
1220
+ 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 `,
1221
+ document.body.appendChild(highlightBox));
1222
+ let recordingIndicator = document.getElementById("sentience-recording-indicator");
1223
+ recordingIndicator || (recordingIndicator = document.createElement("div"), recordingIndicator.id = "sentience-recording-indicator",
1224
+ 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 `,
1225
+ document.body.appendChild(recordingIndicator)), recordingIndicator.style.display = "block";
1226
+ const mouseOverHandler = e => {
1227
+ const el = e.target;
1228
+ if (!el || el === highlightBox || el === recordingIndicator) return;
1229
+ const rect = el.getBoundingClientRect();
1230
+ highlightBox.style.display = "block", highlightBox.style.top = rect.top + window.scrollY + "px",
1231
+ highlightBox.style.left = rect.left + window.scrollX + "px", highlightBox.style.width = rect.width + "px",
1232
+ highlightBox.style.height = rect.height + "px";
1233
+ }, clickHandler = e => {
1234
+ e.preventDefault(), e.stopPropagation();
1235
+ const el = e.target;
1236
+ if (!el || el === highlightBox || el === recordingIndicator) return;
1237
+ const sentienceId = window.sentience_registry_map.get(el);
1238
+ if (void 0 === sentienceId) return void alert("Element not in registry. Run `await window.sentience.snapshot()` first!");
1239
+ const rawData = function(el) {
1240
+ const style = window.getComputedStyle(el), rect = el.getBoundingClientRect();
1241
+ return {
1242
+ tag: el.tagName,
1243
+ rect: {
1244
+ x: Math.round(rect.x),
1245
+ y: Math.round(rect.y),
1246
+ width: Math.round(rect.width),
1247
+ height: Math.round(rect.height)
1248
+ },
1249
+ styles: {
1250
+ cursor: style.cursor || null,
1251
+ backgroundColor: style.backgroundColor || null,
1252
+ color: style.color || null,
1253
+ fontWeight: style.fontWeight || null,
1254
+ fontSize: style.fontSize || null,
1255
+ display: style.display || null,
1256
+ position: style.position || null,
1257
+ zIndex: style.zIndex || null,
1258
+ opacity: style.opacity || null,
1259
+ visibility: style.visibility || null
1260
+ },
1261
+ attributes: {
1262
+ role: el.getAttribute("role") || null,
1263
+ type: el.getAttribute("type") || null,
1264
+ ariaLabel: el.getAttribute("aria-label") || null,
1265
+ id: el.id || null,
1266
+ className: el.className || null
1267
+ }
1268
+ };
1269
+ }(el), selector = function(el) {
1270
+ if (!el || !el.tagName) return "";
1271
+ if (el.id) return `#${el.id}`;
1272
+ for (const attr of el.attributes) if (attr.name.startsWith("data-") || "aria-label" === attr.name) {
1273
+ const value = attr.value ? attr.value.replace(/"/g, '\\"') : "";
1274
+ return `${el.tagName.toLowerCase()}[${attr.name}="${value}"]`;
1275
+ }
1276
+ const path = [];
1277
+ let current = el;
1278
+ for (;current && current !== document.body && current !== document.documentElement; ) {
1279
+ let selector = current.tagName.toLowerCase();
1280
+ if (current.id) {
1281
+ selector = `#${current.id}`, path.unshift(selector);
1282
+ break;
1283
+ }
1284
+ if (current.className && "string" == typeof current.className) {
1285
+ const classes = current.className.trim().split(/\s+/).filter(c => c);
1286
+ classes.length > 0 && (selector += `.${classes[0]}`);
1287
+ }
1288
+ if (current.parentElement) {
1289
+ const sameTagSiblings = Array.from(current.parentElement.children).filter(s => s.tagName === current.tagName), index = sameTagSiblings.indexOf(current);
1290
+ (index > 0 || sameTagSiblings.length > 1) && (selector += `:nth-of-type(${index + 1})`);
1291
+ }
1292
+ path.unshift(selector), current = current.parentElement;
1293
+ }
1294
+ return path.join(" > ") || el.tagName.toLowerCase();
1295
+ }(el), role = el.getAttribute("role") || el.tagName.toLowerCase(), text = getText(el), snippet = {
1296
+ task: `Interact with ${text.substring(0, 20)}${text.length > 20 ? "..." : ""}`,
1297
+ url: window.location.href,
1298
+ timestamp: (new Date).toISOString(),
1299
+ target_criteria: {
1300
+ id: sentienceId,
1301
+ selector: selector,
1302
+ role: role,
1303
+ text: text.substring(0, 50)
1304
+ },
1305
+ debug_snapshot: rawData
1306
+ }, jsonString = JSON.stringify(snippet, null, 2);
1307
+ navigator.clipboard.writeText(jsonString).then(() => {
1308
+ highlightBox.style.border = `2px solid ${successColor}`, highlightBox.style.background = "rgba(0, 255, 0, 0.2)",
1309
+ setTimeout(() => {
1310
+ highlightBox.style.border = `2px solid ${highlightColor}`, highlightBox.style.background = "rgba(255, 0, 0, 0.1)";
1311
+ }, 500);
1312
+ }).catch(err => {
1313
+ alert("Failed to copy to clipboard. Check console for JSON.");
1314
+ });
1315
+ };
1316
+ let timeoutId = null;
1317
+ const stopRecording = () => {
1318
+ document.removeEventListener("mouseover", mouseOverHandler, !0), document.removeEventListener("click", clickHandler, !0),
1319
+ document.removeEventListener("keydown", keyboardHandler, !0), timeoutId && (clearTimeout(timeoutId),
1320
+ timeoutId = null), highlightBox && (highlightBox.style.display = "none"), recordingIndicator && (recordingIndicator.style.display = "none"),
1321
+ window.sentience_registry_map && window.sentience_registry_map.clear(), window.sentience_stopRecording === stopRecording && delete window.sentience_stopRecording;
1322
+ }, keyboardHandler = e => {
1323
+ (e.ctrlKey || e.metaKey) && e.shiftKey && "I" === e.key && (e.preventDefault(),
1324
+ stopRecording());
1325
+ };
1326
+ return document.addEventListener("mouseover", mouseOverHandler, !0), document.addEventListener("click", clickHandler, !0),
1327
+ document.addEventListener("keydown", keyboardHandler, !0), autoDisableTimeout > 0 && (timeoutId = setTimeout(() => {
1328
+ stopRecording();
1329
+ }, autoDisableTimeout)), window.sentience_stopRecording = stopRecording, stopRecording;
1330
+ }
1331
+ function showOverlay(elements, targetElementId = null) {
1332
+ if (!elements || "object" != typeof elements || "number" != typeof elements.length) return;
1333
+ const elementsArray = Array.isArray(elements) ? elements : Array.from(elements);
1334
+ window.postMessage({
1335
+ type: "SENTIENCE_SHOW_OVERLAY",
1336
+ elements: elementsArray,
1337
+ targetElementId: targetElementId,
1338
+ timestamp: Date.now()
1339
+ }, "*");
1340
+ }
1341
+ function showGrid(grids, targetGridId = null) {
1342
+ if (!grids || "object" != typeof grids || "number" != typeof grids.length) return;
1343
+ const gridsArray = Array.isArray(grids) ? grids : Array.from(grids);
1344
+ window.postMessage({
1345
+ type: "SENTIENCE_SHOW_GRID_OVERLAY",
1346
+ grids: gridsArray,
1347
+ targetGridId: targetGridId,
1348
+ timestamp: Date.now()
1349
+ }, "*");
1350
+ }
1351
+ function clearOverlay() {
1352
+ window.postMessage({
1353
+ type: "SENTIENCE_CLEAR_OVERLAY"
1354
+ }, "*");
1355
+ }
1356
+ (async () => {
1357
+ const getExtensionId = () => document.documentElement.dataset.sentienceExtensionId;
1358
+ let extId = getExtensionId();
1359
+ extId || await new Promise(resolve => {
1360
+ const check = setInterval(() => {
1361
+ extId = getExtensionId(), extId && (clearInterval(check), resolve());
1362
+ }, 50);
1363
+ setTimeout(() => resolve(), 5e3);
1364
+ }), extId && (window.sentience_registry = [], window.sentience = {
1365
+ snapshot: snapshot,
1366
+ read: read,
1367
+ findTextRect: findTextRect,
1368
+ click: click,
1369
+ startRecording: startRecording,
1370
+ showOverlay: showOverlay,
1371
+ showGrid: showGrid,
1372
+ clearOverlay: clearOverlay
1373
+ }, window.sentience_iframe_handler_setup || (window.addEventListener("message", async event => {
1374
+ if ("SENTIENCE_IFRAME_SNAPSHOT_REQUEST" === event.data?.type) {
1375
+ const {requestId: requestId, options: options} = event.data;
1376
+ try {
1377
+ const snapshotOptions = {
1378
+ ...options,
1379
+ collectIframes: !0,
1380
+ waitForStability: (options.waitForStability, !1)
1381
+ }, snapshot = await window.sentience.snapshot(snapshotOptions);
1382
+ event.source && event.source.postMessage && event.source.postMessage({
1383
+ type: "SENTIENCE_IFRAME_SNAPSHOT_RESPONSE",
1384
+ requestId: requestId,
1385
+ snapshot: snapshot,
1386
+ error: null
1387
+ }, "*");
1388
+ } catch (error) {
1389
+ event.source && event.source.postMessage && event.source.postMessage({
1390
+ type: "SENTIENCE_IFRAME_SNAPSHOT_RESPONSE",
1391
+ requestId: requestId,
1392
+ snapshot: null,
1393
+ error: error.message
1394
+ }, "*");
1395
+ }
1396
+ }
1397
+ }), window.sentience_iframe_handler_setup = !0));
1398
+ })();
1399
+ }();