@tangle-network/browser-agent-driver 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/LICENSE +196 -0
  2. package/README.md +149 -0
  3. package/dist/artifacts/composite-sink.d.ts +15 -0
  4. package/dist/artifacts/composite-sink.d.ts.map +1 -0
  5. package/dist/artifacts/composite-sink.js +27 -0
  6. package/dist/artifacts/composite-sink.js.map +1 -0
  7. package/dist/artifacts/filesystem-sink.d.ts +26 -0
  8. package/dist/artifacts/filesystem-sink.d.ts.map +1 -0
  9. package/dist/artifacts/filesystem-sink.js +81 -0
  10. package/dist/artifacts/filesystem-sink.js.map +1 -0
  11. package/dist/artifacts/types.d.ts +97 -0
  12. package/dist/artifacts/types.d.ts.map +1 -0
  13. package/dist/artifacts/types.js +9 -0
  14. package/dist/artifacts/types.js.map +1 -0
  15. package/dist/artifacts/webhook-sink.d.ts +71 -0
  16. package/dist/artifacts/webhook-sink.d.ts.map +1 -0
  17. package/dist/artifacts/webhook-sink.js +117 -0
  18. package/dist/artifacts/webhook-sink.js.map +1 -0
  19. package/dist/brain/index.d.ts +149 -0
  20. package/dist/brain/index.d.ts.map +1 -0
  21. package/dist/brain/index.js +1030 -0
  22. package/dist/brain/index.js.map +1 -0
  23. package/dist/browser-launch.d.ts +27 -0
  24. package/dist/browser-launch.d.ts.map +1 -0
  25. package/dist/browser-launch.js +92 -0
  26. package/dist/browser-launch.js.map +1 -0
  27. package/dist/cli.d.ts +14 -0
  28. package/dist/cli.d.ts.map +1 -0
  29. package/dist/cli.js +1035 -0
  30. package/dist/cli.js.map +1 -0
  31. package/dist/config.d.ts +143 -0
  32. package/dist/config.d.ts.map +1 -0
  33. package/dist/config.js +205 -0
  34. package/dist/config.js.map +1 -0
  35. package/dist/context-budget.d.ts +14 -0
  36. package/dist/context-budget.d.ts.map +1 -0
  37. package/dist/context-budget.js +39 -0
  38. package/dist/context-budget.js.map +1 -0
  39. package/dist/design-audit.d.ts +48 -0
  40. package/dist/design-audit.d.ts.map +1 -0
  41. package/dist/design-audit.js +172 -0
  42. package/dist/design-audit.js.map +1 -0
  43. package/dist/domain-policy.d.ts +4 -0
  44. package/dist/domain-policy.d.ts.map +1 -0
  45. package/dist/domain-policy.js +69 -0
  46. package/dist/domain-policy.js.map +1 -0
  47. package/dist/drivers/block-patterns.d.ts +11 -0
  48. package/dist/drivers/block-patterns.d.ts.map +1 -0
  49. package/dist/drivers/block-patterns.js +123 -0
  50. package/dist/drivers/block-patterns.js.map +1 -0
  51. package/dist/drivers/cdp-page-state.d.ts +22 -0
  52. package/dist/drivers/cdp-page-state.d.ts.map +1 -0
  53. package/dist/drivers/cdp-page-state.js +38 -0
  54. package/dist/drivers/cdp-page-state.js.map +1 -0
  55. package/dist/drivers/cdp-snapshot.d.ts +32 -0
  56. package/dist/drivers/cdp-snapshot.d.ts.map +1 -0
  57. package/dist/drivers/cdp-snapshot.js +120 -0
  58. package/dist/drivers/cdp-snapshot.js.map +1 -0
  59. package/dist/drivers/playwright.d.ts +84 -0
  60. package/dist/drivers/playwright.d.ts.map +1 -0
  61. package/dist/drivers/playwright.js +385 -0
  62. package/dist/drivers/playwright.js.map +1 -0
  63. package/dist/drivers/snapshot.d.ts +134 -0
  64. package/dist/drivers/snapshot.d.ts.map +1 -0
  65. package/dist/drivers/snapshot.js +354 -0
  66. package/dist/drivers/snapshot.js.map +1 -0
  67. package/dist/drivers/types.d.ts +37 -0
  68. package/dist/drivers/types.d.ts.map +1 -0
  69. package/dist/drivers/types.js +5 -0
  70. package/dist/drivers/types.js.map +1 -0
  71. package/dist/env-loader.d.ts +2 -0
  72. package/dist/env-loader.d.ts.map +1 -0
  73. package/dist/env-loader.js +35 -0
  74. package/dist/env-loader.js.map +1 -0
  75. package/dist/formatters/slack.d.ts +37 -0
  76. package/dist/formatters/slack.d.ts.map +1 -0
  77. package/dist/formatters/slack.js +97 -0
  78. package/dist/formatters/slack.js.map +1 -0
  79. package/dist/index.d.ts +60 -0
  80. package/dist/index.d.ts.map +1 -0
  81. package/dist/index.js +53 -0
  82. package/dist/index.js.map +1 -0
  83. package/dist/memory/analyzer.d.ts +67 -0
  84. package/dist/memory/analyzer.d.ts.map +1 -0
  85. package/dist/memory/analyzer.js +265 -0
  86. package/dist/memory/analyzer.js.map +1 -0
  87. package/dist/memory/knowledge.d.ts +55 -0
  88. package/dist/memory/knowledge.d.ts.map +1 -0
  89. package/dist/memory/knowledge.js +115 -0
  90. package/dist/memory/knowledge.js.map +1 -0
  91. package/dist/memory/project-store.d.ts +43 -0
  92. package/dist/memory/project-store.d.ts.map +1 -0
  93. package/dist/memory/project-store.js +119 -0
  94. package/dist/memory/project-store.js.map +1 -0
  95. package/dist/memory/selectors.d.ts +46 -0
  96. package/dist/memory/selectors.d.ts.map +1 -0
  97. package/dist/memory/selectors.js +89 -0
  98. package/dist/memory/selectors.js.map +1 -0
  99. package/dist/memory/store.d.ts +39 -0
  100. package/dist/memory/store.d.ts.map +1 -0
  101. package/dist/memory/store.js +193 -0
  102. package/dist/memory/store.js.map +1 -0
  103. package/dist/model-pricing.d.ts +41 -0
  104. package/dist/model-pricing.d.ts.map +1 -0
  105. package/dist/model-pricing.js +197 -0
  106. package/dist/model-pricing.js.map +1 -0
  107. package/dist/multi-actor.d.ts +108 -0
  108. package/dist/multi-actor.d.ts.map +1 -0
  109. package/dist/multi-actor.js +192 -0
  110. package/dist/multi-actor.js.map +1 -0
  111. package/dist/override-pipeline.d.ts +57 -0
  112. package/dist/override-pipeline.d.ts.map +1 -0
  113. package/dist/override-pipeline.js +26 -0
  114. package/dist/override-pipeline.js.map +1 -0
  115. package/dist/personas.d.ts +19 -0
  116. package/dist/personas.d.ts.map +1 -0
  117. package/dist/personas.js +86 -0
  118. package/dist/personas.js.map +1 -0
  119. package/dist/preview.d.ts +32 -0
  120. package/dist/preview.d.ts.map +1 -0
  121. package/dist/preview.js +138 -0
  122. package/dist/preview.js.map +1 -0
  123. package/dist/provider-defaults.d.ts +6 -0
  124. package/dist/provider-defaults.d.ts.map +1 -0
  125. package/dist/provider-defaults.js +40 -0
  126. package/dist/provider-defaults.js.map +1 -0
  127. package/dist/providers/sandbox-backend.d.ts +22 -0
  128. package/dist/providers/sandbox-backend.d.ts.map +1 -0
  129. package/dist/providers/sandbox-backend.js +259 -0
  130. package/dist/providers/sandbox-backend.js.map +1 -0
  131. package/dist/recovery.d.ts +91 -0
  132. package/dist/recovery.d.ts.map +1 -0
  133. package/dist/recovery.js +500 -0
  134. package/dist/recovery.js.map +1 -0
  135. package/dist/reporters/junit.d.ts +8 -0
  136. package/dist/reporters/junit.d.ts.map +1 -0
  137. package/dist/reporters/junit.js +99 -0
  138. package/dist/reporters/junit.js.map +1 -0
  139. package/dist/run-metrics.d.ts +4 -0
  140. package/dist/run-metrics.d.ts.map +1 -0
  141. package/dist/run-metrics.js +48 -0
  142. package/dist/run-metrics.js.map +1 -0
  143. package/dist/run-state.d.ts +22 -0
  144. package/dist/run-state.d.ts.map +1 -0
  145. package/dist/run-state.js +33 -0
  146. package/dist/run-state.js.map +1 -0
  147. package/dist/runner/goal-verification.d.ts +13 -0
  148. package/dist/runner/goal-verification.d.ts.map +1 -0
  149. package/dist/runner/goal-verification.js +152 -0
  150. package/dist/runner/goal-verification.js.map +1 -0
  151. package/dist/runner/index.d.ts +12 -0
  152. package/dist/runner/index.d.ts.map +1 -0
  153. package/dist/runner/index.js +18 -0
  154. package/dist/runner/index.js.map +1 -0
  155. package/dist/runner/overrides.d.ts +75 -0
  156. package/dist/runner/overrides.d.ts.map +1 -0
  157. package/dist/runner/overrides.js +385 -0
  158. package/dist/runner/overrides.js.map +1 -0
  159. package/dist/runner/page-analysis.d.ts +23 -0
  160. package/dist/runner/page-analysis.d.ts.map +1 -0
  161. package/dist/runner/page-analysis.js +91 -0
  162. package/dist/runner/page-analysis.js.map +1 -0
  163. package/dist/runner/runner.d.ts +66 -0
  164. package/dist/runner/runner.d.ts.map +1 -0
  165. package/dist/runner/runner.js +1314 -0
  166. package/dist/runner/runner.js.map +1 -0
  167. package/dist/runner/scout.d.ts +29 -0
  168. package/dist/runner/scout.d.ts.map +1 -0
  169. package/dist/runner/scout.js +81 -0
  170. package/dist/runner/scout.js.map +1 -0
  171. package/dist/runner/search-guidance.d.ts +31 -0
  172. package/dist/runner/search-guidance.d.ts.map +1 -0
  173. package/dist/runner/search-guidance.js +210 -0
  174. package/dist/runner/search-guidance.js.map +1 -0
  175. package/dist/runner/utils.d.ts +28 -0
  176. package/dist/runner/utils.d.ts.map +1 -0
  177. package/dist/runner/utils.js +119 -0
  178. package/dist/runner/utils.js.map +1 -0
  179. package/dist/runner.d.ts +8 -0
  180. package/dist/runner.d.ts.map +1 -0
  181. package/dist/runner.js +21 -0
  182. package/dist/runner.js.map +1 -0
  183. package/dist/supervisor/critic.d.ts +29 -0
  184. package/dist/supervisor/critic.d.ts.map +1 -0
  185. package/dist/supervisor/critic.js +320 -0
  186. package/dist/supervisor/critic.js.map +1 -0
  187. package/dist/supervisor/policy.d.ts +11 -0
  188. package/dist/supervisor/policy.d.ts.map +1 -0
  189. package/dist/supervisor/policy.js +118 -0
  190. package/dist/supervisor/policy.js.map +1 -0
  191. package/dist/test-report.d.ts +15 -0
  192. package/dist/test-report.d.ts.map +1 -0
  193. package/dist/test-report.js +241 -0
  194. package/dist/test-report.js.map +1 -0
  195. package/dist/test-runner.d.ts +99 -0
  196. package/dist/test-runner.d.ts.map +1 -0
  197. package/dist/test-runner.js +1075 -0
  198. package/dist/test-runner.js.map +1 -0
  199. package/dist/types.d.ts +493 -0
  200. package/dist/types.d.ts.map +1 -0
  201. package/dist/types.js +5 -0
  202. package/dist/types.js.map +1 -0
  203. package/dist/wallet/automation.d.ts +52 -0
  204. package/dist/wallet/automation.d.ts.map +1 -0
  205. package/dist/wallet/automation.js +507 -0
  206. package/dist/wallet/automation.js.map +1 -0
  207. package/package.json +101 -0
  208. package/scripts/postinstall-provider-patches.mjs +52 -0
@@ -0,0 +1,354 @@
1
+ /**
2
+ * Shared accessibility tree snapshot helper.
3
+ *
4
+ * Uses Playwright's `locator.ariaSnapshot()` to produce a YAML-like tree,
5
+ * assigns STABLE ref IDs to interactive elements (deterministic hash of
6
+ * role+name), and resolves @ref selectors back to Playwright locators via
7
+ * getByRole().
8
+ *
9
+ * Stable refs mean the same element (e.g. button "Send") gets the SAME ref ID
10
+ * across observations. Only elements that truly disappear produce invalid refs.
11
+ * Duplicates (multiple elements with same role+name) get index suffixes.
12
+ *
13
+ * Used by PlaywrightDriver.
14
+ */
15
+ function diffSnapshots(prev, curr) {
16
+ const added = [];
17
+ const removed = [];
18
+ const changed = [];
19
+ for (const [ref, el] of curr) {
20
+ const prevEl = prev.get(ref);
21
+ if (!prevEl) {
22
+ added.push(`+ ${el.role} "${el.name}" [ref=${ref}]`);
23
+ }
24
+ else if (prevEl.value !== el.value) {
25
+ changed.push(`~ ${el.role} "${el.name}" [ref=${ref}] value: "${prevEl.value ?? ''}" → "${el.value ?? ''}"`);
26
+ }
27
+ }
28
+ for (const [ref, el] of prev) {
29
+ if (!curr.has(ref)) {
30
+ removed.push(`- ${el.role} "${el.name}" [ref=${ref}]`);
31
+ }
32
+ }
33
+ return { added, removed, changed, unchangedCount: curr.size - added.length - changed.length };
34
+ }
35
+ /** Format a SnapshotDiff as compact text for brain injection */
36
+ function formatDiff(diff) {
37
+ const lines = [];
38
+ if (diff.added.length)
39
+ lines.push('ADDED:', ...diff.added);
40
+ if (diff.removed.length)
41
+ lines.push('REMOVED:', ...diff.removed);
42
+ if (diff.changed.length)
43
+ lines.push('CHANGED:', ...diff.changed);
44
+ lines.push(`(${diff.unchangedCount} elements unchanged)`);
45
+ return lines.join('\n');
46
+ }
47
+ export const INTERACTIVE_ROLES = new Set([
48
+ 'button', 'link', 'textbox', 'checkbox', 'radio',
49
+ 'combobox', 'listbox', 'menuitem', 'menuitemcheckbox',
50
+ 'menuitemradio', 'option', 'searchbox', 'slider',
51
+ 'spinbutton', 'switch', 'tab', 'treeitem',
52
+ ]);
53
+ /**
54
+ * Generate a short deterministic hash from role+name.
55
+ * Produces a 3-4 char hex string (e.g. "b3f", "1a2c").
56
+ */
57
+ export function stableHash(role, name) {
58
+ const str = `${role}:${name}`;
59
+ let h = 0x811c9dc5; // FNV-1a offset basis
60
+ for (let i = 0; i < str.length; i++) {
61
+ h ^= str.charCodeAt(i);
62
+ h = Math.imul(h, 0x01000193); // FNV prime
63
+ }
64
+ // Take lower 14 bits -> 0-16383 -> 1-4 hex chars, prefix with role initial
65
+ const hex = ((h >>> 0) & 0x3fff).toString(16);
66
+ return `${role[0]}${hex}`;
67
+ }
68
+ export class AriaSnapshotHelper {
69
+ refMap = new Map();
70
+ /** Track how many times each base hash has been seen (for duplicate disambiguation) */
71
+ hashCounts = new Map();
72
+ /** Previous snapshot's parsed elements for diffing */
73
+ prevElements = new Map();
74
+ /** Current snapshot's parsed elements (populated during parseAriaSnapshot) */
75
+ currElements = new Map();
76
+ /** Last computed diff (undefined on first observe) */
77
+ lastDiff;
78
+ /** Clear refs -- call at the start of each observe() cycle */
79
+ reset() {
80
+ this.refMap.clear();
81
+ this.hashCounts.clear();
82
+ }
83
+ /**
84
+ * Import refs and elements from an external source (e.g., CDP snapshot).
85
+ *
86
+ * Populates the internal refMap and currElements so that resolveLocator()
87
+ * and getDiff() work identically to the Playwright ariaSnapshot path.
88
+ */
89
+ importCdpRefs(refMap, elements) {
90
+ // Save previous elements for diffing
91
+ this.prevElements = this.currElements;
92
+ this.currElements = new Map(elements);
93
+ // Import refs into our refMap
94
+ for (const [refId, entry] of refMap) {
95
+ this.refMap.set(refId, { role: entry.role, name: entry.name });
96
+ }
97
+ // Compute diff
98
+ if (this.prevElements.size > 0) {
99
+ this.lastDiff = diffSnapshots(this.prevElements, this.currElements);
100
+ }
101
+ else {
102
+ this.lastDiff = undefined;
103
+ }
104
+ }
105
+ /**
106
+ * Build an accessibility tree snapshot with stable ref IDs.
107
+ *
108
+ * Calls `page.locator('body').ariaSnapshot()` and parses the YAML output,
109
+ * assigning deterministic `[ref=XX]` to interactive/named elements.
110
+ */
111
+ async buildSnapshot(page) {
112
+ const rawSnapshot = await page.locator('body').ariaSnapshot({ timeout: 10_000 })
113
+ .catch(() => '');
114
+ if (!rawSnapshot.trim())
115
+ return '(empty page)';
116
+ // Save previous elements before parsing new snapshot
117
+ this.prevElements = this.currElements;
118
+ this.currElements = new Map();
119
+ let snapshot = this.parseAriaSnapshot(rawSnapshot);
120
+ // Compute diff after parsing (currElements is now populated)
121
+ if (this.prevElements.size > 0) {
122
+ this.lastDiff = diffSnapshots(this.prevElements, this.currElements);
123
+ }
124
+ else {
125
+ this.lastDiff = undefined;
126
+ }
127
+ // Augment with data-testid elements -- helps LLMs identify elements
128
+ // that have no accessible name (e.g., icon-only buttons)
129
+ const testIds = await page.evaluate(() => {
130
+ const INTERACTIVE = new Set(['button', 'input', 'textarea', 'select', 'a']);
131
+ const elements = document.querySelectorAll('[data-testid]');
132
+ return Array.from(elements)
133
+ .filter(el => INTERACTIVE.has(el.tagName.toLowerCase()) || el.getAttribute('role'))
134
+ .slice(0, 30) // Limit to avoid token bloat
135
+ .map(el => ({
136
+ testId: el.getAttribute('data-testid') || '',
137
+ tag: el.tagName.toLowerCase(),
138
+ text: (el.textContent || '').trim().slice(0, 40),
139
+ disabled: el.disabled || false,
140
+ }));
141
+ }).catch(() => []);
142
+ if (testIds.length > 0) {
143
+ snapshot += '\n\nDATA-TESTID SELECTORS (use [data-testid="..."] as selector):';
144
+ for (const el of testIds) {
145
+ const disabled = el.disabled ? ' [disabled]' : '';
146
+ const text = el.text ? ` "${el.text}"` : '';
147
+ snapshot += `\n [data-testid="${el.testId}"] ${el.tag}${text}${disabled}`;
148
+ }
149
+ }
150
+ return snapshot;
151
+ }
152
+ /**
153
+ * Resolve a selector to a Playwright Locator.
154
+ *
155
+ * - `@b3f` -> resolved from ref map via getByRole()
156
+ * - Standard selectors (CSS, text=, role=, [data-testid=...]) -> page.locator()
157
+ */
158
+ resolveLocator(page, selector) {
159
+ if (selector.startsWith('@')) {
160
+ const refId = selector.slice(1);
161
+ const entry = this.refMap.get(refId);
162
+ if (entry) {
163
+ const roleLocator = page.getByRole(entry.role, {
164
+ name: entry.name,
165
+ exact: entry.name.length > 0,
166
+ });
167
+ // Suffixed refs (e.g., t31b3_2) represent the Nth duplicate of a role+name combo.
168
+ // Use nth() to target the correct instance instead of always picking first().
169
+ const suffixMatch = refId.match(/_(\d+)$/);
170
+ if (suffixMatch) {
171
+ const index = parseInt(suffixMatch[1], 10);
172
+ return roleLocator.nth(index);
173
+ }
174
+ return roleLocator.first();
175
+ }
176
+ // Ref not found in current snapshot -- throw with available refs for
177
+ // auto-retry or Brain feedback
178
+ throw new StaleRefError(refId, [...this.refMap.keys()]);
179
+ }
180
+ return page.locator(selector).first();
181
+ }
182
+ /**
183
+ * Parse Playwright's ARIA snapshot YAML and assign stable ref IDs.
184
+ *
185
+ * Ref IDs are deterministic hashes of role+name, so the same element gets
186
+ * the same ref across observations. Duplicates get index suffixes (_1, _2).
187
+ *
188
+ * Input:
189
+ * - button "Sign in"
190
+ * - textbox "Email" [value=""]
191
+ * - list "Nav":
192
+ * - link "Home"
193
+ *
194
+ * Output:
195
+ * - button "Sign in" [ref=b2a1]
196
+ * - textbox "Email" [ref=t3f0] [value=""]
197
+ * - list "Nav" [ref=l1b2]:
198
+ * - link "Home" [ref=la3c]
199
+ */
200
+ parseAriaSnapshot(raw) {
201
+ const lines = raw.split('\n');
202
+ const result = [];
203
+ for (const line of lines) {
204
+ const match = line.match(/^(\s*-\s+)(\w+)(?:\s+"([^"]*)")?(.*)$/);
205
+ if (!match) {
206
+ result.push(line);
207
+ continue;
208
+ }
209
+ const [, indent, role, name, rest] = match;
210
+ if (INTERACTIVE_ROLES.has(role) || (name && role !== 'text')) {
211
+ const baseHash = stableHash(role, name || '');
212
+ // Track duplicates: first occurrence gets bare hash, subsequent get _N suffix
213
+ const count = this.hashCounts.get(baseHash) || 0;
214
+ this.hashCounts.set(baseHash, count + 1);
215
+ const refId = count === 0 ? baseHash : `${baseHash}_${count}`;
216
+ this.refMap.set(refId, { role, name: name || '' });
217
+ // Extract value for diff tracking
218
+ const valueMatch = rest.match(/\[value="([^"]*)"\]/);
219
+ this.currElements.set(refId, {
220
+ ref: refId,
221
+ role,
222
+ name: name || '',
223
+ value: valueMatch ? valueMatch[1] : undefined,
224
+ });
225
+ const cleanRest = rest.replace(/:$/, '').trim();
226
+ const colon = rest.trimEnd().endsWith(':') ? ':' : '';
227
+ const nameStr = name ? ` "${name}"` : '';
228
+ const refStr = ` [ref=${refId}]`;
229
+ const propsStr = cleanRest ? ` ${cleanRest}` : '';
230
+ result.push(`${indent}${role}${nameStr}${refStr}${propsStr}${colon}`);
231
+ }
232
+ else {
233
+ result.push(line);
234
+ }
235
+ }
236
+ return result.join('\n');
237
+ }
238
+ /**
239
+ * Get the diff from the last buildSnapshot() call.
240
+ * Returns undefined on the first call (no previous snapshot to diff against).
241
+ */
242
+ getDiff() {
243
+ if (!this.lastDiff)
244
+ return undefined;
245
+ return formatDiff(this.lastDiff);
246
+ }
247
+ /** Get the raw structured diff (for programmatic use) */
248
+ getRawDiff() {
249
+ return this.lastDiff;
250
+ }
251
+ /**
252
+ * Format a snapshot in compact form: one line per element, ref-first,
253
+ * flat (no nesting), ~50-60% fewer tokens.
254
+ *
255
+ * Full format:
256
+ * - button "Sign in" [ref=b2a1]
257
+ * - textbox "Email" [ref=t3f0] [value=""]
258
+ * - list "Nav" [ref=l1b2]:
259
+ * - link "Home" [ref=la3c]
260
+ *
261
+ * Compact format:
262
+ * @b2a1 button "Sign in"
263
+ * @t3f0 textbox "Email" val=""
264
+ * @l1b2 list "Nav"
265
+ * @la3c link "Home"
266
+ */
267
+ static formatCompact(snapshot) {
268
+ const lines = snapshot.split('\n');
269
+ const compact = [];
270
+ for (const line of lines) {
271
+ const match = line.match(/\s*-\s+(\w+)\s+"([^"]*)"?\s*\[ref=(\w+)\](.*)?$/);
272
+ if (!match)
273
+ continue;
274
+ const [, role, name, ref, rest] = match;
275
+ const valueMatch = rest?.match(/\[value="([^"]*)"\]/);
276
+ const value = valueMatch ? ` val="${valueMatch[1]}"` : '';
277
+ compact.push(`@${ref} ${role} "${name}"${value}`);
278
+ }
279
+ return compact.join('\n');
280
+ }
281
+ }
282
+ /**
283
+ * Typed error for stale ref detection -- allows runner to catch specifically
284
+ * and auto-retry with a fresh observation.
285
+ */
286
+ export class StaleRefError extends Error {
287
+ staleRef;
288
+ availableRefs;
289
+ constructor(staleRef, availableRefs) {
290
+ super(`Ref "@${staleRef}" not found in current snapshot ` +
291
+ `(available: ${availableRefs.join(', ') || 'none'}). ` +
292
+ `Use a ref from the CURRENT observation.`);
293
+ this.name = 'StaleRefError';
294
+ this.staleRef = staleRef;
295
+ this.availableRefs = availableRefs;
296
+ }
297
+ }
298
+ /**
299
+ * Dismiss blocking overlays (dialogs, modals, Vite errors).
300
+ * Shared between drivers that operate on a Playwright page.
301
+ *
302
+ * Returns 'clicked' if a close button was found and clicked,
303
+ * 'found' if an overlay exists but no close button was found (Escape pressed),
304
+ * or false if no overlay was detected.
305
+ */
306
+ export async function dismissOverlays(page) {
307
+ const result = await page.evaluate(() => {
308
+ const dialog = document.querySelector('[role="dialog"]');
309
+ if (dialog) {
310
+ const closeByLabel = dialog.querySelector('button[aria-label="Close"]');
311
+ if (closeByLabel) {
312
+ closeByLabel.click();
313
+ return 'clicked';
314
+ }
315
+ const btns = dialog.querySelectorAll('button');
316
+ for (const btn of btns) {
317
+ const text = (btn.textContent || '').toLowerCase().trim();
318
+ if (text === 'close' || text.includes('cancel') || text.includes('maybe later') || text.includes('dismiss') || text.includes('skip')) {
319
+ btn.click();
320
+ return 'clicked';
321
+ }
322
+ }
323
+ return 'found'; // Dialog found but no close button -- needs Escape
324
+ }
325
+ const overlay = document.querySelector('div.fixed.inset-0[class*="z-"]');
326
+ if (overlay) {
327
+ const closeBtn = overlay.querySelector('button[aria-label="Close"]');
328
+ if (closeBtn) {
329
+ closeBtn.click();
330
+ return 'clicked';
331
+ }
332
+ return 'found';
333
+ }
334
+ const viteOverlay = document.querySelector('vite-error-overlay');
335
+ if (viteOverlay) {
336
+ viteOverlay.remove();
337
+ return 'clicked';
338
+ }
339
+ return false;
340
+ });
341
+ if (result === 'clicked') {
342
+ // Close button handled it -- just wait for animation, no Escape needed
343
+ await page.waitForTimeout(300);
344
+ }
345
+ else if (result === 'found') {
346
+ // Overlay detected but no close button -- try Escape as fallback
347
+ await page.waitForTimeout(300);
348
+ await page.keyboard.press('Escape');
349
+ await page.waitForTimeout(200);
350
+ }
351
+ // result === false: no overlay, no action needed
352
+ return result;
353
+ }
354
+ //# sourceMappingURL=snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snapshot.js","sourceRoot":"","sources":["../../src/drivers/snapshot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Driver interface - abstraction over browser automation
3
+ */
4
+ import type { Action, PageState } from '../types.js';
5
+ export interface ActionResult {
6
+ success: boolean;
7
+ error?: string;
8
+ /** Data returned by the action (e.g., runScript result) */
9
+ data?: string;
10
+ }
11
+ export interface ResourceBlockingOptions {
12
+ /** Block image loading (png, jpg, gif, svg, webp, ico, etc.) */
13
+ blockImages?: boolean;
14
+ /** Block media loading (video, audio) */
15
+ blockMedia?: boolean;
16
+ /** Block analytics/tracking scripts */
17
+ blockAnalytics?: boolean;
18
+ /** Custom URL patterns to block (matched via url.includes()) */
19
+ blockPatterns?: string[];
20
+ }
21
+ export interface Driver {
22
+ /** Get current page state (DOM snapshot, optionally screenshot) */
23
+ observe(): Promise<PageState>;
24
+ /** Execute an action */
25
+ execute(action: Action): Promise<ActionResult>;
26
+ /** Get the underlying Playwright page (if available) */
27
+ getPage?(): import('playwright').Page | undefined;
28
+ /** Take a screenshot on demand */
29
+ screenshot?(): Promise<Buffer>;
30
+ /** Best-effort href inspection for a selector before executing a click */
31
+ inspectSelectorHref?(selector: string): Promise<string | undefined>;
32
+ /** Optional run-time diagnostics for startup and browser/session setup */
33
+ getDiagnostics?(): Record<string, unknown>;
34
+ /** Close/cleanup the driver */
35
+ close?(): Promise<void>;
36
+ }
37
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/drivers/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,gEAAgE;IAChE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,yCAAyC;IACzC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,uCAAuC;IACvC,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,MAAM;IACrB,mEAAmE;IACnE,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC,CAAC;IAE9B,wBAAwB;IACxB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAE/C,wDAAwD;IACxD,OAAO,CAAC,IAAI,OAAO,YAAY,EAAE,IAAI,GAAG,SAAS,CAAC;IAElD,kCAAkC;IAClC,UAAU,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAE/B,0EAA0E;IAC1E,mBAAmB,CAAC,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAEpE,0EAA0E;IAC1E,cAAc,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAE3C,+BAA+B;IAC/B,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Driver interface - abstraction over browser automation
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/drivers/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,2 @@
1
+ export declare function loadLocalEnvFiles(startDir: string, files?: string[]): void;
2
+ //# sourceMappingURL=env-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-loader.d.ts","sourceRoot":"","sources":["../src/env-loader.ts"],"names":[],"mappings":"AAGA,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,WAAyB,GAAG,IAAI,CAWxF"}
@@ -0,0 +1,35 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ export function loadLocalEnvFiles(startDir, files = ['.env.local', '.env']) {
4
+ for (const file of files) {
5
+ const filePath = path.join(startDir, file);
6
+ if (!fs.existsSync(filePath))
7
+ continue;
8
+ const parsed = parseEnvFile(fs.readFileSync(filePath, 'utf-8'));
9
+ for (const [key, value] of Object.entries(parsed)) {
10
+ if (!(key in process.env)) {
11
+ process.env[key] = value;
12
+ }
13
+ }
14
+ }
15
+ }
16
+ function parseEnvFile(contents) {
17
+ const out = {};
18
+ for (const rawLine of contents.split(/\r?\n/)) {
19
+ const line = rawLine.trim();
20
+ if (!line || line.startsWith('#'))
21
+ continue;
22
+ const match = line.match(/^([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/);
23
+ if (!match)
24
+ continue;
25
+ const key = match[1];
26
+ let value = match[2] ?? '';
27
+ if ((value.startsWith('"') && value.endsWith('"')) ||
28
+ (value.startsWith("'") && value.endsWith("'"))) {
29
+ value = value.slice(1, -1);
30
+ }
31
+ out[key] = value;
32
+ }
33
+ return out;
34
+ }
35
+ //# sourceMappingURL=env-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-loader.js","sourceRoot":"","sources":["../src/env-loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,MAAM,UAAU,iBAAiB,CAAC,QAAgB,EAAE,KAAK,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC;IAChF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC3C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,SAAS;QACvC,MAAM,MAAM,GAAG,YAAY,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;QAChE,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAClD,IAAI,CAAC,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,QAAgB;IACpC,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,OAAO,IAAI,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAClE,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACrB,IAAI,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC3B,IACE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YAC9C,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAC9C,CAAC;YACD,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QACD,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACnB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Slack payload formatter for WebhookSink.
3
+ *
4
+ * Transforms WebhookPayload into Slack Block Kit format for incoming webhooks.
5
+ * Use with: new WebhookSink({ url: SLACK_WEBHOOK_URL, formatPayload: slackFormatter })
6
+ */
7
+ import type { WebhookPayload } from '../artifacts/webhook-sink.js';
8
+ interface SlackBlock {
9
+ type: string;
10
+ text?: {
11
+ type: string;
12
+ text: string;
13
+ emoji?: boolean;
14
+ };
15
+ elements?: Array<{
16
+ type: string;
17
+ text: string;
18
+ emoji?: boolean;
19
+ }>;
20
+ fields?: Array<{
21
+ type: string;
22
+ text: string;
23
+ }>;
24
+ }
25
+ interface SlackMessage {
26
+ text: string;
27
+ blocks?: SlackBlock[];
28
+ }
29
+ /**
30
+ * Format a WebhookPayload as a Slack Block Kit message.
31
+ *
32
+ * - `artifact` events: compact one-liner with test ID and artifact type
33
+ * - `suite:complete` events: rich summary with pass/fail counts and test list
34
+ */
35
+ export declare function slackFormatter(payload: WebhookPayload): SlackMessage;
36
+ export {};
37
+ //# sourceMappingURL=slack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.d.ts","sourceRoot":"","sources":["../../src/formatters/slack.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE,UAAU,UAAU;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACvD,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAClE,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD;AAED,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;CACvB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,YAAY,CAMpE"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Slack payload formatter for WebhookSink.
3
+ *
4
+ * Transforms WebhookPayload into Slack Block Kit format for incoming webhooks.
5
+ * Use with: new WebhookSink({ url: SLACK_WEBHOOK_URL, formatPayload: slackFormatter })
6
+ */
7
+ /**
8
+ * Format a WebhookPayload as a Slack Block Kit message.
9
+ *
10
+ * - `artifact` events: compact one-liner with test ID and artifact type
11
+ * - `suite:complete` events: rich summary with pass/fail counts and test list
12
+ */
13
+ export function slackFormatter(payload) {
14
+ if (payload.event === 'suite:complete') {
15
+ return formatSuiteComplete(payload);
16
+ }
17
+ return formatArtifact(payload);
18
+ }
19
+ function formatSuiteComplete(payload) {
20
+ const { manifest, summary } = payload;
21
+ const testIds = [...new Set(manifest.map((e) => e.testId).filter((id) => id !== 'suite'))];
22
+ const hasSummary = summary && summary.total > 0;
23
+ const passed = summary?.passed ?? 0;
24
+ const failed = summary?.failed ?? 0;
25
+ const total = summary?.total ?? testIds.length;
26
+ const allPassed = failed === 0 && passed > 0;
27
+ const icon = allPassed ? ':white_check_mark:' : ':x:';
28
+ const headline = allPassed
29
+ ? `${icon} All ${total} tests passed`
30
+ : `${icon} ${passed}/${total} passed, ${failed} failed`;
31
+ const blocks = [
32
+ {
33
+ type: 'header',
34
+ text: { type: 'plain_text', text: 'browser-agent-driver', emoji: true },
35
+ },
36
+ {
37
+ type: 'section',
38
+ text: { type: 'mrkdwn', text: headline },
39
+ },
40
+ ];
41
+ if (hasSummary) {
42
+ blocks.push({
43
+ type: 'section',
44
+ fields: [
45
+ { type: 'mrkdwn', text: `*Passed:* ${passed}` },
46
+ { type: 'mrkdwn', text: `*Failed:* ${failed}` },
47
+ { type: 'mrkdwn', text: `*Total:* ${total}` },
48
+ ],
49
+ });
50
+ }
51
+ // List test IDs
52
+ if (testIds.length > 0 && testIds.length <= 20) {
53
+ const testList = testIds.map((id) => `\`${id}\``).join(', ');
54
+ blocks.push({
55
+ type: 'section',
56
+ text: { type: 'mrkdwn', text: `*Tests:* ${testList}` },
57
+ });
58
+ }
59
+ // Artifacts count
60
+ const screenshotCount = manifest.filter((e) => e.type === 'screenshot').length;
61
+ const reportCount = manifest.filter((e) => e.type.startsWith('report-')).length;
62
+ if (screenshotCount > 0 || reportCount > 0) {
63
+ const parts = [];
64
+ if (reportCount > 0)
65
+ parts.push(`${reportCount} reports`);
66
+ if (screenshotCount > 0)
67
+ parts.push(`${screenshotCount} screenshots`);
68
+ blocks.push({
69
+ type: 'context',
70
+ elements: [{ type: 'mrkdwn', text: `Artifacts: ${parts.join(', ')}` }],
71
+ });
72
+ }
73
+ return {
74
+ text: headline.replace(/:[a-z_]+:/g, '').trim(), // fallback text without emoji
75
+ blocks,
76
+ };
77
+ }
78
+ function formatArtifact(payload) {
79
+ const text = `*${payload.type}* \`${payload.name}\` for test \`${payload.testId}\` (${formatBytes(payload.sizeBytes)})`;
80
+ return {
81
+ text: `${payload.type}: ${payload.name} for ${payload.testId}`,
82
+ blocks: [
83
+ {
84
+ type: 'section',
85
+ text: { type: 'mrkdwn', text },
86
+ },
87
+ ],
88
+ };
89
+ }
90
+ function formatBytes(bytes) {
91
+ if (bytes < 1024)
92
+ return `${bytes}B`;
93
+ if (bytes < 1024 * 1024)
94
+ return `${(bytes / 1024).toFixed(1)}KB`;
95
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
96
+ }
97
+ //# sourceMappingURL=slack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack.js","sourceRoot":"","sources":["../../src/formatters/slack.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAgBH;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,OAAuB;IACpD,IAAI,OAAO,CAAC,KAAK,KAAK,gBAAgB,EAAE,CAAC;QACvC,OAAO,mBAAmB,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,OAAO,cAAc,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,mBAAmB,CAAC,OAA6D;IACxF,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;IACtC,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IAE3F,MAAM,UAAU,GAAG,OAAO,IAAI,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC;IAChD,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,IAAI,CAAC,CAAC;IACpC,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,OAAO,CAAC,MAAM,CAAC;IAE/C,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,IAAI,MAAM,GAAG,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,KAAK,CAAC;IACtD,MAAM,QAAQ,GAAG,SAAS;QACxB,CAAC,CAAC,GAAG,IAAI,QAAQ,KAAK,eAAe;QACrC,CAAC,CAAC,GAAG,IAAI,IAAI,MAAM,IAAI,KAAK,YAAY,MAAM,SAAS,CAAC;IAE1D,MAAM,MAAM,GAAiB;QAC3B;YACE,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,sBAAsB,EAAE,KAAK,EAAE,IAAI,EAAE;SACxE;QACD;YACE,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE;SACzC;KACF,CAAC;IAEF,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,SAAS;YACf,MAAM,EAAE;gBACN,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,MAAM,EAAE,EAAE;gBAC/C,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,MAAM,EAAE,EAAE;gBAC/C,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,KAAK,EAAE,EAAE;aAC9C;SACF,CAAC,CAAC;IACL,CAAC;IAED,gBAAgB;IAChB,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7D,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,QAAQ,EAAE,EAAE;SACvD,CAAC,CAAC;IACL,CAAC;IAED,kBAAkB;IAClB,MAAM,eAAe,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,MAAM,CAAC;IAC/E,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;IAChF,IAAI,eAAe,GAAG,CAAC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QAC3C,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,IAAI,WAAW,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,WAAW,UAAU,CAAC,CAAC;QAC1D,IAAI,eAAe,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,eAAe,cAAc,CAAC,CAAC;QACtE,MAAM,CAAC,IAAI,CAAC;YACV,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;SACvE,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,8BAA8B;QAC/E,MAAM;KACP,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CAAC,OAAuD;IAC7E,MAAM,IAAI,GAAG,IAAI,OAAO,CAAC,IAAI,OAAO,OAAO,CAAC,IAAI,iBAAiB,OAAO,CAAC,MAAM,OAAO,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC;IACxH,OAAO;QACL,IAAI,EAAE,GAAG,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,IAAI,QAAQ,OAAO,CAAC,MAAM,EAAE;QAC9D,MAAM,EAAE;YACN;gBACE,IAAI,EAAE,SAAS;gBACf,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;aAC/B;SACF;KACF,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAAC,KAAa;IAChC,IAAI,KAAK,GAAG,IAAI;QAAE,OAAO,GAAG,KAAK,GAAG,CAAC;IACrC,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;IACjE,OAAO,GAAG,CAAC,KAAK,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACnD,CAAC"}