@kritchoff/agent-browser 0.9.2
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/LICENSE +201 -0
- package/README.md +903 -0
- package/README.sdk.md +77 -0
- package/bin/agent-browser-linux-x64 +0 -0
- package/bin/agent-browser.js +109 -0
- package/dist/actions.d.ts +17 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +1427 -0
- package/dist/actions.js.map +1 -0
- package/dist/browser.d.ts +474 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +1566 -0
- package/dist/browser.js.map +1 -0
- package/dist/cdp-client.d.ts +103 -0
- package/dist/cdp-client.d.ts.map +1 -0
- package/dist/cdp-client.js +223 -0
- package/dist/cdp-client.js.map +1 -0
- package/dist/daemon.d.ts +60 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +401 -0
- package/dist/daemon.js.map +1 -0
- package/dist/dualmode-config.d.ts +37 -0
- package/dist/dualmode-config.d.ts.map +1 -0
- package/dist/dualmode-config.js +44 -0
- package/dist/dualmode-config.js.map +1 -0
- package/dist/dualmode-fetcher.d.ts +60 -0
- package/dist/dualmode-fetcher.d.ts.map +1 -0
- package/dist/dualmode-fetcher.js +449 -0
- package/dist/dualmode-fetcher.js.map +1 -0
- package/dist/dualmode-types.d.ts +183 -0
- package/dist/dualmode-types.d.ts.map +1 -0
- package/dist/dualmode-types.js +8 -0
- package/dist/dualmode-types.js.map +1 -0
- package/dist/ios-actions.d.ts +11 -0
- package/dist/ios-actions.d.ts.map +1 -0
- package/dist/ios-actions.js +228 -0
- package/dist/ios-actions.js.map +1 -0
- package/dist/ios-manager.d.ts +266 -0
- package/dist/ios-manager.d.ts.map +1 -0
- package/dist/ios-manager.js +1073 -0
- package/dist/ios-manager.js.map +1 -0
- package/dist/protocol.d.ts +26 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +832 -0
- package/dist/protocol.js.map +1 -0
- package/dist/snapshot.d.ts +83 -0
- package/dist/snapshot.d.ts.map +1 -0
- package/dist/snapshot.js +653 -0
- package/dist/snapshot.js.map +1 -0
- package/dist/stream-server.d.ts +117 -0
- package/dist/stream-server.d.ts.map +1 -0
- package/dist/stream-server.js +305 -0
- package/dist/stream-server.js.map +1 -0
- package/dist/types.d.ts +742 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/docker-compose.sdk.yml +45 -0
- package/package.json +85 -0
- package/scripts/benchmark.sh +80 -0
- package/scripts/build-all-platforms.sh +68 -0
- package/scripts/check-version-sync.js +39 -0
- package/scripts/copy-native.js +36 -0
- package/scripts/fast_reset.sh +108 -0
- package/scripts/postinstall.js +235 -0
- package/scripts/publish_images.sh +55 -0
- package/scripts/snapshot_manager.sh +293 -0
- package/scripts/start-android-agent.sh +49 -0
- package/scripts/sync-version.js +69 -0
- package/scripts/vaccine-run +26 -0
- package/sdk.sh +153 -0
- package/skills/agent-browser/SKILL.md +217 -0
- package/skills/agent-browser/references/authentication.md +202 -0
- package/skills/agent-browser/references/commands.md +259 -0
- package/skills/agent-browser/references/proxy-support.md +188 -0
- package/skills/agent-browser/references/session-management.md +193 -0
- package/skills/agent-browser/references/snapshot-refs.md +194 -0
- package/skills/agent-browser/references/video-recording.md +173 -0
- package/skills/agent-browser/templates/authenticated-session.sh +97 -0
- package/skills/agent-browser/templates/capture-workflow.sh +69 -0
- package/skills/agent-browser/templates/form-automation.sh +62 -0
- package/skills/skill-creator/LICENSE.txt +202 -0
- package/skills/skill-creator/SKILL.md +356 -0
- package/skills/skill-creator/references/output-patterns.md +82 -0
- package/skills/skill-creator/references/workflows.md +28 -0
- package/skills/skill-creator/scripts/init_skill.py +303 -0
- package/skills/skill-creator/scripts/package_skill.py +113 -0
- package/skills/skill-creator/scripts/quick_validate.py +95 -0
package/dist/snapshot.js
ADDED
|
@@ -0,0 +1,653 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced snapshot with element refs for deterministic element selection.
|
|
3
|
+
*
|
|
4
|
+
* This module generates accessibility snapshots with embedded refs that can be
|
|
5
|
+
* used to click/fill/interact with elements without re-querying the DOM.
|
|
6
|
+
*
|
|
7
|
+
* Supports dual-mode operation:
|
|
8
|
+
* - Playwright mode: Uses Playwright's ARIA snapshot (fast, local)
|
|
9
|
+
* - WootzApp mode: Uses DualMode AXTree from Android browser (rich semantics)
|
|
10
|
+
*
|
|
11
|
+
* Example output:
|
|
12
|
+
* - heading "Example Domain" [ref=e1] [level=1]
|
|
13
|
+
* - paragraph: Some text content
|
|
14
|
+
* - button "Submit" [ref=e2]
|
|
15
|
+
* - textbox "Email" [ref=e3]
|
|
16
|
+
*
|
|
17
|
+
* Usage:
|
|
18
|
+
* agent-browser snapshot # Full snapshot
|
|
19
|
+
* agent-browser snapshot -i # Interactive elements only
|
|
20
|
+
* agent-browser snapshot --depth 3 # Limit depth
|
|
21
|
+
* agent-browser click @e2 # Click element by ref
|
|
22
|
+
*/
|
|
23
|
+
import { isWootzAppEnabled, getCDPEndpoint } from './dualmode-config.js';
|
|
24
|
+
import { DualModeAXTreeFetcher } from './dualmode-fetcher.js';
|
|
25
|
+
// Counter for generating refs
|
|
26
|
+
let refCounter = 0;
|
|
27
|
+
/**
|
|
28
|
+
* Reset ref counter (call at start of each snapshot)
|
|
29
|
+
*/
|
|
30
|
+
export function resetRefs() {
|
|
31
|
+
refCounter = 0;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Generate next ref ID
|
|
35
|
+
*/
|
|
36
|
+
function nextRef() {
|
|
37
|
+
return `e${++refCounter}`;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Roles that are interactive and should get refs
|
|
41
|
+
*/
|
|
42
|
+
const INTERACTIVE_ROLES = new Set([
|
|
43
|
+
'button',
|
|
44
|
+
'link',
|
|
45
|
+
'textbox',
|
|
46
|
+
'checkbox',
|
|
47
|
+
'radio',
|
|
48
|
+
'combobox',
|
|
49
|
+
'listbox',
|
|
50
|
+
'menuitem',
|
|
51
|
+
'menuitemcheckbox',
|
|
52
|
+
'menuitemradio',
|
|
53
|
+
'option',
|
|
54
|
+
'searchbox',
|
|
55
|
+
'slider',
|
|
56
|
+
'spinbutton',
|
|
57
|
+
'switch',
|
|
58
|
+
'tab',
|
|
59
|
+
'treeitem',
|
|
60
|
+
]);
|
|
61
|
+
/**
|
|
62
|
+
* Roles that provide structure/context (get refs for text extraction)
|
|
63
|
+
*/
|
|
64
|
+
const CONTENT_ROLES = new Set([
|
|
65
|
+
'heading',
|
|
66
|
+
'cell',
|
|
67
|
+
'gridcell',
|
|
68
|
+
'columnheader',
|
|
69
|
+
'rowheader',
|
|
70
|
+
'listitem',
|
|
71
|
+
'article',
|
|
72
|
+
'region',
|
|
73
|
+
'main',
|
|
74
|
+
'navigation',
|
|
75
|
+
]);
|
|
76
|
+
/**
|
|
77
|
+
* Roles that are purely structural (can be filtered in compact mode)
|
|
78
|
+
*/
|
|
79
|
+
const STRUCTURAL_ROLES = new Set([
|
|
80
|
+
'generic',
|
|
81
|
+
'group',
|
|
82
|
+
'list',
|
|
83
|
+
'table',
|
|
84
|
+
'row',
|
|
85
|
+
'rowgroup',
|
|
86
|
+
'grid',
|
|
87
|
+
'treegrid',
|
|
88
|
+
'menu',
|
|
89
|
+
'menubar',
|
|
90
|
+
'toolbar',
|
|
91
|
+
'tablist',
|
|
92
|
+
'tree',
|
|
93
|
+
'directory',
|
|
94
|
+
'document',
|
|
95
|
+
'application',
|
|
96
|
+
'presentation',
|
|
97
|
+
'none',
|
|
98
|
+
]);
|
|
99
|
+
/**
|
|
100
|
+
* Build a selector string for storing in ref map
|
|
101
|
+
*/
|
|
102
|
+
function buildSelector(role, name) {
|
|
103
|
+
if (name) {
|
|
104
|
+
const escapedName = name.replace(/"/g, '\\"');
|
|
105
|
+
return `getByRole('${role}', { name: "${escapedName}", exact: true })`;
|
|
106
|
+
}
|
|
107
|
+
return `getByRole('${role}')`;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Query the page for clickable elements that might not have proper ARIA roles.
|
|
111
|
+
* This finds elements with cursor: pointer or onclick handlers.
|
|
112
|
+
*/
|
|
113
|
+
async function findCursorInteractiveElements(page, selector) {
|
|
114
|
+
const rootSelector = selector || 'body';
|
|
115
|
+
// Use a string function body to avoid TypeScript transpilation issues
|
|
116
|
+
const scriptBody = `(rootSel) => {
|
|
117
|
+
const results = [];
|
|
118
|
+
|
|
119
|
+
// Elements that already have interactive ARIA roles - skip these
|
|
120
|
+
const interactiveRoles = new Set([
|
|
121
|
+
'button', 'link', 'textbox', 'checkbox', 'radio', 'combobox', 'listbox',
|
|
122
|
+
'menuitem', 'menuitemcheckbox', 'menuitemradio', 'option', 'searchbox',
|
|
123
|
+
'slider', 'spinbutton', 'switch', 'tab', 'treeitem'
|
|
124
|
+
]);
|
|
125
|
+
|
|
126
|
+
// Tags that are already interactive by default
|
|
127
|
+
const interactiveTags = new Set([
|
|
128
|
+
'a', 'button', 'input', 'select', 'textarea', 'details', 'summary'
|
|
129
|
+
]);
|
|
130
|
+
|
|
131
|
+
const root = document.querySelector(rootSel) || document.body;
|
|
132
|
+
const allElements = root.querySelectorAll('*');
|
|
133
|
+
|
|
134
|
+
// Build a unique selector for an element
|
|
135
|
+
const buildSelector = (el) => {
|
|
136
|
+
const testId = el.getAttribute('data-testid');
|
|
137
|
+
if (testId) return '[data-testid="' + testId + '"]';
|
|
138
|
+
if (el.id) return '#' + CSS.escape(el.id);
|
|
139
|
+
|
|
140
|
+
const path = [];
|
|
141
|
+
let current = el;
|
|
142
|
+
while (current && current !== document.body) {
|
|
143
|
+
let sel = current.tagName.toLowerCase();
|
|
144
|
+
const classes = Array.from(current.classList).filter(c => c.trim());
|
|
145
|
+
if (classes.length > 0) sel += '.' + CSS.escape(classes[0]);
|
|
146
|
+
|
|
147
|
+
const parent = current.parentElement;
|
|
148
|
+
if (parent) {
|
|
149
|
+
const siblings = Array.from(parent.children);
|
|
150
|
+
const matching = siblings.filter(s => {
|
|
151
|
+
if (s.tagName !== current.tagName) return false;
|
|
152
|
+
if (classes.length > 0 && !s.classList.contains(classes[0])) return false;
|
|
153
|
+
return true;
|
|
154
|
+
});
|
|
155
|
+
if (matching.length > 1) {
|
|
156
|
+
const idx = matching.indexOf(current) + 1;
|
|
157
|
+
sel += ':nth-of-type(' + idx + ')';
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
path.unshift(sel);
|
|
161
|
+
current = current.parentElement;
|
|
162
|
+
if (path.length >= 3) break;
|
|
163
|
+
}
|
|
164
|
+
return path.join(' > ');
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
for (const el of allElements) {
|
|
168
|
+
const tagName = el.tagName.toLowerCase();
|
|
169
|
+
if (interactiveTags.has(tagName)) continue;
|
|
170
|
+
|
|
171
|
+
const role = el.getAttribute('role');
|
|
172
|
+
if (role && interactiveRoles.has(role.toLowerCase())) continue;
|
|
173
|
+
|
|
174
|
+
const computedStyle = getComputedStyle(el);
|
|
175
|
+
const hasCursorPointer = computedStyle.cursor === 'pointer';
|
|
176
|
+
const hasOnClick = el.hasAttribute('onclick') || el.onclick !== null;
|
|
177
|
+
const tabIndex = el.getAttribute('tabindex');
|
|
178
|
+
const hasTabIndex = tabIndex !== null && tabIndex !== '-1';
|
|
179
|
+
|
|
180
|
+
if (!hasCursorPointer && !hasOnClick && !hasTabIndex) continue;
|
|
181
|
+
|
|
182
|
+
const text = (el.textContent || '').trim().slice(0, 100);
|
|
183
|
+
if (!text) continue;
|
|
184
|
+
|
|
185
|
+
const rect = el.getBoundingClientRect();
|
|
186
|
+
if (rect.width === 0 || rect.height === 0) continue;
|
|
187
|
+
|
|
188
|
+
results.push({
|
|
189
|
+
selector: buildSelector(el),
|
|
190
|
+
text,
|
|
191
|
+
tagName,
|
|
192
|
+
hasOnClick,
|
|
193
|
+
hasCursorPointer,
|
|
194
|
+
hasTabIndex
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
return results;
|
|
198
|
+
}`;
|
|
199
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval
|
|
200
|
+
const fn = new Function('return ' + scriptBody)();
|
|
201
|
+
return page.evaluate(fn, rootSelector);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Get enhanced snapshot with refs and optional filtering
|
|
205
|
+
*
|
|
206
|
+
* ALWAYS uses DualMode AXTree from Android emulator browser via CDP
|
|
207
|
+
*
|
|
208
|
+
* Flow:
|
|
209
|
+
* 1. Get current URL from Playwright browser
|
|
210
|
+
* 2. Connect to CDP (localhost:9224)
|
|
211
|
+
* 3. Load URL in emulator browser and wait for complete load
|
|
212
|
+
* 4. Call getDualModeAXTree via CDP
|
|
213
|
+
* 5. Clear chromium app data with pm clear
|
|
214
|
+
*/
|
|
215
|
+
export async function getEnhancedSnapshot(page, options = {}) {
|
|
216
|
+
if (isWootzAppEnabled()) {
|
|
217
|
+
console.log('\n========================================');
|
|
218
|
+
console.log('[Snapshot] Starting DualMode AXTree snapshot');
|
|
219
|
+
console.log('[Snapshot] Playwright URL:', page.url());
|
|
220
|
+
console.log('========================================\n');
|
|
221
|
+
// Use DualMode flow if enabled
|
|
222
|
+
return getEnhancedSnapshotDualMode(page, options);
|
|
223
|
+
}
|
|
224
|
+
// Default to Playwright ARIA snapshot
|
|
225
|
+
return getEnhancedSnapshotPlaywright(page, options);
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Get enhanced snapshot using WootzApp DualMode AXTree
|
|
229
|
+
*
|
|
230
|
+
* Implements the exact flow from accessibility_tree.py:
|
|
231
|
+
* 1. Get current URL from Playwright
|
|
232
|
+
* 2. Connect to CDP on localhost:9224
|
|
233
|
+
* 3. Navigate emulator browser to URL and wait for load
|
|
234
|
+
* 4. Call getDualModeAXTree
|
|
235
|
+
* 5. Clear browser with pm clear
|
|
236
|
+
*/
|
|
237
|
+
async function getEnhancedSnapshotDualMode(page, options = {}) {
|
|
238
|
+
const { CDPClient } = await import('./cdp-client.js');
|
|
239
|
+
const { exec } = await import('child_process');
|
|
240
|
+
const { promisify } = await import('util');
|
|
241
|
+
const execAsync = promisify(exec);
|
|
242
|
+
const { host: cdpHost, port: cdpPort } = getCDPEndpoint();
|
|
243
|
+
const cdpClient = new CDPClient({ timeout: 30000, commandTimeout: 15000 });
|
|
244
|
+
try {
|
|
245
|
+
// Step 1: Get current URL from Playwright browser
|
|
246
|
+
const url = page.url();
|
|
247
|
+
console.log(`[DualMode] Step 1: Got URL from Playwright: ${url}`);
|
|
248
|
+
// Step 1.5: Ensure Chrome is running with CDP enabled (matching cdp_start.sh)
|
|
249
|
+
console.log('[DualMode] Step 1.5: Starting Chrome with CDP...');
|
|
250
|
+
try {
|
|
251
|
+
// Stop Chrome if running
|
|
252
|
+
await execAsync('docker exec android-world adb shell am force-stop org.chromium.chrome');
|
|
253
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
254
|
+
// Set Chrome command line flags for remote debugging
|
|
255
|
+
const chromeFlags = '_ --disable-fre --no-default-browser-check --no-first-run --remote-debugging-port=9223';
|
|
256
|
+
await execAsync(`docker exec android-world adb shell "echo '${chromeFlags}' > /data/local/tmp/chrome-command-line"`);
|
|
257
|
+
// Start Chrome
|
|
258
|
+
await execAsync('docker exec android-world adb shell am start -n org.chromium.chrome/com.google.android.apps.chrome.Main');
|
|
259
|
+
// Wait for Chrome and CDP to be ready
|
|
260
|
+
console.log('[DualMode] Waiting for CDP to be available...');
|
|
261
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
262
|
+
console.log('[DualMode] ✓ Chrome started with CDP');
|
|
263
|
+
}
|
|
264
|
+
catch (startError) {
|
|
265
|
+
console.warn('[DualMode] Warning: Chrome start issue:', startError.message);
|
|
266
|
+
}
|
|
267
|
+
// Step 2: Connect to CDP (references cdp_start.sh and accessibility_tree.py)
|
|
268
|
+
console.log(`[DualMode] Step 2: Connecting to CDP at ${cdpHost}:${cdpPort}`);
|
|
269
|
+
const wsUrl = await CDPClient.getWebSocketDebuggerUrl(cdpHost, cdpPort);
|
|
270
|
+
console.log(`[DualMode] Got WebSocket URL: ${wsUrl}`);
|
|
271
|
+
await cdpClient.connect(wsUrl);
|
|
272
|
+
console.log('[DualMode] ✓ Connected to CDP');
|
|
273
|
+
// Step 3: Load URL in emulator browser and wait for complete load
|
|
274
|
+
console.log('[DualMode] Step 3: Loading URL in emulator browser...');
|
|
275
|
+
// Enable Page domain
|
|
276
|
+
await cdpClient.send('Page.enable');
|
|
277
|
+
// Navigate to URL
|
|
278
|
+
console.log(`[DualMode] Navigating to: ${url}`);
|
|
279
|
+
const navResp = await cdpClient.send('Page.navigate', { url });
|
|
280
|
+
if (navResp.error) {
|
|
281
|
+
throw new Error(`Navigation error: ${navResp.error.message || JSON.stringify(navResp.error)}`);
|
|
282
|
+
}
|
|
283
|
+
// Wait for page to load
|
|
284
|
+
console.log('[DualMode] Waiting for page load...');
|
|
285
|
+
try {
|
|
286
|
+
await cdpClient.waitForEvent('Page.loadEventFired', 30000);
|
|
287
|
+
await new Promise(resolve => setTimeout(resolve, 3000)); // Wait for tree to settle
|
|
288
|
+
console.log('[DualMode] ✓ Page loaded');
|
|
289
|
+
}
|
|
290
|
+
catch (error) {
|
|
291
|
+
console.warn('[DualMode] ⚠️ Page load timeout, continuing anyway...');
|
|
292
|
+
}
|
|
293
|
+
// Step 4: Call getDualModeAXTree via CDP
|
|
294
|
+
console.log('[DualMode] Step 4: Fetching DualMode AXTree...');
|
|
295
|
+
// Enable Accessibility domain
|
|
296
|
+
console.log('[DualMode] Enabling Accessibility domain...');
|
|
297
|
+
const enableResp = await cdpClient.send('Accessibility.enable');
|
|
298
|
+
if (enableResp.error) {
|
|
299
|
+
throw new Error(`Failed to enable Accessibility domain: ${enableResp.error.message || JSON.stringify(enableResp.error)}`);
|
|
300
|
+
}
|
|
301
|
+
// Get the accessibility tree
|
|
302
|
+
console.log('[DualMode] Fetching DualMode accessibility tree...');
|
|
303
|
+
const axResp = await cdpClient.send('Accessibility.getDualModeAXTree', {});
|
|
304
|
+
if (axResp.error) {
|
|
305
|
+
throw new Error(`Failed to get accessibility tree: ${axResp.error.message || JSON.stringify(axResp.error)}`);
|
|
306
|
+
}
|
|
307
|
+
const nodes = axResp.nodes || [];
|
|
308
|
+
console.log(`[DualMode] ✓ Retrieved ${nodes.length} nodes`);
|
|
309
|
+
// Disable Accessibility domain
|
|
310
|
+
await cdpClient.send('Accessibility.disable');
|
|
311
|
+
// Close CDP connection
|
|
312
|
+
await cdpClient.close();
|
|
313
|
+
// Step 5: Clear chromium app data with pm clear
|
|
314
|
+
console.log('[DualMode] Step 5: Clearing browser data...');
|
|
315
|
+
try {
|
|
316
|
+
await execAsync('docker exec android-world adb shell pm clear org.chromium.chrome');
|
|
317
|
+
console.log('[DualMode] ✓ Browser data cleared');
|
|
318
|
+
}
|
|
319
|
+
catch (clearError) {
|
|
320
|
+
console.warn('[DualMode] Warning: Failed to clear browser data:', clearError.message);
|
|
321
|
+
}
|
|
322
|
+
// Convert nodes to enhanced snapshot format using fetcher's build methods
|
|
323
|
+
console.log('[DualMode] Converting tree to snapshot format...');
|
|
324
|
+
const fetcher = new DualModeAXTreeFetcher(cdpHost, cdpPort);
|
|
325
|
+
const response = { nodes };
|
|
326
|
+
const tree = fetcher.buildTree(response);
|
|
327
|
+
// Convert SnapshotOptions to DualModeSnapshotOptions
|
|
328
|
+
const dualModeOptions = {
|
|
329
|
+
interactive: options.interactive,
|
|
330
|
+
maxDepth: options.maxDepth,
|
|
331
|
+
includeMetadata: false,
|
|
332
|
+
};
|
|
333
|
+
const textTree = fetcher.generateTextTree(tree, dualModeOptions);
|
|
334
|
+
// Build refs map
|
|
335
|
+
const refs = {};
|
|
336
|
+
for (const elem of tree.interactiveElements) {
|
|
337
|
+
refs[elem.ref] = {
|
|
338
|
+
selector: elem.selector || '',
|
|
339
|
+
role: elem.node.xrayMode?.semantics?.role || elem.node.core.className,
|
|
340
|
+
name: elem.node.xrayMode?.semantics?.name || elem.node.core.text,
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
console.log(`[DualMode] ✓ Snapshot complete with ${Object.keys(refs).length} refs`);
|
|
344
|
+
return {
|
|
345
|
+
tree: textTree,
|
|
346
|
+
refs,
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
catch (error) {
|
|
350
|
+
console.error('[DualMode] ❌ Error:', error.message);
|
|
351
|
+
console.error('[DualMode] Stack:', error.stack);
|
|
352
|
+
await cdpClient.close();
|
|
353
|
+
throw error;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Get enhanced snapshot using Playwright ARIA tree (original implementation)
|
|
358
|
+
*/
|
|
359
|
+
async function getEnhancedSnapshotPlaywright(page, options = {}) {
|
|
360
|
+
resetRefs();
|
|
361
|
+
const refs = {};
|
|
362
|
+
// Get ARIA snapshot from Playwright
|
|
363
|
+
const locator = options.selector ? page.locator(options.selector) : page.locator(':root');
|
|
364
|
+
const ariaTree = await locator.ariaSnapshot();
|
|
365
|
+
if (!ariaTree) {
|
|
366
|
+
return {
|
|
367
|
+
tree: '(empty)',
|
|
368
|
+
refs: {},
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
// Parse and enhance the ARIA tree
|
|
372
|
+
const enhancedTree = processAriaTree(ariaTree, refs, options);
|
|
373
|
+
// When cursor flag is set, also find cursor-interactive elements
|
|
374
|
+
// that may not have proper ARIA roles
|
|
375
|
+
if (options.cursor) {
|
|
376
|
+
const cursorElements = await findCursorInteractiveElements(page, options.selector);
|
|
377
|
+
// Filter out elements whose text is already captured in the snapshot
|
|
378
|
+
const existingTexts = new Set(Object.values(refs).map((r) => r.name?.toLowerCase()));
|
|
379
|
+
const additionalLines = [];
|
|
380
|
+
for (const el of cursorElements) {
|
|
381
|
+
// Skip if text already captured (likely already in ARIA tree)
|
|
382
|
+
if (existingTexts.has(el.text.toLowerCase()))
|
|
383
|
+
continue;
|
|
384
|
+
const ref = nextRef();
|
|
385
|
+
const role = el.hasCursorPointer ? 'clickable' : el.hasOnClick ? 'clickable' : 'focusable';
|
|
386
|
+
refs[ref] = {
|
|
387
|
+
selector: el.selector,
|
|
388
|
+
role: role,
|
|
389
|
+
name: el.text,
|
|
390
|
+
};
|
|
391
|
+
// Build description of why it's interactive
|
|
392
|
+
const hints = [];
|
|
393
|
+
if (el.hasCursorPointer)
|
|
394
|
+
hints.push('cursor:pointer');
|
|
395
|
+
if (el.hasOnClick)
|
|
396
|
+
hints.push('onclick');
|
|
397
|
+
if (el.hasTabIndex)
|
|
398
|
+
hints.push('tabindex');
|
|
399
|
+
additionalLines.push(`- ${role} "${el.text}" [ref=${ref}] [${hints.join(', ')}]`);
|
|
400
|
+
}
|
|
401
|
+
if (additionalLines.length > 0) {
|
|
402
|
+
const separator = enhancedTree === '(no interactive elements)' ? '' : '\n# Cursor-interactive elements:\n';
|
|
403
|
+
const base = enhancedTree === '(no interactive elements)' ? '' : enhancedTree;
|
|
404
|
+
return {
|
|
405
|
+
tree: base + separator + additionalLines.join('\n'),
|
|
406
|
+
refs,
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return { tree: enhancedTree, refs };
|
|
411
|
+
}
|
|
412
|
+
function createRoleNameTracker() {
|
|
413
|
+
const counts = new Map();
|
|
414
|
+
const refsByKey = new Map();
|
|
415
|
+
return {
|
|
416
|
+
counts,
|
|
417
|
+
refsByKey,
|
|
418
|
+
getKey(role, name) {
|
|
419
|
+
return `${role}:${name ?? ''}`;
|
|
420
|
+
},
|
|
421
|
+
getNextIndex(role, name) {
|
|
422
|
+
const key = this.getKey(role, name);
|
|
423
|
+
const current = counts.get(key) ?? 0;
|
|
424
|
+
counts.set(key, current + 1);
|
|
425
|
+
return current;
|
|
426
|
+
},
|
|
427
|
+
trackRef(role, name, ref) {
|
|
428
|
+
const key = this.getKey(role, name);
|
|
429
|
+
const refs = refsByKey.get(key) ?? [];
|
|
430
|
+
refs.push(ref);
|
|
431
|
+
refsByKey.set(key, refs);
|
|
432
|
+
},
|
|
433
|
+
getDuplicateKeys() {
|
|
434
|
+
const duplicates = new Set();
|
|
435
|
+
for (const [key, refs] of refsByKey) {
|
|
436
|
+
if (refs.length > 1) {
|
|
437
|
+
duplicates.add(key);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
return duplicates;
|
|
441
|
+
},
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Process ARIA snapshot: add refs and apply filters
|
|
446
|
+
*/
|
|
447
|
+
function processAriaTree(ariaTree, refs, options) {
|
|
448
|
+
const lines = ariaTree.split('\n');
|
|
449
|
+
const result = [];
|
|
450
|
+
const tracker = createRoleNameTracker();
|
|
451
|
+
// For interactive-only mode, we collect just interactive elements
|
|
452
|
+
if (options.interactive) {
|
|
453
|
+
for (const line of lines) {
|
|
454
|
+
const match = line.match(/^(\s*-\s*)(\w+)(?:\s+"([^"]*)")?(.*)$/);
|
|
455
|
+
if (!match)
|
|
456
|
+
continue;
|
|
457
|
+
const [, , role, name, suffix] = match;
|
|
458
|
+
const roleLower = role.toLowerCase();
|
|
459
|
+
if (INTERACTIVE_ROLES.has(roleLower)) {
|
|
460
|
+
const ref = nextRef();
|
|
461
|
+
const nth = tracker.getNextIndex(roleLower, name);
|
|
462
|
+
tracker.trackRef(roleLower, name, ref);
|
|
463
|
+
refs[ref] = {
|
|
464
|
+
selector: buildSelector(roleLower, name),
|
|
465
|
+
role: roleLower,
|
|
466
|
+
name,
|
|
467
|
+
nth, // Always store nth, we'll use it for duplicates
|
|
468
|
+
};
|
|
469
|
+
let enhanced = `- ${role}`;
|
|
470
|
+
if (name)
|
|
471
|
+
enhanced += ` "${name}"`;
|
|
472
|
+
enhanced += ` [ref=${ref}]`;
|
|
473
|
+
// Only show nth in output if it's > 0 (for readability)
|
|
474
|
+
if (nth > 0)
|
|
475
|
+
enhanced += ` [nth=${nth}]`;
|
|
476
|
+
if (suffix && suffix.includes('['))
|
|
477
|
+
enhanced += suffix;
|
|
478
|
+
result.push(enhanced);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
// Post-process: remove nth from refs that don't have duplicates
|
|
482
|
+
removeNthFromNonDuplicates(refs, tracker);
|
|
483
|
+
return result.join('\n') || '(no interactive elements)';
|
|
484
|
+
}
|
|
485
|
+
// Normal processing with depth/compact filters
|
|
486
|
+
for (const line of lines) {
|
|
487
|
+
const processed = processLine(line, refs, options, tracker);
|
|
488
|
+
if (processed !== null) {
|
|
489
|
+
result.push(processed);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
// Post-process: remove nth from refs that don't have duplicates
|
|
493
|
+
removeNthFromNonDuplicates(refs, tracker);
|
|
494
|
+
// If compact mode, remove empty structural elements
|
|
495
|
+
if (options.compact) {
|
|
496
|
+
return compactTree(result.join('\n'));
|
|
497
|
+
}
|
|
498
|
+
return result.join('\n');
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* Remove nth from refs that ended up not having duplicates
|
|
502
|
+
* This keeps single-element locators simple (no unnecessary .nth(0))
|
|
503
|
+
*/
|
|
504
|
+
function removeNthFromNonDuplicates(refs, tracker) {
|
|
505
|
+
const duplicateKeys = tracker.getDuplicateKeys();
|
|
506
|
+
for (const [ref, data] of Object.entries(refs)) {
|
|
507
|
+
const key = tracker.getKey(data.role, data.name);
|
|
508
|
+
if (!duplicateKeys.has(key)) {
|
|
509
|
+
// Not a duplicate, remove nth to keep locator simple
|
|
510
|
+
delete refs[ref].nth;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Get indentation level (number of spaces / 2)
|
|
516
|
+
*/
|
|
517
|
+
function getIndentLevel(line) {
|
|
518
|
+
const match = line.match(/^(\s*)/);
|
|
519
|
+
return match ? Math.floor(match[1].length / 2) : 0;
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Process a single line: add ref if needed, filter if requested
|
|
523
|
+
*/
|
|
524
|
+
function processLine(line, refs, options, tracker) {
|
|
525
|
+
const depth = getIndentLevel(line);
|
|
526
|
+
// Check max depth
|
|
527
|
+
if (options.maxDepth !== undefined && depth > options.maxDepth) {
|
|
528
|
+
return null;
|
|
529
|
+
}
|
|
530
|
+
// Match lines like:
|
|
531
|
+
// - button "Submit"
|
|
532
|
+
// - heading "Title" [level=1]
|
|
533
|
+
// - link "Click me":
|
|
534
|
+
const match = line.match(/^(\s*-\s*)(\w+)(?:\s+"([^"]*)")?(.*)$/);
|
|
535
|
+
if (!match) {
|
|
536
|
+
// Metadata lines (like /url:) or text content
|
|
537
|
+
if (options.interactive) {
|
|
538
|
+
// In interactive mode, only keep metadata under interactive elements
|
|
539
|
+
return null;
|
|
540
|
+
}
|
|
541
|
+
return line;
|
|
542
|
+
}
|
|
543
|
+
const [, prefix, role, name, suffix] = match;
|
|
544
|
+
const roleLower = role.toLowerCase();
|
|
545
|
+
// Skip metadata lines (like /url:)
|
|
546
|
+
if (role.startsWith('/')) {
|
|
547
|
+
return line;
|
|
548
|
+
}
|
|
549
|
+
const isInteractive = INTERACTIVE_ROLES.has(roleLower);
|
|
550
|
+
const isContent = CONTENT_ROLES.has(roleLower);
|
|
551
|
+
const isStructural = STRUCTURAL_ROLES.has(roleLower);
|
|
552
|
+
// In interactive-only mode, filter non-interactive elements
|
|
553
|
+
if (options.interactive && !isInteractive) {
|
|
554
|
+
return null;
|
|
555
|
+
}
|
|
556
|
+
// In compact mode, skip unnamed structural elements
|
|
557
|
+
if (options.compact && isStructural && !name) {
|
|
558
|
+
return null;
|
|
559
|
+
}
|
|
560
|
+
// Add ref for interactive or named content elements
|
|
561
|
+
const shouldHaveRef = isInteractive || (isContent && name);
|
|
562
|
+
if (shouldHaveRef) {
|
|
563
|
+
const ref = nextRef();
|
|
564
|
+
const nth = tracker.getNextIndex(roleLower, name);
|
|
565
|
+
tracker.trackRef(roleLower, name, ref);
|
|
566
|
+
refs[ref] = {
|
|
567
|
+
selector: buildSelector(roleLower, name),
|
|
568
|
+
role: roleLower,
|
|
569
|
+
name,
|
|
570
|
+
nth, // Always store nth, we'll clean up non-duplicates later
|
|
571
|
+
};
|
|
572
|
+
// Build enhanced line with ref
|
|
573
|
+
let enhanced = `${prefix}${role}`;
|
|
574
|
+
if (name)
|
|
575
|
+
enhanced += ` "${name}"`;
|
|
576
|
+
enhanced += ` [ref=${ref}]`;
|
|
577
|
+
// Only show nth in output if it's > 0 (for readability)
|
|
578
|
+
if (nth > 0)
|
|
579
|
+
enhanced += ` [nth=${nth}]`;
|
|
580
|
+
if (suffix)
|
|
581
|
+
enhanced += suffix;
|
|
582
|
+
return enhanced;
|
|
583
|
+
}
|
|
584
|
+
return line;
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Remove empty structural branches in compact mode
|
|
588
|
+
*/
|
|
589
|
+
function compactTree(tree) {
|
|
590
|
+
const lines = tree.split('\n');
|
|
591
|
+
const result = [];
|
|
592
|
+
// Simple pass: keep lines that have content or refs
|
|
593
|
+
for (let i = 0; i < lines.length; i++) {
|
|
594
|
+
const line = lines[i];
|
|
595
|
+
// Always keep lines with refs
|
|
596
|
+
if (line.includes('[ref=')) {
|
|
597
|
+
result.push(line);
|
|
598
|
+
continue;
|
|
599
|
+
}
|
|
600
|
+
// Keep lines with text content (after :)
|
|
601
|
+
if (line.includes(':') && !line.endsWith(':')) {
|
|
602
|
+
result.push(line);
|
|
603
|
+
continue;
|
|
604
|
+
}
|
|
605
|
+
// Check if this structural element has children with refs
|
|
606
|
+
const currentIndent = getIndentLevel(line);
|
|
607
|
+
let hasRelevantChildren = false;
|
|
608
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
609
|
+
const childIndent = getIndentLevel(lines[j]);
|
|
610
|
+
if (childIndent <= currentIndent)
|
|
611
|
+
break;
|
|
612
|
+
if (lines[j].includes('[ref=')) {
|
|
613
|
+
hasRelevantChildren = true;
|
|
614
|
+
break;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
if (hasRelevantChildren) {
|
|
618
|
+
result.push(line);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
return result.join('\n');
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Parse a ref from command argument (e.g., "@e1" -> "e1")
|
|
625
|
+
*/
|
|
626
|
+
export function parseRef(arg) {
|
|
627
|
+
if (arg.startsWith('@')) {
|
|
628
|
+
return arg.slice(1);
|
|
629
|
+
}
|
|
630
|
+
if (arg.startsWith('ref=')) {
|
|
631
|
+
return arg.slice(4);
|
|
632
|
+
}
|
|
633
|
+
if (/^e\d+$/.test(arg)) {
|
|
634
|
+
return arg;
|
|
635
|
+
}
|
|
636
|
+
return null;
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* Get snapshot statistics
|
|
640
|
+
*/
|
|
641
|
+
export function getSnapshotStats(tree, refs) {
|
|
642
|
+
const interactive = Object.values(refs).filter((r) => INTERACTIVE_ROLES.has(r.role)).length;
|
|
643
|
+
return {
|
|
644
|
+
lines: tree.split('\n').length,
|
|
645
|
+
chars: tree.length,
|
|
646
|
+
tokens: Math.ceil(tree.length / 4),
|
|
647
|
+
refs: Object.keys(refs).length,
|
|
648
|
+
interactive,
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
export { DualModeAXTreeFetcher } from './dualmode-fetcher.js';
|
|
652
|
+
export { getDualModeConfig, isWootzAppEnabled, getCDPEndpoint } from './dualmode-config.js';
|
|
653
|
+
//# sourceMappingURL=snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../src/snapshot.ts"],"names":[],"mappings":"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"}
|