agent-web-interface 4.2.0 → 4.4.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 (265) hide show
  1. package/dist/src/browser/connection-utils.d.ts +48 -0
  2. package/dist/src/browser/connection-utils.d.ts.map +1 -0
  3. package/dist/src/browser/connection-utils.js +129 -0
  4. package/dist/src/browser/connection-utils.js.map +1 -0
  5. package/dist/src/browser/index.d.ts +3 -1
  6. package/dist/src/browser/index.d.ts.map +1 -1
  7. package/dist/src/browser/index.js +2 -1
  8. package/dist/src/browser/index.js.map +1 -1
  9. package/dist/src/browser/session-manager.d.ts +1 -89
  10. package/dist/src/browser/session-manager.d.ts.map +1 -1
  11. package/dist/src/browser/session-manager.js +1 -116
  12. package/dist/src/browser/session-manager.js.map +1 -1
  13. package/dist/src/browser/session-manager.types.d.ts +90 -0
  14. package/dist/src/browser/session-manager.types.d.ts.map +1 -0
  15. package/dist/src/browser/session-manager.types.js +7 -0
  16. package/dist/src/browser/session-manager.types.js.map +1 -0
  17. package/dist/src/form/constraint-extraction.d.ts +31 -0
  18. package/dist/src/form/constraint-extraction.d.ts.map +1 -0
  19. package/dist/src/form/constraint-extraction.js +110 -0
  20. package/dist/src/form/constraint-extraction.js.map +1 -0
  21. package/dist/src/form/field-extractor.d.ts.map +1 -1
  22. package/dist/src/form/field-extractor.js +3 -444
  23. package/dist/src/form/field-extractor.js.map +1 -1
  24. package/dist/src/form/field-state-extractor.d.ts +22 -0
  25. package/dist/src/form/field-state-extractor.d.ts.map +1 -0
  26. package/dist/src/form/field-state-extractor.js +55 -0
  27. package/dist/src/form/field-state-extractor.js.map +1 -0
  28. package/dist/src/form/form-actions.d.ts +45 -0
  29. package/dist/src/form/form-actions.d.ts.map +1 -0
  30. package/dist/src/form/form-actions.js +108 -0
  31. package/dist/src/form/form-actions.js.map +1 -0
  32. package/dist/src/form/form-detector.d.ts +0 -36
  33. package/dist/src/form/form-detector.d.ts.map +1 -1
  34. package/dist/src/form/form-detector.js +11 -376
  35. package/dist/src/form/form-detector.js.map +1 -1
  36. package/dist/src/form/input-clustering.d.ts +15 -0
  37. package/dist/src/form/input-clustering.d.ts.map +1 -0
  38. package/dist/src/form/input-clustering.js +61 -0
  39. package/dist/src/form/input-clustering.js.map +1 -0
  40. package/dist/src/form/intent-inference.d.ts +28 -0
  41. package/dist/src/form/intent-inference.d.ts.map +1 -0
  42. package/dist/src/form/intent-inference.js +137 -0
  43. package/dist/src/form/intent-inference.js.map +1 -0
  44. package/dist/src/form/purpose-inference.d.ts +50 -0
  45. package/dist/src/form/purpose-inference.d.ts.map +1 -0
  46. package/dist/src/form/purpose-inference.js +313 -0
  47. package/dist/src/form/purpose-inference.js.map +1 -0
  48. package/dist/src/form/submit-detection.d.ts +36 -0
  49. package/dist/src/form/submit-detection.d.ts.map +1 -0
  50. package/dist/src/form/submit-detection.js +101 -0
  51. package/dist/src/form/submit-detection.js.map +1 -0
  52. package/dist/src/form/types.d.ts +2 -2
  53. package/dist/src/index.js +65 -48
  54. package/dist/src/index.js.map +1 -1
  55. package/dist/src/observation/observation-accumulator.d.ts +1 -1
  56. package/dist/src/observation/observation-accumulator.js +1 -1
  57. package/dist/src/observation/observer-script.d.ts +1 -1
  58. package/dist/src/observation/observer-script.d.ts.map +1 -1
  59. package/dist/src/observation/observer-script.js +129 -7
  60. package/dist/src/observation/observer-script.js.map +1 -1
  61. package/dist/src/query/disambiguation.d.ts +18 -0
  62. package/dist/src/query/disambiguation.d.ts.map +1 -0
  63. package/dist/src/query/disambiguation.js +123 -0
  64. package/dist/src/query/disambiguation.js.map +1 -0
  65. package/dist/src/query/fuzzy-match.d.ts +17 -0
  66. package/dist/src/query/fuzzy-match.d.ts.map +1 -0
  67. package/dist/src/query/fuzzy-match.js +34 -0
  68. package/dist/src/query/fuzzy-match.js.map +1 -0
  69. package/dist/src/query/index.d.ts +3 -0
  70. package/dist/src/query/index.d.ts.map +1 -1
  71. package/dist/src/query/index.js +6 -0
  72. package/dist/src/query/index.js.map +1 -1
  73. package/dist/src/query/query-engine.d.ts +0 -35
  74. package/dist/src/query/query-engine.d.ts.map +1 -1
  75. package/dist/src/query/query-engine.js +9 -309
  76. package/dist/src/query/query-engine.js.map +1 -1
  77. package/dist/src/query/scoring.d.ts +52 -0
  78. package/dist/src/query/scoring.d.ts.map +1 -0
  79. package/dist/src/query/scoring.js +162 -0
  80. package/dist/src/query/scoring.js.map +1 -0
  81. package/dist/src/server/mcp-server.d.ts.map +1 -1
  82. package/dist/src/server/mcp-server.js +29 -1
  83. package/dist/src/server/mcp-server.js.map +1 -1
  84. package/dist/src/snapshot/element-resolver.d.ts +50 -18
  85. package/dist/src/snapshot/element-resolver.d.ts.map +1 -1
  86. package/dist/src/snapshot/element-resolver.js +180 -101
  87. package/dist/src/snapshot/element-resolver.js.map +1 -1
  88. package/dist/src/snapshot/extractors/ax-extractor.d.ts +1 -1
  89. package/dist/src/snapshot/extractors/ax-extractor.d.ts.map +1 -1
  90. package/dist/src/snapshot/extractors/ax-extractor.js +4 -1
  91. package/dist/src/snapshot/extractors/ax-extractor.js.map +1 -1
  92. package/dist/src/snapshot/extractors/index.d.ts +1 -1
  93. package/dist/src/snapshot/extractors/index.d.ts.map +1 -1
  94. package/dist/src/snapshot/extractors/index.js +1 -1
  95. package/dist/src/snapshot/extractors/index.js.map +1 -1
  96. package/dist/src/snapshot/extractors/region-resolver.d.ts.map +1 -1
  97. package/dist/src/snapshot/extractors/region-resolver.js +8 -0
  98. package/dist/src/snapshot/extractors/region-resolver.js.map +1 -1
  99. package/dist/src/snapshot/extractors/types.d.ts +8 -0
  100. package/dist/src/snapshot/extractors/types.d.ts.map +1 -1
  101. package/dist/src/snapshot/extractors/types.js +16 -0
  102. package/dist/src/snapshot/extractors/types.js.map +1 -1
  103. package/dist/src/snapshot/frame-context.d.ts +68 -0
  104. package/dist/src/snapshot/frame-context.d.ts.map +1 -0
  105. package/dist/src/snapshot/frame-context.js +131 -0
  106. package/dist/src/snapshot/frame-context.js.map +1 -0
  107. package/dist/src/snapshot/heading-index.d.ts +28 -0
  108. package/dist/src/snapshot/heading-index.d.ts.map +1 -0
  109. package/dist/src/snapshot/heading-index.js +108 -0
  110. package/dist/src/snapshot/heading-index.js.map +1 -0
  111. package/dist/src/snapshot/index.d.ts +5 -3
  112. package/dist/src/snapshot/index.d.ts.map +1 -1
  113. package/dist/src/snapshot/index.js +3 -2
  114. package/dist/src/snapshot/index.js.map +1 -1
  115. package/dist/src/snapshot/kind-mapping.d.ts +30 -0
  116. package/dist/src/snapshot/kind-mapping.d.ts.map +1 -0
  117. package/dist/src/snapshot/kind-mapping.js +114 -0
  118. package/dist/src/snapshot/kind-mapping.js.map +1 -0
  119. package/dist/src/snapshot/node-filter.d.ts +31 -0
  120. package/dist/src/snapshot/node-filter.d.ts.map +1 -0
  121. package/dist/src/snapshot/node-filter.js +137 -0
  122. package/dist/src/snapshot/node-filter.js.map +1 -0
  123. package/dist/src/snapshot/node-synthesizer.d.ts +62 -0
  124. package/dist/src/snapshot/node-synthesizer.d.ts.map +1 -0
  125. package/dist/src/snapshot/node-synthesizer.js +185 -0
  126. package/dist/src/snapshot/node-synthesizer.js.map +1 -0
  127. package/dist/src/snapshot/snapshot-compiler.d.ts +2 -36
  128. package/dist/src/snapshot/snapshot-compiler.d.ts.map +1 -1
  129. package/dist/src/snapshot/snapshot-compiler.js +28 -520
  130. package/dist/src/snapshot/snapshot-compiler.js.map +1 -1
  131. package/dist/src/snapshot/snapshot.types.d.ts +7 -2
  132. package/dist/src/snapshot/snapshot.types.d.ts.map +1 -1
  133. package/dist/src/snapshot/snapshot.types.js +9 -0
  134. package/dist/src/snapshot/snapshot.types.js.map +1 -1
  135. package/dist/src/state/actionables-filter.d.ts +5 -0
  136. package/dist/src/state/actionables-filter.d.ts.map +1 -1
  137. package/dist/src/state/actionables-filter.js +22 -3
  138. package/dist/src/state/actionables-filter.js.map +1 -1
  139. package/dist/src/state/diff-engine.js +3 -3
  140. package/dist/src/state/diff-engine.js.map +1 -1
  141. package/dist/src/state/element-registry.d.ts.map +1 -1
  142. package/dist/src/state/element-registry.js +6 -4
  143. package/dist/src/state/element-registry.js.map +1 -1
  144. package/dist/src/state/hash-utils.d.ts +24 -0
  145. package/dist/src/state/hash-utils.d.ts.map +1 -0
  146. package/dist/src/state/hash-utils.js +41 -0
  147. package/dist/src/state/hash-utils.js.map +1 -0
  148. package/dist/src/state/layer-detector.d.ts.map +1 -1
  149. package/dist/src/state/layer-detector.js +15 -286
  150. package/dist/src/state/layer-detector.js.map +1 -1
  151. package/dist/src/state/layer-detectors/drawer-detector.d.ts +32 -0
  152. package/dist/src/state/layer-detectors/drawer-detector.d.ts.map +1 -0
  153. package/dist/src/state/layer-detectors/drawer-detector.js +96 -0
  154. package/dist/src/state/layer-detectors/drawer-detector.js.map +1 -0
  155. package/dist/src/state/layer-detectors/index.d.ts +10 -0
  156. package/dist/src/state/layer-detectors/index.d.ts.map +1 -0
  157. package/dist/src/state/layer-detectors/index.js +10 -0
  158. package/dist/src/state/layer-detectors/index.js.map +1 -0
  159. package/dist/src/state/layer-detectors/modal-detector.d.ts +30 -0
  160. package/dist/src/state/layer-detectors/modal-detector.d.ts.map +1 -0
  161. package/dist/src/state/layer-detectors/modal-detector.js +127 -0
  162. package/dist/src/state/layer-detectors/modal-detector.js.map +1 -0
  163. package/dist/src/state/layer-detectors/popover-detector.d.ts +20 -0
  164. package/dist/src/state/layer-detectors/popover-detector.d.ts.map +1 -0
  165. package/dist/src/state/layer-detectors/popover-detector.js +76 -0
  166. package/dist/src/state/layer-detectors/popover-detector.js.map +1 -0
  167. package/dist/src/state/layer-detectors/toast-detector.d.ts +24 -0
  168. package/dist/src/state/layer-detectors/toast-detector.d.ts.map +1 -0
  169. package/dist/src/state/layer-detectors/toast-detector.js +48 -0
  170. package/dist/src/state/layer-detectors/toast-detector.js.map +1 -0
  171. package/dist/src/state/region-mapping.d.ts +13 -0
  172. package/dist/src/state/region-mapping.d.ts.map +1 -0
  173. package/dist/src/state/region-mapping.js +25 -0
  174. package/dist/src/state/region-mapping.js.map +1 -0
  175. package/dist/src/state/state-manager.d.ts.map +1 -1
  176. package/dist/src/state/state-manager.js +8 -192
  177. package/dist/src/state/state-manager.js.map +1 -1
  178. package/dist/src/state/state-renderer.d.ts.map +1 -1
  179. package/dist/src/state/state-renderer.js +16 -2
  180. package/dist/src/state/state-renderer.js.map +1 -1
  181. package/dist/src/state/types.d.ts +8 -4
  182. package/dist/src/state/types.d.ts.map +1 -1
  183. package/dist/src/state/url-sanitization.d.ts +22 -0
  184. package/dist/src/state/url-sanitization.d.ts.map +1 -0
  185. package/dist/src/state/url-sanitization.js +60 -0
  186. package/dist/src/state/url-sanitization.js.map +1 -0
  187. package/dist/src/state/value-masking.d.ts +36 -0
  188. package/dist/src/state/value-masking.d.ts.map +1 -0
  189. package/dist/src/state/value-masking.js +86 -0
  190. package/dist/src/state/value-masking.js.map +1 -0
  191. package/dist/src/tools/action-context.d.ts +60 -0
  192. package/dist/src/tools/action-context.d.ts.map +1 -0
  193. package/dist/src/tools/action-context.js +78 -0
  194. package/dist/src/tools/action-context.js.map +1 -0
  195. package/dist/src/tools/action-stabilization.d.ts +48 -0
  196. package/dist/src/tools/action-stabilization.d.ts.map +1 -0
  197. package/dist/src/tools/action-stabilization.js +87 -0
  198. package/dist/src/tools/action-stabilization.js.map +1 -0
  199. package/dist/src/tools/browser-tools.d.ts +8 -146
  200. package/dist/src/tools/browser-tools.d.ts.map +1 -1
  201. package/dist/src/tools/browser-tools.js +13 -689
  202. package/dist/src/tools/browser-tools.js.map +1 -1
  203. package/dist/src/tools/canvas-tools.d.ts +32 -0
  204. package/dist/src/tools/canvas-tools.d.ts.map +1 -0
  205. package/dist/src/tools/canvas-tools.js +370 -0
  206. package/dist/src/tools/canvas-tools.js.map +1 -0
  207. package/dist/src/tools/effect-tracker.d.ts +25 -0
  208. package/dist/src/tools/effect-tracker.d.ts.map +1 -0
  209. package/dist/src/tools/effect-tracker.js +69 -0
  210. package/dist/src/tools/effect-tracker.js.map +1 -0
  211. package/dist/src/tools/execute-action.d.ts +1 -31
  212. package/dist/src/tools/execute-action.d.ts.map +1 -1
  213. package/dist/src/tools/execute-action.js +7 -276
  214. package/dist/src/tools/execute-action.js.map +1 -1
  215. package/dist/src/tools/form-tools.d.ts +4 -6
  216. package/dist/src/tools/form-tools.d.ts.map +1 -1
  217. package/dist/src/tools/form-tools.js +10 -42
  218. package/dist/src/tools/form-tools.js.map +1 -1
  219. package/dist/src/tools/index.d.ts +6 -4
  220. package/dist/src/tools/index.d.ts.map +1 -1
  221. package/dist/src/tools/index.js +21 -10
  222. package/dist/src/tools/index.js.map +1 -1
  223. package/dist/src/tools/interaction-tools.d.ts +46 -0
  224. package/dist/src/tools/interaction-tools.d.ts.map +1 -0
  225. package/dist/src/tools/interaction-tools.js +138 -0
  226. package/dist/src/tools/interaction-tools.js.map +1 -0
  227. package/dist/src/tools/navigation-detection.d.ts +31 -0
  228. package/dist/src/tools/navigation-detection.d.ts.map +1 -0
  229. package/dist/src/tools/navigation-detection.js +46 -0
  230. package/dist/src/tools/navigation-detection.js.map +1 -0
  231. package/dist/src/tools/navigation-tools.d.ts +57 -0
  232. package/dist/src/tools/navigation-tools.d.ts.map +1 -0
  233. package/dist/src/tools/navigation-tools.js +178 -0
  234. package/dist/src/tools/navigation-tools.js.map +1 -0
  235. package/dist/src/tools/observation-tools.d.ts +53 -0
  236. package/dist/src/tools/observation-tools.d.ts.map +1 -0
  237. package/dist/src/tools/observation-tools.js +247 -0
  238. package/dist/src/tools/observation-tools.js.map +1 -0
  239. package/dist/src/tools/response-builder.js +2 -2
  240. package/dist/src/tools/response-builder.js.map +1 -1
  241. package/dist/src/tools/stale-element-retry.d.ts +37 -0
  242. package/dist/src/tools/stale-element-retry.d.ts.map +1 -0
  243. package/dist/src/tools/stale-element-retry.js +68 -0
  244. package/dist/src/tools/stale-element-retry.js.map +1 -0
  245. package/dist/src/tools/state-manager-registry.d.ts +26 -0
  246. package/dist/src/tools/state-manager-registry.d.ts.map +1 -0
  247. package/dist/src/tools/state-manager-registry.js +39 -0
  248. package/dist/src/tools/state-manager-registry.js.map +1 -0
  249. package/dist/src/tools/tool-context.d.ts +53 -0
  250. package/dist/src/tools/tool-context.d.ts.map +1 -0
  251. package/dist/src/tools/tool-context.js +119 -0
  252. package/dist/src/tools/tool-context.js.map +1 -0
  253. package/dist/src/tools/tool-result.types.d.ts +16 -1
  254. package/dist/src/tools/tool-result.types.d.ts.map +1 -1
  255. package/dist/src/tools/tool-result.types.js +11 -0
  256. package/dist/src/tools/tool-result.types.js.map +1 -1
  257. package/dist/src/tools/tool-schemas.d.ts +358 -146
  258. package/dist/src/tools/tool-schemas.d.ts.map +1 -1
  259. package/dist/src/tools/tool-schemas.js +142 -19
  260. package/dist/src/tools/tool-schemas.js.map +1 -1
  261. package/dist/src/tools/viewport-tools.d.ts +36 -0
  262. package/dist/src/tools/viewport-tools.d.ts.map +1 -0
  263. package/dist/src/tools/viewport-tools.js +105 -0
  264. package/dist/src/tools/viewport-tools.js.map +1 -0
  265. package/package.json +1 -1
package/dist/src/index.js CHANGED
@@ -29,11 +29,11 @@ export function getSessionStore() {
29
29
  export function getSessionBinding() {
30
30
  return sessionBinding;
31
31
  }
32
- import { initializeTools, initializeFormTools,
32
+ import { initializeToolContext,
33
33
  // Tool handlers
34
- listPages, closePage, closeSession, navigate, goBack, goForward, reload, captureSnapshot, findElements, getNodeDetails, scrollElementIntoView, scrollPage, click, type, press, select, hover, getFormUnderstanding, getFieldContext, takeScreenshot,
34
+ listPages, closePage, closeSession, navigate, goBack, goForward, reload, captureSnapshot, findElements, getNodeDetails, scrollElementIntoView, scrollPage, click, type, press, select, hover, drag, wheel, getFormUnderstanding, getFieldContext, takeScreenshot, inspectCanvas,
35
35
  // Input schemas only (all outputs are XML strings now)
36
- ListPagesInputSchema, ClosePageInputSchema, CloseSessionInputSchema, NavigateInputSchema, GoBackInputSchema, GoForwardInputSchema, ReloadInputSchema, CaptureSnapshotInputSchema, FindElementsInputSchema, GetNodeDetailsInputSchema, ScrollElementIntoViewInputSchemaBase, ScrollPageInputSchema, ClickInputSchemaBase, TypeInputSchemaBase, PressInputSchema, SelectInputSchemaBase, HoverInputSchemaBase, GetFormUnderstandingInputSchema, GetFieldContextInputSchema, TakeScreenshotInputSchemaBase, } from './tools/index.js';
36
+ ListPagesInputSchema, ClosePageInputSchema, CloseSessionInputSchema, NavigateInputSchema, GoBackInputSchema, GoForwardInputSchema, ReloadInputSchema, CaptureSnapshotInputSchema, FindElementsInputSchema, GetNodeDetailsInputSchema, ScrollElementIntoViewInputSchemaBase, ScrollPageInputSchema, ClickInputSchemaBase, TypeInputSchemaBase, PressInputSchema, SelectInputSchemaBase, HoverInputSchemaBase, DragInputSchemaBase, WheelInputSchemaBase, GetFormUnderstandingInputSchema, GetFieldContextInputSchema, TakeScreenshotInputSchemaBase, InspectCanvasInputSchemaBase, } from './tools/index.js';
37
37
  /**
38
38
  * Wrap a tool handler with lazy browser initialization.
39
39
  * Works with both sync and async handlers - sync return values are automatically
@@ -107,14 +107,13 @@ function initializeServer() {
107
107
  });
108
108
  // Initialize session manager and tools
109
109
  const session = getSessionManager();
110
- initializeTools(session);
111
- initializeFormTools(session);
110
+ initializeToolContext(session);
112
111
  // ============================================================================
113
112
  // SESSION TOOLS
114
113
  // ============================================================================
115
114
  server.registerTool('list_pages', {
116
115
  title: 'List Pages',
117
- description: 'List all open browser pages with their page_id, URL, and title. Use when working with multiple pages or to get the page_id for targeting a specific page.',
116
+ description: 'List all open browser pages with their page_id, URL, and title.',
118
117
  inputSchema: ListPagesInputSchema.shape,
119
118
  }, withLazyInit(listPages, 'list_pages'));
120
119
  server.registerTool('close_page', {
@@ -124,7 +123,7 @@ function initializeServer() {
124
123
  }, withLazyInit(closePage, 'close_page'));
125
124
  server.registerTool('close_session', {
126
125
  title: 'Close Session',
127
- description: 'Close the entire browser and clear all state. Use when done with browser tasks or to reset after errors. Browser auto-restarts on next tool call.',
126
+ description: 'Close the entire browser and clear all state.',
128
127
  inputSchema: CloseSessionInputSchema.shape,
129
128
  }, withLazyInit(closeSession, 'close_session'));
130
129
  // ============================================================================
@@ -132,98 +131,116 @@ function initializeServer() {
132
131
  // ============================================================================
133
132
  server.registerTool('navigate', {
134
133
  title: 'Navigate',
135
- description: 'Go to a URL. Returns page snapshot with interactive elements. This is typically your first action when starting browser automation.',
134
+ description: 'Go to a URL. Returns page snapshot with interactive elements.',
136
135
  inputSchema: NavigateInputSchema.shape,
137
136
  }, withLazyInit(navigate, 'navigate'));
138
137
  server.registerTool('go_back', {
139
138
  title: 'Go Back',
140
- description: 'Go back one page in browser history (like clicking the back button). Returns updated page snapshot.',
139
+ description: 'Go back one page in browser history.',
141
140
  inputSchema: GoBackInputSchema.shape,
142
141
  }, withLazyInit(goBack, 'go_back'));
143
142
  server.registerTool('go_forward', {
144
143
  title: 'Go Forward',
145
- description: 'Go forward one page in browser history. Returns updated page snapshot.',
144
+ description: 'Go forward one page in browser history.',
146
145
  inputSchema: GoForwardInputSchema.shape,
147
146
  }, withLazyInit(goForward, 'go_forward'));
148
147
  server.registerTool('reload', {
149
148
  title: 'Reload',
150
- description: 'Refresh the current page. Use when content may be stale or after waiting for server-side changes. Returns updated snapshot.',
149
+ description: 'Refresh the current page.',
151
150
  inputSchema: ReloadInputSchema.shape,
152
151
  }, withLazyInit(reload, 'reload'));
153
- server.registerTool('capture_snapshot', {
154
- title: 'Capture Snapshot',
155
- description: 'Re-capture the page state without performing any action. Use when the page may have changed on its own (timers, live updates, animations completing). NOT needed after click/type/etc - those already return fresh snapshots.',
152
+ server.registerTool('snapshot', {
153
+ title: 'Snapshot',
154
+ description: 'Re-capture the page state without performing any action. Use when the page may have changed on its own (timers, live updates, animations).',
156
155
  inputSchema: CaptureSnapshotInputSchema.shape,
157
- }, withLazyInit(captureSnapshot, 'capture_snapshot'));
156
+ }, withLazyInit(captureSnapshot, 'snapshot'));
158
157
  // ============================================================================
159
158
  // OBSERVATION TOOLS
160
159
  // ============================================================================
161
- server.registerTool('find_elements', {
162
- title: 'Find Elements',
163
- description: 'Search for interactive elements OR read page text content. Filter by `kind` (button, link, textbox), `label` (case-insensitive substring match), or `region` (header, main, footer). To READ page content, ensure `include_readable: true` (default) which includes paragraphs and headings.',
160
+ server.registerTool('find', {
161
+ title: 'Find',
162
+ description: 'Search for interactive elements OR read page text content. Filter by `kind` (button, link, textbox, canvas), `label` (case-insensitive substring match), or `region` (header, main, footer).',
164
163
  inputSchema: FindElementsInputSchema.shape,
165
- }, withLazyInit(findElements, 'find_elements'));
166
- server.registerTool('get_element_details', {
167
- title: 'Get Element Details',
168
- description: 'Get complete details for one element: exact position, size, state, attributes. Use when you need more info than find_elements provides, like precise coordinates or full attribute list.',
164
+ }, withLazyInit(findElements, 'find'));
165
+ server.registerTool('get_element', {
166
+ title: 'Get Element',
167
+ description: 'Get complete details for one element: exact position, size, state, attributes.',
169
168
  inputSchema: GetNodeDetailsInputSchema.shape,
170
- }, withLazyInit(getNodeDetails, 'get_element_details'));
171
- server.registerTool('take_screenshot', {
172
- title: 'Take Screenshot',
173
- description: 'Capture a screenshot of the current page or a specific element. Returns the image directly for small screenshots (<2MB) or saves to a temp file for large ones. Use `eid` for element screenshots (requires a prior snapshot) or `fullPage: true` for full-page capture. Supports PNG (lossless, default) and JPEG (lossy with quality 0-100). Cannot combine eid and fullPage.',
169
+ }, withLazyInit(getNodeDetails, 'get_element'));
170
+ server.registerTool('screenshot', {
171
+ title: 'Screenshot',
172
+ description: 'Capture a screenshot of the current page or a specific element.',
174
173
  inputSchema: TakeScreenshotInputSchemaBase.shape,
175
- }, withLazyInit(takeScreenshot, 'take_screenshot'));
174
+ }, withLazyInit(takeScreenshot, 'screenshot'));
176
175
  // ============================================================================
177
176
  // INTERACTION TOOLS
178
177
  // ============================================================================
179
- server.registerTool('scroll_element_into_view', {
180
- title: 'Scroll Element Into View',
181
- description: 'Scroll until a specific element is visible in the viewport. Use BEFORE clicking or interacting with elements that are off-screen.',
178
+ server.registerTool('scroll_to', {
179
+ title: 'Scroll To',
180
+ description: 'Scroll until a specific element is visible in the viewport.',
182
181
  inputSchema: ScrollElementIntoViewInputSchemaBase.shape,
183
- }, withLazyInit(scrollElementIntoView, 'scroll_element_into_view'));
184
- server.registerTool('scroll_page', {
185
- title: 'Scroll Page',
186
- description: 'Scroll the viewport up or down by pixels. Use to explore page content, load lazy content, or reach elements below the fold. Returns updated snapshot.',
182
+ }, withLazyInit(scrollElementIntoView, 'scroll_to'));
183
+ server.registerTool('scroll', {
184
+ title: 'Scroll',
185
+ description: 'Scroll the viewport up or down by pixels.',
187
186
  inputSchema: ScrollPageInputSchema.shape,
188
- }, withLazyInit(scrollPage, 'scroll_page'));
187
+ }, withLazyInit(scrollPage, 'scroll'));
189
188
  server.registerTool('click', {
190
189
  title: 'Click Element',
191
- description: 'Click an element. Use for buttons, links, checkboxes, or any clickable element. Returns updated page snapshot reflecting any changes from the click.',
190
+ description: 'Click an element or at viewport coordinates.',
192
191
  inputSchema: ClickInputSchemaBase.shape,
193
192
  }, withLazyInit(click, 'click'));
194
193
  server.registerTool('type', {
195
194
  title: 'Type Text',
196
- description: 'Type text into an input field, search box, or text area. Set `clear: true` to replace existing text instead of appending. Returns updated snapshot.',
195
+ description: 'Type text into an input field or text area.',
197
196
  inputSchema: TypeInputSchemaBase.shape,
198
197
  }, withLazyInit(type, 'type'));
199
198
  server.registerTool('press', {
200
199
  title: 'Press Key',
201
- description: 'Press a keyboard key (Enter, Tab, Escape, arrows, etc.) with optional Ctrl/Shift/Alt modifiers. Use for: submitting forms (Enter), moving between fields (Tab), closing dialogs (Escape), or keyboard shortcuts.',
200
+ description: 'Press a keyboard key with optional modifiers.',
202
201
  inputSchema: PressInputSchema.shape,
203
202
  }, withLazyInit(press, 'press'));
204
203
  server.registerTool('select', {
205
204
  title: 'Select Option',
206
- description: 'Choose an option from a dropdown menu. Specify the option by its value attribute or visible text. Returns updated snapshot.',
205
+ description: 'Choose an option from a dropdown menu by value or visible text.',
207
206
  inputSchema: SelectInputSchemaBase.shape,
208
207
  }, withLazyInit(select, 'select'));
209
208
  server.registerTool('hover', {
210
209
  title: 'Hover Element',
211
- description: 'Move mouse over an element without clicking. Use to trigger hover menus, tooltips, or reveal hidden content that appears on mouseover.',
210
+ description: 'Move mouse over an element without clicking. Triggers hover menus and tooltips.',
212
211
  inputSchema: HoverInputSchemaBase.shape,
213
212
  }, withLazyInit(hover, 'hover'));
213
+ server.registerTool('drag', {
214
+ title: 'Drag',
215
+ description: 'Drag from one point to another.',
216
+ inputSchema: DragInputSchemaBase.shape,
217
+ }, withLazyInit(drag, 'drag'));
218
+ server.registerTool('wheel', {
219
+ title: 'Wheel',
220
+ description: 'Dispatch a mouse wheel event at specific coordinates. Use for scroll-to-zoom (with Control modifier) or horizontal scrolling.',
221
+ inputSchema: WheelInputSchemaBase.shape,
222
+ }, withLazyInit(wheel, 'wheel'));
223
+ // ============================================================================
224
+ // CANVAS INSPECTION TOOLS
225
+ // ============================================================================
226
+ server.registerTool('inspect_canvas', {
227
+ title: 'Inspect Canvas',
228
+ description: 'Analyze a canvas element: auto-detect the rendering library, query its scene graph, and return an annotated screenshot with coordinate grid overlay.',
229
+ inputSchema: InspectCanvasInputSchemaBase.shape,
230
+ }, withLazyInit(inspectCanvas, 'inspect_canvas'));
214
231
  // ============================================================================
215
232
  // FORM UNDERSTANDING TOOLS
216
233
  // ============================================================================
217
- server.registerTool('get_form_understanding', {
218
- title: 'Get Form Understanding',
219
- description: 'Analyze all forms on the page: fields, required inputs, validation rules, and field dependencies. Use BEFORE filling complex forms (multi-step, conditional fields) to understand what is required and in what order.',
234
+ server.registerTool('get_form', {
235
+ title: 'Get Form',
236
+ description: 'Analyze all forms on the page: fields, required inputs, validation rules, and field dependencies.',
220
237
  inputSchema: GetFormUnderstandingInputSchema.shape,
221
- }, withLazyInit(getFormUnderstanding, 'get_form_understanding'));
222
- server.registerTool('get_field_context', {
223
- title: 'Get Field Context',
224
- description: 'Get detailed info about one form field: what it is for, valid input formats, dependencies on other fields, and suggested values. Use when unsure how to fill a specific field.',
238
+ }, withLazyInit(getFormUnderstanding, 'get_form'));
239
+ server.registerTool('get_field', {
240
+ title: 'Get Field',
241
+ description: 'Get detailed info about one form field: purpose, valid input formats, dependencies, and suggested values.',
225
242
  inputSchema: GetFieldContextInputSchema.shape,
226
- }, withLazyInit(getFieldContext, 'get_field_context'));
243
+ }, withLazyInit(getFieldContext, 'get_field'));
227
244
  return server;
228
245
  }
229
246
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -34,7 +34,7 @@ export declare class ObservationAccumulator {
34
34
  getObservations(page: Page, actionStartTime: number): Promise<ObservationGroups>;
35
35
  /**
36
36
  * Get accumulated observations without action context.
37
- * Used by capture_snapshot to report accumulated changes.
37
+ * Used by snapshot tool to report accumulated changes.
38
38
  */
39
39
  getAccumulatedObservations(page: Page): Promise<ObservationGroups>;
40
40
  /**
@@ -102,7 +102,7 @@ export class ObservationAccumulator {
102
102
  }
103
103
  /**
104
104
  * Get accumulated observations without action context.
105
- * Used by capture_snapshot to report accumulated changes.
105
+ * Used by snapshot tool to report accumulated changes.
106
106
  */
107
107
  async getAccumulatedObservations(page) {
108
108
  try {
@@ -15,5 +15,5 @@
15
15
  *
16
16
  * The script is returned as a string for page.evaluate().
17
17
  */
18
- export declare const OBSERVATION_OBSERVER_SCRIPT = "\n(function() {\n // Prevent double-injection\n if (window.__observationAccumulator) return;\n\n const MAX_ENTRIES = 500;\n const MAX_TEXT_LENGTH = 200;\n const MAX_SHADOW_OBSERVERS = 50; // Limit to prevent performance issues\n // IMPORTANT: Must match SIGNIFICANCE_THRESHOLD in observation.types.ts\n const SIGNIFICANCE_THRESHOLD = 4;\n // Node type constant for shadow root parent check\n const DOCUMENT_FRAGMENT_NODE = 11;\n\n // Significance weights (must match server-side observation.types.ts)\n const WEIGHTS = {\n // Semantic signals (strongest)\n hasAlertRole: 3,\n hasAriaLive: 3,\n isDialog: 3,\n\n // Visual signals\n isFixedOrSticky: 2,\n hasHighZIndex: 1,\n coversSignificantViewport: 2,\n\n // Structural signals\n isBodyDirectChild: 1,\n containsInteractiveElements: 1,\n\n // New universal signals - work without ARIA\n isVisibleInViewport: 2, // Element is visible in viewport\n hasNonTrivialText: 1, // Has meaningful text content\n // Temporal signals computed later\n };\n\n // Shadow DOM tracking\n // Map: shadowRoot -> { observer, hostPath }\n const shadowObservers = new Map();\n\n // Track processed elements to avoid duplicate observations\n // WeakSet allows garbage collection of removed elements\n let processedElements = new WeakSet();\n\n /**\n * Generate a stable identifier for an element (for shadow path tracking).\n * Format: TAG#id or TAG.className or TAG[index]\n */\n function getElementIdentifier(el) {\n const tag = el.tagName.toLowerCase();\n if (el.id) {\n return tag + '#' + el.id;\n }\n // For custom elements, use the tag name (usually descriptive like 'my-toast')\n if (tag.includes('-')) {\n return tag;\n }\n // Fallback: use first class or just tag\n const className = el.className && typeof el.className === 'string'\n ? el.className.split(' ')[0]\n : '';\n if (className) {\n return tag + '.' + className;\n }\n return tag;\n }\n\n // Tags whose text content should be excluded from extraction\n const EXCLUDED_TEXT_TAGS = new Set(['STYLE', 'SCRIPT', 'NOSCRIPT', 'TEMPLATE', 'SVG']);\n\n /**\n * Get clean text content from an element, excluding CSS/JS content.\n * Uses TreeWalker to iterate only text nodes, skipping those inside\n * excluded tags (STYLE, SCRIPT, NOSCRIPT, TEMPLATE, SVG).\n *\n * @param {Element} el - The DOM element to extract text from\n * @param {number} maxLength - Maximum text length (truncates result)\n * @returns {string} Clean text content, space-joined, truncated to maxLength\n */\n function getCleanTextContent(el, maxLength) {\n // If element itself is an excluded tag, return empty\n if (EXCLUDED_TEXT_TAGS.has(el.tagName.toUpperCase())) {\n return '';\n }\n\n const walker = document.createTreeWalker(el, 4, { // NodeFilter.SHOW_TEXT = 4\n acceptNode: function(node) {\n let parent = node.parentElement;\n while (parent && parent !== el) {\n if (EXCLUDED_TEXT_TAGS.has(parent.tagName.toUpperCase())) {\n return 2; // FILTER_REJECT\n }\n parent = parent.parentElement;\n }\n return 1; // FILTER_ACCEPT\n }\n });\n\n const textParts = [];\n let totalLength = 0;\n let node;\n\n while ((node = walker.nextNode()) && totalLength < maxLength) {\n const text = node.nodeValue;\n if (text) {\n const trimmed = text.trim();\n if (trimmed) {\n textParts.push(trimmed);\n totalLength += trimmed.length;\n }\n }\n }\n\n return textParts.join(' ').substring(0, maxLength);\n }\n\n /**\n * Compute significance signals from element.\n * Uses universal web standards (ARIA, CSS positioning, DOM structure, visibility).\n */\n function computeSignals(el, shadowPath) {\n const role = el.getAttribute('role');\n const ariaLive = el.getAttribute('aria-live');\n const ariaModal = el.getAttribute('aria-modal');\n const tagName = el.tagName.toLowerCase();\n\n // Get computed style (may fail for detached elements)\n let style = null;\n let rect = null;\n try {\n style = getComputedStyle(el);\n rect = el.getBoundingClientRect();\n } catch (e) {\n // Element may be detached\n }\n\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n\n // Check if element is visible in viewport\n const isVisibleInViewport = rect && style &&\n rect.width > 0 && rect.height > 0 &&\n rect.bottom > 0 && rect.top < vh &&\n rect.right > 0 && rect.left < vw &&\n style.display !== 'none' &&\n style.visibility !== 'hidden' &&\n style.opacity !== '0';\n\n // Check for non-trivial text (at least 3 chars, not just whitespace)\n // Use short sample for signal check - excludes style/script content\n const text = getCleanTextContent(el, 100);\n const hasNonTrivialText = text.length >= 3;\n\n // For shadow DOM elements, isBodyDirectChild is false but we still want to capture them\n // Check if parent is a shadow root (which indicates top-level in shadow DOM)\n const isTopLevelInShadow = shadowPath && shadowPath.length > 0 &&\n el.parentNode && el.parentNode.nodeType === DOCUMENT_FRAGMENT_NODE;\n\n return {\n // Semantic signals\n hasAlertRole: ['alert', 'status', 'log', 'alertdialog'].includes(role),\n hasAriaLive: ariaLive === 'polite' || ariaLive === 'assertive',\n isDialog: role === 'dialog' || tagName === 'dialog' || ariaModal === 'true',\n\n // Visual signals\n isFixedOrSticky: style && (style.position === 'fixed' || style.position === 'sticky'),\n // Note: parseInt returns NaN for non-numeric values like \"auto\", which correctly fails the > 1000 check\n hasHighZIndex: style && parseInt(style.zIndex, 10) > 1000,\n coversSignificantViewport: rect && ((rect.width > vw * 0.5) || (rect.height > vh * 0.3)),\n\n // Structural signals - consider top-level shadow DOM elements as equivalent to body children\n isBodyDirectChild: el.parentElement === document.body || isTopLevelInShadow,\n containsInteractiveElements: el.querySelector('button, a, input, select, textarea') !== null,\n\n // Universal signals (work without ARIA)\n isVisibleInViewport: !!isVisibleInViewport,\n hasNonTrivialText: hasNonTrivialText,\n\n // Temporal signals (set by accumulator later)\n appearedAfterDelay: false,\n wasShortLived: false,\n };\n }\n\n /**\n * Calculate significance score from signals using weighted sum.\n * @param signals - The computed significance signals for an element\n * @returns The total significance score\n */\n function computeSignificance(signals) {\n let score = 0;\n for (const [key, weight] of Object.entries(WEIGHTS)) {\n if (signals[key]) score += weight;\n }\n return score;\n }\n\n /**\n * Capture a mutation entry from an element.\n * @param node - The DOM node\n * @param type - 'added' or 'removed'\n * @param shadowPath - Optional array of shadow host identifiers\n */\n function captureEntry(node, type, shadowPath) {\n if (node.nodeType !== 1) return null; // Element nodes only\n\n const el = node;\n const signals = computeSignals(el, shadowPath);\n const significance = computeSignificance(signals);\n\n // Only capture if meets threshold\n if (significance < SIGNIFICANCE_THRESHOLD) return null;\n\n // Capture content - excludes style/script content\n const text = getCleanTextContent(el, MAX_TEXT_LENGTH);\n const hasInteractives = signals.containsInteractiveElements;\n\n // Get viewport coverage for later analysis\n let viewportCoverage = { widthPct: 0, heightPct: 0 };\n try {\n const rect = el.getBoundingClientRect();\n viewportCoverage = {\n widthPct: Math.round((rect.width / window.innerWidth) * 100),\n heightPct: Math.round((rect.height / window.innerHeight) * 100),\n };\n } catch (e) {\n // Element may be detached\n }\n\n // Get z-index\n let zIndex = 0;\n try {\n zIndex = parseInt(getComputedStyle(el).zIndex, 10) || 0;\n } catch (e) {\n // Element may be detached\n }\n\n const entry = {\n type: type,\n timestamp: Date.now(),\n tag: el.tagName.toLowerCase(),\n id: el.id || undefined,\n\n // Semantic attributes\n role: el.getAttribute('role') || undefined,\n ariaLive: el.getAttribute('aria-live') || undefined,\n ariaLabel: el.getAttribute('aria-label') || undefined,\n ariaModal: el.getAttribute('aria-modal') || undefined,\n\n // Content\n text: text,\n hasInteractives: hasInteractives,\n\n // Visual signals\n isFixedOrSticky: signals.isFixedOrSticky,\n zIndex: zIndex,\n viewportCoverage: viewportCoverage,\n\n // Structural\n isBodyDirectChild: signals.isBodyDirectChild,\n\n // Universal signals\n isVisibleInViewport: signals.isVisibleInViewport,\n hasNonTrivialText: signals.hasNonTrivialText,\n\n // Shadow DOM context\n shadowPath: shadowPath && shadowPath.length > 0 ? shadowPath : undefined,\n\n // Significance\n significance: significance,\n };\n\n return entry;\n }\n\n const log = [];\n const pageLoadTime = Date.now();\n\n /**\n * Process added nodes - capture entries and check for shadow roots.\n * @param node - The added node\n * @param shadowPath - Current shadow path context\n */\n function processAddedNode(node, shadowPath) {\n // Skip if already processed (prevents duplicates from nested shadow DOM)\n if (node.nodeType === 1 && processedElements.has(node)) {\n return;\n }\n\n const entry = captureEntry(node, 'added', shadowPath);\n if (entry) {\n entry.appearedAfterDelay = (entry.timestamp - pageLoadTime) > 100;\n log.push(entry);\n // Mark as processed\n if (node.nodeType === 1) {\n processedElements.add(node);\n }\n }\n\n // Check significant children - both ARIA-attributed and visible text elements\n if (node.nodeType === 1) {\n // First: ARIA-attributed elements (high confidence)\n const ariaChildren = node.querySelectorAll(\n '[role=\"alert\"], [role=\"status\"], [role=\"dialog\"], [role=\"alertdialog\"], [aria-live], [aria-modal], dialog'\n );\n for (const child of ariaChildren) {\n // Skip if already processed\n if (processedElements.has(child)) continue;\n\n const childEntry = captureEntry(child, 'added', shadowPath);\n if (childEntry) {\n childEntry.appearedAfterDelay = (childEntry.timestamp - pageLoadTime) > 100;\n log.push(childEntry);\n processedElements.add(child);\n }\n }\n\n // Second: Any visible element with text (broader capture for sites without ARIA)\n const textChildren = node.querySelectorAll('span, div, p, small, strong, em, label, li');\n for (const child of textChildren) {\n // Skip if already processed\n if (processedElements.has(child)) continue;\n\n // Skip if already captured via ARIA query\n if (child.hasAttribute('role') || child.hasAttribute('aria-live')) continue;\n\n // Only capture leaf-ish elements (minimal nested structure)\n const hasDeepNesting = child.querySelector('div, p, ul, ol, table');\n if (hasDeepNesting) continue;\n\n const childEntry = captureEntry(child, 'added', shadowPath);\n if (childEntry) {\n childEntry.appearedAfterDelay = (childEntry.timestamp - pageLoadTime) > 100;\n log.push(childEntry);\n processedElements.add(child);\n }\n }\n\n // Check for shadow roots in this element and its descendants\n checkAndObserveShadowRoots(node, shadowPath || []);\n }\n }\n\n /**\n * Process removed nodes - capture entries and cleanup shadow observers.\n * @param node - The removed node\n * @param shadowPath - Current shadow path context\n */\n function processRemovedNode(node, shadowPath) {\n const entry = captureEntry(node, 'removed', shadowPath);\n if (entry) {\n log.push(entry);\n }\n\n // Cleanup shadow observers for removed elements\n if (node.nodeType === 1) {\n cleanupShadowObservers(node);\n }\n }\n\n /**\n * Create a mutation callback for observing a specific context (main DOM or shadow root).\n * @param shadowPath - The shadow path context for this observer\n */\n function createMutationCallback(shadowPath) {\n return function(mutations) {\n for (const m of mutations) {\n // Capture added nodes\n for (const node of m.addedNodes) {\n processAddedNode(node, shadowPath);\n }\n\n // Capture removed nodes\n for (const node of m.removedNodes) {\n processRemovedNode(node, shadowPath);\n }\n }\n\n // Trim if over limit (FIFO)\n if (log.length > MAX_ENTRIES) {\n const excess = log.length - MAX_ENTRIES;\n log.splice(0, excess);\n }\n };\n }\n\n /**\n * Observe a shadow root for mutations.\n * @param shadowRoot - The shadow root to observe\n * @param shadowPath - The path of shadow host identifiers leading to this shadow root\n */\n function observeShadowRoot(shadowRoot, shadowPath) {\n // Already observing this shadow root\n if (shadowObservers.has(shadowRoot)) return;\n\n // Limit number of shadow observers for performance\n if (shadowObservers.size >= MAX_SHADOW_OBSERVERS) {\n console.warn('[ObservationAccumulator] Max shadow observers reached, skipping:', shadowPath);\n return;\n }\n\n const observer = new MutationObserver(createMutationCallback(shadowPath));\n observer.observe(shadowRoot, {\n childList: true,\n subtree: true,\n });\n\n shadowObservers.set(shadowRoot, { observer, hostPath: shadowPath });\n }\n\n /**\n * Recursively check element and descendants for open shadow roots.\n * @param element - The element to check\n * @param currentShadowPath - The current shadow path context\n * @param visited - Set of already-visited elements to prevent infinite recursion\n */\n function checkAndObserveShadowRoots(element, currentShadowPath, visited) {\n if (!element || element.nodeType !== 1) return;\n\n // Initialize visited set on first call\n if (!visited) {\n visited = new Set();\n }\n\n // Prevent infinite recursion from circular references\n if (visited.has(element)) return;\n visited.add(element);\n\n // Check if this element has an open shadow root\n if (element.shadowRoot) {\n const newPath = [...currentShadowPath, getElementIdentifier(element)];\n observeShadowRoot(element.shadowRoot, newPath);\n\n // Check shadow root's children for nested shadow roots\n const shadowChildren = element.shadowRoot.querySelectorAll('*');\n for (const child of shadowChildren) {\n if (child.shadowRoot) {\n checkAndObserveShadowRoots(child, newPath, visited);\n }\n }\n }\n\n // Check light DOM children for shadow roots\n const children = element.querySelectorAll('*');\n for (const child of children) {\n if (child.shadowRoot) {\n checkAndObserveShadowRoots(child, currentShadowPath, visited);\n }\n }\n }\n\n /**\n * Cleanup shadow observers for a removed element and its descendants.\n * @param element - The element being removed\n */\n function cleanupShadowObservers(element) {\n if (!element || element.nodeType !== 1) return;\n\n // If element is a shadow host, cleanup its observer\n if (element.shadowRoot && shadowObservers.has(element.shadowRoot)) {\n const { observer } = shadowObservers.get(element.shadowRoot);\n observer.disconnect();\n shadowObservers.delete(element.shadowRoot);\n }\n\n // Recursively cleanup descendant shadow hosts\n try {\n const descendants = element.querySelectorAll('*');\n for (const child of descendants) {\n if (child.shadowRoot && shadowObservers.has(child.shadowRoot)) {\n const { observer } = shadowObservers.get(child.shadowRoot);\n observer.disconnect();\n shadowObservers.delete(child.shadowRoot);\n }\n }\n } catch (e) {\n // Element may be detached, ignore errors\n }\n }\n\n // Create main observer for document.body\n const observer = new MutationObserver(createMutationCallback(null));\n\n // Start observing\n if (document.body) {\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n });\n\n // Initial scan for existing shadow roots in the DOM\n checkAndObserveShadowRoots(document.body, []);\n }\n\n window.__observationAccumulator = {\n log: log,\n observer: observer,\n shadowObservers: shadowObservers, // Expose for debugging/testing\n observedBody: document.body, // Track which body we're observing for staleness detection\n pageLoadTime: pageLoadTime,\n lastReportedIndex: 0, // Track what's been reported\n\n // Get all entries since timestamp\n getSince: function(timestamp) {\n return this.log.filter(e => e.timestamp >= timestamp);\n },\n\n // Get significant entries since timestamp\n getSignificant: function(timestamp, threshold) {\n threshold = threshold || SIGNIFICANCE_THRESHOLD;\n return this.log.filter(e => e.timestamp >= timestamp && e.significance >= threshold);\n },\n\n // Get unreported entries (for accumulation between tool calls)\n getUnreported: function() {\n const unreported = this.log.slice(this.lastReportedIndex);\n return unreported.filter(e => e.significance >= SIGNIFICANCE_THRESHOLD);\n },\n\n // Mark entries as reported\n markReported: function() {\n this.lastReportedIndex = this.log.length;\n },\n\n // Reset on navigation\n reset: function() {\n this.log.length = 0;\n this.lastReportedIndex = 0;\n this.pageLoadTime = Date.now();\n // Cleanup all shadow observers\n for (const [shadowRoot, { observer }] of this.shadowObservers) {\n observer.disconnect();\n }\n this.shadowObservers.clear();\n // Clear processed elements tracking (create fresh WeakSet)\n processedElements = new WeakSet();\n },\n\n // Re-scan for shadow roots (useful after dynamic content load)\n rescanShadowRoots: function() {\n if (document.body) {\n checkAndObserveShadowRoots(document.body, []);\n }\n },\n\n // Get shadow observer count (for debugging)\n getShadowObserverCount: function() {\n return this.shadowObservers.size;\n },\n };\n})();\n";
18
+ export declare const OBSERVATION_OBSERVER_SCRIPT = "\n(function() {\n // Prevent double-injection\n if (window.__observationAccumulator) return;\n\n const MAX_ENTRIES = 500;\n const MAX_TEXT_LENGTH = 200;\n const MAX_SHADOW_OBSERVERS = 50; // Limit to prevent performance issues\n // IMPORTANT: Must match SIGNIFICANCE_THRESHOLD in observation.types.ts\n const SIGNIFICANCE_THRESHOLD = 4;\n // Node type constant for shadow root parent check\n const DOCUMENT_FRAGMENT_NODE = 11;\n // ARIA roles that indicate live regions (text mutations are significant)\n const LIVE_REGION_ROLES = new Set(['alert', 'status', 'log', 'marquee', 'timer']);\n // Attributes whose changes can reveal hidden elements (visibility tracking)\n const VISIBILITY_ATTRS = ['style', 'class', 'hidden', 'aria-hidden'];\n\n // Known toast library selectors (unsemantic \u2014 no ARIA roles).\n // Keep in sync with TOAST_DATA_ATTRS / TOAST_CLASS_PATTERNS in snapshot-compiler.ts.\n const TOAST_LIBRARY_PARTS = [\n '[data-sonner-toaster]',\n '[data-sonner-toast]',\n '[data-hot-toast]',\n '.Toastify__toast-container',\n '.Toastify__toast',\n '.ant-message',\n '.ant-message-notice',\n ];\n const TOAST_LIBRARY_SELECTOR = TOAST_LIBRARY_PARTS.join(', ');\n\n // Significance weights (must match server-side observation.types.ts)\n const WEIGHTS = {\n // Semantic signals (strongest)\n hasAlertRole: 3,\n hasAriaLive: 3,\n isDialog: 3,\n\n // Visual signals\n isFixedOrSticky: 2,\n hasHighZIndex: 1,\n coversSignificantViewport: 2,\n\n // Structural signals\n isBodyDirectChild: 1,\n containsInteractiveElements: 1,\n\n // Known toast library patterns (unsemantic but significant)\n isKnownToastLibrary: 3, // Equivalent to hasAlertRole\n\n // New universal signals - work without ARIA\n isVisibleInViewport: 2, // Element is visible in viewport\n hasNonTrivialText: 1, // Has meaningful text content\n // Temporal signals computed later\n };\n\n // Shadow DOM tracking\n // Map: shadowRoot -> { observer, hostPath }\n const shadowObservers = new Map();\n\n // Track processed elements to avoid duplicate observations\n // WeakSet allows garbage collection of removed elements\n let processedElements = new WeakSet();\n\n /**\n * Generate a stable identifier for an element (for shadow path tracking).\n * Format: TAG#id or TAG.className or TAG[index]\n */\n function getElementIdentifier(el) {\n const tag = el.tagName.toLowerCase();\n if (el.id) {\n return tag + '#' + el.id;\n }\n // For custom elements, use the tag name (usually descriptive like 'my-toast')\n if (tag.includes('-')) {\n return tag;\n }\n // Fallback: use first class or just tag\n const className = el.className && typeof el.className === 'string'\n ? el.className.split(' ')[0]\n : '';\n if (className) {\n return tag + '.' + className;\n }\n return tag;\n }\n\n // Tags whose text content should be excluded from extraction\n const EXCLUDED_TEXT_TAGS = new Set(['STYLE', 'SCRIPT', 'NOSCRIPT', 'TEMPLATE', 'SVG']);\n\n /**\n * Get clean text content from an element, excluding CSS/JS content.\n * Uses TreeWalker to iterate only text nodes, skipping those inside\n * excluded tags (STYLE, SCRIPT, NOSCRIPT, TEMPLATE, SVG).\n *\n * @param {Element} el - The DOM element to extract text from\n * @param {number} maxLength - Maximum text length (truncates result)\n * @returns {string} Clean text content, space-joined, truncated to maxLength\n */\n function getCleanTextContent(el, maxLength) {\n // If element itself is an excluded tag, return empty\n if (EXCLUDED_TEXT_TAGS.has(el.tagName.toUpperCase())) {\n return '';\n }\n\n const walker = document.createTreeWalker(el, 4, { // NodeFilter.SHOW_TEXT = 4\n acceptNode: function(node) {\n let parent = node.parentElement;\n while (parent && parent !== el) {\n if (EXCLUDED_TEXT_TAGS.has(parent.tagName.toUpperCase())) {\n return 2; // FILTER_REJECT\n }\n parent = parent.parentElement;\n }\n return 1; // FILTER_ACCEPT\n }\n });\n\n const textParts = [];\n let totalLength = 0;\n let node;\n\n while ((node = walker.nextNode()) && totalLength < maxLength) {\n const text = node.nodeValue;\n if (text) {\n const trimmed = text.trim();\n if (trimmed) {\n textParts.push(trimmed);\n totalLength += trimmed.length;\n }\n }\n }\n\n return textParts.join(' ').substring(0, maxLength);\n }\n\n /**\n * Compute significance signals from element.\n * Uses universal web standards (ARIA, CSS positioning, DOM structure, visibility).\n */\n function computeSignals(el, shadowPath) {\n const role = el.getAttribute('role');\n const ariaLive = el.getAttribute('aria-live');\n const ariaModal = el.getAttribute('aria-modal');\n const tagName = el.tagName.toLowerCase();\n\n // Get computed style (may fail for detached elements)\n let style = null;\n let rect = null;\n try {\n style = getComputedStyle(el);\n rect = el.getBoundingClientRect();\n } catch (e) {\n // Element may be detached\n }\n\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n\n // Check if element is visible in viewport\n const isVisibleInViewport = rect && style &&\n rect.width > 0 && rect.height > 0 &&\n rect.bottom > 0 && rect.top < vh &&\n rect.right > 0 && rect.left < vw &&\n style.display !== 'none' &&\n style.visibility !== 'hidden' &&\n style.opacity !== '0';\n\n // Check for non-trivial text (at least 3 chars, not just whitespace)\n // Use short sample for signal check - excludes style/script content\n const text = getCleanTextContent(el, 100);\n const hasNonTrivialText = text.length >= 3;\n\n // For shadow DOM elements, isBodyDirectChild is false but we still want to capture them\n // Check if parent is a shadow root (which indicates top-level in shadow DOM)\n const isTopLevelInShadow = shadowPath && shadowPath.length > 0 &&\n el.parentNode && el.parentNode.nodeType === DOCUMENT_FRAGMENT_NODE;\n\n return {\n // Semantic signals\n hasAlertRole: ['alert', 'status', 'log', 'alertdialog'].includes(role),\n hasAriaLive: ariaLive === 'polite' || ariaLive === 'assertive',\n isDialog: role === 'dialog' || tagName === 'dialog' || ariaModal === 'true',\n\n // Visual signals\n isFixedOrSticky: style && (style.position === 'fixed' || style.position === 'sticky'),\n // Note: parseInt returns NaN for non-numeric values like \"auto\", which correctly fails the > 1000 check\n hasHighZIndex: style && parseInt(style.zIndex, 10) > 1000,\n coversSignificantViewport: rect && ((rect.width > vw * 0.5) || (rect.height > vh * 0.3)),\n\n // Structural signals - consider top-level shadow DOM elements as equivalent to body children\n isBodyDirectChild: el.parentElement === document.body || isTopLevelInShadow,\n containsInteractiveElements: el.querySelector('button, a, input, select, textarea') !== null,\n\n // Known toast library detection (unsemantic but significant)\n isKnownToastLibrary: el.matches(TOAST_LIBRARY_SELECTOR) || (typeof el.className === 'string' && el.className.includes('chakra-toast')),\n\n // Universal signals (work without ARIA)\n isVisibleInViewport: !!isVisibleInViewport,\n hasNonTrivialText: hasNonTrivialText,\n\n // Temporal signals (set by accumulator later)\n appearedAfterDelay: false,\n wasShortLived: false,\n };\n }\n\n /**\n * Calculate significance score from signals using weighted sum.\n * @param signals - The computed significance signals for an element\n * @returns The total significance score\n */\n function computeSignificance(signals) {\n let score = 0;\n for (const [key, weight] of Object.entries(WEIGHTS)) {\n if (signals[key]) score += weight;\n }\n return score;\n }\n\n /**\n * Capture a mutation entry from an element.\n * @param node - The DOM node\n * @param type - 'added' or 'removed'\n * @param shadowPath - Optional array of shadow host identifiers\n */\n function captureEntry(node, type, shadowPath) {\n if (node.nodeType !== 1) return null; // Element nodes only\n\n const el = node;\n const signals = computeSignals(el, shadowPath);\n const significance = computeSignificance(signals);\n\n // Only capture if meets threshold\n if (significance < SIGNIFICANCE_THRESHOLD) return null;\n\n // Capture content - excludes style/script content\n const text = getCleanTextContent(el, MAX_TEXT_LENGTH);\n const hasInteractives = signals.containsInteractiveElements;\n\n // Get viewport coverage for later analysis\n let viewportCoverage = { widthPct: 0, heightPct: 0 };\n try {\n const rect = el.getBoundingClientRect();\n viewportCoverage = {\n widthPct: Math.round((rect.width / window.innerWidth) * 100),\n heightPct: Math.round((rect.height / window.innerHeight) * 100),\n };\n } catch (e) {\n // Element may be detached\n }\n\n // Get z-index\n let zIndex = 0;\n try {\n zIndex = parseInt(getComputedStyle(el).zIndex, 10) || 0;\n } catch (e) {\n // Element may be detached\n }\n\n const entry = {\n type: type,\n timestamp: Date.now(),\n tag: el.tagName.toLowerCase(),\n id: el.id || undefined,\n\n // Semantic attributes\n role: el.getAttribute('role') || undefined,\n ariaLive: el.getAttribute('aria-live') || undefined,\n ariaLabel: el.getAttribute('aria-label') || undefined,\n ariaModal: el.getAttribute('aria-modal') || undefined,\n\n // Content\n text: text,\n hasInteractives: hasInteractives,\n\n // Visual signals\n isFixedOrSticky: signals.isFixedOrSticky,\n zIndex: zIndex,\n viewportCoverage: viewportCoverage,\n\n // Structural\n isBodyDirectChild: signals.isBodyDirectChild,\n\n // Universal signals\n isVisibleInViewport: signals.isVisibleInViewport,\n hasNonTrivialText: signals.hasNonTrivialText,\n\n // Shadow DOM context\n shadowPath: shadowPath && shadowPath.length > 0 ? shadowPath : undefined,\n\n // Significance\n significance: significance,\n };\n\n return entry;\n }\n\n const log = [];\n const pageLoadTime = Date.now();\n\n /**\n * Process added nodes - capture entries and check for shadow roots.\n * @param node - The added node\n * @param shadowPath - Current shadow path context\n */\n function processAddedNode(node, shadowPath) {\n // Skip if already processed (prevents duplicates from nested shadow DOM)\n if (node.nodeType === 1 && processedElements.has(node)) {\n return;\n }\n\n const entry = captureEntry(node, 'added', shadowPath);\n if (entry) {\n entry.appearedAfterDelay = (entry.timestamp - pageLoadTime) > 100;\n log.push(entry);\n // Mark as processed\n if (node.nodeType === 1) {\n processedElements.add(node);\n }\n }\n\n // Check significant children - both ARIA-attributed and visible text elements\n if (node.nodeType === 1) {\n // First: ARIA-attributed elements (high confidence)\n const ariaChildren = node.querySelectorAll(\n '[role=\"alert\"], [role=\"status\"], [role=\"dialog\"], [role=\"alertdialog\"], [aria-live], [aria-modal], dialog'\n );\n for (const child of ariaChildren) {\n // Skip if already processed\n if (processedElements.has(child)) continue;\n\n const childEntry = captureEntry(child, 'added', shadowPath);\n if (childEntry) {\n childEntry.appearedAfterDelay = (childEntry.timestamp - pageLoadTime) > 100;\n log.push(childEntry);\n processedElements.add(child);\n }\n }\n\n // Second: Any visible element with text (broader capture for sites without ARIA)\n const textChildren = node.querySelectorAll('span, div, p, small, strong, em, label, li');\n for (const child of textChildren) {\n // Skip if already processed\n if (processedElements.has(child)) continue;\n\n // Skip if already captured via ARIA query\n if (child.hasAttribute('role') || child.hasAttribute('aria-live')) continue;\n\n // Only capture leaf-ish elements (minimal nested structure)\n const hasDeepNesting = child.querySelector('div, p, ul, ol, table');\n if (hasDeepNesting) continue;\n\n const childEntry = captureEntry(child, 'added', shadowPath);\n if (childEntry) {\n childEntry.appearedAfterDelay = (childEntry.timestamp - pageLoadTime) > 100;\n log.push(childEntry);\n processedElements.add(child);\n }\n }\n\n // Check for shadow roots in this element and its descendants\n checkAndObserveShadowRoots(node, shadowPath || []);\n }\n }\n\n /**\n * Process removed nodes - capture entries and cleanup shadow observers.\n * @param node - The removed node\n * @param shadowPath - Current shadow path context\n */\n function processRemovedNode(node, shadowPath) {\n const entry = captureEntry(node, 'removed', shadowPath);\n if (entry) {\n log.push(entry);\n }\n\n // Cleanup shadow observers for removed elements\n if (node.nodeType === 1) {\n cleanupShadowObservers(node);\n }\n }\n\n /**\n * Find the nearest ancestor (or self) with a live region role.\n * Returns the element if found, null otherwise.\n */\n function findLiveRegionAncestor(node) {\n let el = node.nodeType === 1 ? node : node.parentElement;\n while (el && el !== document.body) {\n const role = el.getAttribute && el.getAttribute('role');\n if (role && LIVE_REGION_ROLES.has(role)) return el;\n const ariaLive = el.getAttribute && el.getAttribute('aria-live');\n if (ariaLive === 'polite' || ariaLive === 'assertive') return el;\n el = el.parentElement;\n }\n return null;\n }\n\n /**\n * Handle characterData mutations (text-only changes in existing elements).\n * Captures the live region container when its text content changes.\n */\n function processCharacterDataMutation(mutation, shadowPath) {\n const textNode = mutation.target;\n const liveRegion = findLiveRegionAncestor(textNode);\n if (!liveRegion) return;\n\n // Avoid re-capturing the same live region for rapid successive text changes\n // Use a short debounce window (same element within 100ms)\n const now = Date.now();\n if (liveRegion.__lastTextCapture && (now - liveRegion.__lastTextCapture) < 100) return;\n liveRegion.__lastTextCapture = now;\n\n const entry = captureEntry(liveRegion, 'added', shadowPath);\n if (entry) {\n entry.appearedAfterDelay = (entry.timestamp - pageLoadTime) > 100;\n log.push(entry);\n }\n }\n\n /**\n * Handle attribute mutations that may reveal hidden elements.\n * Detects visibility changes (display:none \u2192 block, hidden removal, etc.)\n */\n function processAttributeMutation(mutation, shadowPath) {\n const el = mutation.target;\n if (el.nodeType !== 1) return;\n\n // Skip if already processed in this cycle\n if (processedElements.has(el)) return;\n\n // Check if this attribute change made the element visible\n const attrName = mutation.attributeName;\n\n // For 'hidden' attribute: element becomes visible when hidden is removed\n if (attrName === 'hidden' && el.hasAttribute('hidden')) return; // Still hidden\n\n // For 'aria-hidden': element becomes visible when set to false or removed\n if (attrName === 'aria-hidden') {\n const val = el.getAttribute('aria-hidden');\n if (val === 'true') return; // Still hidden\n }\n\n // For 'style' or 'class': check computed visibility\n if (attrName === 'style' || attrName === 'class') {\n try {\n const style = getComputedStyle(el);\n if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') {\n return; // Still hidden\n }\n } catch (e) {\n return; // Detached element\n }\n }\n\n // Check if this element (or a live region ancestor) is significant\n // Only capture if the element has meaningful content and meets threshold\n const entry = captureEntry(el, 'added', shadowPath);\n if (entry) {\n entry.appearedAfterDelay = (entry.timestamp - pageLoadTime) > 100;\n log.push(entry);\n processedElements.add(el);\n }\n }\n\n /**\n * Create a mutation callback for observing a specific context (main DOM or shadow root).\n * @param shadowPath - The shadow path context for this observer\n */\n function createMutationCallback(shadowPath) {\n return function(mutations) {\n for (const m of mutations) {\n if (m.type === 'childList') {\n // Capture added nodes\n for (const node of m.addedNodes) {\n processAddedNode(node, shadowPath);\n }\n\n // Capture removed nodes\n for (const node of m.removedNodes) {\n processRemovedNode(node, shadowPath);\n }\n } else if (m.type === 'characterData') {\n // Text content changed in an existing node (live region updates)\n processCharacterDataMutation(m, shadowPath);\n } else if (m.type === 'attributes') {\n // Attribute changed \u2014 may reveal hidden elements (visibility tracking)\n processAttributeMutation(m, shadowPath);\n }\n }\n\n // Trim if over limit (FIFO)\n if (log.length > MAX_ENTRIES) {\n const excess = log.length - MAX_ENTRIES;\n log.splice(0, excess);\n }\n };\n }\n\n /**\n * Observe a shadow root for mutations.\n * @param shadowRoot - The shadow root to observe\n * @param shadowPath - The path of shadow host identifiers leading to this shadow root\n */\n function observeShadowRoot(shadowRoot, shadowPath) {\n // Already observing this shadow root\n if (shadowObservers.has(shadowRoot)) return;\n\n // Limit number of shadow observers for performance\n if (shadowObservers.size >= MAX_SHADOW_OBSERVERS) {\n console.warn('[ObservationAccumulator] Max shadow observers reached, skipping:', shadowPath);\n return;\n }\n\n const observer = new MutationObserver(createMutationCallback(shadowPath));\n observer.observe(shadowRoot, {\n childList: true,\n subtree: true,\n characterData: true,\n characterDataOldValue: true,\n attributes: true,\n attributeFilter: VISIBILITY_ATTRS,\n });\n\n shadowObservers.set(shadowRoot, { observer, hostPath: shadowPath });\n }\n\n /**\n * Recursively check element and descendants for open shadow roots.\n * @param element - The element to check\n * @param currentShadowPath - The current shadow path context\n * @param visited - Set of already-visited elements to prevent infinite recursion\n */\n function checkAndObserveShadowRoots(element, currentShadowPath, visited) {\n if (!element || element.nodeType !== 1) return;\n\n // Initialize visited set on first call\n if (!visited) {\n visited = new Set();\n }\n\n // Prevent infinite recursion from circular references\n if (visited.has(element)) return;\n visited.add(element);\n\n // Check if this element has an open shadow root\n if (element.shadowRoot) {\n const newPath = [...currentShadowPath, getElementIdentifier(element)];\n observeShadowRoot(element.shadowRoot, newPath);\n\n // Check shadow root's children for nested shadow roots\n const shadowChildren = element.shadowRoot.querySelectorAll('*');\n for (const child of shadowChildren) {\n if (child.shadowRoot) {\n checkAndObserveShadowRoots(child, newPath, visited);\n }\n }\n }\n\n // Check light DOM children for shadow roots\n const children = element.querySelectorAll('*');\n for (const child of children) {\n if (child.shadowRoot) {\n checkAndObserveShadowRoots(child, currentShadowPath, visited);\n }\n }\n }\n\n /**\n * Cleanup shadow observers for a removed element and its descendants.\n * @param element - The element being removed\n */\n function cleanupShadowObservers(element) {\n if (!element || element.nodeType !== 1) return;\n\n // If element is a shadow host, cleanup its observer\n if (element.shadowRoot && shadowObservers.has(element.shadowRoot)) {\n const { observer } = shadowObservers.get(element.shadowRoot);\n observer.disconnect();\n shadowObservers.delete(element.shadowRoot);\n }\n\n // Recursively cleanup descendant shadow hosts\n try {\n const descendants = element.querySelectorAll('*');\n for (const child of descendants) {\n if (child.shadowRoot && shadowObservers.has(child.shadowRoot)) {\n const { observer } = shadowObservers.get(child.shadowRoot);\n observer.disconnect();\n shadowObservers.delete(child.shadowRoot);\n }\n }\n } catch (e) {\n // Element may be detached, ignore errors\n }\n }\n\n // Create main observer for document.body\n const observer = new MutationObserver(createMutationCallback(null));\n\n // Start observing\n if (document.body) {\n observer.observe(document.body, {\n childList: true,\n subtree: true,\n characterData: true,\n characterDataOldValue: true,\n attributes: true,\n attributeFilter: VISIBILITY_ATTRS,\n });\n\n // Initial scan for existing shadow roots in the DOM\n checkAndObserveShadowRoots(document.body, []);\n }\n\n window.__observationAccumulator = {\n log: log,\n observer: observer,\n shadowObservers: shadowObservers, // Expose for debugging/testing\n observedBody: document.body, // Track which body we're observing for staleness detection\n pageLoadTime: pageLoadTime,\n lastReportedIndex: 0, // Track what's been reported\n\n // Get all entries since timestamp\n getSince: function(timestamp) {\n return this.log.filter(e => e.timestamp >= timestamp);\n },\n\n // Get significant entries since timestamp\n getSignificant: function(timestamp, threshold) {\n threshold = threshold || SIGNIFICANCE_THRESHOLD;\n return this.log.filter(e => e.timestamp >= timestamp && e.significance >= threshold);\n },\n\n // Get unreported entries (for accumulation between tool calls)\n getUnreported: function() {\n const unreported = this.log.slice(this.lastReportedIndex);\n return unreported.filter(e => e.significance >= SIGNIFICANCE_THRESHOLD);\n },\n\n // Mark entries as reported\n markReported: function() {\n this.lastReportedIndex = this.log.length;\n },\n\n // Reset on navigation\n reset: function() {\n this.log.length = 0;\n this.lastReportedIndex = 0;\n this.pageLoadTime = Date.now();\n // Cleanup all shadow observers\n for (const [shadowRoot, { observer }] of this.shadowObservers) {\n observer.disconnect();\n }\n this.shadowObservers.clear();\n // Clear processed elements tracking (create fresh WeakSet)\n processedElements = new WeakSet();\n },\n\n // Re-scan for shadow roots (useful after dynamic content load)\n rescanShadowRoots: function() {\n if (document.body) {\n checkAndObserveShadowRoots(document.body, []);\n }\n },\n\n // Get shadow observer count (for debugging)\n getShadowObserverCount: function() {\n return this.shadowObservers.size;\n },\n };\n})();\n";
19
19
  //# sourceMappingURL=observer-script.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"observer-script.d.ts","sourceRoot":"","sources":["../../../src/observation/observer-script.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,eAAO,MAAM,2BAA2B,s4kBAsiBvC,CAAC"}
1
+ {"version":3,"file":"observer-script.d.ts","sourceRoot":"","sources":["../../../src/observation/observer-script.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,eAAO,MAAM,2BAA2B,wuuBAgqBvC,CAAC"}
@@ -27,6 +27,23 @@ export const OBSERVATION_OBSERVER_SCRIPT = `
27
27
  const SIGNIFICANCE_THRESHOLD = 4;
28
28
  // Node type constant for shadow root parent check
29
29
  const DOCUMENT_FRAGMENT_NODE = 11;
30
+ // ARIA roles that indicate live regions (text mutations are significant)
31
+ const LIVE_REGION_ROLES = new Set(['alert', 'status', 'log', 'marquee', 'timer']);
32
+ // Attributes whose changes can reveal hidden elements (visibility tracking)
33
+ const VISIBILITY_ATTRS = ['style', 'class', 'hidden', 'aria-hidden'];
34
+
35
+ // Known toast library selectors (unsemantic — no ARIA roles).
36
+ // Keep in sync with TOAST_DATA_ATTRS / TOAST_CLASS_PATTERNS in snapshot-compiler.ts.
37
+ const TOAST_LIBRARY_PARTS = [
38
+ '[data-sonner-toaster]',
39
+ '[data-sonner-toast]',
40
+ '[data-hot-toast]',
41
+ '.Toastify__toast-container',
42
+ '.Toastify__toast',
43
+ '.ant-message',
44
+ '.ant-message-notice',
45
+ ];
46
+ const TOAST_LIBRARY_SELECTOR = TOAST_LIBRARY_PARTS.join(', ');
30
47
 
31
48
  // Significance weights (must match server-side observation.types.ts)
32
49
  const WEIGHTS = {
@@ -44,6 +61,9 @@ export const OBSERVATION_OBSERVER_SCRIPT = `
44
61
  isBodyDirectChild: 1,
45
62
  containsInteractiveElements: 1,
46
63
 
64
+ // Known toast library patterns (unsemantic but significant)
65
+ isKnownToastLibrary: 3, // Equivalent to hasAlertRole
66
+
47
67
  // New universal signals - work without ARIA
48
68
  isVisibleInViewport: 2, // Element is visible in viewport
49
69
  hasNonTrivialText: 1, // Has meaningful text content
@@ -188,6 +208,9 @@ export const OBSERVATION_OBSERVER_SCRIPT = `
188
208
  isBodyDirectChild: el.parentElement === document.body || isTopLevelInShadow,
189
209
  containsInteractiveElements: el.querySelector('button, a, input, select, textarea') !== null,
190
210
 
211
+ // Known toast library detection (unsemantic but significant)
212
+ isKnownToastLibrary: el.matches(TOAST_LIBRARY_SELECTOR) || (typeof el.className === 'string' && el.className.includes('chakra-toast')),
213
+
191
214
  // Universal signals (work without ARIA)
192
215
  isVisibleInViewport: !!isVisibleInViewport,
193
216
  hasNonTrivialText: hasNonTrivialText,
@@ -374,6 +397,89 @@ export const OBSERVATION_OBSERVER_SCRIPT = `
374
397
  }
375
398
  }
376
399
 
400
+ /**
401
+ * Find the nearest ancestor (or self) with a live region role.
402
+ * Returns the element if found, null otherwise.
403
+ */
404
+ function findLiveRegionAncestor(node) {
405
+ let el = node.nodeType === 1 ? node : node.parentElement;
406
+ while (el && el !== document.body) {
407
+ const role = el.getAttribute && el.getAttribute('role');
408
+ if (role && LIVE_REGION_ROLES.has(role)) return el;
409
+ const ariaLive = el.getAttribute && el.getAttribute('aria-live');
410
+ if (ariaLive === 'polite' || ariaLive === 'assertive') return el;
411
+ el = el.parentElement;
412
+ }
413
+ return null;
414
+ }
415
+
416
+ /**
417
+ * Handle characterData mutations (text-only changes in existing elements).
418
+ * Captures the live region container when its text content changes.
419
+ */
420
+ function processCharacterDataMutation(mutation, shadowPath) {
421
+ const textNode = mutation.target;
422
+ const liveRegion = findLiveRegionAncestor(textNode);
423
+ if (!liveRegion) return;
424
+
425
+ // Avoid re-capturing the same live region for rapid successive text changes
426
+ // Use a short debounce window (same element within 100ms)
427
+ const now = Date.now();
428
+ if (liveRegion.__lastTextCapture && (now - liveRegion.__lastTextCapture) < 100) return;
429
+ liveRegion.__lastTextCapture = now;
430
+
431
+ const entry = captureEntry(liveRegion, 'added', shadowPath);
432
+ if (entry) {
433
+ entry.appearedAfterDelay = (entry.timestamp - pageLoadTime) > 100;
434
+ log.push(entry);
435
+ }
436
+ }
437
+
438
+ /**
439
+ * Handle attribute mutations that may reveal hidden elements.
440
+ * Detects visibility changes (display:none → block, hidden removal, etc.)
441
+ */
442
+ function processAttributeMutation(mutation, shadowPath) {
443
+ const el = mutation.target;
444
+ if (el.nodeType !== 1) return;
445
+
446
+ // Skip if already processed in this cycle
447
+ if (processedElements.has(el)) return;
448
+
449
+ // Check if this attribute change made the element visible
450
+ const attrName = mutation.attributeName;
451
+
452
+ // For 'hidden' attribute: element becomes visible when hidden is removed
453
+ if (attrName === 'hidden' && el.hasAttribute('hidden')) return; // Still hidden
454
+
455
+ // For 'aria-hidden': element becomes visible when set to false or removed
456
+ if (attrName === 'aria-hidden') {
457
+ const val = el.getAttribute('aria-hidden');
458
+ if (val === 'true') return; // Still hidden
459
+ }
460
+
461
+ // For 'style' or 'class': check computed visibility
462
+ if (attrName === 'style' || attrName === 'class') {
463
+ try {
464
+ const style = getComputedStyle(el);
465
+ if (style.display === 'none' || style.visibility === 'hidden' || style.opacity === '0') {
466
+ return; // Still hidden
467
+ }
468
+ } catch (e) {
469
+ return; // Detached element
470
+ }
471
+ }
472
+
473
+ // Check if this element (or a live region ancestor) is significant
474
+ // Only capture if the element has meaningful content and meets threshold
475
+ const entry = captureEntry(el, 'added', shadowPath);
476
+ if (entry) {
477
+ entry.appearedAfterDelay = (entry.timestamp - pageLoadTime) > 100;
478
+ log.push(entry);
479
+ processedElements.add(el);
480
+ }
481
+ }
482
+
377
483
  /**
378
484
  * Create a mutation callback for observing a specific context (main DOM or shadow root).
379
485
  * @param shadowPath - The shadow path context for this observer
@@ -381,14 +487,22 @@ export const OBSERVATION_OBSERVER_SCRIPT = `
381
487
  function createMutationCallback(shadowPath) {
382
488
  return function(mutations) {
383
489
  for (const m of mutations) {
384
- // Capture added nodes
385
- for (const node of m.addedNodes) {
386
- processAddedNode(node, shadowPath);
387
- }
490
+ if (m.type === 'childList') {
491
+ // Capture added nodes
492
+ for (const node of m.addedNodes) {
493
+ processAddedNode(node, shadowPath);
494
+ }
388
495
 
389
- // Capture removed nodes
390
- for (const node of m.removedNodes) {
391
- processRemovedNode(node, shadowPath);
496
+ // Capture removed nodes
497
+ for (const node of m.removedNodes) {
498
+ processRemovedNode(node, shadowPath);
499
+ }
500
+ } else if (m.type === 'characterData') {
501
+ // Text content changed in an existing node (live region updates)
502
+ processCharacterDataMutation(m, shadowPath);
503
+ } else if (m.type === 'attributes') {
504
+ // Attribute changed — may reveal hidden elements (visibility tracking)
505
+ processAttributeMutation(m, shadowPath);
392
506
  }
393
507
  }
394
508
 
@@ -419,6 +533,10 @@ export const OBSERVATION_OBSERVER_SCRIPT = `
419
533
  observer.observe(shadowRoot, {
420
534
  childList: true,
421
535
  subtree: true,
536
+ characterData: true,
537
+ characterDataOldValue: true,
538
+ attributes: true,
539
+ attributeFilter: VISIBILITY_ATTRS,
422
540
  });
423
541
 
424
542
  shadowObservers.set(shadowRoot, { observer, hostPath: shadowPath });
@@ -502,6 +620,10 @@ export const OBSERVATION_OBSERVER_SCRIPT = `
502
620
  observer.observe(document.body, {
503
621
  childList: true,
504
622
  subtree: true,
623
+ characterData: true,
624
+ characterDataOldValue: true,
625
+ attributes: true,
626
+ attributeFilter: VISIBILITY_ATTRS,
505
627
  });
506
628
 
507
629
  // Initial scan for existing shadow roots in the DOM
@@ -1 +1 @@
1
- {"version":3,"file":"observer-script.js","sourceRoot":"","sources":["../../../src/observation/observer-script.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,CAAC,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsiB1C,CAAC"}
1
+ {"version":3,"file":"observer-script.js","sourceRoot":"","sources":["../../../src/observation/observer-script.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,CAAC,MAAM,2BAA2B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgqB1C,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Disambiguation
3
+ *
4
+ * Generate suggestions to narrow ambiguous query results.
5
+ * Analyzes matched nodes and suggests refinements.
6
+ */
7
+ import type { ReadableNode } from '../snapshot/snapshot.types.js';
8
+ import type { FindElementsRequest, MatchedNode, DisambiguationSuggestion } from './types/query.types.js';
9
+ /**
10
+ * Generate disambiguation suggestions when query matches multiple elements.
11
+ * Suggests refinements that would narrow down the results.
12
+ */
13
+ export declare function generateSuggestions(matches: MatchedNode[], request: FindElementsRequest): DisambiguationSuggestion[];
14
+ /**
15
+ * Count nodes by a given attribute.
16
+ */
17
+ export declare function countByAttribute<T>(nodes: ReadableNode[], getter: (node: ReadableNode) => T): Map<T, number>;
18
+ //# sourceMappingURL=disambiguation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disambiguation.d.ts","sourceRoot":"","sources":["../../../src/query/disambiguation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EACV,mBAAmB,EACnB,WAAW,EACX,wBAAwB,EACzB,MAAM,wBAAwB,CAAC;AAIhC;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,WAAW,EAAE,EACtB,OAAO,EAAE,mBAAmB,GAC3B,wBAAwB,EAAE,CA2G5B;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,KAAK,EAAE,YAAY,EAAE,EACrB,MAAM,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,CAAC,GAChC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAOhB"}