expo-agent-bridge 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Fs02
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,234 @@
1
+ # expo-agent-bridge ๐ŸŒ‰
2
+
3
+ **Autonomous AI Agent Dev Bridge for Expo & React Native apps.**
4
+
5
+ Give AI coding agents (Antigravity, Cursor, Claude Code, Windsurf, Devin) complete visual feedback and device control over your live running mobile app โ€” **without USB cables, without custom tunnels, and fully compatible with WSL & Wi-Fi.**
6
+
7
+ ---
8
+
9
+ ## โœจ Features
10
+
11
+ - ๐Ÿ“ธ **Live Visual Feedback (`get_screenshot`)**: Real-time full-screen captures directly from physical devices or simulators.
12
+ - ๐Ÿชต **Real-Time Error Streaming (`get_logs`)**: Captures `console.error`, `console.warn`, and unhandled JS exceptions with full stack traces.
13
+ - ๐Ÿ” **Dual-Layer Reload (`reload`)**: Reloads the app via Metro broadcast and in-app `DevSettings.reload` (works even if JS thread is stuck).
14
+ - ๐Ÿงญ **Navigation Control (`navigate` & `get_route`)**: Navigate Expo Router screens and verify active route segments.
15
+ - ๐ŸŽฏ **Targeted Element Interaction (`tap`, `scroll`, `type_text`)**: Interacts with UI components via `testID` or hooks without fragile pixel-coordinate guessing.
16
+ - ๐Ÿ” **Element Discovery (`get_elements`)**: Lists all currently mounted interactive buttons and inputs on screen.
17
+ - ๐Ÿงน **Storage & State Reset (`reset_storage`, `get_state`)**: Clears AsyncStorage on the fly to test clean first-install experience.
18
+ - ๐Ÿชถ **Zero Production Footprint**: Evaluates to `null` and empty functions when `!__DEV__`.
19
+
20
+ ---
21
+
22
+ ## ๐Ÿš€ Quickstart
23
+
24
+ ### 1. Install in your Expo project
25
+
26
+ ```bash
27
+ # Using npm
28
+ npm install expo-agent-bridge react-native-view-shot
29
+
30
+ # Using yarn
31
+ yarn add expo-agent-bridge react-native-view-shot
32
+ ```
33
+
34
+ For a local sibling checkout of this repository, install the bridge explicitly
35
+ from that checkout:
36
+
37
+ ```bash
38
+ yarn add expo-agent-bridge@file:../expo-agent-bridge react-native-view-shot
39
+ ```
40
+
41
+ This local-file setup is for development only. Do not leave a `file:../โ€ฆ`
42
+ bridge dependency in an EAS or other remote production build: the sibling
43
+ checkout is not part of the build upload. Use a published package there, or
44
+ remove the bridge from the release dependency graph and resolve it only in
45
+ local development.
46
+
47
+ ### 2. Initialize Agent Config & Skills
48
+
49
+ Run in your project root:
50
+
51
+ ```bash
52
+ npx expo-agent-bridge init
53
+ ```
54
+
55
+ The default Antigravity profile generates:
56
+ - `.agents/mcp_config.json` (MCP server configuration)
57
+ - `.agents/skills/expo-agent-bridge/SKILL.md` (MCP-first instructions with CLI fallback)
58
+
59
+ Choose another supported agent profile when needed:
60
+
61
+ ```bash
62
+ npx expo-agent-bridge init --agent claude-code
63
+ npx expo-agent-bridge init --agent cursor
64
+ npx expo-agent-bridge init --agent windsurf
65
+ ```
66
+
67
+ If multiple Expo/Metro servers are running, assign each project its own port
68
+ and pass it during initialization:
69
+
70
+ ```bash
71
+ npx expo-agent-bridge init --metro-port 8082
72
+ ```
73
+
74
+ Start that app on the same port, for example `npx expo start --port 8082`.
75
+
76
+ For direct CLI commands, pass the same port with `--metro-port <port>` (or `--port <port>`). The option may appear anywhere after the command:
77
+
78
+ ```bash
79
+ npx expo-agent-bridge screenshot /tmp/screen.png --metro-port 8082
80
+ npx expo-agent-bridge navigate /settings --metro-port=8082
81
+ ```
82
+
83
+ The generated MCP configuration pins the bridge to that projectโ€™s port.
84
+
85
+ Each profile writes its MCP configuration and skill to that agent's project directory.
86
+ For an unsupported or custom agent, specify the skill location directly:
87
+
88
+ ```bash
89
+ npx expo-agent-bridge init \
90
+ --skills-dir .my-agent/skills
91
+ ```
92
+
93
+ Existing bridge skills are left untouched; pass `--force` to replace one.
94
+
95
+ MCP is enabled by default, but the generated skill falls back to the direct CLI
96
+ when an MCP call is unavailable or cannot reach the running app. To configure a
97
+ CLI-only project, use `npx expo-agent-bridge init --no-mcp`.
98
+
99
+ ### 3. Mount in your Root Layout
100
+
101
+ In your root layout (e.g. `app/_layout.tsx` or `App.tsx`), load the component
102
+ only in development:
103
+
104
+ ```tsx
105
+ import React from 'react';
106
+
107
+ // Keeps the bridge component out of the production module graph.
108
+ const DevAgentBridge = __DEV__
109
+ ? (require('expo-agent-bridge').AgentBridge as React.ComponentType)
110
+ : null;
111
+
112
+ export default function RootLayout() {
113
+ return (
114
+ <>
115
+ {__DEV__ && DevAgentBridge ? <DevAgentBridge /> : null}
116
+ {/* Rest of your app */}
117
+ </>
118
+ );
119
+ }
120
+ ```
121
+
122
+ The package still has to be resolvable when Metro builds a development bundle.
123
+ For remote release builds, either use a published package or configure Metro
124
+ to map `expo-agent-bridge` to a local no-op module, as the app's release setup
125
+ requires.
126
+
127
+ ### 4. Run Expo
128
+
129
+ ```bash
130
+ npx expo start
131
+ # Or on WSL:
132
+ npx expo start --tunnel
133
+ ```
134
+
135
+ Scan the QR code with your iPhone/Android device. Your AI agent can now immediately inspect and control the app!
136
+
137
+ ---
138
+
139
+ ## ๐Ÿ› ๏ธ Bridge Commands
140
+
141
+ | Command | Description |
142
+ |---|---|
143
+ | `screenshot [file]` | Captures current mobile screen as PNG |
144
+ | `logs` | Streams recent errors, warnings, and exceptions |
145
+ | `reload` | Reloads the app bundle on device |
146
+ | `route` | Returns the active route |
147
+ | `elements` | Lists mounted interactive elements |
148
+ | `state` | Inspects exposed custom state |
149
+ | `reset-storage` | Clears AsyncStorage |
150
+ | `dev-menu` | Opens the developer menu |
151
+ | `navigate <route>` | Navigates to an Expo Router route |
152
+ | `tap <testID>` | Taps an element by test ID |
153
+ | `scroll <up\|down> [amount]` | Scrolls the active view |
154
+ | `type-text <testID> <text>` | Types text into a TextInput |
155
+
156
+ ## ๐Ÿ–ฅ๏ธ Direct CLI Commands
157
+
158
+ The bridge can also be used directly from a shell without creating a temporary
159
+ JavaScript client:
160
+
161
+ ```bash
162
+ npx expo-agent-bridge screenshot /tmp/screen.png
163
+ npx expo-agent-bridge logs
164
+ npx expo-agent-bridge route
165
+ npx expo-agent-bridge navigate /settings
166
+ npx expo-agent-bridge tap settings-button
167
+ npx expo-agent-bridge scroll down 300
168
+ npx expo-agent-bridge type-text search-input "Mecca"
169
+ ```
170
+
171
+ These commands are the supported fallback for the MCP tools. They use the same
172
+ live app connection and do not require temporary JavaScript files.
173
+
174
+ ---
175
+
176
+ ## ๐Ÿงฉ Element Registration
177
+
178
+ Components with `testID` can be registered declaratively:
179
+
180
+ ```tsx
181
+ import { useAgentElement } from 'expo-agent-bridge';
182
+
183
+ function CustomButton({ onPress, title }) {
184
+ useAgentElement('my-btn', { onPress, title, type: 'button' });
185
+
186
+ return (
187
+ <TouchableOpacity testID="my-btn" onPress={onPress}>
188
+ <Text>{title}</Text>
189
+ </TouchableOpacity>
190
+ );
191
+ }
192
+ ```
193
+
194
+ Or imperatively:
195
+
196
+ ```tsx
197
+ import { registerElement, unregisterElement } from 'expo-agent-bridge';
198
+
199
+ registerElement('submit-btn', { onPress: handleSubmit, title: 'Submit' });
200
+ ```
201
+
202
+ ---
203
+
204
+ ## ๐Ÿ—๏ธ Architecture
205
+
206
+ ```
207
+ AI Coding Agent (Antigravity / Cursor / Claude)
208
+ โ”‚
209
+ โ”‚ MCP stdio protocol
210
+ โ–ผ
211
+ npx --no-install expo-agent-bridge mcp
212
+ โ”‚
213
+ โ”‚ WebSocket (ws://localhost:8081/expo-dev-plugins/broadcast)
214
+ โ–ผ
215
+ Metro Dev Server (Standard Expo Bundler)
216
+ โ”‚
217
+ โ”‚ Existing DevTools Plugin channel (ws:// or wss:// via tunnel)
218
+ โ–ผ
219
+ <AgentBridge /> (in running mobile app)
220
+ โ”‚
221
+ โ”œโ”€ react-native-view-shot (native screenshot capture)
222
+ โ”œโ”€ ErrorUtils & console hook (live error streaming)
223
+ โ””โ”€ Element Registry (tap, scroll, type dispatch)
224
+ ```
225
+
226
+ - **No second tunnel**: Piggybacks on Metro's existing WebSocket broadcast channel.
227
+ - **No ATS overrides**: Tunnel mode uses `wss://` (secure TLS) automatically.
228
+ - **Works in WSL**: Connects over the single existing Expo tunnel.
229
+
230
+ ---
231
+
232
+ ## ๐Ÿ“„ License
233
+
234
+ MIT ยฉ Fs02
package/bin/cli.js ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ const { runCli } = require('../dist/cli.js');
3
+
4
+ try {
5
+ runCli(process.argv.slice(2));
6
+ } catch (error) {
7
+ process.stderr.write(`[expo-agent-bridge] ${error.message}\n`);
8
+ process.exitCode = 1;
9
+ }
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ export declare const PLUGIN_NAME = "expo-agent-bridge";
3
+ export type ElementHandler = {
4
+ ref?: React.RefObject<any>;
5
+ onPress?: () => void;
6
+ onChangeText?: (text: string) => void;
7
+ type?: string;
8
+ title?: string;
9
+ };
10
+ export type LogEntry = {
11
+ level: 'error' | 'warn' | 'log';
12
+ message: string;
13
+ stack?: string;
14
+ timestamp: number;
15
+ };
16
+ export declare const logBuffer: LogEntry[];
17
+ export declare const elementRegistry: Map<string, ElementHandler>;
18
+ export declare function registerElement(testID: string, handler: ElementHandler | React.RefObject<any>): void;
19
+ export declare function unregisterElement(testID: string): void;
20
+ /**
21
+ * Hook to declaratively register any interactive component with the agent bridge.
22
+ * Example:
23
+ * useAgentElement('my-button', { onPress, title: 'Submit' });
24
+ */
25
+ export declare function useAgentElement(testID: string, handler: ElementHandler): void;
26
+ export interface AgentBridgeProps {
27
+ pluginName?: string;
28
+ }
29
+ export declare function AgentBridge({ pluginName }: AgentBridgeProps): React.JSX.Element | null;
30
+ export default AgentBridge;
31
+ //# sourceMappingURL=DevAgentBridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DevAgentBridge.d.ts","sourceRoot":"","sources":["../src/DevAgentBridge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAGjD,eAAO,MAAM,WAAW,sBAAsB,CAAC;AAE/C,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAGF,eAAO,MAAM,SAAS,EAAE,QAAQ,EAAO,CAAC;AACxC,eAAO,MAAM,eAAe,6BAAoC,CAAC;AAEjE,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,QAkB7F;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,QAG/C;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,QAMtE;AAyOD,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,EAAE,UAAwB,EAAE,EAAE,gBAAgB,4BAOzE;AAmDD,eAAe,WAAW,CAAC"}
@@ -0,0 +1,355 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.elementRegistry = exports.logBuffer = exports.PLUGIN_NAME = void 0;
37
+ exports.registerElement = registerElement;
38
+ exports.unregisterElement = unregisterElement;
39
+ exports.useAgentElement = useAgentElement;
40
+ exports.AgentBridge = AgentBridge;
41
+ const react_1 = __importStar(require("react"));
42
+ const react_native_1 = require("react-native");
43
+ exports.PLUGIN_NAME = 'expo-agent-bridge';
44
+ const MAX_LOGS = 100;
45
+ exports.logBuffer = [];
46
+ exports.elementRegistry = new Map();
47
+ function registerElement(testID, handler) {
48
+ if (typeof __DEV__ !== 'undefined' && !__DEV__)
49
+ return;
50
+ if (handler && 'current' in handler) {
51
+ exports.elementRegistry.set(testID, { ref: handler });
52
+ }
53
+ else {
54
+ const originalOnPress = handler.onPress;
55
+ const wrappedHandler = {
56
+ ...handler,
57
+ onPress: originalOnPress
58
+ ? () => {
59
+ const label = handler.title ? `"${handler.title}" (${testID})` : `"${testID}"`;
60
+ recordLog('log', `[Interaction] Pressed ${label}`);
61
+ return originalOnPress();
62
+ }
63
+ : undefined,
64
+ };
65
+ exports.elementRegistry.set(testID, wrappedHandler);
66
+ }
67
+ }
68
+ function unregisterElement(testID) {
69
+ if (typeof __DEV__ !== 'undefined' && !__DEV__)
70
+ return;
71
+ exports.elementRegistry.delete(testID);
72
+ }
73
+ /**
74
+ * Hook to declaratively register any interactive component with the agent bridge.
75
+ * Example:
76
+ * useAgentElement('my-button', { onPress, title: 'Submit' });
77
+ */
78
+ function useAgentElement(testID, handler) {
79
+ (0, react_1.useEffect)(() => {
80
+ if (typeof __DEV__ !== 'undefined' && !__DEV__)
81
+ return;
82
+ registerElement(testID, handler);
83
+ return () => unregisterElement(testID);
84
+ }, [testID, handler.onPress, handler.onChangeText, handler.title]);
85
+ }
86
+ // โ”€โ”€โ”€ Route Tracking โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
87
+ let currentRouteState = {
88
+ pathname: '/',
89
+ segments: [],
90
+ };
91
+ // โ”€โ”€โ”€ Log & Error Monitoring โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
92
+ let isLogging = false;
93
+ let activeClient = null;
94
+ function recordLog(level, message, stack) {
95
+ if (isLogging)
96
+ return;
97
+ isLogging = true;
98
+ try {
99
+ const entry = {
100
+ level,
101
+ message,
102
+ stack,
103
+ timestamp: Date.now(),
104
+ };
105
+ exports.logBuffer.push(entry);
106
+ if (exports.logBuffer.length > MAX_LOGS)
107
+ exports.logBuffer.shift();
108
+ if (activeClient && activeClient.isConnected?.()) {
109
+ activeClient.sendMessage('log', entry);
110
+ }
111
+ }
112
+ catch {
113
+ // Ignore logging errors
114
+ }
115
+ finally {
116
+ isLogging = false;
117
+ }
118
+ }
119
+ function formatArgs(args) {
120
+ return args
121
+ .map((arg) => {
122
+ if (typeof arg === 'string')
123
+ return arg;
124
+ if (arg instanceof Error)
125
+ return `${arg.name}: ${arg.message}${arg.stack ? `\n${arg.stack}` : ''}`;
126
+ try {
127
+ return JSON.stringify(arg);
128
+ }
129
+ catch {
130
+ return String(arg);
131
+ }
132
+ })
133
+ .join(' ');
134
+ }
135
+ // Hook console and ErrorUtils once in DEV mode
136
+ if (typeof __DEV__ !== 'undefined' && __DEV__ && !global.__expoAgentBridgeLogsHooked) {
137
+ global.__expoAgentBridgeLogsHooked = true;
138
+ const originalError = console.error;
139
+ const originalWarn = console.warn;
140
+ const originalLog = console.log;
141
+ console.error = (...args) => {
142
+ const msg = formatArgs(args);
143
+ if (!msg.startsWith('[AgentBridge]') && !msg.startsWith('[DevAgentBridge]')) {
144
+ const errorObj = args.find((a) => a instanceof Error);
145
+ recordLog('error', msg, errorObj?.stack);
146
+ }
147
+ originalError(...args);
148
+ };
149
+ console.warn = (...args) => {
150
+ const msg = formatArgs(args);
151
+ if (!msg.startsWith('[AgentBridge]') && !msg.startsWith('[DevAgentBridge]')) {
152
+ recordLog('warn', msg);
153
+ }
154
+ originalWarn(...args);
155
+ };
156
+ console.log = (...args) => {
157
+ const msg = formatArgs(args);
158
+ recordLog('log', msg);
159
+ originalLog(...args);
160
+ };
161
+ const ErrorUtils = global.ErrorUtils;
162
+ if (ErrorUtils && typeof ErrorUtils.getGlobalHandler === 'function') {
163
+ const defaultHandler = ErrorUtils.getGlobalHandler();
164
+ ErrorUtils.setGlobalHandler((error, isFatal) => {
165
+ const message = error?.message ? `${error.name || 'Error'}: ${error.message}` : String(error);
166
+ recordLog('error', `[Unhandled ${isFatal ? 'Fatal ' : ''}Exception] ${message}`, error?.stack);
167
+ defaultHandler?.(error, isFatal);
168
+ });
169
+ }
170
+ }
171
+ // โ”€โ”€โ”€ Command dispatch โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
172
+ async function handleCommand(cmd) {
173
+ const { id, action } = cmd;
174
+ switch (action) {
175
+ case 'screenshot': {
176
+ console.log('[expo-agent-bridge] โ† screenshot');
177
+ recordLog('log', '[Bridge] Screenshot captured');
178
+ const { captureScreen } = require('react-native-view-shot');
179
+ const base64 = await captureScreen({ format: 'png', result: 'base64' });
180
+ return { id, data: base64 };
181
+ }
182
+ case 'navigate': {
183
+ console.log(`[expo-agent-bridge] โ† navigate ${cmd.route}`);
184
+ recordLog('log', `[Bridge] Navigate to ${cmd.route}`);
185
+ try {
186
+ const { router } = require('expo-router');
187
+ router.push(cmd.route);
188
+ return { id, success: true };
189
+ }
190
+ catch (e) {
191
+ recordLog('error', `[Bridge] Navigate error: ${e?.message}`);
192
+ return { id, error: 'Expo Router not available: ' + e?.message };
193
+ }
194
+ }
195
+ case 'get_route': {
196
+ return { id, route: currentRouteState };
197
+ }
198
+ case 'get_elements': {
199
+ const elements = Array.from(exports.elementRegistry.entries()).map(([testID, handler]) => ({
200
+ testID,
201
+ type: handler.type || (handler.onPress ? 'button' : handler.onChangeText ? 'input' : 'element'),
202
+ title: handler.title,
203
+ }));
204
+ return { id, elements };
205
+ }
206
+ case 'get_state': {
207
+ try {
208
+ // Look for common stores or custom global state
209
+ const stateObj = {};
210
+ if (global.__AGENT_CUSTOM_STATE__) {
211
+ stateObj.custom = global.__AGENT_CUSTOM_STATE__();
212
+ }
213
+ return { id, state: stateObj };
214
+ }
215
+ catch (err) {
216
+ return { id, error: err.message };
217
+ }
218
+ }
219
+ case 'reset_storage': {
220
+ try {
221
+ const AsyncStorage = require('@react-native-async-storage/async-storage').default;
222
+ await AsyncStorage.clear();
223
+ recordLog('log', '[Bridge] Storage reset cleared');
224
+ return { id, success: true };
225
+ }
226
+ catch (err) {
227
+ return { id, error: err.message };
228
+ }
229
+ }
230
+ case 'open_dev_menu': {
231
+ try {
232
+ if (react_native_1.NativeModules.DevMenu?.show) {
233
+ react_native_1.NativeModules.DevMenu.show();
234
+ }
235
+ }
236
+ catch { }
237
+ return { id, success: true };
238
+ }
239
+ case 'tap': {
240
+ console.log(`[expo-agent-bridge] โ† tap "${cmd.target}"`);
241
+ const handler = exports.elementRegistry.get(cmd.target);
242
+ if (handler?.onPress) {
243
+ recordLog('log', `[Bridge] Tap "${cmd.target}" (${handler.title || 'button'})`);
244
+ handler.onPress();
245
+ return { id, success: true };
246
+ }
247
+ const node = handler?.ref?.current;
248
+ if (typeof node?.props?.onPress === 'function') {
249
+ recordLog('log', `[Bridge] Tap "${cmd.target}" via ref`);
250
+ node.props.onPress();
251
+ return { id, success: true };
252
+ }
253
+ recordLog('warn', `[Bridge] Tap "${cmd.target}" failed: not found in element registry`);
254
+ return { id, success: false };
255
+ }
256
+ case 'scroll': {
257
+ console.log(`[expo-agent-bridge] โ† scroll ${cmd.direction}`);
258
+ recordLog('log', `[Bridge] Scroll ${cmd.direction}`);
259
+ for (const [, handler] of exports.elementRegistry) {
260
+ const node = handler?.ref?.current;
261
+ if (node && 'scrollToEnd' in node) {
262
+ const sv = node;
263
+ if (cmd.direction === 'down')
264
+ sv.scrollToEnd({ animated: true });
265
+ else
266
+ sv.scrollTo({ y: 0, animated: true });
267
+ return { id, success: true };
268
+ }
269
+ }
270
+ return { id, success: false };
271
+ }
272
+ case 'type': {
273
+ console.log(`[expo-agent-bridge] โ† type "${cmd.target}": "${cmd.text}"`);
274
+ recordLog('log', `[Bridge] Type into "${cmd.target}": "${cmd.text}"`);
275
+ const handler = exports.elementRegistry.get(cmd.target);
276
+ if (handler?.onChangeText) {
277
+ handler.onChangeText(cmd.text);
278
+ return { id, success: true };
279
+ }
280
+ const node = handler?.ref?.current;
281
+ if (typeof node?.props?.onChangeText === 'function') {
282
+ node.props.onChangeText(cmd.text);
283
+ return { id, success: true };
284
+ }
285
+ return { id, success: false };
286
+ }
287
+ case 'get_logs': {
288
+ return { id, logs: exports.logBuffer };
289
+ }
290
+ case 'reload': {
291
+ console.log('[expo-agent-bridge] โ† reload');
292
+ recordLog('log', '[Bridge] App reload requested');
293
+ if (typeof react_native_1.DevSettings?.reload === 'function') {
294
+ react_native_1.DevSettings.reload('Agent requested reload');
295
+ }
296
+ return { id, success: true };
297
+ }
298
+ default:
299
+ throw new Error(`Unknown action: ${action}`);
300
+ }
301
+ }
302
+ function AgentBridge({ pluginName = exports.PLUGIN_NAME }) {
303
+ // If production, render nothing and initialize nothing
304
+ if (typeof __DEV__ !== 'undefined' && !__DEV__) {
305
+ return null;
306
+ }
307
+ return <DevAgentBridgeImpl pluginName={pluginName}/>;
308
+ }
309
+ function DevAgentBridgeImpl({ pluginName }) {
310
+ let client = null;
311
+ try {
312
+ const { useDevToolsPluginClient } = require('@expo/devtools');
313
+ client = useDevToolsPluginClient(pluginName);
314
+ }
315
+ catch (e) {
316
+ console.warn('[AgentBridge] @expo/devtools not available in this environment');
317
+ }
318
+ const subRef = (0, react_1.useRef)(null);
319
+ // Attempt to hook Expo Router if present
320
+ try {
321
+ const { usePathname, useSegments } = require('expo-router');
322
+ const pathname = usePathname();
323
+ const segments = useSegments();
324
+ (0, react_1.useEffect)(() => {
325
+ currentRouteState = { pathname, segments };
326
+ }, [pathname, segments]);
327
+ }
328
+ catch {
329
+ // Non-Expo-Router app fallback
330
+ }
331
+ (0, react_1.useEffect)(() => {
332
+ if (!client)
333
+ return;
334
+ activeClient = client;
335
+ console.log(`[AgentBridge] Connected via DevTools Plugin (${pluginName}) โœ“`);
336
+ recordLog('log', `AgentBridge initialized and connected (${pluginName})`);
337
+ subRef.current = client.addMessageListener('command', async (cmd) => {
338
+ let result;
339
+ try {
340
+ result = await handleCommand(cmd);
341
+ }
342
+ catch (err) {
343
+ result = { id: cmd.id, error: err?.message ?? String(err) };
344
+ }
345
+ client.sendMessage('result', result);
346
+ });
347
+ return () => {
348
+ activeClient = null;
349
+ subRef.current?.remove();
350
+ };
351
+ }, [client, pluginName]);
352
+ return null;
353
+ }
354
+ exports.default = AgentBridge;
355
+ //# sourceMappingURL=DevAgentBridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DevAgentBridge.js","sourceRoot":"","sources":["../src/DevAgentBridge.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,0CAkBC;AAED,8CAGC;AAOD,0CAMC;AA6OD,kCAOC;AAhTD,+CAAiD;AACjD,+CAAsE;AAEzD,QAAA,WAAW,GAAG,mBAAmB,CAAC;AAiB/C,MAAM,QAAQ,GAAG,GAAG,CAAC;AACR,QAAA,SAAS,GAAe,EAAE,CAAC;AAC3B,QAAA,eAAe,GAAG,IAAI,GAAG,EAA0B,CAAC;AAEjE,SAAgB,eAAe,CAAC,MAAc,EAAE,OAA8C;IAC5F,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,CAAC,OAAO;QAAE,OAAO;IACvD,IAAI,OAAO,IAAI,SAAS,IAAI,OAAO,EAAE,CAAC;QACpC,uBAAe,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;IAChD,CAAC;SAAM,CAAC;QACN,MAAM,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC;QACxC,MAAM,cAAc,GAAmB;YACrC,GAAG,OAAO;YACV,OAAO,EAAE,eAAe;gBACtB,CAAC,CAAC,GAAG,EAAE;oBACH,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,MAAM,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI,MAAM,GAAG,CAAC;oBAC/E,SAAS,CAAC,KAAK,EAAE,yBAAyB,KAAK,EAAE,CAAC,CAAC;oBACnD,OAAO,eAAe,EAAE,CAAC;gBAC3B,CAAC;gBACH,CAAC,CAAC,SAAS;SACd,CAAC;QACF,uBAAe,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC;AAED,SAAgB,iBAAiB,CAAC,MAAc;IAC9C,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,CAAC,OAAO;QAAE,OAAO;IACvD,uBAAe,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC;AAED;;;;GAIG;AACH,SAAgB,eAAe,CAAC,MAAc,EAAE,OAAuB;IACrE,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,CAAC,OAAO;YAAE,OAAO;QACvD,eAAe,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACjC,OAAO,GAAG,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACzC,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;AACrE,CAAC;AAED,iFAAiF;AAEjF,IAAI,iBAAiB,GAA6C;IAChE,QAAQ,EAAE,GAAG;IACb,QAAQ,EAAE,EAAE;CACb,CAAC;AAEF,iFAAiF;AAEjF,IAAI,SAAS,GAAG,KAAK,CAAC;AACtB,IAAI,YAAY,GAAQ,IAAI,CAAC;AAE7B,SAAS,SAAS,CAAC,KAA+B,EAAE,OAAe,EAAE,KAAc;IACjF,IAAI,SAAS;QAAE,OAAO;IACtB,SAAS,GAAG,IAAI,CAAC;IACjB,IAAI,CAAC;QACH,MAAM,KAAK,GAAa;YACtB,KAAK;YACL,OAAO;YACP,KAAK;YACL,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC;QACF,iBAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtB,IAAI,iBAAS,CAAC,MAAM,GAAG,QAAQ;YAAE,iBAAS,CAAC,KAAK,EAAE,CAAC;QAEnD,IAAI,YAAY,IAAI,YAAY,CAAC,WAAW,EAAE,EAAE,EAAE,CAAC;YACjD,YAAY,CAAC,WAAW,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,wBAAwB;IAC1B,CAAC;YAAS,CAAC;QACT,SAAS,GAAG,KAAK,CAAC;IACpB,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,IAAW;IAC7B,OAAO,IAAI;SACR,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACX,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,OAAO,GAAG,CAAC;QACxC,IAAI,GAAG,YAAY,KAAK;YAAE,OAAO,GAAG,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QACnG,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;IACH,CAAC,CAAC;SACD,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC;AAED,+CAA+C;AAC/C,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,IAAI,CAAE,MAAc,CAAC,2BAA2B,EAAE,CAAC;IAC7F,MAAc,CAAC,2BAA2B,GAAG,IAAI,CAAC;IAEnD,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,CAAC;IACpC,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAClC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC;IAEhC,OAAO,CAAC,KAAK,GAAG,CAAC,GAAG,IAAW,EAAE,EAAE;QACjC,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;YAC5E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC;YACtD,SAAS,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC3C,CAAC;QACD,aAAa,CAAC,GAAG,IAAI,CAAC,CAAC;IACzB,CAAC,CAAC;IAEF,OAAO,CAAC,IAAI,GAAG,CAAC,GAAG,IAAW,EAAE,EAAE;QAChC,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;YAC5E,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACzB,CAAC;QACD,YAAY,CAAC,GAAG,IAAI,CAAC,CAAC;IACxB,CAAC,CAAC;IAEF,OAAO,CAAC,GAAG,GAAG,CAAC,GAAG,IAAW,EAAE,EAAE;QAC/B,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;QAC7B,SAAS,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QACtB,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC;IACvB,CAAC,CAAC;IAEF,MAAM,UAAU,GAAI,MAAc,CAAC,UAAU,CAAC;IAC9C,IAAI,UAAU,IAAI,OAAO,UAAU,CAAC,gBAAgB,KAAK,UAAU,EAAE,CAAC;QACpE,MAAM,cAAc,GAAG,UAAU,CAAC,gBAAgB,EAAE,CAAC;QACrD,UAAU,CAAC,gBAAgB,CAAC,CAAC,KAAU,EAAE,OAAiB,EAAE,EAAE;YAC5D,MAAM,OAAO,GAAG,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,IAAI,OAAO,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC9F,SAAS,CAAC,OAAO,EAAE,cAAc,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,cAAc,OAAO,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;YAC/F,cAAc,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,iFAAiF;AAEjF,KAAK,UAAU,aAAa,CAAC,GAAwB;IACnD,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC;IAE3B,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;YAChD,SAAS,CAAC,KAAK,EAAE,8BAA8B,CAAC,CAAC;YACjD,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAC;YAC5D,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;YACxE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAC9B,CAAC;QAED,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,kCAAkC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;YAC3D,SAAS,CAAC,KAAK,EAAE,wBAAwB,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;YACtD,IAAI,CAAC;gBACH,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;gBAC1C,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBACvB,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC/B,CAAC;YAAC,OAAO,CAAM,EAAE,CAAC;gBAChB,SAAS,CAAC,OAAO,EAAE,4BAA4B,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC7D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,6BAA6B,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC;YACnE,CAAC;QACH,CAAC;QAED,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC;QAC1C,CAAC;QAED,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,uBAAe,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;gBACjF,MAAM;gBACN,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC/F,KAAK,EAAE,OAAO,CAAC,KAAK;aACrB,CAAC,CAAC,CAAC;YACJ,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC;QAC1B,CAAC;QAED,KAAK,WAAW,CAAC,CAAC,CAAC;YACjB,IAAI,CAAC;gBACH,gDAAgD;gBAChD,MAAM,QAAQ,GAAwB,EAAE,CAAC;gBACzC,IAAK,MAAc,CAAC,sBAAsB,EAAE,CAAC;oBAC3C,QAAQ,CAAC,MAAM,GAAI,MAAc,CAAC,sBAAsB,EAAE,CAAC;gBAC7D,CAAC;gBACD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;YACjC,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;YACpC,CAAC;QACH,CAAC;QAED,KAAK,eAAe,CAAC,CAAC,CAAC;YACrB,IAAI,CAAC;gBACH,MAAM,YAAY,GAAG,OAAO,CAAC,2CAA2C,CAAC,CAAC,OAAO,CAAC;gBAClF,MAAM,YAAY,CAAC,KAAK,EAAE,CAAC;gBAC3B,SAAS,CAAC,KAAK,EAAE,gCAAgC,CAAC,CAAC;gBACnD,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC/B,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;YACpC,CAAC;QACH,CAAC;QAED,KAAK,eAAe,CAAC,CAAC,CAAC;YACrB,IAAI,CAAC;gBACH,IAAI,4BAAa,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;oBAChC,4BAAa,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;gBAC/B,CAAC;YACH,CAAC;YAAC,MAAM,CAAC,CAAA,CAAC;YACV,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC/B,CAAC;QAED,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,8BAA8B,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;YACzD,MAAM,OAAO,GAAG,uBAAe,CAAC,GAAG,CAAC,GAAG,CAAC,MAAgB,CAAC,CAAC;YAC1D,IAAI,OAAO,EAAE,OAAO,EAAE,CAAC;gBACrB,SAAS,CAAC,KAAK,EAAE,iBAAiB,GAAG,CAAC,MAAM,MAAM,OAAO,CAAC,KAAK,IAAI,QAAQ,GAAG,CAAC,CAAC;gBAChF,OAAO,CAAC,OAAO,EAAE,CAAC;gBAClB,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC/B,CAAC;YACD,MAAM,IAAI,GAAG,OAAO,EAAE,GAAG,EAAE,OAAc,CAAC;YAC1C,IAAI,OAAO,IAAI,EAAE,KAAK,EAAE,OAAO,KAAK,UAAU,EAAE,CAAC;gBAC/C,SAAS,CAAC,KAAK,EAAE,iBAAiB,GAAG,CAAC,MAAM,WAAW,CAAC,CAAC;gBACzD,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;gBACrB,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC/B,CAAC;YACD,SAAS,CAAC,MAAM,EAAE,iBAAiB,GAAG,CAAC,MAAM,yCAAyC,CAAC,CAAC;YACxF,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAChC,CAAC;QAED,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,gCAAgC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC;YAC7D,SAAS,CAAC,KAAK,EAAE,mBAAmB,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC;YACrD,KAAK,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,uBAAe,EAAE,CAAC;gBAC1C,MAAM,IAAI,GAAG,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC;gBACnC,IAAI,IAAI,IAAI,aAAa,IAAI,IAAI,EAAE,CAAC;oBAClC,MAAM,EAAE,GAAG,IAAkB,CAAC;oBAC9B,IAAI,GAAG,CAAC,SAAS,KAAK,MAAM;wBAAE,EAAE,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;;wBAC5D,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;oBAC3C,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;gBAC/B,CAAC;YACH,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAChC,CAAC;QAED,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,+BAA+B,GAAG,CAAC,MAAM,OAAO,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC;YACzE,SAAS,CAAC,KAAK,EAAE,uBAAuB,GAAG,CAAC,MAAM,OAAO,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC;YACtE,MAAM,OAAO,GAAG,uBAAe,CAAC,GAAG,CAAC,GAAG,CAAC,MAAgB,CAAC,CAAC;YAC1D,IAAI,OAAO,EAAE,YAAY,EAAE,CAAC;gBAC1B,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,IAAc,CAAC,CAAC;gBACzC,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC/B,CAAC;YACD,MAAM,IAAI,GAAG,OAAO,EAAE,GAAG,EAAE,OAAc,CAAC;YAC1C,IAAI,OAAO,IAAI,EAAE,KAAK,EAAE,YAAY,KAAK,UAAU,EAAE,CAAC;gBACpD,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,IAAc,CAAC,CAAC;gBAC5C,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC/B,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;QAChC,CAAC;QAED,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,iBAAS,EAAE,CAAC;QACjC,CAAC;QAED,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;YAC5C,SAAS,CAAC,KAAK,EAAE,+BAA+B,CAAC,CAAC;YAClD,IAAI,OAAO,0BAAW,EAAE,MAAM,KAAK,UAAU,EAAE,CAAC;gBAC9C,0BAAW,CAAC,MAAM,CAAC,wBAAwB,CAAC,CAAC;YAC/C,CAAC;YACD,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC/B,CAAC;QAED;YACE,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,EAAE,CAAC,CAAC;IACjD,CAAC;AACH,CAAC;AAMD,SAAgB,WAAW,CAAC,EAAE,UAAU,GAAG,mBAAW,EAAoB;IACxE,uDAAuD;IACvD,IAAI,OAAO,OAAO,KAAK,WAAW,IAAI,CAAC,OAAO,EAAE,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,EAAG,CAAC;AACxD,CAAC;AAED,SAAS,kBAAkB,CAAC,EAAE,UAAU,EAA0B;IAChE,IAAI,MAAM,GAAQ,IAAI,CAAC;IACvB,IAAI,CAAC;QACH,MAAM,EAAE,uBAAuB,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;QAC9D,MAAM,GAAG,uBAAuB,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CAAC,gEAAgE,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,MAAM,GAAG,IAAA,cAAM,EAAgC,IAAI,CAAC,CAAC;IAE3D,yCAAyC;IACzC,IAAI,CAAC;QACH,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;QAC5D,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAC;QAC/B,IAAA,iBAAS,EAAC,GAAG,EAAE;YACb,iBAAiB,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;QAC7C,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,+BAA+B;IACjC,CAAC;IAED,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,CAAC,MAAM;YAAE,OAAO;QAEpB,YAAY,GAAG,MAAM,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,gDAAgD,UAAU,KAAK,CAAC,CAAC;QAC7E,SAAS,CAAC,KAAK,EAAE,0CAA0C,UAAU,GAAG,CAAC,CAAC;QAE1E,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,kBAAkB,CAAC,SAAS,EAAE,KAAK,EAAE,GAAwB,EAAE,EAAE;YACvF,IAAI,MAA2B,CAAC;YAChC,IAAI,CAAC;gBACH,MAAM,GAAG,MAAM,aAAa,CAAC,GAAG,CAAC,CAAC;YACpC,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,MAAM,GAAG,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YAC9D,CAAC;YACD,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,OAAO,GAAG,EAAE;YACV,YAAY,GAAG,IAAI,CAAC;YACpB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QAC3B,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAEzB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,kBAAe,WAAW,CAAC"}