athena-browser-mcp 2.0.3 → 2.0.5

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 (63) hide show
  1. package/README.md +183 -84
  2. package/dist/src/browser/page-network-tracker.d.ts +88 -0
  3. package/dist/src/browser/page-network-tracker.d.ts.map +1 -0
  4. package/dist/src/browser/page-network-tracker.js +271 -0
  5. package/dist/src/browser/page-network-tracker.js.map +1 -0
  6. package/dist/src/browser/page-stabilization.d.ts +35 -0
  7. package/dist/src/browser/page-stabilization.d.ts.map +1 -0
  8. package/dist/src/browser/page-stabilization.js +42 -0
  9. package/dist/src/browser/page-stabilization.js.map +1 -0
  10. package/dist/src/browser/session-manager.d.ts +4 -0
  11. package/dist/src/browser/session-manager.d.ts.map +1 -1
  12. package/dist/src/browser/session-manager.js +34 -0
  13. package/dist/src/browser/session-manager.js.map +1 -1
  14. package/dist/src/index.js +7 -7
  15. package/dist/src/index.js.map +1 -1
  16. package/dist/src/observation/eid-linker.d.ts +84 -0
  17. package/dist/src/observation/eid-linker.d.ts.map +1 -0
  18. package/dist/src/observation/eid-linker.js +268 -0
  19. package/dist/src/observation/eid-linker.js.map +1 -0
  20. package/dist/src/observation/index.d.ts +12 -0
  21. package/dist/src/observation/index.d.ts.map +1 -0
  22. package/dist/src/observation/index.js +15 -0
  23. package/dist/src/observation/index.js.map +1 -0
  24. package/dist/src/observation/observation-accumulator.d.ts +58 -0
  25. package/dist/src/observation/observation-accumulator.d.ts.map +1 -0
  26. package/dist/src/observation/observation-accumulator.js +213 -0
  27. package/dist/src/observation/observation-accumulator.js.map +1 -0
  28. package/dist/src/observation/observation.types.d.ts +108 -0
  29. package/dist/src/observation/observation.types.d.ts.map +1 -0
  30. package/dist/src/observation/observation.types.js +44 -0
  31. package/dist/src/observation/observation.types.js.map +1 -0
  32. package/dist/src/observation/observer-script.d.ts +19 -0
  33. package/dist/src/observation/observer-script.d.ts.map +1 -0
  34. package/dist/src/observation/observer-script.js +519 -0
  35. package/dist/src/observation/observer-script.js.map +1 -0
  36. package/dist/src/snapshot/snapshot.types.d.ts +6 -0
  37. package/dist/src/snapshot/snapshot.types.d.ts.map +1 -1
  38. package/dist/src/snapshot/snapshot.types.js.map +1 -1
  39. package/dist/src/state/actionables-filter.js +1 -1
  40. package/dist/src/state/actionables-filter.js.map +1 -1
  41. package/dist/src/state/diff-engine.d.ts.map +1 -1
  42. package/dist/src/state/diff-engine.js +129 -1
  43. package/dist/src/state/diff-engine.js.map +1 -1
  44. package/dist/src/state/state-manager.d.ts.map +1 -1
  45. package/dist/src/state/state-manager.js +9 -0
  46. package/dist/src/state/state-manager.js.map +1 -1
  47. package/dist/src/state/state-renderer.d.ts +13 -0
  48. package/dist/src/state/state-renderer.d.ts.map +1 -1
  49. package/dist/src/state/state-renderer.js +172 -2
  50. package/dist/src/state/state-renderer.js.map +1 -1
  51. package/dist/src/state/types.d.ts +37 -0
  52. package/dist/src/state/types.d.ts.map +1 -1
  53. package/dist/src/tools/browser-tools.d.ts.map +1 -1
  54. package/dist/src/tools/browser-tools.js +15 -1
  55. package/dist/src/tools/browser-tools.js.map +1 -1
  56. package/dist/src/tools/execute-action.d.ts +22 -6
  57. package/dist/src/tools/execute-action.d.ts.map +1 -1
  58. package/dist/src/tools/execute-action.js +80 -21
  59. package/dist/src/tools/execute-action.js.map +1 -1
  60. package/dist/src/tools/tool-schemas.d.ts +68 -68
  61. package/dist/src/tools/tool-schemas.js +7 -7
  62. package/dist/src/tools/tool-schemas.js.map +1 -1
  63. package/package.json +10 -10
package/README.md CHANGED
@@ -4,13 +4,44 @@
4
4
  [![npm version](https://badge.fury.io/js/athena-browser-mcp.svg)](https://www.npmjs.com/package/athena-browser-mcp)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
6
 
7
- Minimal MCP server for AI browser automation - 11 simple tools.
7
+ MCP server for AI browser automation - 18 tools with semantic element targeting.
8
8
 
9
- ## Design Philosophy
9
+ ## Why Athena?
10
10
 
11
- 1. **Page state in system prompt** - Agent always knows current page state without querying
12
- 2. **Lightweight delta responses** - Tools return what changed, not full snapshots
13
- 3. **Simple verb-based naming** - `click`, `type`, `press` instead of `action_click`, `action_type`
11
+ LLM agents face two hard constraints: limited context windows and expensive tokens. Yet browser automation requires understanding complex, ever-changing page state. Traditional tools dump raw accessibility trees or screenshots, wasting precious context and creating needle-in-haystack problems where agents struggle to locate relevant elements.
12
+
13
+ Athena solves this with **semantic page snapshots** - compact, structured representations designed for LLM consumption:
14
+
15
+ - **Token-efficient** - Hierarchical layers and regions eliminate noise, fitting more page understanding into less context
16
+ - **High recall** - Structured XML with semantic element IDs lets agents find elements without scanning entire DOM trees
17
+ - **Intuitive querying** - `find_elements` with semantic filters (kind, label, region) so agents ask for what they need
18
+ - **Stable references** - Semantic `eid`s survive DOM mutations, eliminating stale element errors
19
+
20
+ The result: fewer tokens, faster task completion, and higher-quality outputs with fewer errors.
21
+
22
+ ## Benchmark
23
+
24
+ Comparison between Athena Browser MCP and Playwright MCP on real-world browser automation tasks. Tests run in Claude Code with Claude Opus 4.5.
25
+
26
+ | # | Task | Agent | Result | Tokens Used | Time Taken |
27
+ | --- | ------------------------------------------------------------------------------------- | -------------- | ---------- | ----------- | ---------- |
28
+ | 1 | Login → Create wishlist "Summer Escapes" → Add beach property (Airbnb) | **Athena** | ✅ Success | 92,870 | 2m 08s |
29
+ | | | **Playwright** | ✅ Success | 137,063 | 5m 23s |
30
+ | 2 | Bangkok Experiences → Food tour → Extract itinerary & pricing (Airbnb) | **Athena** | ✅ Success | 87,194 | 3m 27s |
31
+ | | | **Playwright** | ✅ Success | 94,942 | 3m 38s |
32
+ | 3 | Miami → Beachfront stays under $300 → Top 3 names + prices (Airbnb) | **Athena** | ✅ Success | 124,597 | 5m 38s |
33
+ | | | **Playwright** | ✅ Success | 122,077 | 4m 51s |
34
+ | 4 | Paris → "Play" section → Top 5 titles + descriptions (Airbnb) | **Athena** | ❌ Failed | 146,575 | 4m 15s |
35
+ | | | **Playwright** | ❌ Failed | 189,495 | 7m 37s |
36
+ | 5 | Navigate Apple → find iPhone → configure iPhone 17 → add 256GB Black → confirm in bag | **Athena** | ✅ Success | 65,629 | 3m 30s |
37
+ | | | **Playwright** | ✅ Success | 102,754 | 6m 59s |
38
+
39
+ **Total Results:**
40
+
41
+ - **Tokens**: Athena used **125,341 fewer tokens** (~19.4% more efficient)
42
+ - **Time**: Athena completed tasks **9m 30s faster** (~33.4% faster)
43
+
44
+ _Benchmark on a larger dataset coming soon._
14
45
 
15
46
  ## Architecture
16
47
 
@@ -18,15 +49,17 @@ Minimal MCP server for AI browser automation - 11 simple tools.
18
49
  ┌─────────────────────────────────────────────────────────────────┐
19
50
  │ AI Agent │
20
51
  │ ┌────────────────────────────────────────────────────────────┐ │
21
- │ │ System Prompt: Current page state (URL, forms, actions) │ │
52
+ │ │ System Prompt: XML state (layers, actionables, atoms) │ │
22
53
  │ └────────────────────────────────────────────────────────────┘ │
23
54
  └───────────────────────────┬─────────────────────────────────────┘
24
55
  │ MCP Protocol (stdio)
25
56
  ┌───────────────────────────▼─────────────────────────────────────┐
26
- │ SESSION: open, close
27
- NAVIGATION: goto
28
- OBSERVATION: snapshot, find
29
- INTERACTION: click, type, press, select, hover, scroll
57
+ │ SESSION: launch_browser, connect_browser, close_page,
58
+ close_session
59
+ NAVIGATION: navigate, go_back, go_forward, reload
60
+ OBSERVATION: capture_snapshot, find_elements, get_node_details
61
+ │ INTERACTION: click, type, press, select, hover, │
62
+ │ scroll_element_into_view, scroll_page │
30
63
  └───────────────────────────┬─────────────────────────────────────┘
31
64
  │ Playwright + CDP
32
65
  ┌───────────────────────────▼─────────────────────────────────────┐
@@ -38,111 +71,129 @@ Minimal MCP server for AI browser automation - 11 simple tools.
38
71
 
39
72
  ### Session
40
73
 
41
- | Tool | Purpose | Input |
42
- | ------- | --------------------- | ---------------------------- |
43
- | `open` | Start browser session | `{ headless?, connect_to? }` |
44
- | `close` | End browser session | `{ page_id? }` |
74
+ | Tool | Purpose | Input |
75
+ | ----------------- | ------------------------- | ------------------- |
76
+ | `launch_browser` | Launch new browser | `{ headless? }` |
77
+ | `connect_browser` | Connect to existing (CDP) | `{ endpoint_url? }` |
78
+ | `close_page` | Close specific page | `{ page_id }` |
79
+ | `close_session` | Close entire browser | `{}` |
45
80
 
46
81
  ### Navigation
47
82
 
48
- | Tool | Purpose | Input |
49
- | ------ | ----------------------- | ------------------------------------------------------------ |
50
- | `goto` | Navigate to URL | `{ url: "https://..." }` |
51
- | | Go back/forward/refresh | `{ back: true }` / `{ forward: true }` / `{ refresh: true }` |
83
+ | Tool | Purpose | Input |
84
+ | ------------ | --------------- | ------------------- |
85
+ | `navigate` | Go to URL | `{ url, page_id? }` |
86
+ | `go_back` | Browser back | `{ page_id? }` |
87
+ | `go_forward` | Browser forward | `{ page_id? }` |
88
+ | `reload` | Refresh page | `{ page_id? }` |
52
89
 
53
90
  ### Observation
54
91
 
55
- | Tool | Purpose | Input |
56
- | ---------- | ----------------------------- | --------------------------------------- |
57
- | `snapshot` | Capture fresh page state | `{ include_factpack?, include_nodes? }` |
58
- | `find` | Find elements by criteria | `{ kind?, label?, region? }` |
59
- | | Get details for specific node | `{ node_id }` |
92
+ | Tool | Purpose | Input |
93
+ | ------------------ | ------------------- | ----------------------------------------------------------------- |
94
+ | `capture_snapshot` | Capture page state | `{ page_id? }` |
95
+ | `find_elements` | Find by criteria | `{ kind?, label?, region?, limit?, include_readable?, page_id? }` |
96
+ | `get_node_details` | Get element details | `{ eid, page_id? }` |
60
97
 
61
98
  ### Interaction
62
99
 
63
- | Tool | Purpose | Input |
64
- | -------- | ---------------------- | ------------------------------------------ |
65
- | `click` | Click element | `{ node_id }` |
66
- | `type` | Type text into element | `{ text, node_id?, clear? }` |
67
- | `press` | Press keyboard key | `{ key }` (Enter, Tab, Escape, etc.) |
68
- | `select` | Choose dropdown option | `{ node_id, value }` |
69
- | `hover` | Hover over element | `{ node_id }` (reveal menus/tooltips) |
70
- | `scroll` | Scroll page or element | `{ node_id? }` or `{ direction, amount? }` |
100
+ | Tool | Purpose | Input |
101
+ | -------------------------- | ------------------ | ---------------------------------- |
102
+ | `click` | Click element | `{ eid, page_id? }` |
103
+ | `type` | Type text | `{ eid, text, clear?, page_id? }` |
104
+ | `press` | Press keyboard key | `{ key, modifiers?, page_id? }` |
105
+ | `select` | Select option | `{ eid, value, page_id? }` |
106
+ | `hover` | Hover element | `{ eid, page_id? }` |
107
+ | `scroll_element_into_view` | Scroll to element | `{ eid, page_id? }` |
108
+ | `scroll_page` | Scroll viewport | `{ direction, amount?, page_id? }` |
71
109
 
72
- ## Response Format
110
+ ## Element IDs (eid)
73
111
 
74
- Tools return lightweight deltas describing what changed:
112
+ Elements are identified by stable semantic IDs (`eid`) instead of transient DOM node IDs:
75
113
 
76
- ```json
77
- {
78
- "delta": {
79
- "action": "Clicked 'Sign In' button",
80
- "changes": [
81
- { "type": "navigation", "from": "/login", "to": "/dashboard" }
82
- ]
83
- },
84
- "page_state": { ... }
85
- }
114
+ ```xml
115
+ <match eid="a1b2c3d4e5f6" kind="button" label="Sign In" region="header" />
116
+ ```
117
+
118
+ EIDs are computed from:
119
+
120
+ - Role/kind (button, link, input)
121
+ - Accessible name (label text)
122
+ - Landmark path (region + group hierarchy)
123
+ - Position hint (screen zone, quadrant)
124
+
125
+ This means the same logical element keeps its `eid` across page updates.
126
+
127
+ ## Response Format
128
+
129
+ Tools return XML state responses with page understanding:
130
+
131
+ ```xml
132
+ <state page_id="abc123" url="https://example.com" title="Example">
133
+ <layer type="main" active="true">
134
+ <actionables count="12">
135
+ <el eid="a1b2c3" kind="button" label="Sign In" />
136
+ <el eid="d4e5f6" kind="link" label="Forgot password?" />
137
+ <el eid="g7h8i9" kind="input" label="Email" type="email" />
138
+ </actionables>
139
+ </layer>
140
+ <atoms>
141
+ <viewport w="1280" h="720" />
142
+ <scroll x="0" y="0" />
143
+ </atoms>
144
+ </state>
86
145
  ```
87
146
 
88
- ### Change Types
147
+ ### Layer Types
89
148
 
90
- | Type | Description |
91
- | ---------------- | ------------------------- |
92
- | `focused` | Element received focus |
93
- | `filled` | Input field value changed |
94
- | `selected` | Dropdown option selected |
95
- | `clicked` | Element was clicked |
96
- | `navigation` | URL changed |
97
- | `page_changed` | Page type changed |
98
- | `modal_opened` | Modal dialog appeared |
99
- | `modal_closed` | Modal dialog dismissed |
100
- | `form_submitted` | Form was submitted |
149
+ | Layer | Description |
150
+ | --------- | -------------------------- |
151
+ | `main` | Primary page content |
152
+ | `modal` | Dialog overlays |
153
+ | `drawer` | Slide-in panels |
154
+ | `popover` | Dropdowns, tooltips, menus |
101
155
 
102
156
  ## Usage Examples
103
157
 
104
158
  ### Login Flow
105
159
 
106
160
  ```
107
- 1. open { }
108
- System prompt updated with initial page state
161
+ 1. launch_browser { }
162
+ XML state with initial page
109
163
 
110
- 2. goto { url: "https://example.com/login" }
111
- Page changed: login form detected
112
- → System prompt updated with form fields
164
+ 2. navigate { url: "https://example.com/login" }
165
+ State shows login form elements
113
166
 
114
- 3. find { kind: "input", label: "email" }
115
- { matches: [{ node_id: "42", label: "Email" }] }
167
+ 3. find_elements { kind: "input", label: "email" }
168
+ <match eid="abc123" kind="input" label="Email" />
116
169
 
117
- 4. click { node_id: "42" }
118
- Focused: Email field
170
+ 4. click { eid: "abc123" }
171
+ Element focused
119
172
 
120
- 5. type { text: "user@example.com" }
121
- Filled: Email = "user@example.com"
173
+ 5. type { eid: "abc123", text: "user@example.com" }
174
+ Value filled
122
175
 
123
176
  6. press { key: "Tab" }
124
- Focused: Password field
177
+ Focus moved to password field
125
178
 
126
- 7. type { text: "password123" }
127
- Filled: Password = "••••••••••••"
179
+ 7. type { eid: "def456", text: "password123" }
180
+ → Password filled
128
181
 
129
182
  8. press { key: "Enter" }
130
- → Form submitted
131
- → Navigation: /login → /dashboard
183
+ → Form submitted, navigation to dashboard
132
184
  ```
133
185
 
134
- ### E-commerce Purchase
186
+ ### Cookie Consent (Multi-Frame)
135
187
 
136
188
  ```
137
- 1. goto { url: "https://shop.example.com/product/123" }
138
- System prompt: product page, Add to Cart [node:101], Size [node:103]
189
+ 1. navigate { url: "https://news-site.com" }
190
+ Modal layer detected (cookie consent iframe)
139
191
 
140
- 2. select { node_id: "103", value: "Large" }
141
- Selected: Size = "Large"
192
+ 2. find_elements { label: "Accept", kind: "button" }
193
+ <match eid="xyz789" kind="button" label="Accept All" />
142
194
 
143
- 3. click { node_id: "101" }
144
- Clicked: Add to Cart
145
- → Modal opened: "Added to cart"
195
+ 3. click { eid: "xyz789" }
196
+ Modal closed, main layer active
146
197
  ```
147
198
 
148
199
  ## Installation
@@ -166,18 +217,66 @@ Add to your Claude Desktop config:
166
217
  {
167
218
  "mcpServers": {
168
219
  "browser": {
169
- "command": "node",
170
- "args": ["/path/to/athena-browser-mcp/dist/src/index.js"]
220
+ "command": "npx",
221
+ "args": ["athena-browser-mcp@latest"]
171
222
  }
172
223
  }
173
224
  }
174
225
  ```
175
226
 
227
+ ### Claude Code
228
+
229
+ ```bash
230
+ claude mcp add athena-browser-mcp npx athena-browser-mcp@latest
231
+ ```
232
+
233
+ ### VS Code
234
+
235
+ ```bash
236
+ code --add-mcp '{"name":"athena-browser-mcp","command":"npx","args":["athena-browser-mcp@latest"]}'
237
+ ```
238
+
239
+ ### Cursor
240
+
241
+ Go to **Cursor Settings → MCP → Add new MCP Server**. Use command type with:
242
+
243
+ ```
244
+ npx athena-browser-mcp@latest
245
+ ```
246
+
247
+ ### Codex
248
+
249
+ ```bash
250
+ codex mcp add athena-browser-mcp npx athena-browser-mcp@latest
251
+ ```
252
+
253
+ ### Gemini CLI
254
+
255
+ ```bash
256
+ gemini mcp add -s user athena-browser-mcp -- npx athena-browser-mcp@latest
257
+ ```
258
+
259
+ ### Connect to Existing Browser
260
+
261
+ To connect to an existing Chromium browser with CDP enabled:
262
+
263
+ ```bash
264
+ # Start Chrome with remote debugging
265
+ google-chrome --remote-debugging-port=9222
266
+
267
+ # Or use environment variables
268
+ export CEF_BRIDGE_HOST=127.0.0.1
269
+ export CEF_BRIDGE_PORT=9222
270
+ ```
271
+
272
+ Then use `connect_browser` instead of `launch_browser`.
273
+
176
274
  ### Environment Variables
177
275
 
178
- | Variable | Description | Default |
179
- | -------------------- | ------------------------- | ------- |
180
- | `DEFAULT_TIMEOUT_MS` | Default operation timeout | `30000` |
276
+ | Variable | Description | Default |
277
+ | ----------------- | -------------------- | ----------- |
278
+ | `CEF_BRIDGE_HOST` | CDP host for connect | `127.0.0.1` |
279
+ | `CEF_BRIDGE_PORT` | CDP port for connect | `9223` |
181
280
 
182
281
  ## Development
183
282
 
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Page Network Tracker
3
+ *
4
+ * Tracks in-flight network requests for a page and provides a reliable
5
+ * "network quiet" wait mechanism. Unlike Playwright's waitForLoadState('networkidle'),
6
+ * this tracks requests triggered after page load (e.g., by user actions).
7
+ *
8
+ * Uses a generation counter to safely handle navigation - late events from
9
+ * previous documents are ignored.
10
+ */
11
+ import type { Page } from 'playwright';
12
+ /**
13
+ * Tracks network requests for a single page.
14
+ *
15
+ * Attach to a page via `attach()`, then use `waitForQuiet()` to wait for
16
+ * network activity to settle. Call `markNavigation()` when navigating to
17
+ * safely reset state without race conditions.
18
+ */
19
+ export declare class PageNetworkTracker {
20
+ private page;
21
+ private inflightCount;
22
+ private generation;
23
+ private currentGeneration;
24
+ private quietTimer;
25
+ private quietWindowMs;
26
+ private quietResolvers;
27
+ private onRequest;
28
+ private onRequestFinished;
29
+ private onRequestFailed;
30
+ /**
31
+ * Attach network event listeners to a page.
32
+ *
33
+ * Must be called before `waitForQuiet()` can be used.
34
+ * Safe to call multiple times - will detach previous listeners first.
35
+ */
36
+ attach(page: Page): void;
37
+ /**
38
+ * Detach all event listeners and cleanup timers.
39
+ *
40
+ * Call this when the page is closed or no longer needs tracking.
41
+ */
42
+ detach(): void;
43
+ /**
44
+ * Mark that a navigation occurred.
45
+ *
46
+ * This safely resets state by bumping the generation counter, so any
47
+ * late events from the previous document are ignored. Use this instead
48
+ * of directly resetting state to avoid race conditions.
49
+ */
50
+ markNavigation(): void;
51
+ /**
52
+ * Wait for network to become quiet (no inflight requests for quietWindowMs).
53
+ *
54
+ * @param timeoutMs - Maximum time to wait before returning false
55
+ * @param quietWindowMs - Time with 0 inflight requests to consider "idle"
56
+ * @returns true if network became quiet, false if timed out (never throws)
57
+ */
58
+ waitForQuiet(timeoutMs: number, quietWindowMs?: number): Promise<boolean>;
59
+ /**
60
+ * Get current inflight request count (for debugging/testing).
61
+ */
62
+ getInflightCount(): number;
63
+ /**
64
+ * Check if tracker is attached to a page.
65
+ */
66
+ isAttached(): boolean;
67
+ private cancelQuietTimer;
68
+ private checkQuiet;
69
+ private startQuietTimer;
70
+ }
71
+ /**
72
+ * Get or create a network tracker for a page.
73
+ *
74
+ * Note: This does NOT automatically attach the tracker.
75
+ * Call `tracker.attach(page)` after getting the tracker.
76
+ */
77
+ export declare function getOrCreateTracker(page: Page): PageNetworkTracker;
78
+ /**
79
+ * Remove and detach the tracker for a page.
80
+ *
81
+ * Call this when a page is closed to ensure proper cleanup.
82
+ */
83
+ export declare function removeTracker(page: Page): void;
84
+ /**
85
+ * Check if a page has a tracker attached.
86
+ */
87
+ export declare function hasTracker(page: Page): boolean;
88
+ //# sourceMappingURL=page-network-tracker.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-network-tracker.d.ts","sourceRoot":"","sources":["../../../src/browser/page-network-tracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAW,MAAM,YAAY,CAAC;AAKhD;;;;;;GAMG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,iBAAiB,CAAK;IAG9B,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,aAAa,CAAmC;IACxD,OAAO,CAAC,cAAc,CAAyE;IAG/F,OAAO,CAAC,SAAS,CAAyC;IAC1D,OAAO,CAAC,iBAAiB,CAAyC;IAClE,OAAO,CAAC,eAAe,CAAyC;IAEhE;;;;;OAKG;IACH,MAAM,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IA6CxB;;;;OAIG;IACH,MAAM,IAAI,IAAI;IA6Bd;;;;;;OAMG;IACH,cAAc,IAAI,IAAI;IAkDtB;;;;;;OAMG;IACG,YAAY,CAChB,SAAS,EAAE,MAAM,EACjB,aAAa,GAAE,MAAgC,GAC9C,OAAO,CAAC,OAAO,CAAC;IAuBnB;;OAEG;IACH,gBAAgB,IAAI,MAAM;IAI1B;;OAEG;IACH,UAAU,IAAI,OAAO;IAMrB,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,eAAe;CAexB;AAYD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,kBAAkB,CAOjE;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAM9C;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAE9C"}