@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.
Files changed (88) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +903 -0
  3. package/README.sdk.md +77 -0
  4. package/bin/agent-browser-linux-x64 +0 -0
  5. package/bin/agent-browser.js +109 -0
  6. package/dist/actions.d.ts +17 -0
  7. package/dist/actions.d.ts.map +1 -0
  8. package/dist/actions.js +1427 -0
  9. package/dist/actions.js.map +1 -0
  10. package/dist/browser.d.ts +474 -0
  11. package/dist/browser.d.ts.map +1 -0
  12. package/dist/browser.js +1566 -0
  13. package/dist/browser.js.map +1 -0
  14. package/dist/cdp-client.d.ts +103 -0
  15. package/dist/cdp-client.d.ts.map +1 -0
  16. package/dist/cdp-client.js +223 -0
  17. package/dist/cdp-client.js.map +1 -0
  18. package/dist/daemon.d.ts +60 -0
  19. package/dist/daemon.d.ts.map +1 -0
  20. package/dist/daemon.js +401 -0
  21. package/dist/daemon.js.map +1 -0
  22. package/dist/dualmode-config.d.ts +37 -0
  23. package/dist/dualmode-config.d.ts.map +1 -0
  24. package/dist/dualmode-config.js +44 -0
  25. package/dist/dualmode-config.js.map +1 -0
  26. package/dist/dualmode-fetcher.d.ts +60 -0
  27. package/dist/dualmode-fetcher.d.ts.map +1 -0
  28. package/dist/dualmode-fetcher.js +449 -0
  29. package/dist/dualmode-fetcher.js.map +1 -0
  30. package/dist/dualmode-types.d.ts +183 -0
  31. package/dist/dualmode-types.d.ts.map +1 -0
  32. package/dist/dualmode-types.js +8 -0
  33. package/dist/dualmode-types.js.map +1 -0
  34. package/dist/ios-actions.d.ts +11 -0
  35. package/dist/ios-actions.d.ts.map +1 -0
  36. package/dist/ios-actions.js +228 -0
  37. package/dist/ios-actions.js.map +1 -0
  38. package/dist/ios-manager.d.ts +266 -0
  39. package/dist/ios-manager.d.ts.map +1 -0
  40. package/dist/ios-manager.js +1073 -0
  41. package/dist/ios-manager.js.map +1 -0
  42. package/dist/protocol.d.ts +26 -0
  43. package/dist/protocol.d.ts.map +1 -0
  44. package/dist/protocol.js +832 -0
  45. package/dist/protocol.js.map +1 -0
  46. package/dist/snapshot.d.ts +83 -0
  47. package/dist/snapshot.d.ts.map +1 -0
  48. package/dist/snapshot.js +653 -0
  49. package/dist/snapshot.js.map +1 -0
  50. package/dist/stream-server.d.ts +117 -0
  51. package/dist/stream-server.d.ts.map +1 -0
  52. package/dist/stream-server.js +305 -0
  53. package/dist/stream-server.js.map +1 -0
  54. package/dist/types.d.ts +742 -0
  55. package/dist/types.d.ts.map +1 -0
  56. package/dist/types.js +2 -0
  57. package/dist/types.js.map +1 -0
  58. package/docker-compose.sdk.yml +45 -0
  59. package/package.json +85 -0
  60. package/scripts/benchmark.sh +80 -0
  61. package/scripts/build-all-platforms.sh +68 -0
  62. package/scripts/check-version-sync.js +39 -0
  63. package/scripts/copy-native.js +36 -0
  64. package/scripts/fast_reset.sh +108 -0
  65. package/scripts/postinstall.js +235 -0
  66. package/scripts/publish_images.sh +55 -0
  67. package/scripts/snapshot_manager.sh +293 -0
  68. package/scripts/start-android-agent.sh +49 -0
  69. package/scripts/sync-version.js +69 -0
  70. package/scripts/vaccine-run +26 -0
  71. package/sdk.sh +153 -0
  72. package/skills/agent-browser/SKILL.md +217 -0
  73. package/skills/agent-browser/references/authentication.md +202 -0
  74. package/skills/agent-browser/references/commands.md +259 -0
  75. package/skills/agent-browser/references/proxy-support.md +188 -0
  76. package/skills/agent-browser/references/session-management.md +193 -0
  77. package/skills/agent-browser/references/snapshot-refs.md +194 -0
  78. package/skills/agent-browser/references/video-recording.md +173 -0
  79. package/skills/agent-browser/templates/authenticated-session.sh +97 -0
  80. package/skills/agent-browser/templates/capture-workflow.sh +69 -0
  81. package/skills/agent-browser/templates/form-automation.sh +62 -0
  82. package/skills/skill-creator/LICENSE.txt +202 -0
  83. package/skills/skill-creator/SKILL.md +356 -0
  84. package/skills/skill-creator/references/output-patterns.md +82 -0
  85. package/skills/skill-creator/references/workflows.md +28 -0
  86. package/skills/skill-creator/scripts/init_skill.py +303 -0
  87. package/skills/skill-creator/scripts/package_skill.py +113 -0
  88. package/skills/skill-creator/scripts/quick_validate.py +95 -0
@@ -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":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AA+B9D,8BAA8B;AAC9B,IAAI,UAAU,GAAG,CAAC,CAAC;AAEnB;;GAEG;AACH,MAAM,UAAU,SAAS;IACvB,UAAU,GAAG,CAAC,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,SAAS,OAAO;IACd,OAAO,IAAI,EAAE,UAAU,EAAE,CAAC;AAC5B,CAAC;AAED;;GAEG;AACH,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,QAAQ;IACR,MAAM;IACN,SAAS;IACT,UAAU;IACV,OAAO;IACP,UAAU;IACV,SAAS;IACT,UAAU;IACV,kBAAkB;IAClB,eAAe;IACf,QAAQ;IACR,WAAW;IACX,QAAQ;IACR,YAAY;IACZ,QAAQ;IACR,KAAK;IACL,UAAU;CACX,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IAC5B,SAAS;IACT,MAAM;IACN,UAAU;IACV,cAAc;IACd,WAAW;IACX,UAAU;IACV,SAAS;IACT,QAAQ;IACR,MAAM;IACN,YAAY;CACb,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC;IAC/B,SAAS;IACT,OAAO;IACP,MAAM;IACN,OAAO;IACP,KAAK;IACL,UAAU;IACV,MAAM;IACN,UAAU;IACV,MAAM;IACN,SAAS;IACT,SAAS;IACT,SAAS;IACT,MAAM;IACN,WAAW;IACX,UAAU;IACV,aAAa;IACb,cAAc;IACd,MAAM;CACP,CAAC,CAAC;AAEH;;GAEG;AACH,SAAS,aAAa,CAAC,IAAY,EAAE,IAAa;IAChD,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC9C,OAAO,cAAc,IAAI,eAAe,WAAW,mBAAmB,CAAC;IACzE,CAAC;IACD,OAAO,cAAc,IAAI,IAAI,CAAC;AAChC,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,6BAA6B,CAC1C,IAAU,EACV,QAAiB;IAWjB,MAAM,YAAY,GAAG,QAAQ,IAAI,MAAM,CAAC;IAExC,sEAAsE;IACtE,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAkFjB,CAAC;IAEH,8DAA8D;IAC9D,MAAM,EAAE,GAAG,IAAI,QAAQ,CAAC,SAAS,GAAG,UAAU,CAAC,EAAE,CAAC;IAClD,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAU,EACV,UAA2B,EAAE;IAE7B,IAAI,iBAAiB,EAAE,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;QAC1D,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;QAC5D,OAAO,CAAC,GAAG,CAAC,4BAA4B,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACtD,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;QAE1D,+BAA+B;QAC/B,OAAO,2BAA2B,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,sCAAsC;IACtC,OAAO,6BAA6B,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;AACtD,CAAC;AAED;;;;;;;;;GASG;AACH,KAAK,UAAU,2BAA2B,CACxC,IAAU,EACV,UAA2B,EAAE;IAE7B,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAC;IACtD,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;IAC/C,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;IAC3C,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAElC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC1D,MAAM,SAAS,GAAG,IAAI,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;IAE3E,IAAI,CAAC;QACH,kDAAkD;QAClD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,+CAA+C,GAAG,EAAE,CAAC,CAAC;QAElE,8EAA8E;QAC9E,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;QAChE,IAAI,CAAC;YACH,yBAAyB;YACzB,MAAM,SAAS,CAAC,uEAAuE,CAAC,CAAC;YACzF,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;YAEvD,qDAAqD;YACrD,MAAM,WAAW,GAAG,wFAAwF,CAAC;YAC7G,MAAM,SAAS,CAAC,8CAA8C,WAAW,0CAA0C,CAAC,CAAC;YAErH,eAAe;YACf,MAAM,SAAS,CAAC,yGAAyG,CAAC,CAAC;YAE3H,sCAAsC;YACtC,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;YAC7D,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;YACxD,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;QACtD,CAAC;QAAC,OAAO,UAAe,EAAE,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC,yCAAyC,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;QAC9E,CAAC;QAED,6EAA6E;QAC7E,OAAO,CAAC,GAAG,CAAC,2CAA2C,OAAO,IAAI,OAAO,EAAE,CAAC,CAAC;QAC7E,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,uBAAuB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxE,OAAO,CAAC,GAAG,CAAC,iCAAiC,KAAK,EAAE,CAAC,CAAC;QACtD,MAAM,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAE7C,kEAAkE;QAClE,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC;QAErE,qBAAqB;QACrB,MAAM,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAEpC,kBAAkB;QAClB,OAAO,CAAC,GAAG,CAAC,6BAA6B,GAAG,EAAE,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;QAE/D,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,qBAAqB,OAAO,CAAC,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACjG,CAAC;QAED,wBAAwB;QACxB,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;QACnD,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,YAAY,CAAC,qBAAqB,EAAE,KAAK,CAAC,CAAC;YAC3D,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,0BAA0B;YACnF,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;QAC1C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC;QACxE,CAAC;QAED,yCAAyC;QACzC,OAAO,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;QAE9D,8BAA8B;QAC9B,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;QAC3D,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QAEhE,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,0CAA0C,UAAU,CAAC,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC5H,CAAC;QAED,6BAA6B;QAC7B,OAAO,CAAC,GAAG,CAAC,oDAAoD,CAAC,CAAC;QAClE,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,IAAI,CAAC,iCAAiC,EAAE,EAAE,CAAC,CAAC;QAE3E,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,qCAAqC,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC/G,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;QACjC,OAAO,CAAC,GAAG,CAAC,0BAA0B,KAAK,CAAC,MAAM,QAAQ,CAAC,CAAC;QAE5D,+BAA+B;QAC/B,MAAM,SAAS,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QAE9C,uBAAuB;QACvB,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;QAExB,gDAAgD;QAChD,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;QAC3D,IAAI,CAAC;YACH,MAAM,SAAS,CAAC,kEAAkE,CAAC,CAAC;YACpF,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;QACnD,CAAC;QAAC,OAAO,UAAe,EAAE,CAAC;YACzB,OAAO,CAAC,IAAI,CAAC,mDAAmD,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;QACxF,CAAC;QAED,0EAA0E;QAC1E,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;QAChE,MAAM,OAAO,GAAG,IAAI,qBAAqB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5D,MAAM,QAAQ,GAAG,EAAE,KAAK,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAEzC,qDAAqD;QACrD,MAAM,eAAe,GAA4B;YAC/C,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,eAAe,EAAE,KAAK;SACvB,CAAC;QAEF,MAAM,QAAQ,GAAG,OAAO,CAAC,gBAAgB,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QAEjE,iBAAiB;QACjB,MAAM,IAAI,GAAW,EAAE,CAAC;QACxB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC5C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG;gBACf,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,EAAE;gBAC7B,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS;gBACrE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;aACjE,CAAC;QACJ,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,uCAAuC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,OAAO,CAAC,CAAC;QAEpF,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,IAAI;SACL,CAAC;IACJ,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,qBAAqB,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACpD,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAChD,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;QACxB,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,6BAA6B,CAC1C,IAAU,EACV,UAA2B,EAAE;IAE7B,SAAS,EAAE,CAAC;IACZ,MAAM,IAAI,GAAW,EAAE,CAAC;IAExB,oCAAoC;IACpC,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1F,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC;IAE9C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO;YACL,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,EAAE;SACT,CAAC;IACJ,CAAC;IAED,kCAAkC;IAClC,MAAM,YAAY,GAAG,eAAe,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAE9D,iEAAiE;IACjE,sCAAsC;IACtC,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,MAAM,cAAc,GAAG,MAAM,6BAA6B,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;QAEnF,qEAAqE;QACrE,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;QAErF,MAAM,eAAe,GAAa,EAAE,CAAC;QACrC,KAAK,MAAM,EAAE,IAAI,cAAc,EAAE,CAAC;YAChC,8DAA8D;YAC9D,IAAI,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;gBAAE,SAAS;YAEvD,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;YACtB,MAAM,IAAI,GAAG,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC;YAE3F,IAAI,CAAC,GAAG,CAAC,GAAG;gBACV,QAAQ,EAAE,EAAE,CAAC,QAAQ;gBACrB,IAAI,EAAE,IAAI;gBACV,IAAI,EAAE,EAAE,CAAC,IAAI;aACd,CAAC;YAEF,4CAA4C;YAC5C,MAAM,KAAK,GAAa,EAAE,CAAC;YAC3B,IAAI,EAAE,CAAC,gBAAgB;gBAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACtD,IAAI,EAAE,CAAC,UAAU;gBAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACzC,IAAI,EAAE,CAAC,WAAW;gBAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAE3C,eAAe,CAAC,IAAI,CAAC,KAAK,IAAI,KAAK,EAAE,CAAC,IAAI,UAAU,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpF,CAAC;QAED,IAAI,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC/B,MAAM,SAAS,GACb,YAAY,KAAK,2BAA2B,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,oCAAoC,CAAC;YAC3F,MAAM,IAAI,GAAG,YAAY,KAAK,2BAA2B,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;YAC9E,OAAO;gBACL,IAAI,EAAE,IAAI,GAAG,SAAS,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC;gBACnD,IAAI;aACL,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;AACtC,CAAC;AAgBD,SAAS,qBAAqB;IAC5B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC9C,OAAO;QACL,MAAM;QACN,SAAS;QACT,MAAM,CAAC,IAAY,EAAE,IAAa;YAChC,OAAO,GAAG,IAAI,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC;QACjC,CAAC;QACD,YAAY,CAAC,IAAY,EAAE,IAAa;YACtC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACpC,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACrC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,GAAG,CAAC,CAAC,CAAC;YAC7B,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,QAAQ,CAAC,IAAY,EAAE,IAAwB,EAAE,GAAW;YAC1D,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACpC,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YACtC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACf,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC3B,CAAC;QACD,gBAAgB;YACd,MAAM,UAAU,GAAG,IAAI,GAAG,EAAU,CAAC;YACrC,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,SAAS,EAAE,CAAC;gBACpC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACpB,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBACtB,CAAC;YACH,CAAC;YACD,OAAO,UAAU,CAAC;QACpB,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,QAAgB,EAAE,IAAY,EAAE,OAAwB;IAC/E,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAG,qBAAqB,EAAE,CAAC;IAExC,kEAAkE;IAClE,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;QACxB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;YAClE,IAAI,CAAC,KAAK;gBAAE,SAAS;YAErB,MAAM,CAAC,EAAE,AAAD,EAAG,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC;YACvC,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YAErC,IAAI,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBACrC,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;gBACtB,MAAM,GAAG,GAAG,OAAO,CAAC,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;gBAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;gBACvC,IAAI,CAAC,GAAG,CAAC,GAAG;oBACV,QAAQ,EAAE,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC;oBACxC,IAAI,EAAE,SAAS;oBACf,IAAI;oBACJ,GAAG,EAAE,gDAAgD;iBACtD,CAAC;gBAEF,IAAI,QAAQ,GAAG,KAAK,IAAI,EAAE,CAAC;gBAC3B,IAAI,IAAI;oBAAE,QAAQ,IAAI,KAAK,IAAI,GAAG,CAAC;gBACnC,QAAQ,IAAI,SAAS,GAAG,GAAG,CAAC;gBAC5B,wDAAwD;gBACxD,IAAI,GAAG,GAAG,CAAC;oBAAE,QAAQ,IAAI,SAAS,GAAG,GAAG,CAAC;gBACzC,IAAI,MAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;oBAAE,QAAQ,IAAI,MAAM,CAAC;gBAEvD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QAED,gEAAgE;QAChE,0BAA0B,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAE1C,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,2BAA2B,CAAC;IAC1D,CAAC;IAED,+CAA+C;IAC/C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,SAAS,GAAG,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC5D,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACvB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,gEAAgE;IAChE,0BAA0B,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAE1C,oDAAoD;IACpD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,SAAS,0BAA0B,CAAC,IAAY,EAAE,OAAwB;IACxE,MAAM,aAAa,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAEjD,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5B,qDAAqD;YACrD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC;QACvB,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACnC,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrD,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAClB,IAAY,EACZ,IAAY,EACZ,OAAwB,EACxB,OAAwB;IAExB,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IAEnC,kBAAkB;IAClB,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,IAAI,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;QAC/D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oBAAoB;IACpB,sBAAsB;IACtB,gCAAgC;IAChC,uBAAuB;IACvB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAElE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,8CAA8C;QAC9C,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACxB,qEAAqE;YACrE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC;IAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAErC,mCAAmC;IACnC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,aAAa,GAAG,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC/C,MAAM,YAAY,GAAG,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAErD,4DAA4D;IAC5D,IAAI,OAAO,CAAC,WAAW,IAAI,CAAC,aAAa,EAAE,CAAC;QAC1C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oDAAoD;IACpD,IAAI,OAAO,CAAC,OAAO,IAAI,YAAY,IAAI,CAAC,IAAI,EAAE,CAAC;QAC7C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,oDAAoD;IACpD,MAAM,aAAa,GAAG,aAAa,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC;IAE3D,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,OAAO,CAAC,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAClD,OAAO,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC;QAEvC,IAAI,CAAC,GAAG,CAAC,GAAG;YACV,QAAQ,EAAE,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC;YACxC,IAAI,EAAE,SAAS;YACf,IAAI;YACJ,GAAG,EAAE,wDAAwD;SAC9D,CAAC;QAEF,+BAA+B;QAC/B,IAAI,QAAQ,GAAG,GAAG,MAAM,GAAG,IAAI,EAAE,CAAC;QAClC,IAAI,IAAI;YAAE,QAAQ,IAAI,KAAK,IAAI,GAAG,CAAC;QACnC,QAAQ,IAAI,SAAS,GAAG,GAAG,CAAC;QAC5B,wDAAwD;QACxD,IAAI,GAAG,GAAG,CAAC;YAAE,QAAQ,IAAI,SAAS,GAAG,GAAG,CAAC;QACzC,IAAI,MAAM;YAAE,QAAQ,IAAI,MAAM,CAAC;QAE/B,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,IAAY;IAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,oDAAoD;IACpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAEtB,8BAA8B;QAC9B,IAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClB,SAAS;QACX,CAAC;QAED,yCAAyC;QACzC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9C,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAClB,SAAS;QACX,CAAC;QAED,0DAA0D;QAC1D,MAAM,aAAa,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;QAC3C,IAAI,mBAAmB,GAAG,KAAK,CAAC;QAEhC,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAC7C,IAAI,WAAW,IAAI,aAAa;gBAAE,MAAM;YACxC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC/B,mBAAmB,GAAG,IAAI,CAAC;gBAC3B,MAAM;YACR,CAAC;QACH,CAAC;QAED,IAAI,mBAAmB,EAAE,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACtB,CAAC;IACD,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACtB,CAAC;IACD,IAAI,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,IAAY;IAQZ,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;IAE5F,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM;QAC9B,KAAK,EAAE,IAAI,CAAC,MAAM;QAClB,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAClC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM;QAC9B,WAAW;KACZ,CAAC;AACJ,CAAC;AASD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACf,MAAM,sBAAsB,CAAC"}