agent-web-interface 4.0.1 → 4.1.1

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 (38) hide show
  1. package/dist/src/snapshot/extractors/index.d.ts +2 -1
  2. package/dist/src/snapshot/extractors/index.d.ts.map +1 -1
  3. package/dist/src/snapshot/extractors/index.js +2 -0
  4. package/dist/src/snapshot/extractors/index.js.map +1 -1
  5. package/dist/src/snapshot/extractors/interactivity-detector.d.ts +27 -0
  6. package/dist/src/snapshot/extractors/interactivity-detector.d.ts.map +1 -0
  7. package/dist/src/snapshot/extractors/interactivity-detector.js +190 -0
  8. package/dist/src/snapshot/extractors/interactivity-detector.js.map +1 -0
  9. package/dist/src/snapshot/extractors/types.d.ts +15 -0
  10. package/dist/src/snapshot/extractors/types.d.ts.map +1 -1
  11. package/dist/src/snapshot/extractors/types.js.map +1 -1
  12. package/dist/src/snapshot/snapshot-compiler.d.ts +14 -0
  13. package/dist/src/snapshot/snapshot-compiler.d.ts.map +1 -1
  14. package/dist/src/snapshot/snapshot-compiler.js +153 -3
  15. package/dist/src/snapshot/snapshot-compiler.js.map +1 -1
  16. package/dist/src/snapshot/snapshot.types.d.ts +2 -0
  17. package/dist/src/snapshot/snapshot.types.d.ts.map +1 -1
  18. package/dist/src/snapshot/snapshot.types.js +1 -1
  19. package/dist/src/snapshot/snapshot.types.js.map +1 -1
  20. package/dist/src/state/actionables-filter.d.ts.map +1 -1
  21. package/dist/src/state/actionables-filter.js +9 -31
  22. package/dist/src/state/actionables-filter.js.map +1 -1
  23. package/dist/src/state/element-registry.js +2 -2
  24. package/dist/src/state/element-registry.js.map +1 -1
  25. package/dist/src/state/locator-generator.d.ts.map +1 -1
  26. package/dist/src/state/locator-generator.js +1 -10
  27. package/dist/src/state/locator-generator.js.map +1 -1
  28. package/dist/src/state/node-layer.d.ts +22 -0
  29. package/dist/src/state/node-layer.d.ts.map +1 -0
  30. package/dist/src/state/node-layer.js +42 -0
  31. package/dist/src/state/node-layer.js.map +1 -0
  32. package/dist/src/state/state-manager.d.ts.map +1 -1
  33. package/dist/src/state/state-manager.js +9 -8
  34. package/dist/src/state/state-manager.js.map +1 -1
  35. package/dist/src/state/state-renderer.d.ts.map +1 -1
  36. package/dist/src/state/state-renderer.js +4 -0
  37. package/dist/src/state/state-renderer.js.map +1 -1
  38. package/package.json +1 -1
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * @module snapshot/extractors
7
7
  */
8
- export type { RawDomNode, RawAxNode, AxProperty, AxPropertyValue, NodeLayoutInfo, RawNodeData, ExtractorContext, DomExtractionResult, AxExtractionResult, LayoutExtractionResult, } from './types.js';
8
+ export type { RawDomNode, RawAxNode, AxProperty, AxPropertyValue, NodeLayoutInfo, RawNodeData, ExtractorContext, DomExtractionResult, AxExtractionResult, LayoutExtractionResult, InteractivitySignals, } from './types.js';
9
9
  export { createExtractorContext, isValidRawDomNode, isValidRawAxNode, isValidNodeLayoutInfo, DOM_NODE_TYPES, INTERACTIVE_AX_ROLES, READABLE_AX_ROLES, STRUCTURAL_AX_ROLES, } from './types.js';
10
10
  export { extractDom } from './dom-extractor.js';
11
11
  export { extractAx, classifyAxRole, type RoleClassification } from './ax-extractor.js';
@@ -16,4 +16,5 @@ export { resolveRegion } from './region-resolver.js';
16
16
  export { buildLocators } from './locator-builder.js';
17
17
  export { resolveGrouping, type GroupingInfo } from './grouping-resolver.js';
18
18
  export { extractAttributes, sanitizeUrl, type AttributeExtractionOptions, } from './attribute-extractor.js';
19
+ export { detectInteractivity } from './interactivity-detector.js';
19
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/snapshot/extractors/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,YAAY,EACV,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGhD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAGvF,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG5F,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGpD,OAAO,EAAE,YAAY,EAAE,KAAK,eAAe,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAG3F,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,OAAO,EAAE,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG5E,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,KAAK,0BAA0B,GAChC,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/snapshot/extractors/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,YAAY,EACV,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,mBAAmB,EACnB,kBAAkB,EAClB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGhD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAGvF,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG5F,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGpD,OAAO,EAAE,YAAY,EAAE,KAAK,eAAe,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAG3F,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,OAAO,EAAE,eAAe,EAAE,KAAK,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG5E,OAAO,EACL,iBAAiB,EACjB,WAAW,EACX,KAAK,0BAA0B,GAChC,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC"}
@@ -24,4 +24,6 @@ export { buildLocators } from './locator-builder.js';
24
24
  export { resolveGrouping } from './grouping-resolver.js';
25
25
  // Attribute Extractor
26
26
  export { extractAttributes, sanitizeUrl, } from './attribute-extractor.js';
27
+ // Interactivity Detector
28
+ export { detectInteractivity } from './interactivity-detector.js';
27
29
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/snapshot/extractors/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAgBH,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAEpB,gBAAgB;AAChB,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,eAAe;AACf,OAAO,EAAE,SAAS,EAAE,cAAc,EAA2B,MAAM,mBAAmB,CAAC;AAEvF,mBAAmB;AACnB,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE5F,kBAAkB;AAClB,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,iBAAiB;AACjB,OAAO,EAAE,YAAY,EAA0C,MAAM,qBAAqB,CAAC;AAE3F,kBAAkB;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,kBAAkB;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,oBAAoB;AACpB,OAAO,EAAE,eAAe,EAAqB,MAAM,wBAAwB,CAAC;AAE5E,sBAAsB;AACtB,OAAO,EACL,iBAAiB,EACjB,WAAW,GAEZ,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/snapshot/extractors/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAiBH,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,YAAY,CAAC;AAEpB,gBAAgB;AAChB,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,eAAe;AACf,OAAO,EAAE,SAAS,EAAE,cAAc,EAA2B,MAAM,mBAAmB,CAAC;AAEvF,mBAAmB;AACnB,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE5F,kBAAkB;AAClB,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,iBAAiB;AACjB,OAAO,EAAE,YAAY,EAA0C,MAAM,qBAAqB,CAAC;AAE3F,kBAAkB;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,kBAAkB;AAClB,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,oBAAoB;AACpB,OAAO,EAAE,eAAe,EAAqB,MAAM,wBAAwB,CAAC;AAE5E,sBAAsB;AACtB,OAAO,EACL,iBAAiB,EACjB,WAAW,GAEZ,MAAM,0BAA0B,CAAC;AAElC,yBAAyB;AACzB,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Interactivity Detector
3
+ *
4
+ * Detects implicit interactivity signals on non-semantic elements:
5
+ * - Event listeners (click/mousedown/pointerdown) on self or ancestors
6
+ * - CSS cursor: pointer
7
+ * - tabindex >= 0
8
+ *
9
+ * @module snapshot/extractors/interactivity-detector
10
+ *
11
+ * CDP Domains:
12
+ * - DOM: pushNodesByBackendIdsToFrontend, resolveNode
13
+ * - CSS: getComputedStyleForNode
14
+ * - DOMDebugger: getEventListeners
15
+ * - Runtime: releaseObject
16
+ */
17
+ import type { ExtractorContext, RawDomNode, InteractivitySignals } from './types.js';
18
+ /**
19
+ * Detect implicit interactivity signals on non-interactive elements.
20
+ *
21
+ * @param ctx - Extractor context with CDP client
22
+ * @param candidateIds - backendNodeIds of non-interactive nodes to check
23
+ * @param domNodes - DOM tree for attribute lookup and ancestor walking
24
+ * @returns Map of backendNodeId → InteractivitySignals (only for nodes with positive signals)
25
+ */
26
+ export declare function detectInteractivity(ctx: ExtractorContext, candidateIds: number[], domNodes: Map<number, RawDomNode>): Promise<Map<number, InteractivitySignals>>;
27
+ //# sourceMappingURL=interactivity-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactivity-detector.d.ts","sourceRoot":"","sources":["../../../../src/snapshot/extractors/interactivity-detector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAsBrF;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,gBAAgB,EACrB,YAAY,EAAE,MAAM,EAAE,EACtB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,GAChC,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAyI5C"}
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Interactivity Detector
3
+ *
4
+ * Detects implicit interactivity signals on non-semantic elements:
5
+ * - Event listeners (click/mousedown/pointerdown) on self or ancestors
6
+ * - CSS cursor: pointer
7
+ * - tabindex >= 0
8
+ *
9
+ * @module snapshot/extractors/interactivity-detector
10
+ *
11
+ * CDP Domains:
12
+ * - DOM: pushNodesByBackendIdsToFrontend, resolveNode
13
+ * - CSS: getComputedStyleForNode
14
+ * - DOMDebugger: getEventListeners
15
+ * - Runtime: releaseObject
16
+ */
17
+ /** Event types that indicate click interactivity */
18
+ const CLICK_EVENT_TYPES = new Set(['click', 'mousedown', 'pointerdown']);
19
+ /** Maximum ancestor levels to walk for delegated event detection */
20
+ const MAX_ANCESTOR_DEPTH = 5;
21
+ /**
22
+ * Detect implicit interactivity signals on non-interactive elements.
23
+ *
24
+ * @param ctx - Extractor context with CDP client
25
+ * @param candidateIds - backendNodeIds of non-interactive nodes to check
26
+ * @param domNodes - DOM tree for attribute lookup and ancestor walking
27
+ * @returns Map of backendNodeId → InteractivitySignals (only for nodes with positive signals)
28
+ */
29
+ export async function detectInteractivity(ctx, candidateIds, domNodes) {
30
+ const results = new Map();
31
+ if (candidateIds.length === 0)
32
+ return results;
33
+ const { cdp } = ctx;
34
+ // Phase 1: Check tabindex from DOM attributes (free — no CDP calls)
35
+ const tabindexResults = new Map();
36
+ for (const id of candidateIds) {
37
+ const domNode = domNodes.get(id);
38
+ if (domNode?.attributes?.tabindex !== undefined) {
39
+ const tabindex = parseInt(domNode.attributes.tabindex, 10);
40
+ tabindexResults.set(id, !isNaN(tabindex) && tabindex >= 0);
41
+ }
42
+ }
43
+ // Phase 2: Batch resolve backendNodeIds → nodeIds for CSS and event listener checks
44
+ let nodeIdMap;
45
+ try {
46
+ const pushResult = await cdp.send('DOM.pushNodesByBackendIdsToFrontend', { backendNodeIds: candidateIds });
47
+ nodeIdMap = new Map();
48
+ for (let i = 0; i < candidateIds.length; i++) {
49
+ if (pushResult.nodeIds[i] !== 0) {
50
+ nodeIdMap.set(candidateIds[i], pushResult.nodeIds[i]);
51
+ }
52
+ }
53
+ }
54
+ catch {
55
+ // If push fails, return what we have from tabindex
56
+ for (const [id, hasTabindex] of tabindexResults) {
57
+ if (hasTabindex) {
58
+ results.set(id, {
59
+ has_click_listener: false,
60
+ has_cursor_pointer: false,
61
+ has_tabindex: true,
62
+ listener_source: 'none',
63
+ });
64
+ }
65
+ }
66
+ return results;
67
+ }
68
+ // Phase 3: Check cursor:pointer and event listeners for each candidate
69
+ // Cache ancestor listener results to avoid redundant checks
70
+ const ancestorListenerCache = new Map();
71
+ for (const backendNodeId of candidateIds) {
72
+ const nodeId = nodeIdMap.get(backendNodeId);
73
+ if (!nodeId)
74
+ continue;
75
+ const signals = {
76
+ has_click_listener: false,
77
+ has_cursor_pointer: false,
78
+ has_tabindex: tabindexResults.get(backendNodeId) ?? false,
79
+ listener_source: 'none',
80
+ };
81
+ // Check cursor:pointer
82
+ try {
83
+ const styleResult = await cdp.send('CSS.getComputedStyleForNode', { nodeId });
84
+ const cursorProp = styleResult.computedStyle.find((p) => p.name === 'cursor');
85
+ if (cursorProp?.value === 'pointer') {
86
+ signals.has_cursor_pointer = true;
87
+ }
88
+ }
89
+ catch {
90
+ // CSS check failed — continue with other signals
91
+ }
92
+ // Short-circuit: skip expensive listener checks if we already have a positive signal
93
+ if (signals.has_cursor_pointer || signals.has_tabindex) {
94
+ results.set(backendNodeId, signals);
95
+ continue;
96
+ }
97
+ // Check event listeners on self
98
+ let objectId;
99
+ try {
100
+ const resolveResult = await cdp.send('DOM.resolveNode', {
101
+ backendNodeId,
102
+ });
103
+ objectId = resolveResult.object.objectId;
104
+ if (objectId) {
105
+ const listenersResult = await cdp.send('DOMDebugger.getEventListeners', { objectId });
106
+ const hasClickListener = listenersResult.listeners.some((l) => CLICK_EVENT_TYPES.has(l.type));
107
+ if (hasClickListener) {
108
+ signals.has_click_listener = true;
109
+ signals.listener_source = 'self';
110
+ }
111
+ }
112
+ }
113
+ catch {
114
+ // Resolve or listener check failed — continue
115
+ }
116
+ finally {
117
+ // Release the remote object to prevent memory leaks
118
+ if (objectId) {
119
+ try {
120
+ await cdp.send('Runtime.releaseObject', { objectId });
121
+ }
122
+ catch {
123
+ // Ignore release failures
124
+ }
125
+ }
126
+ }
127
+ // Check ancestor event listeners (if no self listener found)
128
+ if (!signals.has_click_listener) {
129
+ const hasAncestorListener = await checkAncestorListeners(cdp, backendNodeId, domNodes, ancestorListenerCache);
130
+ if (hasAncestorListener) {
131
+ signals.has_click_listener = true;
132
+ signals.listener_source = 'ancestor';
133
+ }
134
+ }
135
+ // Only add to results if any signal is positive
136
+ if (signals.has_click_listener || signals.has_cursor_pointer || signals.has_tabindex) {
137
+ results.set(backendNodeId, signals);
138
+ }
139
+ }
140
+ return results;
141
+ }
142
+ /**
143
+ * Walk up ancestor chain checking for delegated click listeners.
144
+ * Results are cached to avoid redundant CDP calls when siblings share parents.
145
+ */
146
+ async function checkAncestorListeners(cdp, backendNodeId, domNodes, cache) {
147
+ let currentId = backendNodeId;
148
+ for (let depth = 0; depth < MAX_ANCESTOR_DEPTH; depth++) {
149
+ const domNode = domNodes.get(currentId);
150
+ const parentId = domNode?.parentId;
151
+ if (parentId === undefined)
152
+ break;
153
+ // Check cache first
154
+ if (cache.has(parentId)) {
155
+ return cache.get(parentId);
156
+ }
157
+ // Check parent's event listeners
158
+ let objectId;
159
+ try {
160
+ const resolveResult = await cdp.send('DOM.resolveNode', {
161
+ backendNodeId: parentId,
162
+ });
163
+ objectId = resolveResult.object.objectId;
164
+ if (objectId) {
165
+ const listenersResult = await cdp.send('DOMDebugger.getEventListeners', { objectId });
166
+ const hasClickListener = listenersResult.listeners.some((l) => CLICK_EVENT_TYPES.has(l.type));
167
+ cache.set(parentId, hasClickListener);
168
+ if (hasClickListener) {
169
+ return true;
170
+ }
171
+ }
172
+ }
173
+ catch {
174
+ cache.set(parentId, false);
175
+ }
176
+ finally {
177
+ if (objectId) {
178
+ try {
179
+ await cdp.send('Runtime.releaseObject', { objectId });
180
+ }
181
+ catch {
182
+ // Ignore release failures
183
+ }
184
+ }
185
+ }
186
+ currentId = parentId;
187
+ }
188
+ return false;
189
+ }
190
+ //# sourceMappingURL=interactivity-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interactivity-detector.js","sourceRoot":"","sources":["../../../../src/snapshot/extractors/interactivity-detector.ts"],"names":[],"mappings":"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"}
@@ -114,6 +114,21 @@ export interface RawNodeData {
114
114
  layout?: NodeLayoutInfo;
115
115
  /** Backend node ID (primary key for correlation) */
116
116
  backendNodeId: number;
117
+ /** Implicit interactivity signals (click listeners, cursor:pointer, tabindex) */
118
+ interactivity?: InteractivitySignals;
119
+ }
120
+ /**
121
+ * Implicit interactivity detection result for a node.
122
+ */
123
+ export interface InteractivitySignals {
124
+ /** Element has click/mousedown/pointerdown event listener */
125
+ has_click_listener: boolean;
126
+ /** Element has CSS cursor: pointer */
127
+ has_cursor_pointer: boolean;
128
+ /** Element has tabindex >= 0 */
129
+ has_tabindex: boolean;
130
+ /** Where the click listener was found */
131
+ listener_source: 'self' | 'ancestor' | 'none';
117
132
  }
118
133
  /**
119
134
  * Context passed to all extractors for accessing CDP and configuration
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/snapshot/extractors/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/snapshot/extractors/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/snapshot/extractors/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/snapshot/extractors/types.ts"],"names":[],"mappings":"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"}
@@ -13,6 +13,7 @@
13
13
  import type { Page } from 'puppeteer-core';
14
14
  import type { CdpClient } from '../cdp/cdp-client.interface.js';
15
15
  import type { BaseSnapshot, SnapshotOptions } from './snapshot.types.js';
16
+ import { type RawNodeData } from './extractors/index.js';
16
17
  /**
17
18
  * Snapshot compiler options
18
19
  */
@@ -66,6 +67,19 @@ export declare class SnapshotCompiler {
66
67
  */
67
68
  private filterNoiseNodes;
68
69
  }
70
+ /**
71
+ * Slice nodes to max_nodes budget while preserving high z-index overlay content.
72
+ *
73
+ * Portal-rendered content (dropdowns, popovers, modals) appears at the end of
74
+ * DOM order. On heavy pages, a naive slice truncates it.
75
+ *
76
+ * Strategy:
77
+ * 1. Partition nodes into overlay (z-index > threshold) and main
78
+ * 2. Take all overlay nodes (up to 30% of budget)
79
+ * 3. Fill remaining budget with main nodes (DOM order)
80
+ * 4. Re-sort by original DOM order
81
+ */
82
+ export declare function sliceWithOverlayPriority(nodes: RawNodeData[], maxNodes: number): RawNodeData[];
69
83
  /**
70
84
  * Export a compile function for simpler usage.
71
85
  */
@@ -1 +1 @@
1
- {"version":3,"file":"snapshot-compiler.d.ts","sourceRoot":"","sources":["../../../src/snapshot/snapshot-compiler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,KAAK,EACV,YAAY,EAGZ,eAAe,EAMhB,MAAM,qBAAqB,CAAC;AAoT7B;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,OAAO,CAAC,eAAe,CAAC;IAC9D,2EAA2E;IAC3E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,4DAA4D;IAC5D,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAuED;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IAEnD,iDAAiD;IACjD,OAAO,CAAC,eAAe,CAAK;gBAEhB,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC;IAI7C;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAK1B;;;;;;;OAOG;IACG,OAAO,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAwPjF;;OAEG;YACW,iBAAiB;IAe/B;;OAEG;IACH,OAAO,CAAC,aAAa;IA8GrB;;OAEG;IACH,OAAO,CAAC,cAAc;IA2BtB;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB;CAqGzB;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,SAAS,EACd,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAChC,OAAO,CAAC,YAAY,CAAC,CAGvB"}
1
+ {"version":3,"file":"snapshot-compiler.d.ts","sourceRoot":"","sources":["../../../src/snapshot/snapshot-compiler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,KAAK,EACV,YAAY,EAGZ,eAAe,EAMhB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAYL,KAAK,WAAW,EAOjB,MAAM,uBAAuB,CAAC;AAkS/B;;GAEG;AACH,MAAM,WAAW,cAAe,SAAQ,OAAO,CAAC,eAAe,CAAC;IAC9D,2EAA2E;IAC3E,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,4DAA4D;IAC5D,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAuED;;;;GAIG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IAEnD,iDAAiD;IACjD,OAAO,CAAC,eAAe,CAAK;gBAEhB,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC;IAI7C;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAK1B;;;;;;;OAOG;IACG,OAAO,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAuVjF;;OAEG;YACW,iBAAiB;IAe/B;;OAEG;IACH,OAAO,CAAC,aAAa;IAsHrB;;OAEG;IACH,OAAO,CAAC,cAAc;IA2BtB;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB;CAqGzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,WAAW,EAAE,CA2C9F;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,GAAG,EAAE,SAAS,EACd,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAChC,OAAO,CAAC,YAAY,CAAC,CAGvB"}
@@ -11,6 +11,7 @@
11
11
  * - CSS: Computed styles (optional, for layout)
12
12
  */
13
13
  import { createExtractorContext, extractDom, extractAx, extractLayout, extractState, resolveLabel, resolveRegion, buildLocators, resolveGrouping, classifyAxRole, extractAttributes, } from './extractors/index.js';
14
+ import { detectInteractivity } from './extractors/interactivity-detector.js';
14
15
  import { getTextContent } from '../lib/text-utils.js';
15
16
  const ROOT_CONTEXT = 'root';
16
17
  const LIGHT_DOM_CONTEXT = 'light';
@@ -463,8 +464,101 @@ export class SnapshotCompiler {
463
464
  return orderA - orderB;
464
465
  });
465
466
  }
466
- // Limit nodes (now respects DOM order)
467
- const limitedNodes = nodesToProcess.slice(0, this.options.max_nodes);
467
+ // Phase 2.5: Detect implicit interactivity on non-interactive nodes
468
+ // Also check unincluded AX nodes with unknown classification for interactivity
469
+ const nonInteractiveIds = [];
470
+ const interactiveKindSet = new Set([
471
+ 'button',
472
+ 'link',
473
+ 'input',
474
+ 'textarea',
475
+ 'select',
476
+ 'combobox',
477
+ 'checkbox',
478
+ 'radio',
479
+ 'switch',
480
+ 'slider',
481
+ 'tab',
482
+ 'menuitem',
483
+ ]);
484
+ // Collect non-interactive nodes already in nodesToProcess (Case A)
485
+ for (const nodeData of nodesToProcess) {
486
+ const kind = nodeData.axNode?.role
487
+ ? (mapRoleToKind(nodeData.axNode.role) ?? 'generic')
488
+ : 'generic';
489
+ if (!interactiveKindSet.has(kind)) {
490
+ nonInteractiveIds.push(nodeData.backendNodeId);
491
+ }
492
+ }
493
+ // Collect unknown-classification AX nodes NOT yet in nodesToProcess (Case B)
494
+ // Cap candidates to bound worst-case CDP call volume on complex pages
495
+ const MAX_CASE_B_CANDIDATES = 200;
496
+ const alreadyIncluded = new Set(nodesToProcess.map((n) => n.backendNodeId));
497
+ const caseB_candidates = [];
498
+ if (axResult) {
499
+ for (const [backendNodeId, axNode] of axResult.nodes) {
500
+ if (alreadyIncluded.has(backendNodeId))
501
+ continue;
502
+ if (caseB_candidates.length >= MAX_CASE_B_CANDIDATES)
503
+ break;
504
+ const classification = classifyAxRole(axNode.role);
505
+ if (classification === 'unknown') {
506
+ caseB_candidates.push(backendNodeId);
507
+ }
508
+ }
509
+ }
510
+ // Run interactivity detection on both sets
511
+ let interactivityMap = new Map();
512
+ const allCandidates = [...nonInteractiveIds, ...caseB_candidates];
513
+ if (allCandidates.length > 0 && domResult) {
514
+ try {
515
+ interactivityMap = await detectInteractivity(ctx, allCandidates, domResult.nodes);
516
+ }
517
+ catch (err) {
518
+ const message = err instanceof Error ? err.message : String(err);
519
+ warnings.push(`Interactivity detection failed: ${message}`);
520
+ }
521
+ }
522
+ // Merge interactivity signals into existing nodes (Case A)
523
+ for (const nodeData of nodesToProcess) {
524
+ const signals = interactivityMap.get(nodeData.backendNodeId);
525
+ if (signals) {
526
+ nodeData.interactivity = signals;
527
+ }
528
+ }
529
+ // Add newly discovered interactive nodes (Case B)
530
+ for (const backendNodeId of caseB_candidates) {
531
+ const signals = interactivityMap.get(backendNodeId);
532
+ if (signals) {
533
+ const domNode = domResult?.nodes.get(backendNodeId);
534
+ const axNode = axResult?.nodes.get(backendNodeId);
535
+ nodesToProcess.push({
536
+ backendNodeId,
537
+ domNode,
538
+ axNode,
539
+ interactivity: signals,
540
+ });
541
+ }
542
+ }
543
+ // Re-sort if we added Case B nodes (they need to be in DOM order)
544
+ if (caseB_candidates.some((id) => interactivityMap.has(id))) {
545
+ if (domOrderAvailable && domOrderIndex) {
546
+ const orderMap = domOrderIndex;
547
+ nodesToProcess.sort((a, b) => {
548
+ const orderA = orderMap.get(a.backendNodeId);
549
+ const orderB = orderMap.get(b.backendNodeId);
550
+ if (orderA === undefined && orderB === undefined)
551
+ return 0;
552
+ if (orderA === undefined)
553
+ return 1;
554
+ if (orderB === undefined)
555
+ return -1;
556
+ return orderA - orderB;
557
+ });
558
+ }
559
+ }
560
+ // Limit nodes (now respects DOM order and preserves overlay content)
561
+ const limitedNodes = sliceWithOverlayPriority(nodesToProcess, this.options.max_nodes);
468
562
  // Phase 3: Layout extraction (batched)
469
563
  let layoutResult;
470
564
  if (this.options.includeLayout && limitedNodes.length > 0) {
@@ -507,7 +601,7 @@ export class SnapshotCompiler {
507
601
  'slider',
508
602
  'tab',
509
603
  'menuitem',
510
- ].includes(n.kind)).length;
604
+ ].includes(n.kind) || n.implicitly_interactive).length;
511
605
  const meta = {
512
606
  node_count: nodes.length,
513
607
  interactive_count: interactiveCount,
@@ -628,6 +722,13 @@ export class SnapshotCompiler {
628
722
  if (attributes && Object.keys(attributes).length > 0) {
629
723
  node.attributes = attributes;
630
724
  }
725
+ // Set implicitly_interactive flag
726
+ if (nodeData.interactivity) {
727
+ const { has_click_listener, has_cursor_pointer, has_tabindex } = nodeData.interactivity;
728
+ if (has_click_listener || has_cursor_pointer || has_tabindex) {
729
+ node.implicitly_interactive = true;
730
+ }
731
+ }
631
732
  return node;
632
733
  }
633
734
  /**
@@ -753,6 +854,55 @@ export class SnapshotCompiler {
753
854
  });
754
855
  }
755
856
  }
857
+ /**
858
+ * Slice nodes to max_nodes budget while preserving high z-index overlay content.
859
+ *
860
+ * Portal-rendered content (dropdowns, popovers, modals) appears at the end of
861
+ * DOM order. On heavy pages, a naive slice truncates it.
862
+ *
863
+ * Strategy:
864
+ * 1. Partition nodes into overlay (z-index > threshold) and main
865
+ * 2. Take all overlay nodes (up to 30% of budget)
866
+ * 3. Fill remaining budget with main nodes (DOM order)
867
+ * 4. Re-sort by original DOM order
868
+ */
869
+ export function sliceWithOverlayPriority(nodes, maxNodes) {
870
+ if (nodes.length <= maxNodes) {
871
+ return nodes;
872
+ }
873
+ const OVERLAY_Z_THRESHOLD = 100;
874
+ const MAX_OVERLAY_RATIO = 0.3;
875
+ const overlayNodes = [];
876
+ const mainNodes = [];
877
+ for (const node of nodes) {
878
+ const zIndex = node.layout?.zIndex;
879
+ if (zIndex !== undefined && zIndex > OVERLAY_Z_THRESHOLD) {
880
+ overlayNodes.push(node);
881
+ }
882
+ else {
883
+ mainNodes.push(node);
884
+ }
885
+ }
886
+ // No overlay content → simple slice
887
+ if (overlayNodes.length === 0) {
888
+ return nodes.slice(0, maxNodes);
889
+ }
890
+ // Reserve budget for overlay (capped at 30% of total)
891
+ const maxOverlay = Math.min(overlayNodes.length, Math.floor(maxNodes * MAX_OVERLAY_RATIO));
892
+ const overlaySlice = overlayNodes.slice(0, maxOverlay);
893
+ // Fill remaining budget with main content
894
+ const mainBudget = maxNodes - overlaySlice.length;
895
+ const mainSlice = mainNodes.slice(0, mainBudget);
896
+ // Merge and re-sort by original DOM order
897
+ const merged = [...mainSlice, ...overlaySlice];
898
+ const indexMap = new Map(nodes.map((n, i) => [n.backendNodeId, i]));
899
+ merged.sort((a, b) => {
900
+ const ia = indexMap.get(a.backendNodeId) ?? Infinity;
901
+ const ib = indexMap.get(b.backendNodeId) ?? Infinity;
902
+ return ia - ib;
903
+ });
904
+ return merged;
905
+ }
756
906
  /**
757
907
  * Export a compile function for simpler usage.
758
908
  */