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.
- package/dist/src/browser/connection-utils.d.ts +48 -0
- package/dist/src/browser/connection-utils.d.ts.map +1 -0
- package/dist/src/browser/connection-utils.js +129 -0
- package/dist/src/browser/connection-utils.js.map +1 -0
- package/dist/src/browser/index.d.ts +3 -1
- package/dist/src/browser/index.d.ts.map +1 -1
- package/dist/src/browser/index.js +2 -1
- package/dist/src/browser/index.js.map +1 -1
- package/dist/src/browser/session-manager.d.ts +1 -89
- package/dist/src/browser/session-manager.d.ts.map +1 -1
- package/dist/src/browser/session-manager.js +1 -116
- package/dist/src/browser/session-manager.js.map +1 -1
- package/dist/src/browser/session-manager.types.d.ts +90 -0
- package/dist/src/browser/session-manager.types.d.ts.map +1 -0
- package/dist/src/browser/session-manager.types.js +7 -0
- package/dist/src/browser/session-manager.types.js.map +1 -0
- package/dist/src/form/constraint-extraction.d.ts +31 -0
- package/dist/src/form/constraint-extraction.d.ts.map +1 -0
- package/dist/src/form/constraint-extraction.js +110 -0
- package/dist/src/form/constraint-extraction.js.map +1 -0
- package/dist/src/form/field-extractor.d.ts.map +1 -1
- package/dist/src/form/field-extractor.js +3 -444
- package/dist/src/form/field-extractor.js.map +1 -1
- package/dist/src/form/field-state-extractor.d.ts +22 -0
- package/dist/src/form/field-state-extractor.d.ts.map +1 -0
- package/dist/src/form/field-state-extractor.js +55 -0
- package/dist/src/form/field-state-extractor.js.map +1 -0
- package/dist/src/form/form-actions.d.ts +45 -0
- package/dist/src/form/form-actions.d.ts.map +1 -0
- package/dist/src/form/form-actions.js +108 -0
- package/dist/src/form/form-actions.js.map +1 -0
- package/dist/src/form/form-detector.d.ts +0 -36
- package/dist/src/form/form-detector.d.ts.map +1 -1
- package/dist/src/form/form-detector.js +11 -376
- package/dist/src/form/form-detector.js.map +1 -1
- package/dist/src/form/input-clustering.d.ts +15 -0
- package/dist/src/form/input-clustering.d.ts.map +1 -0
- package/dist/src/form/input-clustering.js +61 -0
- package/dist/src/form/input-clustering.js.map +1 -0
- package/dist/src/form/intent-inference.d.ts +28 -0
- package/dist/src/form/intent-inference.d.ts.map +1 -0
- package/dist/src/form/intent-inference.js +137 -0
- package/dist/src/form/intent-inference.js.map +1 -0
- package/dist/src/form/purpose-inference.d.ts +50 -0
- package/dist/src/form/purpose-inference.d.ts.map +1 -0
- package/dist/src/form/purpose-inference.js +313 -0
- package/dist/src/form/purpose-inference.js.map +1 -0
- package/dist/src/form/submit-detection.d.ts +36 -0
- package/dist/src/form/submit-detection.d.ts.map +1 -0
- package/dist/src/form/submit-detection.js +101 -0
- package/dist/src/form/submit-detection.js.map +1 -0
- package/dist/src/form/types.d.ts +2 -2
- package/dist/src/index.js +65 -48
- package/dist/src/index.js.map +1 -1
- package/dist/src/observation/observation-accumulator.d.ts +1 -1
- package/dist/src/observation/observation-accumulator.js +1 -1
- package/dist/src/observation/observer-script.d.ts +1 -1
- package/dist/src/observation/observer-script.d.ts.map +1 -1
- package/dist/src/observation/observer-script.js +129 -7
- package/dist/src/observation/observer-script.js.map +1 -1
- package/dist/src/query/disambiguation.d.ts +18 -0
- package/dist/src/query/disambiguation.d.ts.map +1 -0
- package/dist/src/query/disambiguation.js +123 -0
- package/dist/src/query/disambiguation.js.map +1 -0
- package/dist/src/query/fuzzy-match.d.ts +17 -0
- package/dist/src/query/fuzzy-match.d.ts.map +1 -0
- package/dist/src/query/fuzzy-match.js +34 -0
- package/dist/src/query/fuzzy-match.js.map +1 -0
- package/dist/src/query/index.d.ts +3 -0
- package/dist/src/query/index.d.ts.map +1 -1
- package/dist/src/query/index.js +6 -0
- package/dist/src/query/index.js.map +1 -1
- package/dist/src/query/query-engine.d.ts +0 -35
- package/dist/src/query/query-engine.d.ts.map +1 -1
- package/dist/src/query/query-engine.js +9 -309
- package/dist/src/query/query-engine.js.map +1 -1
- package/dist/src/query/scoring.d.ts +52 -0
- package/dist/src/query/scoring.d.ts.map +1 -0
- package/dist/src/query/scoring.js +162 -0
- package/dist/src/query/scoring.js.map +1 -0
- package/dist/src/server/mcp-server.d.ts.map +1 -1
- package/dist/src/server/mcp-server.js +29 -1
- package/dist/src/server/mcp-server.js.map +1 -1
- package/dist/src/snapshot/element-resolver.d.ts +50 -18
- package/dist/src/snapshot/element-resolver.d.ts.map +1 -1
- package/dist/src/snapshot/element-resolver.js +180 -101
- package/dist/src/snapshot/element-resolver.js.map +1 -1
- package/dist/src/snapshot/extractors/ax-extractor.d.ts +1 -1
- package/dist/src/snapshot/extractors/ax-extractor.d.ts.map +1 -1
- package/dist/src/snapshot/extractors/ax-extractor.js +4 -1
- package/dist/src/snapshot/extractors/ax-extractor.js.map +1 -1
- package/dist/src/snapshot/extractors/index.d.ts +1 -1
- package/dist/src/snapshot/extractors/index.d.ts.map +1 -1
- package/dist/src/snapshot/extractors/index.js +1 -1
- package/dist/src/snapshot/extractors/index.js.map +1 -1
- package/dist/src/snapshot/extractors/region-resolver.d.ts.map +1 -1
- package/dist/src/snapshot/extractors/region-resolver.js +8 -0
- package/dist/src/snapshot/extractors/region-resolver.js.map +1 -1
- package/dist/src/snapshot/extractors/types.d.ts +8 -0
- package/dist/src/snapshot/extractors/types.d.ts.map +1 -1
- package/dist/src/snapshot/extractors/types.js +16 -0
- package/dist/src/snapshot/extractors/types.js.map +1 -1
- package/dist/src/snapshot/frame-context.d.ts +68 -0
- package/dist/src/snapshot/frame-context.d.ts.map +1 -0
- package/dist/src/snapshot/frame-context.js +131 -0
- package/dist/src/snapshot/frame-context.js.map +1 -0
- package/dist/src/snapshot/heading-index.d.ts +28 -0
- package/dist/src/snapshot/heading-index.d.ts.map +1 -0
- package/dist/src/snapshot/heading-index.js +108 -0
- package/dist/src/snapshot/heading-index.js.map +1 -0
- package/dist/src/snapshot/index.d.ts +5 -3
- package/dist/src/snapshot/index.d.ts.map +1 -1
- package/dist/src/snapshot/index.js +3 -2
- package/dist/src/snapshot/index.js.map +1 -1
- package/dist/src/snapshot/kind-mapping.d.ts +30 -0
- package/dist/src/snapshot/kind-mapping.d.ts.map +1 -0
- package/dist/src/snapshot/kind-mapping.js +114 -0
- package/dist/src/snapshot/kind-mapping.js.map +1 -0
- package/dist/src/snapshot/node-filter.d.ts +31 -0
- package/dist/src/snapshot/node-filter.d.ts.map +1 -0
- package/dist/src/snapshot/node-filter.js +137 -0
- package/dist/src/snapshot/node-filter.js.map +1 -0
- package/dist/src/snapshot/node-synthesizer.d.ts +62 -0
- package/dist/src/snapshot/node-synthesizer.d.ts.map +1 -0
- package/dist/src/snapshot/node-synthesizer.js +185 -0
- package/dist/src/snapshot/node-synthesizer.js.map +1 -0
- package/dist/src/snapshot/snapshot-compiler.d.ts +2 -36
- package/dist/src/snapshot/snapshot-compiler.d.ts.map +1 -1
- package/dist/src/snapshot/snapshot-compiler.js +28 -520
- package/dist/src/snapshot/snapshot-compiler.js.map +1 -1
- package/dist/src/snapshot/snapshot.types.d.ts +7 -2
- package/dist/src/snapshot/snapshot.types.d.ts.map +1 -1
- package/dist/src/snapshot/snapshot.types.js +9 -0
- package/dist/src/snapshot/snapshot.types.js.map +1 -1
- package/dist/src/state/actionables-filter.d.ts +5 -0
- package/dist/src/state/actionables-filter.d.ts.map +1 -1
- package/dist/src/state/actionables-filter.js +22 -3
- package/dist/src/state/actionables-filter.js.map +1 -1
- package/dist/src/state/diff-engine.js +3 -3
- package/dist/src/state/diff-engine.js.map +1 -1
- package/dist/src/state/element-registry.d.ts.map +1 -1
- package/dist/src/state/element-registry.js +6 -4
- package/dist/src/state/element-registry.js.map +1 -1
- package/dist/src/state/hash-utils.d.ts +24 -0
- package/dist/src/state/hash-utils.d.ts.map +1 -0
- package/dist/src/state/hash-utils.js +41 -0
- package/dist/src/state/hash-utils.js.map +1 -0
- package/dist/src/state/layer-detector.d.ts.map +1 -1
- package/dist/src/state/layer-detector.js +15 -286
- package/dist/src/state/layer-detector.js.map +1 -1
- package/dist/src/state/layer-detectors/drawer-detector.d.ts +32 -0
- package/dist/src/state/layer-detectors/drawer-detector.d.ts.map +1 -0
- package/dist/src/state/layer-detectors/drawer-detector.js +96 -0
- package/dist/src/state/layer-detectors/drawer-detector.js.map +1 -0
- package/dist/src/state/layer-detectors/index.d.ts +10 -0
- package/dist/src/state/layer-detectors/index.d.ts.map +1 -0
- package/dist/src/state/layer-detectors/index.js +10 -0
- package/dist/src/state/layer-detectors/index.js.map +1 -0
- package/dist/src/state/layer-detectors/modal-detector.d.ts +30 -0
- package/dist/src/state/layer-detectors/modal-detector.d.ts.map +1 -0
- package/dist/src/state/layer-detectors/modal-detector.js +127 -0
- package/dist/src/state/layer-detectors/modal-detector.js.map +1 -0
- package/dist/src/state/layer-detectors/popover-detector.d.ts +20 -0
- package/dist/src/state/layer-detectors/popover-detector.d.ts.map +1 -0
- package/dist/src/state/layer-detectors/popover-detector.js +76 -0
- package/dist/src/state/layer-detectors/popover-detector.js.map +1 -0
- package/dist/src/state/layer-detectors/toast-detector.d.ts +24 -0
- package/dist/src/state/layer-detectors/toast-detector.d.ts.map +1 -0
- package/dist/src/state/layer-detectors/toast-detector.js +48 -0
- package/dist/src/state/layer-detectors/toast-detector.js.map +1 -0
- package/dist/src/state/region-mapping.d.ts +13 -0
- package/dist/src/state/region-mapping.d.ts.map +1 -0
- package/dist/src/state/region-mapping.js +25 -0
- package/dist/src/state/region-mapping.js.map +1 -0
- package/dist/src/state/state-manager.d.ts.map +1 -1
- package/dist/src/state/state-manager.js +8 -192
- package/dist/src/state/state-manager.js.map +1 -1
- package/dist/src/state/state-renderer.d.ts.map +1 -1
- package/dist/src/state/state-renderer.js +16 -2
- package/dist/src/state/state-renderer.js.map +1 -1
- package/dist/src/state/types.d.ts +8 -4
- package/dist/src/state/types.d.ts.map +1 -1
- package/dist/src/state/url-sanitization.d.ts +22 -0
- package/dist/src/state/url-sanitization.d.ts.map +1 -0
- package/dist/src/state/url-sanitization.js +60 -0
- package/dist/src/state/url-sanitization.js.map +1 -0
- package/dist/src/state/value-masking.d.ts +36 -0
- package/dist/src/state/value-masking.d.ts.map +1 -0
- package/dist/src/state/value-masking.js +86 -0
- package/dist/src/state/value-masking.js.map +1 -0
- package/dist/src/tools/action-context.d.ts +60 -0
- package/dist/src/tools/action-context.d.ts.map +1 -0
- package/dist/src/tools/action-context.js +78 -0
- package/dist/src/tools/action-context.js.map +1 -0
- package/dist/src/tools/action-stabilization.d.ts +48 -0
- package/dist/src/tools/action-stabilization.d.ts.map +1 -0
- package/dist/src/tools/action-stabilization.js +87 -0
- package/dist/src/tools/action-stabilization.js.map +1 -0
- package/dist/src/tools/browser-tools.d.ts +8 -146
- package/dist/src/tools/browser-tools.d.ts.map +1 -1
- package/dist/src/tools/browser-tools.js +13 -689
- package/dist/src/tools/browser-tools.js.map +1 -1
- package/dist/src/tools/canvas-tools.d.ts +32 -0
- package/dist/src/tools/canvas-tools.d.ts.map +1 -0
- package/dist/src/tools/canvas-tools.js +370 -0
- package/dist/src/tools/canvas-tools.js.map +1 -0
- package/dist/src/tools/effect-tracker.d.ts +25 -0
- package/dist/src/tools/effect-tracker.d.ts.map +1 -0
- package/dist/src/tools/effect-tracker.js +69 -0
- package/dist/src/tools/effect-tracker.js.map +1 -0
- package/dist/src/tools/execute-action.d.ts +1 -31
- package/dist/src/tools/execute-action.d.ts.map +1 -1
- package/dist/src/tools/execute-action.js +7 -276
- package/dist/src/tools/execute-action.js.map +1 -1
- package/dist/src/tools/form-tools.d.ts +4 -6
- package/dist/src/tools/form-tools.d.ts.map +1 -1
- package/dist/src/tools/form-tools.js +10 -42
- package/dist/src/tools/form-tools.js.map +1 -1
- package/dist/src/tools/index.d.ts +6 -4
- package/dist/src/tools/index.d.ts.map +1 -1
- package/dist/src/tools/index.js +21 -10
- package/dist/src/tools/index.js.map +1 -1
- package/dist/src/tools/interaction-tools.d.ts +46 -0
- package/dist/src/tools/interaction-tools.d.ts.map +1 -0
- package/dist/src/tools/interaction-tools.js +138 -0
- package/dist/src/tools/interaction-tools.js.map +1 -0
- package/dist/src/tools/navigation-detection.d.ts +31 -0
- package/dist/src/tools/navigation-detection.d.ts.map +1 -0
- package/dist/src/tools/navigation-detection.js +46 -0
- package/dist/src/tools/navigation-detection.js.map +1 -0
- package/dist/src/tools/navigation-tools.d.ts +57 -0
- package/dist/src/tools/navigation-tools.d.ts.map +1 -0
- package/dist/src/tools/navigation-tools.js +178 -0
- package/dist/src/tools/navigation-tools.js.map +1 -0
- package/dist/src/tools/observation-tools.d.ts +53 -0
- package/dist/src/tools/observation-tools.d.ts.map +1 -0
- package/dist/src/tools/observation-tools.js +247 -0
- package/dist/src/tools/observation-tools.js.map +1 -0
- package/dist/src/tools/response-builder.js +2 -2
- package/dist/src/tools/response-builder.js.map +1 -1
- package/dist/src/tools/stale-element-retry.d.ts +37 -0
- package/dist/src/tools/stale-element-retry.d.ts.map +1 -0
- package/dist/src/tools/stale-element-retry.js +68 -0
- package/dist/src/tools/stale-element-retry.js.map +1 -0
- package/dist/src/tools/state-manager-registry.d.ts +26 -0
- package/dist/src/tools/state-manager-registry.d.ts.map +1 -0
- package/dist/src/tools/state-manager-registry.js +39 -0
- package/dist/src/tools/state-manager-registry.js.map +1 -0
- package/dist/src/tools/tool-context.d.ts +53 -0
- package/dist/src/tools/tool-context.d.ts.map +1 -0
- package/dist/src/tools/tool-context.js +119 -0
- package/dist/src/tools/tool-context.js.map +1 -0
- package/dist/src/tools/tool-result.types.d.ts +16 -1
- package/dist/src/tools/tool-result.types.d.ts.map +1 -1
- package/dist/src/tools/tool-result.types.js +11 -0
- package/dist/src/tools/tool-result.types.js.map +1 -1
- package/dist/src/tools/tool-schemas.d.ts +358 -146
- package/dist/src/tools/tool-schemas.d.ts.map +1 -1
- package/dist/src/tools/tool-schemas.js +142 -19
- package/dist/src/tools/tool-schemas.js.map +1 -1
- package/dist/src/tools/viewport-tools.d.ts +36 -0
- package/dist/src/tools/viewport-tools.d.ts.map +1 -0
- package/dist/src/tools/viewport-tools.js +105 -0
- package/dist/src/tools/viewport-tools.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Modal Detector
|
|
3
|
+
*
|
|
4
|
+
* Detect modal layers in the snapshot.
|
|
5
|
+
* Patterns: role="dialog" + aria-modal, <dialog open>, portal containers.
|
|
6
|
+
*/
|
|
7
|
+
import { computeEid } from '../element-identity.js';
|
|
8
|
+
/**
|
|
9
|
+
* Detect if node is a modal layer.
|
|
10
|
+
*
|
|
11
|
+
* Patterns:
|
|
12
|
+
* - role="dialog" or role="alertdialog" + aria-modal="true"
|
|
13
|
+
* - <dialog open>
|
|
14
|
+
* - High z-index (>1000) with dialog role
|
|
15
|
+
* - React/Vue portal containers with modal content
|
|
16
|
+
*
|
|
17
|
+
* @param node - Node to check
|
|
18
|
+
* @returns Layer candidate or null
|
|
19
|
+
*/
|
|
20
|
+
export function detectModal(node) {
|
|
21
|
+
const attrs = node.attributes;
|
|
22
|
+
const role = node.attributes?.role;
|
|
23
|
+
// Pattern 1: role="dialog" or role="alertdialog" + aria-modal="true"
|
|
24
|
+
if ((role === 'dialog' || role === 'alertdialog') && attrs?.['aria-modal'] === 'true') {
|
|
25
|
+
return {
|
|
26
|
+
type: 'modal',
|
|
27
|
+
rootEid: computeEid(node, 'modal'),
|
|
28
|
+
zIndex: node.layout.zIndex ?? 0,
|
|
29
|
+
isModal: true,
|
|
30
|
+
confidence: 1.0,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
// Pattern 2: <dialog> element with open attribute
|
|
34
|
+
if (node.kind === 'dialog' && attrs?.open === true) {
|
|
35
|
+
return {
|
|
36
|
+
type: 'modal',
|
|
37
|
+
rootEid: computeEid(node, 'modal'),
|
|
38
|
+
zIndex: node.layout.zIndex ?? 0,
|
|
39
|
+
isModal: true,
|
|
40
|
+
confidence: 0.95,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
// Pattern 3: alertdialog without aria-modal (still modal by nature)
|
|
44
|
+
if (role === 'alertdialog') {
|
|
45
|
+
return {
|
|
46
|
+
type: 'modal',
|
|
47
|
+
rootEid: computeEid(node, 'modal'),
|
|
48
|
+
zIndex: node.layout.zIndex ?? 0,
|
|
49
|
+
isModal: true,
|
|
50
|
+
confidence: 0.9,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
// Pattern 4: High z-index dialog (>1000)
|
|
54
|
+
if (role === 'dialog' && (node.layout.zIndex ?? 0) > 1000) {
|
|
55
|
+
return {
|
|
56
|
+
type: 'modal',
|
|
57
|
+
rootEid: computeEid(node, 'modal'),
|
|
58
|
+
zIndex: node.layout.zIndex ?? 0,
|
|
59
|
+
isModal: true,
|
|
60
|
+
confidence: 0.8,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
// Pattern 5: Portal container detection (React/Vue/Angular)
|
|
64
|
+
// Common portal container patterns
|
|
65
|
+
if (isPortalContainer(node, attrs)) {
|
|
66
|
+
return {
|
|
67
|
+
type: 'modal',
|
|
68
|
+
rootEid: computeEid(node, 'modal'),
|
|
69
|
+
zIndex: node.layout.zIndex ?? 0,
|
|
70
|
+
isModal: true,
|
|
71
|
+
confidence: 0.75,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Check if node is a portal container (React/Vue/Angular patterns).
|
|
78
|
+
*
|
|
79
|
+
* @param node - Node to check
|
|
80
|
+
* @param attrs - Node attributes
|
|
81
|
+
* @returns True if portal container
|
|
82
|
+
*/
|
|
83
|
+
export function isPortalContainer(node, attrs) {
|
|
84
|
+
const zIndex = node.layout.zIndex ?? 0;
|
|
85
|
+
// Must have high z-index
|
|
86
|
+
if (zIndex < 100) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
// Check for common portal container attributes/classes
|
|
90
|
+
const className = attrs?.class ?? attrs?.className;
|
|
91
|
+
if (typeof className === 'string') {
|
|
92
|
+
const portalPatterns = [
|
|
93
|
+
'modal',
|
|
94
|
+
'dialog',
|
|
95
|
+
'overlay',
|
|
96
|
+
'portal',
|
|
97
|
+
'ReactModal',
|
|
98
|
+
'MuiModal',
|
|
99
|
+
'chakra-modal',
|
|
100
|
+
'ant-modal',
|
|
101
|
+
'el-dialog', // Element UI
|
|
102
|
+
'v-dialog', // Vuetify
|
|
103
|
+
];
|
|
104
|
+
const lowerClassName = className.toLowerCase();
|
|
105
|
+
if (portalPatterns.some((p) => lowerClassName.includes(p.toLowerCase()))) {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// Check for data attributes indicating portal
|
|
110
|
+
const dataPortal = attrs?.['data-portal'];
|
|
111
|
+
const dataOverlay = attrs?.['data-overlay'];
|
|
112
|
+
const dataModal = attrs?.['data-modal'];
|
|
113
|
+
if (dataPortal === true || dataOverlay === true || dataModal === true) {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
// Check for aria-hidden siblings pattern (portal often has aria-hidden on root)
|
|
117
|
+
// This is detected by high z-index + covering most of viewport
|
|
118
|
+
const bbox = node.layout.bbox;
|
|
119
|
+
if (bbox && zIndex > 500) {
|
|
120
|
+
// If element covers significant viewport area with high z-index
|
|
121
|
+
if (bbox.w > 200 && bbox.h > 200) {
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=modal-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modal-detector.js","sourceRoot":"","sources":["../../../../src/state/layer-detectors/modal-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Popover Detector
|
|
3
|
+
*
|
|
4
|
+
* Detect popover layers in the snapshot.
|
|
5
|
+
* Patterns: role="menu", "listbox", "tooltip" + z-index > 100.
|
|
6
|
+
*/
|
|
7
|
+
import type { ReadableNode } from '../../snapshot/snapshot.types.js';
|
|
8
|
+
import type { LayerCandidate } from '../types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Detect if node is a popover layer.
|
|
11
|
+
*
|
|
12
|
+
* Patterns:
|
|
13
|
+
* - role="menu", "listbox", "tooltip", "dialog" (non-modal) + z-index > 100
|
|
14
|
+
* - Dropdown/popup class patterns
|
|
15
|
+
*
|
|
16
|
+
* @param node - Node to check
|
|
17
|
+
* @returns Layer candidate or null
|
|
18
|
+
*/
|
|
19
|
+
export declare function detectPopover(node: ReadableNode): LayerCandidate | null;
|
|
20
|
+
//# sourceMappingURL=popover-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"popover-detector.d.ts","sourceRoot":"","sources":["../../../../src/state/layer-detectors/popover-detector.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlD;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,GAAG,cAAc,GAAG,IAAI,CA+DvE"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Popover Detector
|
|
3
|
+
*
|
|
4
|
+
* Detect popover layers in the snapshot.
|
|
5
|
+
* Patterns: role="menu", "listbox", "tooltip" + z-index > 100.
|
|
6
|
+
*/
|
|
7
|
+
import { computeEid } from '../element-identity.js';
|
|
8
|
+
/**
|
|
9
|
+
* Detect if node is a popover layer.
|
|
10
|
+
*
|
|
11
|
+
* Patterns:
|
|
12
|
+
* - role="menu", "listbox", "tooltip", "dialog" (non-modal) + z-index > 100
|
|
13
|
+
* - Dropdown/popup class patterns
|
|
14
|
+
*
|
|
15
|
+
* @param node - Node to check
|
|
16
|
+
* @returns Layer candidate or null
|
|
17
|
+
*/
|
|
18
|
+
export function detectPopover(node) {
|
|
19
|
+
const role = node.attributes?.role;
|
|
20
|
+
const zIndex = node.layout.zIndex ?? 0;
|
|
21
|
+
const attrs = node.attributes;
|
|
22
|
+
if (zIndex <= 100) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
// Pattern 1: Standard popover roles
|
|
26
|
+
const popoverRoles = ['menu', 'listbox', 'tooltip', 'tree'];
|
|
27
|
+
if (role && popoverRoles.includes(role)) {
|
|
28
|
+
return {
|
|
29
|
+
type: 'popover',
|
|
30
|
+
rootEid: computeEid(node, 'popover'),
|
|
31
|
+
zIndex,
|
|
32
|
+
isModal: false,
|
|
33
|
+
confidence: 0.8,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
// Pattern 2: Non-modal dialog (popup)
|
|
37
|
+
if (role === 'dialog' && attrs?.['aria-modal'] !== 'true') {
|
|
38
|
+
return {
|
|
39
|
+
type: 'popover',
|
|
40
|
+
rootEid: computeEid(node, 'popover'),
|
|
41
|
+
zIndex,
|
|
42
|
+
isModal: false,
|
|
43
|
+
confidence: 0.6,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
// Pattern 3: Common popover/dropdown class patterns
|
|
47
|
+
const className = attrs?.class ?? attrs?.className;
|
|
48
|
+
if (typeof className === 'string') {
|
|
49
|
+
const popoverPatterns = [
|
|
50
|
+
'dropdown',
|
|
51
|
+
'popover',
|
|
52
|
+
'popup',
|
|
53
|
+
'tooltip',
|
|
54
|
+
'menu',
|
|
55
|
+
'autocomplete',
|
|
56
|
+
'suggestions',
|
|
57
|
+
'MuiPopover',
|
|
58
|
+
'MuiMenu',
|
|
59
|
+
'ant-dropdown',
|
|
60
|
+
'el-dropdown',
|
|
61
|
+
'el-popover',
|
|
62
|
+
];
|
|
63
|
+
const lowerClassName = className.toLowerCase();
|
|
64
|
+
if (popoverPatterns.some((p) => lowerClassName.includes(p.toLowerCase()))) {
|
|
65
|
+
return {
|
|
66
|
+
type: 'popover',
|
|
67
|
+
rootEid: computeEid(node, 'popover'),
|
|
68
|
+
zIndex,
|
|
69
|
+
isModal: false,
|
|
70
|
+
confidence: 0.65,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=popover-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"popover-detector.js","sourceRoot":"","sources":["../../../../src/state/layer-detectors/popover-detector.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD;;;;;;;;;GASG;AACH,MAAM,UAAU,aAAa,CAAC,IAAkB;IAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,IAAI,CAAC,UAAiD,CAAC;IAErE,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oCAAoC;IACpC,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAC5D,IAAI,IAAI,IAAI,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,OAAO;YACL,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC;YACpC,MAAM;YACN,OAAO,EAAE,KAAK;YACd,UAAU,EAAE,GAAG;SAChB,CAAC;IACJ,CAAC;IAED,sCAAsC;IACtC,IAAI,IAAI,KAAK,QAAQ,IAAI,KAAK,EAAE,CAAC,YAAY,CAAC,KAAK,MAAM,EAAE,CAAC;QAC1D,OAAO;YACL,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC;YACpC,MAAM;YACN,OAAO,EAAE,KAAK;YACd,UAAU,EAAE,GAAG;SAChB,CAAC;IACJ,CAAC;IAED,oDAAoD;IACpD,MAAM,SAAS,GAAG,KAAK,EAAE,KAAK,IAAI,KAAK,EAAE,SAAS,CAAC;IACnD,IAAI,OAAO,SAAS,KAAK,QAAQ,EAAE,CAAC;QAClC,MAAM,eAAe,GAAG;YACtB,UAAU;YACV,SAAS;YACT,OAAO;YACP,SAAS;YACT,MAAM;YACN,cAAc;YACd,aAAa;YACb,YAAY;YACZ,SAAS;YACT,cAAc;YACd,aAAa;YACb,YAAY;SACb,CAAC;QAEF,MAAM,cAAc,GAAG,SAAS,CAAC,WAAW,EAAE,CAAC;QAC/C,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC;YAC1E,OAAO;gBACL,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC;gBACpC,MAAM;gBACN,OAAO,EAAE,KAAK;gBACd,UAAU,EAAE,IAAI;aACjB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Toast Detector
|
|
3
|
+
*
|
|
4
|
+
* Detect toast/alert overlay layers in the snapshot.
|
|
5
|
+
* Toast layers are non-blocking and never become the active layer.
|
|
6
|
+
*/
|
|
7
|
+
import type { ReadableNode } from '../../snapshot/snapshot.types.js';
|
|
8
|
+
import type { LayerCandidate } from '../types.js';
|
|
9
|
+
export declare const TOAST_ROLES: Set<string>;
|
|
10
|
+
/**
|
|
11
|
+
* Detect if node is a toast/alert overlay layer.
|
|
12
|
+
*
|
|
13
|
+
* Patterns:
|
|
14
|
+
* - role="alert" or role="status" with high z-index (non-modal)
|
|
15
|
+
* - Live region kinds: alert, status, log, timer, progressbar with high z-index
|
|
16
|
+
*
|
|
17
|
+
* Toast layers are non-blocking — they appear in the layer stack but never
|
|
18
|
+
* become the active layer.
|
|
19
|
+
*
|
|
20
|
+
* @param node - Node to check
|
|
21
|
+
* @returns Layer candidate or null
|
|
22
|
+
*/
|
|
23
|
+
export declare function detectToast(node: ReadableNode): LayerCandidate | null;
|
|
24
|
+
//# sourceMappingURL=toast-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toast-detector.d.ts","sourceRoot":"","sources":["../../../../src/state/layer-detectors/toast-detector.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAKlD,eAAO,MAAM,WAAW,aAA+B,CAAC;AAExD;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,GAAG,cAAc,GAAG,IAAI,CA4BrE"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Toast Detector
|
|
3
|
+
*
|
|
4
|
+
* Detect toast/alert overlay layers in the snapshot.
|
|
5
|
+
* Toast layers are non-blocking and never become the active layer.
|
|
6
|
+
*/
|
|
7
|
+
import { computeEid } from '../element-identity.js';
|
|
8
|
+
import { isLiveRegionKind } from '../actionables-filter.js';
|
|
9
|
+
// Roles that indicate toast-like overlays (non-modal alert/status patterns)
|
|
10
|
+
export const TOAST_ROLES = new Set(['alert', 'status']);
|
|
11
|
+
/**
|
|
12
|
+
* Detect if node is a toast/alert overlay layer.
|
|
13
|
+
*
|
|
14
|
+
* Patterns:
|
|
15
|
+
* - role="alert" or role="status" with high z-index (non-modal)
|
|
16
|
+
* - Live region kinds: alert, status, log, timer, progressbar with high z-index
|
|
17
|
+
*
|
|
18
|
+
* Toast layers are non-blocking — they appear in the layer stack but never
|
|
19
|
+
* become the active layer.
|
|
20
|
+
*
|
|
21
|
+
* @param node - Node to check
|
|
22
|
+
* @returns Layer candidate or null
|
|
23
|
+
*/
|
|
24
|
+
export function detectToast(node) {
|
|
25
|
+
const role = node.attributes?.role;
|
|
26
|
+
const zIndex = node.layout.zIndex ?? 0;
|
|
27
|
+
const attrs = node.attributes;
|
|
28
|
+
// Must have z-index > 100 to be considered a toast overlay
|
|
29
|
+
if (zIndex <= 100) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
// Must NOT be aria-modal (those are modals/alertdialogs, not toasts)
|
|
33
|
+
if (attrs?.['aria-modal'] === 'true') {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const hasToastRole = role !== undefined && TOAST_ROLES.has(role);
|
|
37
|
+
if (hasToastRole || isLiveRegionKind(node.kind)) {
|
|
38
|
+
return {
|
|
39
|
+
type: 'toast',
|
|
40
|
+
rootEid: computeEid(node, 'toast'),
|
|
41
|
+
zIndex,
|
|
42
|
+
isModal: false,
|
|
43
|
+
confidence: 0.7,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=toast-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toast-detector.js","sourceRoot":"","sources":["../../../../src/state/layer-detectors/toast-detector.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAE5D,4EAA4E;AAC5E,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;AAExD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,WAAW,CAAC,IAAkB;IAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC;IACnC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,IAAI,CAAC,UAAiD,CAAC;IAErE,2DAA2D;IAC3D,IAAI,MAAM,IAAI,GAAG,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,qEAAqE;IACrE,IAAI,KAAK,EAAE,CAAC,YAAY,CAAC,KAAK,MAAM,EAAE,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,YAAY,GAAG,IAAI,KAAK,SAAS,IAAI,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAEjE,IAAI,YAAY,IAAI,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,OAAO;YACL,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,UAAU,CAAC,IAAI,EAAE,OAAO,CAAC;YAClC,MAAM;YACN,OAAO,EAAE,KAAK;YACd,UAAU,EAAE,GAAG;SAChB,CAAC;IACJ,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Region Mapping
|
|
3
|
+
*
|
|
4
|
+
* Extracts region-to-EID mappings from actionables for deduplication.
|
|
5
|
+
*
|
|
6
|
+
* @module state/region-mapping
|
|
7
|
+
*/
|
|
8
|
+
import type { ActionableInfo } from './types.js';
|
|
9
|
+
/**
|
|
10
|
+
* Extract region → ordered eid list mapping from actionables.
|
|
11
|
+
*/
|
|
12
|
+
export declare function extractRegionEidMapping(actionables: ActionableInfo[]): Map<string, string[]>;
|
|
13
|
+
//# sourceMappingURL=region-mapping.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"region-mapping.d.ts","sourceRoot":"","sources":["../../../src/state/region-mapping.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,cAAc,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAc5F"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Region Mapping
|
|
3
|
+
*
|
|
4
|
+
* Extracts region-to-EID mappings from actionables for deduplication.
|
|
5
|
+
*
|
|
6
|
+
* @module state/region-mapping
|
|
7
|
+
*/
|
|
8
|
+
import { normalizeRegion } from './state-renderer.js';
|
|
9
|
+
/**
|
|
10
|
+
* Extract region → ordered eid list mapping from actionables.
|
|
11
|
+
*/
|
|
12
|
+
export function extractRegionEidMapping(actionables) {
|
|
13
|
+
const regions = new Map();
|
|
14
|
+
for (const item of actionables) {
|
|
15
|
+
const region = normalizeRegion(item.ctx.region);
|
|
16
|
+
let eids = regions.get(region);
|
|
17
|
+
if (!eids) {
|
|
18
|
+
eids = [];
|
|
19
|
+
regions.set(region, eids);
|
|
20
|
+
}
|
|
21
|
+
eids.push(item.eid);
|
|
22
|
+
}
|
|
23
|
+
return regions;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=region-mapping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"region-mapping.js","sourceRoot":"","sources":["../../../src/state/region-mapping.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,WAA6B;IACnE,MAAM,OAAO,GAAG,IAAI,GAAG,EAAoB,CAAC;IAE5C,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAChD,IAAI,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,GAAG,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC5B,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtB,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state-manager.d.ts","sourceRoot":"","sources":["../../../src/state/state-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,+BAA+B,CAAC;AAChF,OAAO,KAAK,EACV,aAAa,EAIb,kBAAkB,EAOlB,aAAa,EACd,MAAM,YAAY,CAAC;AASpB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"state-manager.d.ts","sourceRoot":"","sources":["../../../src/state/state-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,+BAA+B,CAAC;AAChF,OAAO,KAAK,EACV,aAAa,EAIb,kBAAkB,EAOlB,aAAa,EACd,MAAM,YAAY,CAAC;AASpB,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAoBxD;;;GAGG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,OAAO,CAAsB;IACrC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,eAAe,CAA6B;IACpD,OAAO,CAAC,eAAe,CAAkB;IAEzC;;;;OAIG;gBACS,OAAO,EAAE;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;KACtC;IAcD;;;OAGG;IACH,kBAAkB,IAAI,eAAe;IAIrC;;;OAGG;IACH,mBAAmB,IAAI,YAAY,GAAG,IAAI;IAI1C;;;OAGG;IACH,cAAc,IAAI,MAAM;IAQxB;;;;;OAKG;IACH,qBAAqB,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa;IAI1D;;;;;;OAMG;IACH,gBAAgB,CAAC,QAAQ,EAAE,YAAY,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,aAAa;IAkChF;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAyH1B;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,eAAe;IAgBvB;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IA+C3B;;;OAGG;IACH,OAAO,CAAC,mCAAmC;IAuE3C;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAyC3B;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAkFzB;;OAEG;IACH,OAAO,CAAC,cAAc;CAIvB"}
|
|
@@ -7,18 +7,22 @@
|
|
|
7
7
|
* Security: Masks sensitive values (passwords, tokens) and sanitizes URLs.
|
|
8
8
|
* Reliability: Includes concurrency protection and error recovery.
|
|
9
9
|
*/
|
|
10
|
-
import {
|
|
10
|
+
import { randomUUID } from 'crypto';
|
|
11
11
|
import { computeEid, resolveEidCollision } from './element-identity.js';
|
|
12
12
|
import { detectLayers } from './layer-detector.js';
|
|
13
13
|
import { computeDiff } from './diff-engine.js';
|
|
14
|
-
import { selectActionables, isInteractiveKind } from './actionables-filter.js';
|
|
14
|
+
import { selectActionables, isInteractiveKind, isLiveRegionKind } from './actionables-filter.js';
|
|
15
15
|
import { getNodeLayer, INCLUSIVE_OVERLAY_LAYERS } from './node-layer.js';
|
|
16
16
|
import { extractAtoms } from './atoms-extractor.js';
|
|
17
17
|
import { linkObservationsToSnapshot } from '../observation/index.js';
|
|
18
18
|
import { generateLocator } from './locator-generator.js';
|
|
19
19
|
import { ElementRegistry } from './element-registry.js';
|
|
20
20
|
import { validateSnapshotHealth, isErrorHealth } from '../snapshot/snapshot-health.js';
|
|
21
|
-
import { renderStateXml
|
|
21
|
+
import { renderStateXml } from './state-renderer.js';
|
|
22
|
+
import { maskValue } from './value-masking.js';
|
|
23
|
+
import { sanitizeUrl, sanitizeHref } from './url-sanitization.js';
|
|
24
|
+
import { computeDocId, computeUiHash, computeLayerHash } from './hash-utils.js';
|
|
25
|
+
import { extractRegionEidMapping } from './region-mapping.js';
|
|
22
26
|
// ============================================================================
|
|
23
27
|
// Default Configuration
|
|
24
28
|
// ============================================================================
|
|
@@ -26,59 +30,6 @@ const DEFAULT_CONFIG = {
|
|
|
26
30
|
maxActionables: 1000, // Show all elements (practically unlimited)
|
|
27
31
|
};
|
|
28
32
|
// ============================================================================
|
|
29
|
-
// Security: Sensitive Field Detection
|
|
30
|
-
// ============================================================================
|
|
31
|
-
/**
|
|
32
|
-
* Sensitive field name patterns (case-insensitive).
|
|
33
|
-
* Values in these fields will be masked.
|
|
34
|
-
*/
|
|
35
|
-
const SENSITIVE_FIELD_PATTERNS = [
|
|
36
|
-
'password',
|
|
37
|
-
'passwd',
|
|
38
|
-
'pass',
|
|
39
|
-
'secret',
|
|
40
|
-
'token',
|
|
41
|
-
'auth',
|
|
42
|
-
'key',
|
|
43
|
-
'api_key',
|
|
44
|
-
'apikey',
|
|
45
|
-
'otp',
|
|
46
|
-
'pin',
|
|
47
|
-
'cvv',
|
|
48
|
-
'cvc',
|
|
49
|
-
'ssn',
|
|
50
|
-
'social',
|
|
51
|
-
'credit',
|
|
52
|
-
'card',
|
|
53
|
-
];
|
|
54
|
-
/**
|
|
55
|
-
* Input types that should always be masked.
|
|
56
|
-
*/
|
|
57
|
-
const MASKED_INPUT_TYPES = ['password'];
|
|
58
|
-
/**
|
|
59
|
-
* Input types with partial masking (show first/last chars).
|
|
60
|
-
*/
|
|
61
|
-
const PARTIAL_MASK_TYPES = ['email', 'tel', 'phone'];
|
|
62
|
-
/**
|
|
63
|
-
* URL query parameters that are safe to keep.
|
|
64
|
-
* All others will be stripped.
|
|
65
|
-
*/
|
|
66
|
-
const SAFE_QUERY_PARAMS = new Set([
|
|
67
|
-
'page',
|
|
68
|
-
'p',
|
|
69
|
-
'sort',
|
|
70
|
-
'order',
|
|
71
|
-
'q',
|
|
72
|
-
'query',
|
|
73
|
-
'search',
|
|
74
|
-
'tab',
|
|
75
|
-
'view',
|
|
76
|
-
'limit',
|
|
77
|
-
'offset',
|
|
78
|
-
'lang',
|
|
79
|
-
'locale',
|
|
80
|
-
]);
|
|
81
|
-
// ============================================================================
|
|
82
33
|
// State Manager Class
|
|
83
34
|
// ============================================================================
|
|
84
35
|
/**
|
|
@@ -225,7 +176,7 @@ export class StateManager {
|
|
|
225
176
|
const actionables = this.formatActionables(actionableNodes, layerResult.active, snapshot.snapshot_id);
|
|
226
177
|
// Count total actionables in active layer
|
|
227
178
|
const skipLayerFilter = INCLUSIVE_OVERLAY_LAYERS.has(layerResult.active);
|
|
228
|
-
const totalInLayer = snapshot.nodes.filter((n) => isInteractiveKind(n.kind) &&
|
|
179
|
+
const totalInLayer = snapshot.nodes.filter((n) => (isInteractiveKind(n.kind) || isLiveRegionKind(n.kind)) &&
|
|
229
180
|
n.state?.visible &&
|
|
230
181
|
(skipLayerFilter || getNodeLayer(n, layerResult.active) === layerResult.active)).length;
|
|
231
182
|
const counts = {
|
|
@@ -509,139 +460,4 @@ export class StateManager {
|
|
|
509
460
|
return Math.ceil(jsonString.length / 4);
|
|
510
461
|
}
|
|
511
462
|
}
|
|
512
|
-
// ============================================================================
|
|
513
|
-
// Security: Value Masking
|
|
514
|
-
// ============================================================================
|
|
515
|
-
/**
|
|
516
|
-
* Mask sensitive values in val_hint.
|
|
517
|
-
*
|
|
518
|
-
* Rules:
|
|
519
|
-
* - password type: always full mask
|
|
520
|
-
* - sensitive field names: always full mask
|
|
521
|
-
* - email/tel: partial mask (show first/last chars)
|
|
522
|
-
* - default: truncate to 12 chars, mask middle
|
|
523
|
-
*/
|
|
524
|
-
function maskValue(value, inputType, label) {
|
|
525
|
-
// Strip newlines first
|
|
526
|
-
const cleanValue = value.replace(/[\r\n]/g, ' ').trim();
|
|
527
|
-
if (!cleanValue)
|
|
528
|
-
return '';
|
|
529
|
-
// Password type: always full mask
|
|
530
|
-
if (inputType && MASKED_INPUT_TYPES.includes(inputType.toLowerCase())) {
|
|
531
|
-
return '••••••••';
|
|
532
|
-
}
|
|
533
|
-
// Check sensitive field names
|
|
534
|
-
const lowerLabel = (label ?? '').toLowerCase();
|
|
535
|
-
for (const pattern of SENSITIVE_FIELD_PATTERNS) {
|
|
536
|
-
if (lowerLabel.includes(pattern)) {
|
|
537
|
-
return '***';
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
// Email/tel: partial mask
|
|
541
|
-
if (inputType && PARTIAL_MASK_TYPES.includes(inputType.toLowerCase())) {
|
|
542
|
-
return partialMask(cleanValue);
|
|
543
|
-
}
|
|
544
|
-
// Default: truncate and partial mask if long
|
|
545
|
-
if (cleanValue.length <= 12) {
|
|
546
|
-
return cleanValue;
|
|
547
|
-
}
|
|
548
|
-
return partialMask(cleanValue.substring(0, 12));
|
|
549
|
-
}
|
|
550
|
-
/**
|
|
551
|
-
* Partial mask: show first 2 and last 2 chars.
|
|
552
|
-
* Example: "example@email.com" -> "ex•••om"
|
|
553
|
-
*/
|
|
554
|
-
function partialMask(value) {
|
|
555
|
-
if (value.length <= 4) {
|
|
556
|
-
return '••••';
|
|
557
|
-
}
|
|
558
|
-
const first = value.substring(0, 2);
|
|
559
|
-
const last = value.substring(value.length - 2);
|
|
560
|
-
return `${first}•••${last}`;
|
|
561
|
-
}
|
|
562
|
-
// ============================================================================
|
|
563
|
-
// Security: URL Sanitization
|
|
564
|
-
// ============================================================================
|
|
565
|
-
/**
|
|
566
|
-
* Sanitize URL by stripping sensitive query parameters.
|
|
567
|
-
* Only keeps safe params like page, sort, q.
|
|
568
|
-
*/
|
|
569
|
-
function sanitizeUrl(rawUrl) {
|
|
570
|
-
try {
|
|
571
|
-
const url = new URL(rawUrl);
|
|
572
|
-
// Build new search params with only safe ones
|
|
573
|
-
const safeParams = new URLSearchParams();
|
|
574
|
-
for (const [key, value] of url.searchParams) {
|
|
575
|
-
if (SAFE_QUERY_PARAMS.has(key.toLowerCase())) {
|
|
576
|
-
safeParams.set(key, value);
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
// Reconstruct URL with sanitized params
|
|
580
|
-
url.search = safeParams.toString();
|
|
581
|
-
return url.toString();
|
|
582
|
-
}
|
|
583
|
-
catch {
|
|
584
|
-
// If URL parsing fails, return origin only
|
|
585
|
-
return rawUrl.split('?')[0];
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
/**
|
|
589
|
-
* Sanitize href attribute (remove tokens from URLs).
|
|
590
|
-
*/
|
|
591
|
-
function sanitizeHref(href) {
|
|
592
|
-
// For relative URLs, return as-is
|
|
593
|
-
if (!href.startsWith('http://') && !href.startsWith('https://')) {
|
|
594
|
-
return href;
|
|
595
|
-
}
|
|
596
|
-
return sanitizeUrl(href);
|
|
597
|
-
}
|
|
598
|
-
// ============================================================================
|
|
599
|
-
// Utilities
|
|
600
|
-
// ============================================================================
|
|
601
|
-
/**
|
|
602
|
-
* Extract region → ordered eid list mapping from actionables.
|
|
603
|
-
*/
|
|
604
|
-
function extractRegionEidMapping(actionables) {
|
|
605
|
-
const regions = new Map();
|
|
606
|
-
for (const item of actionables) {
|
|
607
|
-
const region = normalizeRegion(item.ctx.region);
|
|
608
|
-
let eids = regions.get(region);
|
|
609
|
-
if (!eids) {
|
|
610
|
-
eids = [];
|
|
611
|
-
regions.set(region, eids);
|
|
612
|
-
}
|
|
613
|
-
eids.push(item.eid);
|
|
614
|
-
}
|
|
615
|
-
return regions;
|
|
616
|
-
}
|
|
617
|
-
/**
|
|
618
|
-
* Compute document ID from snapshot.
|
|
619
|
-
*
|
|
620
|
-
* Uses only URL origin + pathname for navigation detection.
|
|
621
|
-
* This ensures DOM mutations (like autocomplete suggestions appearing)
|
|
622
|
-
* are NOT falsely detected as navigation events.
|
|
623
|
-
*
|
|
624
|
-
* NOTE: Previously this included a hash of the first 10 interactive node IDs,
|
|
625
|
-
* which caused false navigation detection when typing triggered autocomplete
|
|
626
|
-
* or other dynamic UI updates. See: https://github.com/lespaceman/agent-web-interface/issues/XXX
|
|
627
|
-
*/
|
|
628
|
-
function computeDocId(snapshot) {
|
|
629
|
-
const url = new URL(snapshot.url);
|
|
630
|
-
// Only use origin + pathname for navigation detection
|
|
631
|
-
// Query params and fragments are ignored (same page, different state)
|
|
632
|
-
return hash(`${url.origin}:${url.pathname}`);
|
|
633
|
-
}
|
|
634
|
-
function computeUiHash(snapshot) {
|
|
635
|
-
const interactiveNodeIds = snapshot.nodes
|
|
636
|
-
.filter((n) => isInteractiveKind(n.kind) && n.state?.visible)
|
|
637
|
-
.map((n) => computeEid(n))
|
|
638
|
-
.join(',');
|
|
639
|
-
return hash(interactiveNodeIds).substring(0, 6);
|
|
640
|
-
}
|
|
641
|
-
function computeLayerHash(stack) {
|
|
642
|
-
return hash(stack.join(',')).substring(0, 6);
|
|
643
|
-
}
|
|
644
|
-
function hash(input) {
|
|
645
|
-
return createHash('sha256').update(input).digest('hex').substring(0, 12);
|
|
646
|
-
}
|
|
647
463
|
//# sourceMappingURL=state-manager.js.map
|