agent-web-interface 4.3.0 → 4.5.0

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 (461) hide show
  1. package/dist/src/browser/browser-session-config.d.ts +33 -0
  2. package/dist/src/browser/browser-session-config.d.ts.map +1 -0
  3. package/dist/src/browser/browser-session-config.js +24 -0
  4. package/dist/src/browser/browser-session-config.js.map +1 -0
  5. package/dist/src/browser/connection-utils.d.ts +48 -0
  6. package/dist/src/browser/connection-utils.d.ts.map +1 -0
  7. package/dist/src/browser/connection-utils.js +129 -0
  8. package/dist/src/browser/connection-utils.js.map +1 -0
  9. package/dist/src/browser/ensure-browser.d.ts +12 -27
  10. package/dist/src/browser/ensure-browser.d.ts.map +1 -1
  11. package/dist/src/browser/ensure-browser.js +104 -37
  12. package/dist/src/browser/ensure-browser.js.map +1 -1
  13. package/dist/src/browser/index.d.ts +4 -1
  14. package/dist/src/browser/index.d.ts.map +1 -1
  15. package/dist/src/browser/index.js +3 -1
  16. package/dist/src/browser/index.js.map +1 -1
  17. package/dist/src/browser/session-manager.d.ts +21 -89
  18. package/dist/src/browser/session-manager.d.ts.map +1 -1
  19. package/dist/src/browser/session-manager.js +122 -132
  20. package/dist/src/browser/session-manager.js.map +1 -1
  21. package/dist/src/browser/session-manager.types.d.ts +102 -0
  22. package/dist/src/browser/session-manager.types.d.ts.map +1 -0
  23. package/dist/src/browser/session-manager.types.js +11 -0
  24. package/dist/src/browser/session-manager.types.js.map +1 -0
  25. package/dist/src/cli/args.d.ts +12 -18
  26. package/dist/src/cli/args.d.ts.map +1 -1
  27. package/dist/src/cli/args.js +35 -40
  28. package/dist/src/cli/args.js.map +1 -1
  29. package/dist/src/form/constraint-extraction.d.ts +36 -0
  30. package/dist/src/form/constraint-extraction.d.ts.map +1 -0
  31. package/dist/src/form/constraint-extraction.js +117 -0
  32. package/dist/src/form/constraint-extraction.js.map +1 -0
  33. package/dist/src/form/field-extractor.d.ts.map +1 -1
  34. package/dist/src/form/field-extractor.js +16 -450
  35. package/dist/src/form/field-extractor.js.map +1 -1
  36. package/dist/src/form/field-state-extractor.d.ts +22 -0
  37. package/dist/src/form/field-state-extractor.d.ts.map +1 -0
  38. package/dist/src/form/field-state-extractor.js +55 -0
  39. package/dist/src/form/field-state-extractor.js.map +1 -0
  40. package/dist/src/form/form-actions.d.ts +45 -0
  41. package/dist/src/form/form-actions.d.ts.map +1 -0
  42. package/dist/src/form/form-actions.js +108 -0
  43. package/dist/src/form/form-actions.js.map +1 -0
  44. package/dist/src/form/form-detector.d.ts +0 -36
  45. package/dist/src/form/form-detector.d.ts.map +1 -1
  46. package/dist/src/form/form-detector.js +11 -376
  47. package/dist/src/form/form-detector.js.map +1 -1
  48. package/dist/src/form/form-state.d.ts.map +1 -1
  49. package/dist/src/form/form-state.js +16 -4
  50. package/dist/src/form/form-state.js.map +1 -1
  51. package/dist/src/form/input-clustering.d.ts +15 -0
  52. package/dist/src/form/input-clustering.d.ts.map +1 -0
  53. package/dist/src/form/input-clustering.js +61 -0
  54. package/dist/src/form/input-clustering.js.map +1 -0
  55. package/dist/src/form/intent-inference.d.ts +28 -0
  56. package/dist/src/form/intent-inference.d.ts.map +1 -0
  57. package/dist/src/form/intent-inference.js +137 -0
  58. package/dist/src/form/intent-inference.js.map +1 -0
  59. package/dist/src/form/purpose-inference.d.ts +50 -0
  60. package/dist/src/form/purpose-inference.d.ts.map +1 -0
  61. package/dist/src/form/purpose-inference.js +313 -0
  62. package/dist/src/form/purpose-inference.js.map +1 -0
  63. package/dist/src/form/submit-detection.d.ts +36 -0
  64. package/dist/src/form/submit-detection.d.ts.map +1 -0
  65. package/dist/src/form/submit-detection.js +101 -0
  66. package/dist/src/form/submit-detection.js.map +1 -0
  67. package/dist/src/form/types.d.ts +2 -2
  68. package/dist/src/gateway/http-gateway.d.ts +56 -0
  69. package/dist/src/gateway/http-gateway.d.ts.map +1 -0
  70. package/dist/src/gateway/http-gateway.js +229 -0
  71. package/dist/src/gateway/http-gateway.js.map +1 -0
  72. package/dist/src/gateway/json-rpc-errors.d.ts +6 -0
  73. package/dist/src/gateway/json-rpc-errors.d.ts.map +1 -0
  74. package/dist/src/gateway/json-rpc-errors.js +11 -0
  75. package/dist/src/gateway/json-rpc-errors.js.map +1 -0
  76. package/dist/src/gateway/session-router.d.ts +80 -0
  77. package/dist/src/gateway/session-router.d.ts.map +1 -0
  78. package/dist/src/gateway/session-router.js +177 -0
  79. package/dist/src/gateway/session-router.js.map +1 -0
  80. package/dist/src/http-entry.d.ts +20 -0
  81. package/dist/src/http-entry.d.ts.map +1 -0
  82. package/dist/src/http-entry.js +112 -0
  83. package/dist/src/http-entry.js.map +1 -0
  84. package/dist/src/index.d.ts +1 -10
  85. package/dist/src/index.d.ts.map +1 -1
  86. package/dist/src/index.js +25 -227
  87. package/dist/src/index.js.map +1 -1
  88. package/dist/src/lib/text-utils.d.ts +0 -24
  89. package/dist/src/lib/text-utils.d.ts.map +1 -1
  90. package/dist/src/lib/text-utils.js +2 -38
  91. package/dist/src/lib/text-utils.js.map +1 -1
  92. package/dist/src/observation/eid-linker.d.ts.map +1 -1
  93. package/dist/src/observation/eid-linker.js +1 -21
  94. package/dist/src/observation/eid-linker.js.map +1 -1
  95. package/dist/src/observation/observation-accumulator.d.ts +1 -1
  96. package/dist/src/observation/observation-accumulator.js +1 -1
  97. package/dist/src/observation/observer-script.d.ts +1 -1
  98. package/dist/src/observation/observer-script.d.ts.map +1 -1
  99. package/dist/src/observation/observer-script.js +129 -7
  100. package/dist/src/observation/observer-script.js.map +1 -1
  101. package/dist/src/query/disambiguation.d.ts +18 -0
  102. package/dist/src/query/disambiguation.d.ts.map +1 -0
  103. package/dist/src/query/disambiguation.js +123 -0
  104. package/dist/src/query/disambiguation.js.map +1 -0
  105. package/dist/src/query/fuzzy-match.d.ts +17 -0
  106. package/dist/src/query/fuzzy-match.d.ts.map +1 -0
  107. package/dist/src/query/fuzzy-match.js +34 -0
  108. package/dist/src/query/fuzzy-match.js.map +1 -0
  109. package/dist/src/query/index.d.ts +3 -0
  110. package/dist/src/query/index.d.ts.map +1 -1
  111. package/dist/src/query/index.js +6 -0
  112. package/dist/src/query/index.js.map +1 -1
  113. package/dist/src/query/query-engine.d.ts +0 -35
  114. package/dist/src/query/query-engine.d.ts.map +1 -1
  115. package/dist/src/query/query-engine.js +9 -309
  116. package/dist/src/query/query-engine.js.map +1 -1
  117. package/dist/src/query/scoring.d.ts +52 -0
  118. package/dist/src/query/scoring.d.ts.map +1 -0
  119. package/dist/src/query/scoring.js +162 -0
  120. package/dist/src/query/scoring.js.map +1 -0
  121. package/dist/src/server/index.d.ts +0 -1
  122. package/dist/src/server/index.d.ts.map +1 -1
  123. package/dist/src/server/index.js +0 -1
  124. package/dist/src/server/index.js.map +1 -1
  125. package/dist/src/server/mcp-server.d.ts +6 -2
  126. package/dist/src/server/mcp-server.d.ts.map +1 -1
  127. package/dist/src/server/mcp-server.js +3 -91
  128. package/dist/src/server/mcp-server.js.map +1 -1
  129. package/dist/src/server/server-config.d.ts +4 -20
  130. package/dist/src/server/server-config.d.ts.map +1 -1
  131. package/dist/src/server/server-config.js +6 -50
  132. package/dist/src/server/server-config.js.map +1 -1
  133. package/dist/src/server/tool-registrar.types.d.ts +25 -0
  134. package/dist/src/server/tool-registrar.types.d.ts.map +1 -0
  135. package/dist/src/server/tool-registrar.types.js +10 -0
  136. package/dist/src/server/tool-registrar.types.js.map +1 -0
  137. package/dist/src/server/tool-result-handler.d.ts +61 -0
  138. package/dist/src/server/tool-result-handler.d.ts.map +1 -0
  139. package/dist/src/server/tool-result-handler.js +137 -0
  140. package/dist/src/server/tool-result-handler.js.map +1 -0
  141. package/dist/src/session/session-controller.d.ts +123 -0
  142. package/dist/src/session/session-controller.d.ts.map +1 -0
  143. package/dist/src/session/session-controller.js +273 -0
  144. package/dist/src/session/session-controller.js.map +1 -0
  145. package/dist/src/shared/services/index.d.ts +0 -2
  146. package/dist/src/shared/services/index.d.ts.map +1 -1
  147. package/dist/src/shared/services/index.js +0 -2
  148. package/dist/src/shared/services/index.js.map +1 -1
  149. package/dist/src/shared/version.d.ts +10 -0
  150. package/dist/src/shared/version.d.ts.map +1 -0
  151. package/dist/src/shared/version.js +32 -0
  152. package/dist/src/shared/version.js.map +1 -0
  153. package/dist/src/snapshot/element-resolver.d.ts +27 -15
  154. package/dist/src/snapshot/element-resolver.d.ts.map +1 -1
  155. package/dist/src/snapshot/element-resolver.js +196 -91
  156. package/dist/src/snapshot/element-resolver.js.map +1 -1
  157. package/dist/src/snapshot/extractors/attribute-extractor.d.ts.map +1 -1
  158. package/dist/src/snapshot/extractors/attribute-extractor.js +4 -0
  159. package/dist/src/snapshot/extractors/attribute-extractor.js.map +1 -1
  160. package/dist/src/snapshot/extractors/ax-extractor.d.ts +1 -1
  161. package/dist/src/snapshot/extractors/ax-extractor.d.ts.map +1 -1
  162. package/dist/src/snapshot/extractors/ax-extractor.js +4 -1
  163. package/dist/src/snapshot/extractors/ax-extractor.js.map +1 -1
  164. package/dist/src/snapshot/extractors/index.d.ts +1 -1
  165. package/dist/src/snapshot/extractors/index.d.ts.map +1 -1
  166. package/dist/src/snapshot/extractors/index.js +1 -1
  167. package/dist/src/snapshot/extractors/index.js.map +1 -1
  168. package/dist/src/snapshot/extractors/layout-extractor.d.ts +9 -7
  169. package/dist/src/snapshot/extractors/layout-extractor.d.ts.map +1 -1
  170. package/dist/src/snapshot/extractors/layout-extractor.js +34 -19
  171. package/dist/src/snapshot/extractors/layout-extractor.js.map +1 -1
  172. package/dist/src/snapshot/extractors/region-resolver.d.ts.map +1 -1
  173. package/dist/src/snapshot/extractors/region-resolver.js +8 -0
  174. package/dist/src/snapshot/extractors/region-resolver.js.map +1 -1
  175. package/dist/src/snapshot/extractors/state-extractor.d.ts +2 -2
  176. package/dist/src/snapshot/extractors/state-extractor.d.ts.map +1 -1
  177. package/dist/src/snapshot/extractors/state-extractor.js +22 -2
  178. package/dist/src/snapshot/extractors/state-extractor.js.map +1 -1
  179. package/dist/src/snapshot/extractors/types.d.ts +14 -0
  180. package/dist/src/snapshot/extractors/types.d.ts.map +1 -1
  181. package/dist/src/snapshot/extractors/types.js +16 -0
  182. package/dist/src/snapshot/extractors/types.js.map +1 -1
  183. package/dist/src/snapshot/frame-context.d.ts +68 -0
  184. package/dist/src/snapshot/frame-context.d.ts.map +1 -0
  185. package/dist/src/snapshot/frame-context.js +131 -0
  186. package/dist/src/snapshot/frame-context.js.map +1 -0
  187. package/dist/src/snapshot/heading-index.d.ts +28 -0
  188. package/dist/src/snapshot/heading-index.d.ts.map +1 -0
  189. package/dist/src/snapshot/heading-index.js +108 -0
  190. package/dist/src/snapshot/heading-index.js.map +1 -0
  191. package/dist/src/snapshot/index.d.ts +5 -3
  192. package/dist/src/snapshot/index.d.ts.map +1 -1
  193. package/dist/src/snapshot/index.js +3 -2
  194. package/dist/src/snapshot/index.js.map +1 -1
  195. package/dist/src/snapshot/kind-mapping.d.ts +30 -0
  196. package/dist/src/snapshot/kind-mapping.d.ts.map +1 -0
  197. package/dist/src/snapshot/kind-mapping.js +114 -0
  198. package/dist/src/snapshot/kind-mapping.js.map +1 -0
  199. package/dist/src/snapshot/node-filter.d.ts +31 -0
  200. package/dist/src/snapshot/node-filter.d.ts.map +1 -0
  201. package/dist/src/snapshot/node-filter.js +137 -0
  202. package/dist/src/snapshot/node-filter.js.map +1 -0
  203. package/dist/src/snapshot/node-synthesizer.d.ts +62 -0
  204. package/dist/src/snapshot/node-synthesizer.d.ts.map +1 -0
  205. package/dist/src/snapshot/node-synthesizer.js +185 -0
  206. package/dist/src/snapshot/node-synthesizer.js.map +1 -0
  207. package/dist/src/snapshot/snapshot-compiler.d.ts +2 -36
  208. package/dist/src/snapshot/snapshot-compiler.d.ts.map +1 -1
  209. package/dist/src/snapshot/snapshot-compiler.js +40 -549
  210. package/dist/src/snapshot/snapshot-compiler.js.map +1 -1
  211. package/dist/src/snapshot/snapshot.types.d.ts +17 -3
  212. package/dist/src/snapshot/snapshot.types.d.ts.map +1 -1
  213. package/dist/src/snapshot/snapshot.types.js +8 -0
  214. package/dist/src/snapshot/snapshot.types.js.map +1 -1
  215. package/dist/src/state/actionables-filter.d.ts +5 -0
  216. package/dist/src/state/actionables-filter.d.ts.map +1 -1
  217. package/dist/src/state/actionables-filter.js +28 -6
  218. package/dist/src/state/actionables-filter.js.map +1 -1
  219. package/dist/src/state/atoms-extractor.d.ts.map +1 -1
  220. package/dist/src/state/atoms-extractor.js +3 -23
  221. package/dist/src/state/atoms-extractor.js.map +1 -1
  222. package/dist/src/state/diff-engine.d.ts.map +1 -1
  223. package/dist/src/state/diff-engine.js +9 -36
  224. package/dist/src/state/diff-engine.js.map +1 -1
  225. package/dist/src/state/element-identity.d.ts +3 -6
  226. package/dist/src/state/element-identity.d.ts.map +1 -1
  227. package/dist/src/state/element-identity.js +10 -7
  228. package/dist/src/state/element-identity.js.map +1 -1
  229. package/dist/src/state/element-ref.types.d.ts +5 -27
  230. package/dist/src/state/element-ref.types.d.ts.map +1 -1
  231. package/dist/src/state/element-registry.d.ts.map +1 -1
  232. package/dist/src/state/element-registry.js +6 -4
  233. package/dist/src/state/element-registry.js.map +1 -1
  234. package/dist/src/state/hash-utils.d.ts +24 -0
  235. package/dist/src/state/hash-utils.d.ts.map +1 -0
  236. package/dist/src/state/hash-utils.js +41 -0
  237. package/dist/src/state/hash-utils.js.map +1 -0
  238. package/dist/src/state/layer-detector.d.ts.map +1 -1
  239. package/dist/src/state/layer-detector.js +15 -286
  240. package/dist/src/state/layer-detector.js.map +1 -1
  241. package/dist/src/state/layer-detectors/drawer-detector.d.ts +32 -0
  242. package/dist/src/state/layer-detectors/drawer-detector.d.ts.map +1 -0
  243. package/dist/src/state/layer-detectors/drawer-detector.js +96 -0
  244. package/dist/src/state/layer-detectors/drawer-detector.js.map +1 -0
  245. package/dist/src/state/layer-detectors/index.d.ts +10 -0
  246. package/dist/src/state/layer-detectors/index.d.ts.map +1 -0
  247. package/dist/src/state/layer-detectors/index.js +10 -0
  248. package/dist/src/state/layer-detectors/index.js.map +1 -0
  249. package/dist/src/state/layer-detectors/modal-detector.d.ts +30 -0
  250. package/dist/src/state/layer-detectors/modal-detector.d.ts.map +1 -0
  251. package/dist/src/state/layer-detectors/modal-detector.js +127 -0
  252. package/dist/src/state/layer-detectors/modal-detector.js.map +1 -0
  253. package/dist/src/state/layer-detectors/popover-detector.d.ts +20 -0
  254. package/dist/src/state/layer-detectors/popover-detector.d.ts.map +1 -0
  255. package/dist/src/state/layer-detectors/popover-detector.js +76 -0
  256. package/dist/src/state/layer-detectors/popover-detector.js.map +1 -0
  257. package/dist/src/state/layer-detectors/toast-detector.d.ts +24 -0
  258. package/dist/src/state/layer-detectors/toast-detector.d.ts.map +1 -0
  259. package/dist/src/state/layer-detectors/toast-detector.js +48 -0
  260. package/dist/src/state/layer-detectors/toast-detector.js.map +1 -0
  261. package/dist/src/state/region-mapping.d.ts +13 -0
  262. package/dist/src/state/region-mapping.d.ts.map +1 -0
  263. package/dist/src/state/region-mapping.js +25 -0
  264. package/dist/src/state/region-mapping.js.map +1 -0
  265. package/dist/src/state/state-manager.d.ts.map +1 -1
  266. package/dist/src/state/state-manager.js +11 -193
  267. package/dist/src/state/state-manager.js.map +1 -1
  268. package/dist/src/state/state-renderer.d.ts.map +1 -1
  269. package/dist/src/state/state-renderer.js +17 -3
  270. package/dist/src/state/state-renderer.js.map +1 -1
  271. package/dist/src/state/types.d.ts +10 -5
  272. package/dist/src/state/types.d.ts.map +1 -1
  273. package/dist/src/state/url-sanitization.d.ts +22 -0
  274. package/dist/src/state/url-sanitization.d.ts.map +1 -0
  275. package/dist/src/state/url-sanitization.js +76 -0
  276. package/dist/src/state/url-sanitization.js.map +1 -0
  277. package/dist/src/state/value-masking.d.ts +36 -0
  278. package/dist/src/state/value-masking.d.ts.map +1 -0
  279. package/dist/src/state/value-masking.js +86 -0
  280. package/dist/src/state/value-masking.js.map +1 -0
  281. package/dist/src/tools/action-context.d.ts +55 -0
  282. package/dist/src/tools/action-context.d.ts.map +1 -0
  283. package/dist/src/tools/action-context.js +69 -0
  284. package/dist/src/tools/action-context.js.map +1 -0
  285. package/dist/src/tools/action-stabilization.d.ts +48 -0
  286. package/dist/src/tools/action-stabilization.d.ts.map +1 -0
  287. package/dist/src/tools/action-stabilization.js +93 -0
  288. package/dist/src/tools/action-stabilization.js.map +1 -0
  289. package/dist/src/tools/browser-tools.d.ts +9 -167
  290. package/dist/src/tools/browser-tools.d.ts.map +1 -1
  291. package/dist/src/tools/browser-tools.js +15 -651
  292. package/dist/src/tools/browser-tools.js.map +1 -1
  293. package/dist/src/tools/canvas-tools.d.ts +2 -1
  294. package/dist/src/tools/canvas-tools.d.ts.map +1 -1
  295. package/dist/src/tools/canvas-tools.js +5 -7
  296. package/dist/src/tools/canvas-tools.js.map +1 -1
  297. package/dist/src/tools/effect-tracker.d.ts +25 -0
  298. package/dist/src/tools/effect-tracker.d.ts.map +1 -0
  299. package/dist/src/tools/effect-tracker.js +69 -0
  300. package/dist/src/tools/effect-tracker.js.map +1 -0
  301. package/dist/src/tools/errors.d.ts +2 -34
  302. package/dist/src/tools/errors.d.ts.map +1 -1
  303. package/dist/src/tools/errors.js +1 -44
  304. package/dist/src/tools/errors.js.map +1 -1
  305. package/dist/src/tools/execute-action.d.ts +5 -34
  306. package/dist/src/tools/execute-action.d.ts.map +1 -1
  307. package/dist/src/tools/execute-action.js +37 -297
  308. package/dist/src/tools/execute-action.js.map +1 -1
  309. package/dist/src/tools/form-tools.d.ts +5 -10
  310. package/dist/src/tools/form-tools.d.ts.map +1 -1
  311. package/dist/src/tools/form-tools.js +42 -22
  312. package/dist/src/tools/form-tools.js.map +1 -1
  313. package/dist/src/tools/index.d.ts +6 -6
  314. package/dist/src/tools/index.d.ts.map +1 -1
  315. package/dist/src/tools/index.js +16 -17
  316. package/dist/src/tools/index.js.map +1 -1
  317. package/dist/src/tools/interaction-tools.d.ts +47 -0
  318. package/dist/src/tools/interaction-tools.d.ts.map +1 -0
  319. package/dist/src/tools/interaction-tools.js +135 -0
  320. package/dist/src/tools/interaction-tools.js.map +1 -0
  321. package/dist/src/tools/navigation-detection.d.ts +31 -0
  322. package/dist/src/tools/navigation-detection.d.ts.map +1 -0
  323. package/dist/src/tools/navigation-detection.js +46 -0
  324. package/dist/src/tools/navigation-detection.js.map +1 -0
  325. package/dist/src/tools/navigation-tools.d.ts +51 -0
  326. package/dist/src/tools/navigation-tools.d.ts.map +1 -0
  327. package/dist/src/tools/navigation-tools.js +171 -0
  328. package/dist/src/tools/navigation-tools.js.map +1 -0
  329. package/dist/src/tools/observation-tools.d.ts +54 -0
  330. package/dist/src/tools/observation-tools.d.ts.map +1 -0
  331. package/dist/src/tools/observation-tools.js +243 -0
  332. package/dist/src/tools/observation-tools.js.map +1 -0
  333. package/dist/src/tools/readability-tools.d.ts +16 -0
  334. package/dist/src/tools/readability-tools.d.ts.map +1 -0
  335. package/dist/src/tools/readability-tools.js +45 -0
  336. package/dist/src/tools/readability-tools.js.map +1 -0
  337. package/dist/src/tools/response-builder.d.ts +20 -32
  338. package/dist/src/tools/response-builder.d.ts.map +1 -1
  339. package/dist/src/tools/response-builder.js +32 -48
  340. package/dist/src/tools/response-builder.js.map +1 -1
  341. package/dist/src/tools/stale-element-retry.d.ts +37 -0
  342. package/dist/src/tools/stale-element-retry.d.ts.map +1 -0
  343. package/dist/src/tools/stale-element-retry.js +103 -0
  344. package/dist/src/tools/stale-element-retry.js.map +1 -0
  345. package/dist/src/tools/tool-context.d.ts +4 -36
  346. package/dist/src/tools/tool-context.d.ts.map +1 -1
  347. package/dist/src/tools/tool-context.js +6 -75
  348. package/dist/src/tools/tool-context.js.map +1 -1
  349. package/dist/src/tools/tool-context.types.d.ts +141 -0
  350. package/dist/src/tools/tool-context.types.d.ts.map +1 -0
  351. package/dist/src/tools/tool-context.types.js +11 -0
  352. package/dist/src/tools/tool-context.types.js.map +1 -0
  353. package/dist/src/tools/tool-registration.d.ts +25 -0
  354. package/dist/src/tools/tool-registration.d.ts.map +1 -0
  355. package/dist/src/tools/tool-registration.js +180 -0
  356. package/dist/src/tools/tool-registration.js.map +1 -0
  357. package/dist/src/tools/tool-schemas.d.ts +176 -1950
  358. package/dist/src/tools/tool-schemas.d.ts.map +1 -1
  359. package/dist/src/tools/tool-schemas.js +80 -320
  360. package/dist/src/tools/tool-schemas.js.map +1 -1
  361. package/dist/src/tools/viewport-tools.d.ts +37 -0
  362. package/dist/src/tools/viewport-tools.d.ts.map +1 -0
  363. package/dist/src/tools/viewport-tools.js +101 -0
  364. package/dist/src/tools/viewport-tools.js.map +1 -0
  365. package/dist/src/worker/chrome-worker-process.d.ts +4 -0
  366. package/dist/src/worker/chrome-worker-process.d.ts.map +1 -1
  367. package/dist/src/worker/chrome-worker-process.js +1 -1
  368. package/dist/src/worker/chrome-worker-process.js.map +1 -1
  369. package/package.json +7 -3
  370. package/dist/src/factpack/action-selector.d.ts +0 -36
  371. package/dist/src/factpack/action-selector.d.ts.map +0 -1
  372. package/dist/src/factpack/action-selector.js +0 -367
  373. package/dist/src/factpack/action-selector.js.map +0 -1
  374. package/dist/src/factpack/dialog-detector.d.ts +0 -19
  375. package/dist/src/factpack/dialog-detector.d.ts.map +0 -1
  376. package/dist/src/factpack/dialog-detector.js +0 -354
  377. package/dist/src/factpack/dialog-detector.js.map +0 -1
  378. package/dist/src/factpack/form-detector.d.ts +0 -28
  379. package/dist/src/factpack/form-detector.d.ts.map +0 -1
  380. package/dist/src/factpack/form-detector.js +0 -555
  381. package/dist/src/factpack/form-detector.js.map +0 -1
  382. package/dist/src/factpack/index.d.ts +0 -32
  383. package/dist/src/factpack/index.d.ts.map +0 -1
  384. package/dist/src/factpack/index.js +0 -73
  385. package/dist/src/factpack/index.js.map +0 -1
  386. package/dist/src/factpack/page-classifier.d.ts +0 -22
  387. package/dist/src/factpack/page-classifier.d.ts.map +0 -1
  388. package/dist/src/factpack/page-classifier.js +0 -526
  389. package/dist/src/factpack/page-classifier.js.map +0 -1
  390. package/dist/src/factpack/types.d.ts +0 -307
  391. package/dist/src/factpack/types.d.ts.map +0 -1
  392. package/dist/src/factpack/types.js +0 -12
  393. package/dist/src/factpack/types.js.map +0 -1
  394. package/dist/src/lib/constants.d.ts +0 -27
  395. package/dist/src/lib/constants.d.ts.map +0 -1
  396. package/dist/src/lib/constants.js +0 -63
  397. package/dist/src/lib/constants.js.map +0 -1
  398. package/dist/src/lib/index.d.ts +0 -12
  399. package/dist/src/lib/index.d.ts.map +0 -1
  400. package/dist/src/lib/index.js +0 -17
  401. package/dist/src/lib/index.js.map +0 -1
  402. package/dist/src/lib/regions.d.ts +0 -29
  403. package/dist/src/lib/regions.d.ts.map +0 -1
  404. package/dist/src/lib/regions.js +0 -93
  405. package/dist/src/lib/regions.js.map +0 -1
  406. package/dist/src/lib/scoring.d.ts +0 -47
  407. package/dist/src/lib/scoring.d.ts.map +0 -1
  408. package/dist/src/lib/scoring.js +0 -79
  409. package/dist/src/lib/scoring.js.map +0 -1
  410. package/dist/src/lib/selectors.d.ts +0 -42
  411. package/dist/src/lib/selectors.d.ts.map +0 -1
  412. package/dist/src/lib/selectors.js +0 -138
  413. package/dist/src/lib/selectors.js.map +0 -1
  414. package/dist/src/renderer/budget-manager.d.ts +0 -46
  415. package/dist/src/renderer/budget-manager.d.ts.map +0 -1
  416. package/dist/src/renderer/budget-manager.js +0 -133
  417. package/dist/src/renderer/budget-manager.js.map +0 -1
  418. package/dist/src/renderer/constants.d.ts +0 -38
  419. package/dist/src/renderer/constants.d.ts.map +0 -1
  420. package/dist/src/renderer/constants.js +0 -29
  421. package/dist/src/renderer/constants.js.map +0 -1
  422. package/dist/src/renderer/index.d.ts +0 -12
  423. package/dist/src/renderer/index.d.ts.map +0 -1
  424. package/dist/src/renderer/index.js +0 -16
  425. package/dist/src/renderer/index.js.map +0 -1
  426. package/dist/src/renderer/section-renderers.d.ts +0 -42
  427. package/dist/src/renderer/section-renderers.d.ts.map +0 -1
  428. package/dist/src/renderer/section-renderers.js +0 -252
  429. package/dist/src/renderer/section-renderers.js.map +0 -1
  430. package/dist/src/renderer/token-counter.d.ts +0 -45
  431. package/dist/src/renderer/token-counter.d.ts.map +0 -1
  432. package/dist/src/renderer/token-counter.js +0 -65
  433. package/dist/src/renderer/token-counter.js.map +0 -1
  434. package/dist/src/renderer/types.d.ts +0 -71
  435. package/dist/src/renderer/types.d.ts.map +0 -1
  436. package/dist/src/renderer/types.js +0 -7
  437. package/dist/src/renderer/types.js.map +0 -1
  438. package/dist/src/renderer/xml-renderer.d.ts +0 -42
  439. package/dist/src/renderer/xml-renderer.d.ts.map +0 -1
  440. package/dist/src/renderer/xml-renderer.js +0 -103
  441. package/dist/src/renderer/xml-renderer.js.map +0 -1
  442. package/dist/src/server/session-store.d.ts +0 -163
  443. package/dist/src/server/session-store.d.ts.map +0 -1
  444. package/dist/src/server/session-store.js +0 -248
  445. package/dist/src/server/session-store.js.map +0 -1
  446. package/dist/src/session/session-worker-binding.d.ts +0 -57
  447. package/dist/src/session/session-worker-binding.d.ts.map +0 -1
  448. package/dist/src/session/session-worker-binding.js +0 -109
  449. package/dist/src/session/session-worker-binding.js.map +0 -1
  450. package/dist/src/shared/services/dom-transformer.service.d.ts +0 -71
  451. package/dist/src/shared/services/dom-transformer.service.d.ts.map +0 -1
  452. package/dist/src/shared/services/dom-transformer.service.js +0 -190
  453. package/dist/src/shared/services/dom-transformer.service.js.map +0 -1
  454. package/dist/src/shared/services/selector-builder.service.d.ts +0 -53
  455. package/dist/src/shared/services/selector-builder.service.d.ts.map +0 -1
  456. package/dist/src/shared/services/selector-builder.service.js +0 -240
  457. package/dist/src/shared/services/selector-builder.service.js.map +0 -1
  458. package/dist/src/state/constants.d.ts +0 -125
  459. package/dist/src/state/constants.d.ts.map +0 -1
  460. package/dist/src/state/constants.js +0 -131
  461. package/dist/src/state/constants.js.map +0 -1
@@ -10,294 +10,14 @@
10
10
  * - Accessibility: Semantic information
11
11
  * - CSS: Computed styles (optional, for layout)
12
12
  */
13
- import { createExtractorContext, extractDom, extractAx, extractLayout, extractState, resolveLabel, resolveRegion, buildLocators, resolveGrouping, classifyAxRole, extractAttributes, } from './extractors/index.js';
13
+ import { createExtractorContext, extractDom, extractAx, extractLayout, extractState, resolveLabel, resolveRegion, buildLocators, resolveGrouping, classifyAxRole, extractAttributes, LIVE_REGION_AX_ROLES, } from './extractors/index.js';
14
14
  import { detectInteractivity } from './extractors/interactivity-detector.js';
15
15
  import { getTextContent } from '../lib/text-utils.js';
16
- const ROOT_CONTEXT = 'root';
17
- const LIGHT_DOM_CONTEXT = 'light';
18
- /**
19
- * Build a context key based on iframe and shadow ancestry.
20
- */
21
- function buildContextKey(node) {
22
- const frameKey = node.framePath?.length ? node.framePath.join('/') : ROOT_CONTEXT;
23
- const shadowKey = node.shadowPath?.length ? node.shadowPath.join('/') : LIGHT_DOM_CONTEXT;
24
- return `${frameKey}|${shadowKey}`;
25
- }
26
- /**
27
- * Build context-scoped ID maps to avoid cross-frame/shadow collisions.
28
- */
29
- function buildIdMapsByContext(domResult) {
30
- const idMaps = new Map();
31
- for (const node of domResult.nodes.values()) {
32
- const id = node.attributes?.id;
33
- if (!id)
34
- continue;
35
- const contextKey = buildContextKey(node);
36
- let map = idMaps.get(contextKey);
37
- if (!map) {
38
- map = new Map();
39
- idMaps.set(contextKey, map);
40
- }
41
- map.set(id, node);
42
- }
43
- return idMaps;
44
- }
45
- /**
46
- * Get the ID map scoped to a node's frame/shadow context.
47
- */
48
- function getIdMapForNode(node, idMapsByContext) {
49
- if (!node)
50
- return undefined;
51
- return idMapsByContext.get(buildContextKey(node));
52
- }
53
- /**
54
- * Build adjacency maps for shadow roots and iframe content documents.
55
- * Single O(n) pass through all nodes.
56
- *
57
- * @param domResult - DOM extraction result
58
- * @returns Adjacency maps for shadow roots and content documents
59
- */
60
- function buildAdjacencyMaps(domResult) {
61
- const shadowRootsByHost = new Map();
62
- const contentDocsByFrame = new Map();
63
- for (const [nodeId, node] of domResult.nodes) {
64
- if (node.parentId === undefined)
65
- continue;
66
- if (node.nodeName === '#document-fragment') {
67
- // This is a shadow root - add to shadow host's children
68
- const existing = shadowRootsByHost.get(node.parentId) ?? [];
69
- existing.push(nodeId);
70
- shadowRootsByHost.set(node.parentId, existing);
71
- }
72
- else if (node.nodeName === '#document') {
73
- // This is a content document - add to iframe's children
74
- const existing = contentDocsByFrame.get(node.parentId) ?? [];
75
- existing.push(nodeId);
76
- contentDocsByFrame.set(node.parentId, existing);
77
- }
78
- }
79
- return { shadowRootsByHost, contentDocsByFrame };
80
- }
81
- /**
82
- * Build DOM pre-order index by traversing the DOM tree.
83
- * Also traverses into shadow roots and iframe content documents.
84
- *
85
- * @param domResult - DOM extraction result with nodes and rootId
86
- * @param adjacencyMaps - Precomputed maps for shadow roots and content documents
87
- * @returns Map of backendNodeId -> DOM order index
88
- */
89
- function buildDomOrderIndex(domResult, adjacencyMaps) {
90
- const orderIndex = new Map();
91
- const shadowHostSet = new Set(domResult.shadowRoots);
92
- let index = 0;
93
- function traverse(nodeId) {
94
- const node = domResult.nodes.get(nodeId);
95
- if (!node)
96
- return;
97
- orderIndex.set(nodeId, index++);
98
- // 1. Process light DOM children first (pre-order DFS)
99
- if (node.childNodeIds) {
100
- for (const childId of node.childNodeIds) {
101
- traverse(childId);
102
- }
103
- }
104
- // 2. If this node hosts a shadow root, traverse shadow content (O(1) lookup)
105
- if (shadowHostSet.has(nodeId)) {
106
- const shadowRoots = adjacencyMaps.shadowRootsByHost.get(nodeId) ?? [];
107
- for (const shadowRootId of shadowRoots) {
108
- traverse(shadowRootId);
109
- }
110
- }
111
- // 3. If this node is an iframe, traverse content document (O(1) lookup)
112
- if (node.frameId || node.nodeName.toUpperCase() === 'IFRAME') {
113
- const contentDocs = adjacencyMaps.contentDocsByFrame.get(nodeId) ?? [];
114
- for (const contentDocId of contentDocs) {
115
- traverse(contentDocId);
116
- }
117
- }
118
- }
119
- traverse(domResult.rootId);
120
- return orderIndex;
121
- }
122
- /**
123
- * Build heading index mapping each backendNodeId to its heading context.
124
- * Uses DOM order to determine the most recent preceding heading.
125
- * Also traverses into shadow roots and iframe content documents.
126
- *
127
- * Heading context is isolated at iframe boundaries:
128
- * - Heading from parent document does NOT propagate into iframe
129
- * - Heading from iframe does NOT propagate back to parent document
130
- * - Shadow DOM shares heading context with its host document
131
- *
132
- * @param domResult - DOM extraction result
133
- * @param axResult - AX extraction result for heading names
134
- * @param idMap - Map of DOM ID to RawDomNode for aria-labelledby resolution
135
- * @param adjacencyMaps - Precomputed maps for shadow roots and content documents
136
- * @returns Map of backendNodeId -> heading context string
137
- */
138
- function buildHeadingIndex(domResult, axResult, idMapsByContext, adjacencyMaps) {
139
- const headingIndex = new Map();
140
- const shadowHostSet = new Set(domResult.shadowRoots);
141
- // Helper to check if a node is a heading and resolve its name
142
- function isHeading(backendNodeId) {
143
- const domNode = domResult.nodes.get(backendNodeId);
144
- const axNode = axResult?.nodes.get(backendNodeId);
145
- // Check AX role first
146
- const scopedIdMap = domNode ? getIdMapForNode(domNode, idMapsByContext) : undefined;
147
- if (axNode?.role === 'heading') {
148
- // Priority: AX name -> resolveLabel -> DOM text content
149
- let name = axNode.name;
150
- if (!name && domNode) {
151
- const labelResult = resolveLabel(domNode, axNode, scopedIdMap);
152
- if (labelResult.source !== 'none') {
153
- name = labelResult.label;
154
- }
155
- }
156
- name ??= getTextContent(backendNodeId, domResult.nodes);
157
- return { isHeading: true, name };
158
- }
159
- // Check DOM tag (H1-H6)
160
- if (domNode?.nodeName?.match(/^H[1-6]$/i)) {
161
- // Priority: AX name -> resolveLabel -> DOM text content
162
- let name = axNode?.name;
163
- if (!name) {
164
- const labelResult = resolveLabel(domNode, axNode, scopedIdMap);
165
- if (labelResult.source !== 'none') {
166
- name = labelResult.label;
167
- }
168
- }
169
- name ??= getTextContent(backendNodeId, domResult.nodes);
170
- return { isHeading: true, name };
171
- }
172
- return { isHeading: false };
173
- }
174
- // Traverse DOM in pre-order, passing and returning heading context
175
- function traverse(nodeId, currentHeading) {
176
- const node = domResult.nodes.get(nodeId);
177
- if (!node)
178
- return currentHeading;
179
- // Check if this node is a heading
180
- const headingInfo = isHeading(nodeId);
181
- if (headingInfo.isHeading && headingInfo.name) {
182
- currentHeading = headingInfo.name;
183
- }
184
- // Record the current heading context for this node
185
- if (currentHeading) {
186
- headingIndex.set(nodeId, currentHeading);
187
- }
188
- // 1. Process light DOM children first (pre-order DFS)
189
- // Heading context propagates and updates through light DOM
190
- if (node.childNodeIds) {
191
- for (const childId of node.childNodeIds) {
192
- currentHeading = traverse(childId, currentHeading) ?? currentHeading;
193
- }
194
- }
195
- // 2. If this node hosts a shadow root, traverse shadow content (O(1) lookup)
196
- // Shadow DOM shares heading context with host document (same logical document)
197
- if (shadowHostSet.has(nodeId)) {
198
- const shadowRoots = adjacencyMaps.shadowRootsByHost.get(nodeId) ?? [];
199
- for (const shadowRootId of shadowRoots) {
200
- currentHeading = traverse(shadowRootId, currentHeading) ?? currentHeading;
201
- }
202
- }
203
- // 3. If this node is an iframe, traverse content document (O(1) lookup)
204
- // IMPORTANT: Heading context resets at iframe boundary (separate document)
205
- // - Pass undefined to reset context inside iframe
206
- // - Discard returned heading (iframe headings don't affect parent)
207
- if (node.frameId || node.nodeName.toUpperCase() === 'IFRAME') {
208
- const contentDocs = adjacencyMaps.contentDocsByFrame.get(nodeId) ?? [];
209
- for (const contentDocId of contentDocs) {
210
- traverse(contentDocId, undefined);
211
- }
212
- }
213
- return currentHeading;
214
- }
215
- traverse(domResult.rootId, undefined);
216
- return headingIndex;
217
- }
218
- /**
219
- * Recursively collect frame loaderIds from frame tree.
220
- */
221
- function collectFrameLoaderIds(frameTree, frameLoaderIds, _isMainFrame = true) {
222
- const frame = frameTree.frame;
223
- frameLoaderIds.set(frame.id, {
224
- frameId: frame.id,
225
- loaderId: frame.loaderId,
226
- isMainFrame: !frame.parentId,
227
- });
228
- if (frameTree.childFrames) {
229
- for (const child of frameTree.childFrames) {
230
- collectFrameLoaderIds(child, frameLoaderIds, false);
231
- }
232
- }
233
- }
234
- /**
235
- * Default compile options
236
- */
237
- const DEFAULT_OPTIONS = {
238
- include_hidden: false,
239
- max_nodes: 2000,
240
- timeout: 30000,
241
- redact_sensitive: true,
242
- include_values: true, // Enable value extraction with password redaction
243
- includeReadable: true,
244
- includeLayout: true,
245
- };
246
- /**
247
- * Map AX role to NodeKind.
248
- */
249
- function mapRoleToKind(role) {
250
- if (!role)
251
- return undefined;
252
- const normalized = role.toLowerCase();
253
- const kindMap = {
254
- // Interactive
255
- button: 'button',
256
- link: 'link',
257
- textbox: 'input',
258
- searchbox: 'input',
259
- combobox: 'combobox',
260
- listbox: 'select',
261
- checkbox: 'checkbox',
262
- radio: 'radio',
263
- switch: 'switch',
264
- slider: 'slider',
265
- spinbutton: 'slider',
266
- tab: 'tab',
267
- menuitem: 'menuitem',
268
- menuitemcheckbox: 'menuitem',
269
- menuitemradio: 'menuitem',
270
- option: 'menuitem',
271
- // Readable
272
- heading: 'heading',
273
- paragraph: 'paragraph',
274
- text: 'text',
275
- statictext: 'text',
276
- list: 'list',
277
- listitem: 'listitem',
278
- tree: 'list',
279
- treeitem: 'listitem',
280
- image: 'image',
281
- img: 'image',
282
- figure: 'image',
283
- canvas: 'canvas',
284
- table: 'table',
285
- grid: 'table',
286
- treegrid: 'table',
287
- // Structural
288
- form: 'form',
289
- dialog: 'dialog',
290
- alertdialog: 'dialog',
291
- navigation: 'navigation',
292
- region: 'section',
293
- article: 'section',
294
- main: 'section',
295
- banner: 'section',
296
- complementary: 'section',
297
- contentinfo: 'section',
298
- };
299
- return kindMap[normalized];
300
- }
16
+ import { buildIdMapsByContext, getIdMapForNode, buildAdjacencyMaps, buildDomOrderIndex, collectFrameLoaderIds, } from './frame-context.js';
17
+ import { buildHeadingIndex } from './heading-index.js';
18
+ import { synthesizeOptionNodes, synthesizeCanvasNodes, promoteToastNodes, } from './node-synthesizer.js';
19
+ import { filterNoiseNodes, sliceWithOverlayPriority } from './node-filter.js';
20
+ import { mapRoleToKind, getKindFromTag, DEFAULT_OPTIONS, } from './kind-mapping.js';
301
21
  /**
302
22
  * SnapshotCompiler class
303
23
  *
@@ -427,7 +147,10 @@ export class SnapshotCompiler {
427
147
  const isReadable = classification === 'readable' && this.options.includeReadable;
428
148
  const isEssentialStructural = classification === 'structural' &&
429
149
  essentialStructuralRoles.has(axNode.role?.toLowerCase() ?? '');
430
- if (isInteractive || isReadable || isEssentialStructural) {
150
+ // Live region roles (alert, status, log, tooltip, progressbar, timer)
151
+ // are always included — they carry critical action feedback
152
+ const isLiveRegion = classification === 'live';
153
+ if (isInteractive || isReadable || isEssentialStructural || isLiveRegion) {
431
154
  const domNode = domResult?.nodes.get(backendNodeId);
432
155
  nodesToProcess.push({
433
156
  backendNodeId,
@@ -449,90 +172,11 @@ export class SnapshotCompiler {
449
172
  }
450
173
  }
451
174
  }
452
- // Phase 2.1: Synthesize option nodes from <select> children.
453
- // Chrome's AX tree often marks <option> nodes as ignored when the select
454
- // is collapsed, and their bounding boxes are zero (OS-rendered).
455
- // We inject them from the DOM so AI agents can discover available options.
456
- if (domResult) {
457
- const alreadyInSet = new Set(nodesToProcess.map((n) => n.backendNodeId));
458
- for (const nodeData of [...nodesToProcess]) {
459
- const domNode = nodeData.domNode;
460
- if (domNode?.nodeName.toUpperCase() !== 'SELECT')
461
- continue;
462
- const collectOptions = (parentId) => {
463
- const parent = domResult.nodes.get(parentId);
464
- if (!parent?.childNodeIds)
465
- return;
466
- for (const childId of parent.childNodeIds) {
467
- const child = domResult.nodes.get(childId);
468
- if (!child)
469
- continue;
470
- const childTag = child.nodeName.toUpperCase();
471
- if (childTag === 'OPTGROUP') {
472
- // Recurse into optgroup to find nested options
473
- collectOptions(childId);
474
- }
475
- else if (childTag === 'OPTION' && !alreadyInSet.has(childId)) {
476
- // Extract text content from option's child text nodes
477
- const optionText = getTextContent(childId, domResult.nodes);
478
- // Build synthetic AX node so label resolution and state extraction work
479
- const syntheticAx = {
480
- nodeId: `synthetic-opt-${childId}`,
481
- backendDOMNodeId: childId,
482
- role: 'option',
483
- name: optionText ?? '',
484
- properties: [],
485
- };
486
- // Transfer selected attribute to AX property
487
- if (child.attributes?.selected !== undefined) {
488
- syntheticAx.properties.push({
489
- name: 'selected',
490
- value: { type: 'boolean', value: true },
491
- });
492
- }
493
- // Transfer disabled attribute to AX property
494
- if (child.attributes?.disabled !== undefined) {
495
- syntheticAx.properties.push({
496
- name: 'disabled',
497
- value: { type: 'boolean', value: true },
498
- });
499
- }
500
- nodesToProcess.push({
501
- backendNodeId: childId,
502
- domNode: child,
503
- axNode: syntheticAx,
504
- });
505
- alreadyInSet.add(childId);
506
- }
507
- }
508
- };
509
- collectOptions(domNode.backendNodeId);
510
- }
511
- }
512
- // Phase 2.2: Synthesize canvas nodes from DOM.
513
- // Canvas elements are classified as generic/ignored by the AX tree,
514
- // so we inject them from the DOM so AI agents can discover and interact with them.
175
+ // Phase 2.1-2.3: Synthesize missing nodes from DOM
515
176
  if (domResult) {
516
- const alreadyInCanvas = new Set(nodesToProcess.map((n) => n.backendNodeId));
517
- for (const [backendNodeId, domNode] of domResult.nodes) {
518
- if (domNode.nodeName.toUpperCase() !== 'CANVAS')
519
- continue;
520
- if (alreadyInCanvas.has(backendNodeId))
521
- continue;
522
- const syntheticAx = {
523
- nodeId: `synthetic-canvas-${backendNodeId}`,
524
- backendDOMNodeId: backendNodeId,
525
- role: 'canvas',
526
- name: domNode.attributes?.['aria-label'] ?? '',
527
- properties: [],
528
- };
529
- nodesToProcess.push({
530
- backendNodeId,
531
- domNode,
532
- axNode: syntheticAx,
533
- });
534
- alreadyInCanvas.add(backendNodeId);
535
- }
177
+ synthesizeOptionNodes(nodesToProcess, domResult);
178
+ synthesizeCanvasNodes(nodesToProcess, domResult);
179
+ promoteToastNodes(nodesToProcess, domResult);
536
180
  }
537
181
  // Sort by DOM order if available (before max_nodes slicing)
538
182
  if (domOrderAvailable && domOrderIndex) {
@@ -678,7 +322,7 @@ export class SnapshotCompiler {
678
322
  }
679
323
  }
680
324
  // Phase 4.5: Filter noise nodes (empty containers, duplicate text)
681
- const nodes = this.filterNoiseNodes(transformedNodes, domResult?.nodes ?? new Map(), axResult?.nodes ?? new Map());
325
+ const nodes = filterNoiseNodes(transformedNodes, domResult?.nodes ?? new Map(), axResult?.nodes ?? new Map());
682
326
  // Phase 5: Build BaseSnapshot
683
327
  const duration = Date.now() - startTime;
684
328
  const interactiveCount = nodes.filter((n) => [
@@ -710,12 +354,26 @@ export class SnapshotCompiler {
710
354
  if (warnings.length > 0) {
711
355
  meta.warnings = warnings;
712
356
  }
357
+ let scroll;
358
+ try {
359
+ const scrollResult = await cdp.send('Runtime.evaluate', {
360
+ expression: 'JSON.stringify({x:Math.round(window.scrollX),y:Math.round(window.scrollY)})',
361
+ returnByValue: true,
362
+ });
363
+ if (scrollResult.result?.value) {
364
+ scroll = JSON.parse(scrollResult.result.value);
365
+ }
366
+ }
367
+ catch {
368
+ // Scroll position is non-critical; snapshot is still valid without it
369
+ }
713
370
  return {
714
371
  snapshot_id: this.generateSnapshotId(),
715
372
  url: page.url(),
716
373
  title: await page.title(),
717
374
  captured_at: new Date().toISOString(),
718
375
  viewport,
376
+ scroll,
719
377
  nodes,
720
378
  meta,
721
379
  };
@@ -750,14 +408,22 @@ export class SnapshotCompiler {
750
408
  kind = mapRoleToKind(axNode.role) ?? 'generic';
751
409
  }
752
410
  else if (domNode) {
753
- const tagKind = this.getKindFromTag(domNode.nodeName);
411
+ const tagKind = getKindFromTag(domNode.nodeName);
754
412
  if (tagKind)
755
413
  kind = tagKind;
756
414
  }
757
415
  // Resolve label
758
416
  const scopedIdMap = getIdMapForNode(domNode, idMapsByContext);
759
417
  const labelResult = resolveLabel(domNode, axNode, scopedIdMap);
760
- const label = labelResult.label;
418
+ let label = labelResult.label;
419
+ // Fallback for live region containers (alert, status, etc.) with empty labels:
420
+ // Their text typically lives in child StaticText/text nodes, not in the AX name.
421
+ if (!label &&
422
+ axNode?.role &&
423
+ LIVE_REGION_AX_ROLES.has(axNode.role.toLowerCase()) &&
424
+ domTree.size > 0) {
425
+ label = getTextContent(backendNodeId, domTree, 3) ?? '';
426
+ }
761
427
  // Resolve region (pass axTree for ancestor AX role lookup)
762
428
  const region = resolveRegion(domNode, axNode, domTree, axTree);
763
429
  // Resolve grouping (for group_id and group_path only)
@@ -787,8 +453,7 @@ export class SnapshotCompiler {
787
453
  : {
788
454
  bbox: { x: 0, y: 0, w: 0, h: 0 },
789
455
  };
790
- // Extract state
791
- const state = extractState(domNode, axNode, layout);
456
+ const state = extractState(domNode, axNode, layout, nodeData.interactivity);
792
457
  // Build locators
793
458
  const locators = buildLocators(domNode, axNode, label);
794
459
  // Build attributes using extractor module
@@ -825,180 +490,6 @@ export class SnapshotCompiler {
825
490
  }
826
491
  return node;
827
492
  }
828
- /**
829
- * Get NodeKind from HTML tag name.
830
- */
831
- getKindFromTag(tagName) {
832
- const tag = tagName.toUpperCase();
833
- const tagMap = {
834
- BUTTON: 'button',
835
- A: 'link',
836
- INPUT: 'input',
837
- TEXTAREA: 'textarea',
838
- SELECT: 'select',
839
- H1: 'heading',
840
- H2: 'heading',
841
- H3: 'heading',
842
- H4: 'heading',
843
- H5: 'heading',
844
- H6: 'heading',
845
- P: 'paragraph',
846
- IMG: 'image',
847
- TABLE: 'table',
848
- UL: 'list',
849
- OL: 'list',
850
- LI: 'listitem',
851
- FORM: 'form',
852
- DIALOG: 'dialog',
853
- NAV: 'navigation',
854
- OPTION: 'menuitem',
855
- CANVAS: 'canvas',
856
- };
857
- return tagMap[tag];
858
- }
859
- /**
860
- * Filter out noise nodes to reduce snapshot size.
861
- *
862
- * Filters:
863
- * 1. Empty list/listitem containers with no semantic name AND no interactive descendants
864
- * 2. StaticText/text nodes that mirror their parent's label exactly
865
- */
866
- filterNoiseNodes(nodes, domTree, axTree) {
867
- // Build set of interactive node backend IDs for descendant checking
868
- const interactiveKinds = new Set([
869
- 'button',
870
- 'link',
871
- 'input',
872
- 'textarea',
873
- 'select',
874
- 'combobox',
875
- 'checkbox',
876
- 'radio',
877
- 'switch',
878
- 'slider',
879
- 'tab',
880
- 'menuitem',
881
- 'canvas',
882
- ]);
883
- const interactiveBackendIds = new Set(nodes.filter((n) => interactiveKinds.has(n.kind)).map((n) => n.backend_node_id));
884
- // Build parent-child relationship from DOM tree
885
- const childToParent = new Map();
886
- for (const [nodeId, domNode] of domTree) {
887
- if (domNode.parentId !== undefined) {
888
- childToParent.set(nodeId, domNode.parentId);
889
- }
890
- }
891
- // Check if a node has any interactive descendants in the DOM tree
892
- const hasInteractiveDescendant = (nodeId) => {
893
- const domNode = domTree.get(nodeId);
894
- if (!domNode)
895
- return false;
896
- // Check direct children
897
- if (domNode.childNodeIds) {
898
- for (const childId of domNode.childNodeIds) {
899
- if (interactiveBackendIds.has(childId)) {
900
- return true;
901
- }
902
- if (hasInteractiveDescendant(childId)) {
903
- return true;
904
- }
905
- }
906
- }
907
- return false;
908
- };
909
- // Get label of parent node in the node list
910
- const getParentLabel = (nodeId) => {
911
- const parentId = childToParent.get(nodeId);
912
- if (parentId === undefined)
913
- return undefined;
914
- // Look up parent in our node list
915
- const parentNode = nodes.find((n) => n.backend_node_id === parentId);
916
- if (parentNode) {
917
- return parentNode.label;
918
- }
919
- // Parent might be further up - check AX tree for parent's name
920
- const parentAx = axTree.get(parentId);
921
- return parentAx?.name;
922
- };
923
- // Container kinds that can be noisy when empty
924
- const containerKinds = new Set(['list', 'listitem']);
925
- // Text kinds that can duplicate parent labels
926
- const textKinds = new Set(['text']);
927
- return nodes.filter((node) => {
928
- // Rule 1: Filter empty container nodes without interactive descendants
929
- if (containerKinds.has(node.kind)) {
930
- const hasSemanticName = node.label && node.label.trim().length > 0;
931
- if (!hasSemanticName) {
932
- const hasInteractive = hasInteractiveDescendant(node.backend_node_id);
933
- if (!hasInteractive) {
934
- return false; // Filter out empty container without interactive content
935
- }
936
- }
937
- }
938
- // Rule 2: Filter text nodes that mirror parent's label
939
- if (textKinds.has(node.kind)) {
940
- const parentLabel = getParentLabel(node.backend_node_id);
941
- if (parentLabel && node.label) {
942
- // Normalize and compare
943
- const normalizedParent = parentLabel.trim().toLowerCase();
944
- const normalizedNode = node.label.trim().toLowerCase();
945
- if (normalizedNode === normalizedParent) {
946
- return false; // Filter out duplicate text
947
- }
948
- }
949
- }
950
- return true; // Keep the node
951
- });
952
- }
953
- }
954
- /**
955
- * Slice nodes to max_nodes budget while preserving high z-index overlay content.
956
- *
957
- * Portal-rendered content (dropdowns, popovers, modals) appears at the end of
958
- * DOM order. On heavy pages, a naive slice truncates it.
959
- *
960
- * Strategy:
961
- * 1. Partition nodes into overlay (z-index > threshold) and main
962
- * 2. Take all overlay nodes (up to 30% of budget)
963
- * 3. Fill remaining budget with main nodes (DOM order)
964
- * 4. Re-sort by original DOM order
965
- */
966
- export function sliceWithOverlayPriority(nodes, maxNodes) {
967
- if (nodes.length <= maxNodes) {
968
- return nodes;
969
- }
970
- const OVERLAY_Z_THRESHOLD = 100;
971
- const MAX_OVERLAY_RATIO = 0.3;
972
- const overlayNodes = [];
973
- const mainNodes = [];
974
- for (const node of nodes) {
975
- const zIndex = node.layout?.zIndex;
976
- if (zIndex !== undefined && zIndex > OVERLAY_Z_THRESHOLD) {
977
- overlayNodes.push(node);
978
- }
979
- else {
980
- mainNodes.push(node);
981
- }
982
- }
983
- // No overlay content → simple slice
984
- if (overlayNodes.length === 0) {
985
- return nodes.slice(0, maxNodes);
986
- }
987
- // Reserve budget for overlay (capped at 30% of total)
988
- const maxOverlay = Math.min(overlayNodes.length, Math.floor(maxNodes * MAX_OVERLAY_RATIO));
989
- const overlaySlice = overlayNodes.slice(0, maxOverlay);
990
- // Fill remaining budget with main content
991
- const mainBudget = maxNodes - overlaySlice.length;
992
- const mainSlice = mainNodes.slice(0, mainBudget);
993
- // Merge and re-sort by original DOM order
994
- const merged = [...mainSlice, ...overlaySlice];
995
- const indexMap = new Map(nodes.map((n, i) => [n.backendNodeId, i]));
996
- merged.sort((a, b) => {
997
- const ia = indexMap.get(a.backendNodeId) ?? Infinity;
998
- const ib = indexMap.get(b.backendNodeId) ?? Infinity;
999
- return ia - ib;
1000
- });
1001
- return merged;
1002
493
  }
1003
494
  /**
1004
495
  * Export a compile function for simpler usage.