surf-cli 2.18.0 → 2.20.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.
@@ -1 +1 @@
1
- {"version":3,"mappings":"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","names":[],"ignoreList":[],"sources":["../../src/cdp/controller.ts","../../src/utils/debug.ts","../../src/native/port-manager.ts","../../src/service-worker/index.ts"],"sourcesContent":["type Debuggee = chrome.debugger.Debuggee;\ntype MouseButton = \"left\" | \"right\" | \"middle\" | \"none\";\n\nclass CDPControllerError extends Error {\n code: string;\n details?: Record<string, unknown>;\n\n constructor(code: string, message: string, details?: Record<string, unknown>) {\n super(message);\n this.name = \"CDPControllerError\";\n this.code = code;\n this.details = details;\n }\n}\n\ninterface ConsoleMessage {\n type: string;\n text: string;\n timestamp: number;\n url?: string;\n line?: number;\n}\n\ninterface NetworkRequest {\n requestId: string;\n url: string;\n method: string;\n status?: number;\n type?: string;\n timestamp: number;\n requestHeaders?: Record<string, string>;\n requestBody?: string;\n responseHeaders?: Record<string, string>;\n responseBody?: string;\n mimeType?: string;\n duration?: number;\n}\n\nexport interface NetworkEntry {\n id: string; // \"r_<timestamp>_<seq>\"\n ts: number; // Request start timestamp (ms)\n duration?: number; // Total time (ms)\n ttfb?: number; // Time to first byte (ms)\n \n // Request\n method: string;\n url: string;\n origin: string; // Extracted from URL\n requestHeaders: Record<string, string>;\n requestBody?: string; // POST/PUT body\n requestBodySize?: number;\n \n // Response \n status?: number;\n statusText?: string;\n mimeType?: string;\n responseHeaders?: Record<string, string>;\n responseBody?: string; // Will be fetched via getResponseBody\n responseBodyEncoding?: \"base64\";\n responseBodySize?: number;\n bodyCapture: { mode: \"none\" | \"text\" | \"all\"; complete: boolean; reason?: string; capturedBytes?: number };\n \n // Metadata\n tabId: number;\n tabUrl?: string; // Page URL that initiated request\n type?: string; // \"xhr\", \"fetch\", \"document\", etc.\n \n // Flags\n flags: string[]; // [\"binary\", \"truncated\", \"protobuf\", \"failed\"]\n \n // Internal tracking\n _requestId: string; // CDP requestId for lazy loading\n _responseReceived: boolean; // Whether response was received\n _loadingFinished: boolean; // Whether loading finished\n}\n\ninterface PendingDialog {\n type: \"alert\" | \"confirm\" | \"prompt\" | \"beforeunload\";\n message: string;\n defaultPrompt?: string;\n timestamp: number;\n}\n\ntype ConsoleEventCallback = (event: ConsoleMessage) => void;\ntype NetworkEventCallback = (event: {\n method: string;\n url: string;\n status?: number;\n duration?: number;\n timestamp: number;\n}) => void;\n\nconst MODIFIERS = {\n alt: 1,\n ctrl: 2,\n control: 2,\n meta: 4,\n cmd: 4,\n command: 4,\n win: 4,\n windows: 4,\n shift: 8,\n} as const;\n\ninterface KeyDefinition {\n key: string;\n code: string;\n keyCode: number;\n text?: string;\n location?: number;\n}\n\nconst KEY_DEFINITIONS: Record<string, KeyDefinition> = {\n enter: { key: \"Enter\", code: \"Enter\", keyCode: 13, text: \"\\r\" },\n tab: { key: \"Tab\", code: \"Tab\", keyCode: 9 },\n escape: { key: \"Escape\", code: \"Escape\", keyCode: 27 },\n backspace: { key: \"Backspace\", code: \"Backspace\", keyCode: 8 },\n delete: { key: \"Delete\", code: \"Delete\", keyCode: 46 },\n arrowup: { key: \"ArrowUp\", code: \"ArrowUp\", keyCode: 38 },\n arrowdown: { key: \"ArrowDown\", code: \"ArrowDown\", keyCode: 40 },\n arrowleft: { key: \"ArrowLeft\", code: \"ArrowLeft\", keyCode: 37 },\n arrowright: { key: \"ArrowRight\", code: \"ArrowRight\", keyCode: 39 },\n home: { key: \"Home\", code: \"Home\", keyCode: 36 },\n end: { key: \"End\", code: \"End\", keyCode: 35 },\n pageup: { key: \"PageUp\", code: \"PageUp\", keyCode: 33 },\n pagedown: { key: \"PageDown\", code: \"PageDown\", keyCode: 34 },\n space: { key: \" \", code: \"Space\", keyCode: 32, text: \" \" },\n f1: { key: \"F1\", code: \"F1\", keyCode: 112 },\n f2: { key: \"F2\", code: \"F2\", keyCode: 113 },\n f3: { key: \"F3\", code: \"F3\", keyCode: 114 },\n f4: { key: \"F4\", code: \"F4\", keyCode: 115 },\n f5: { key: \"F5\", code: \"F5\", keyCode: 116 },\n f6: { key: \"F6\", code: \"F6\", keyCode: 117 },\n f7: { key: \"F7\", code: \"F7\", keyCode: 118 },\n f8: { key: \"F8\", code: \"F8\", keyCode: 119 },\n f9: { key: \"F9\", code: \"F9\", keyCode: 120 },\n f10: { key: \"F10\", code: \"F10\", keyCode: 121 },\n f11: { key: \"F11\", code: \"F11\", keyCode: 122 },\n f12: { key: \"F12\", code: \"F12\", keyCode: 123 },\n};\n\nexport class CDPController {\n private targets = new Map<number, Debuggee>();\n private consoleMessages: Map<number, ConsoleMessage[]> = new Map();\n private networkRequests: Map<number, NetworkRequest[]> = new Map();\n private networkEntries: Map<number, Map<string, NetworkEntry>> = new Map(); // tabId -> requestId -> entry\n private consoleCallbacks: Map<number, Map<number, ConsoleEventCallback>> = new Map();\n private networkCallbacks: Map<number, Map<number, NetworkEventCallback>> = new Map();\n private networkRequestStartTimes: Map<string, number> = new Map();\n private pendingDialogs: Map<number, PendingDialog> = new Map();\n private detachReasons: Map<number, string> = new Map();\n private networkEntrySeq = 0; // Sequence counter for unique IDs\n private networkBodyBytes: Map<number, number> = new Map();\n private networkCapture: Map<number, { mode: \"none\" | \"text\" | \"all\"; perBodyBytes: number; totalBytes: number }> = new Map();\n private networkEventQueue: Map<number, Promise<void>> = new Map();\n private static debuggerListenerRegistered = false;\n\n // Body fetch settings\n private static readonly DEFAULT_PER_BODY_BYTES = 64 * 1024;\n private static readonly DEFAULT_TOTAL_BODY_BYTES = 2 * 1024 * 1024;\n private static readonly STATIC_ASSET_TYPES = new Set([\n 'image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/svg+xml', 'image/x-icon',\n 'font/woff', 'font/woff2', 'font/ttf', 'font/otf', 'application/font-woff', 'application/font-woff2',\n 'text/css', 'application/javascript', 'text/javascript', 'application/x-javascript',\n ]);\n private static readonly BINARY_TYPES = new Set([\n 'image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/x-icon',\n 'font/woff', 'font/woff2', 'font/ttf', 'font/otf', 'application/font-woff', 'application/font-woff2',\n 'application/octet-stream', 'application/pdf', 'application/zip',\n 'audio/mpeg', 'audio/wav', 'audio/ogg',\n 'video/mp4', 'video/webm', 'video/ogg',\n ]);\n\n async attach(tabId: number): Promise<void> {\n if (this.targets.has(tabId)) return;\n \n const target: Debuggee = { tabId };\n try {\n await chrome.debugger.attach(target, \"1.3\");\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (/already attached/i.test(message)) {\n throw new CDPControllerError(\n \"debugger_busy\",\n `Another debugger already controls tab ${tabId}. Close DevTools or the competing debugger and retry.`,\n { tabId },\n );\n }\n if (message.includes(\"Cannot access\") || message.includes(\"Cannot attach\")) {\n throw new CDPControllerError(\n \"restricted_target\",\n \"Cannot control this page. Chrome restricts automation on chrome://, extensions, and web store pages.\",\n { tabId },\n );\n }\n throw new CDPControllerError(\"debugger_attach_failed\", `Failed to attach debugger: ${message}`, { tabId });\n }\n this.targets.set(tabId, target);\n this.detachReasons.delete(tabId);\n\n this.setupEventListener();\n this.consoleMessages.set(tabId, []);\n this.networkRequests.set(tabId, []);\n\n try {\n await this.send(tabId, \"Page.enable\");\n } catch (e) {}\n }\n\n async detach(tabId: number): Promise<void> {\n const target = this.targets.get(tabId);\n if (target) {\n try {\n await chrome.debugger.detach(target);\n } catch (e) {\n console.warn(\"[CDPController] Error detaching:\", e);\n }\n this.targets.delete(tabId);\n this.consoleMessages.delete(tabId);\n this.networkRequests.delete(tabId);\n this.networkEntries.delete(tabId);\n this.networkBodyBytes.delete(tabId);\n this.networkCapture.delete(tabId);\n this.consoleCallbacks.delete(tabId);\n this.networkCallbacks.delete(tabId);\n this.pendingDialogs.delete(tabId);\n this.clearRequestStartTimes(tabId);\n this.detachReasons.delete(tabId);\n }\n }\n\n async detachAll(): Promise<void> {\n for (const tabId of this.targets.keys()) {\n await this.detach(tabId);\n }\n }\n\n private setupEventListener(): void {\n if (CDPController.debuggerListenerRegistered) return;\n CDPController.debuggerListenerRegistered = true;\n\n chrome.debugger.onEvent.addListener((source, method, params) => {\n const tabId = source.tabId;\n if (!tabId || !this.targets.has(tabId)) return;\n\n this.enqueueCDPEvent(tabId, method, params);\n });\n\n chrome.debugger.onDetach.addListener((source, reason) => {\n const tabId = source.tabId;\n if (tabId && this.targets.has(tabId)) {\n this.detachReasons.set(tabId, reason || \"unknown\");\n this.targets.delete(tabId);\n this.consoleMessages.delete(tabId);\n this.networkRequests.delete(tabId);\n this.networkEntries.delete(tabId);\n this.networkBodyBytes.delete(tabId);\n this.networkCapture.delete(tabId);\n this.consoleCallbacks.delete(tabId);\n this.networkCallbacks.delete(tabId);\n this.pendingDialogs.delete(tabId);\n this.clearRequestStartTimes(tabId);\n }\n });\n }\n\n private requestStartKey(tabId: number, requestId: string): string {\n return `${tabId}:${requestId}`;\n }\n\n private clearRequestStartTimes(tabId: number): void {\n const prefix = `${tabId}:`;\n for (const key of this.networkRequestStartTimes.keys()) {\n if (key.startsWith(prefix)) this.networkRequestStartTimes.delete(key);\n }\n }\n\n private enqueueCDPEvent(tabId: number, method: string, params: any): void {\n const previous = this.networkEventQueue.get(tabId) || Promise.resolve();\n const next = previous\n .catch(() => undefined)\n .then(() => this.handleCDPEvent(tabId, method, params))\n .catch(() => undefined);\n this.networkEventQueue.set(tabId, next);\n next.finally(() => {\n if (this.networkEventQueue.get(tabId) === next) this.networkEventQueue.delete(tabId);\n });\n }\n\n async drainNetworkEvents(tabId: number): Promise<void> {\n await this.networkEventQueue.get(tabId);\n }\n\n private async handleCDPEvent(tabId: number, method: string, params: any): Promise<void> {\n switch (method) {\n case \"Runtime.consoleAPICalled\":\n this.handleRuntimeConsole(tabId, params);\n break;\n case \"Runtime.exceptionThrown\":\n this.handleRuntimeException(tabId, params);\n break;\n case \"Network.requestWillBeSent\":\n this.handleNetworkRequest(tabId, params);\n break;\n case \"Network.responseReceived\":\n this.handleNetworkResponse(tabId, params);\n break;\n case \"Network.loadingFailed\":\n this.handleNetworkFailed(tabId, params);\n break;\n case \"Network.loadingFinished\":\n await this.handleLoadingFinished(tabId, params);\n break;\n case \"Page.javascriptDialogOpening\":\n this.handleDialogOpening(tabId, params);\n break;\n case \"Page.javascriptDialogClosed\":\n this.pendingDialogs.delete(tabId);\n break;\n }\n }\n\n private handleRuntimeConsole(tabId: number, params: any): void {\n const messages = this.consoleMessages.get(tabId) || [];\n const args = params.args || [];\n\n const text = args\n .map((a: any) => {\n if (a.value !== undefined) return String(a.value);\n if (a.description) return a.description;\n return \"\";\n })\n .join(\" \");\n\n const callFrame = params.stackTrace?.callFrames?.[0];\n\n const msg: ConsoleMessage = {\n type: params.type || \"log\",\n text,\n timestamp: params.timestamp || Date.now(),\n url: callFrame?.url,\n line: callFrame?.lineNumber,\n };\n\n messages.push(msg);\n if (messages.length > 1000) messages.shift();\n this.consoleMessages.set(tabId, messages);\n\n const callbacks = this.consoleCallbacks.get(tabId);\n if (callbacks) {\n for (const cb of callbacks.values()) {\n cb(msg);\n }\n }\n }\n\n private handleRuntimeException(tabId: number, params: any): void {\n const messages = this.consoleMessages.get(tabId) || [];\n const details = params.exceptionDetails;\n if (!details) return;\n\n const msg: ConsoleMessage = {\n type: \"exception\",\n text: details.exception?.description || details.text || \"Unknown exception\",\n timestamp: details.timestamp || Date.now(),\n url: details.url,\n line: details.lineNumber,\n };\n\n messages.push(msg);\n if (messages.length > 1000) messages.shift();\n this.consoleMessages.set(tabId, messages);\n\n const callbacks = this.consoleCallbacks.get(tabId);\n if (callbacks) {\n for (const cb of callbacks.values()) {\n cb(msg);\n }\n }\n }\n\n private handleNetworkRequest(tabId: number, params: any): void {\n const requests = this.networkRequests.get(tabId) || [];\n const req = params.request;\n if (!req) return;\n\n const timestamp = params.timestamp ? params.timestamp * 1000 : Date.now();\n this.networkRequestStartTimes.set(this.requestStartKey(tabId, params.requestId), timestamp);\n\n // Legacy format for backward compatibility\n const reqHeaders: Record<string, string> = {};\n if (req.headers) {\n for (const [key, value] of Object.entries(req.headers)) {\n reqHeaders[key] = String(value);\n }\n }\n\n requests.push({\n requestId: params.requestId,\n url: req.url,\n method: req.method,\n type: params.type,\n timestamp,\n requestHeaders: reqHeaders,\n requestBody: req.postData,\n });\n\n if (requests.length > 500) requests.shift();\n this.networkRequests.set(tabId, requests);\n\n // Full NetworkEntry format\n if (!this.networkEntries.has(tabId)) {\n this.networkEntries.set(tabId, new Map());\n }\n const entriesMap = this.networkEntries.get(tabId)!;\n \n // Generate unique ID\n const seq = ++this.networkEntrySeq;\n const entryId = `r_${timestamp}_${seq}`;\n\n // Extract headers as Record\n const requestHeaders: Record<string, string> = {};\n if (req.headers) {\n for (const [key, value] of Object.entries(req.headers)) {\n requestHeaders[key] = String(value);\n }\n }\n\n // Extract request body info\n const requestBody = req.postData;\n const requestBodySize = requestBody ? requestBody.length : undefined;\n\n const entry: NetworkEntry = {\n id: entryId,\n ts: timestamp,\n method: req.method,\n url: req.url,\n origin: this.extractOrigin(req.url),\n requestHeaders,\n requestBody,\n requestBodySize,\n tabId,\n tabUrl: params.documentURL,\n type: params.type,\n flags: [],\n bodyCapture: { mode: this.networkCapture.get(tabId)?.mode || \"none\", complete: false, reason: \"pending\" },\n _requestId: params.requestId,\n _responseReceived: false,\n _loadingFinished: false,\n };\n\n // Limit entries per tab\n if (entriesMap.size > 500) {\n const oldestKey = entriesMap.keys().next().value;\n if (oldestKey) entriesMap.delete(oldestKey);\n }\n \n entriesMap.set(params.requestId, entry);\n }\n\n private handleNetworkResponse(tabId: number, params: any): void {\n const requests = this.networkRequests.get(tabId) || [];\n const existing = requests.find((r) => r.requestId === params.requestId);\n if (existing) {\n existing.status = params.response?.status;\n existing.mimeType = params.response?.mimeType;\n\n // Capture response headers\n if (params.response?.headers) {\n const respHeaders: Record<string, string> = {};\n for (const [key, value] of Object.entries(params.response.headers)) {\n respHeaders[key] = String(value);\n }\n existing.responseHeaders = respHeaders;\n }\n\n const callbacks = this.networkCallbacks.get(tabId);\n if (callbacks) {\n const startTime = this.networkRequestStartTimes.get(this.requestStartKey(tabId, params.requestId));\n const now = Date.now();\n const duration = startTime ? Math.round(now - startTime) : undefined;\n // Don't delete start time yet - we need it for loadingFinished\n // this.networkRequestStartTimes.delete(this.requestStartKey(tabId, params.requestId));\n\n for (const cb of callbacks.values()) {\n cb({\n method: existing.method,\n url: existing.url,\n status: existing.status,\n duration,\n timestamp: now,\n });\n }\n }\n }\n\n // Update full NetworkEntry\n const entriesMap = this.networkEntries.get(tabId);\n const entry = entriesMap?.get(params.requestId);\n if (entry && params.response) {\n const response = params.response;\n \n // Calculate TTFB (time to first byte)\n const startTime = this.networkRequestStartTimes.get(this.requestStartKey(tabId, params.requestId));\n const now = params.timestamp ? params.timestamp * 1000 : Date.now();\n if (startTime) {\n entry.ttfb = Math.round(now - startTime);\n }\n \n entry.status = response.status;\n entry.statusText = response.statusText;\n entry.mimeType = response.mimeType;\n \n // Extract response headers\n const responseHeaders: Record<string, string> = {};\n if (response.headers) {\n for (const [key, value] of Object.entries(response.headers)) {\n responseHeaders[key] = String(value);\n }\n }\n entry.responseHeaders = responseHeaders;\n \n // Check if binary type\n if (this.isBinaryType(response.mimeType)) {\n entry.flags.push('binary');\n }\n \n // Check for protobuf\n if (response.mimeType?.includes('protobuf') || \n response.mimeType?.includes('x-protobuf') ||\n response.mimeType?.includes('application/grpc')) {\n entry.flags.push('protobuf');\n }\n \n entry._responseReceived = true;\n }\n }\n\n private handleNetworkFailed(tabId: number, params: any): void {\n const requests = this.networkRequests.get(tabId) || [];\n const existing = requests.find((r) => r.requestId === params.requestId);\n if (existing && !existing.status) {\n existing.status = 0;\n\n const callbacks = this.networkCallbacks.get(tabId);\n if (callbacks) {\n const startTime = this.networkRequestStartTimes.get(this.requestStartKey(tabId, params.requestId));\n const now = Date.now();\n const duration = startTime ? Math.round(now - startTime) : undefined;\n this.networkRequestStartTimes.delete(this.requestStartKey(tabId, params.requestId));\n\n for (const cb of callbacks.values()) {\n cb({\n method: existing.method,\n url: existing.url,\n status: 0,\n duration,\n timestamp: now,\n });\n }\n }\n }\n\n // Update full NetworkEntry\n const entriesMap = this.networkEntries.get(tabId);\n const entry = entriesMap?.get(params.requestId);\n if (entry) {\n const startTime = this.networkRequestStartTimes.get(this.requestStartKey(tabId, params.requestId));\n const now = params.timestamp ? params.timestamp * 1000 : Date.now();\n if (startTime) {\n entry.duration = Math.round(now - startTime);\n }\n this.networkRequestStartTimes.delete(this.requestStartKey(tabId, params.requestId));\n \n entry.status = 0;\n entry.flags.push('failed');\n entry._loadingFinished = true;\n }\n }\n\n private handleDialogOpening(tabId: number, params: any): void {\n this.pendingDialogs.set(tabId, {\n type: params.type,\n message: params.message,\n defaultPrompt: params.defaultPrompt,\n timestamp: Date.now(),\n });\n }\n\n private async handleLoadingFinished(tabId: number, params: any): Promise<void> {\n // Update the simple requests array\n const requests = this.networkRequests.get(tabId) || [];\n const existing = requests.find((r) => r.requestId === params.requestId);\n if (existing) {\n // Calculate duration\n const startTime = this.networkRequestStartTimes.get(this.requestStartKey(tabId, params.requestId));\n const now = params.timestamp ? params.timestamp * 1000 : Date.now();\n if (startTime) {\n existing.duration = Math.round(now - startTime);\n }\n\n }\n\n // Update full NetworkEntry format\n const entriesMap = this.networkEntries.get(tabId);\n const entry = entriesMap?.get(params.requestId);\n if (!entry) return;\n\n // Calculate total duration\n const startTime = this.networkRequestStartTimes.get(this.requestStartKey(tabId, params.requestId));\n const now = params.timestamp ? params.timestamp * 1000 : Date.now();\n if (startTime) {\n entry.duration = Math.round(now - startTime);\n }\n this.networkRequestStartTimes.delete(this.requestStartKey(tabId, params.requestId));\n\n // Set response body size from encoded data length\n entry.responseBodySize = params.encodedDataLength;\n entry._loadingFinished = true;\n const capture = this.networkCapture.get(tabId) || { mode: \"none\" as const, perBodyBytes: 0, totalBytes: 0 };\n const encodedBytes = Math.max(0, Number(params.encodedDataLength) || 0);\n let reason: string | null = null;\n if (capture.mode === \"none\") reason = \"disabled\";\n else if (capture.mode === \"text\" && (this.isStaticAsset(entry.mimeType) || this.isBinaryType(entry.mimeType))) reason = \"content-mode\";\n else if (encodedBytes > capture.perBodyBytes) reason = \"per-body-cap\";\n else if ((this.networkBodyBytes.get(tabId) || 0) + encodedBytes > capture.totalBytes) reason = \"session-cap\";\n if (reason) {\n entry.bodyCapture = { mode: capture.mode, complete: false, reason };\n if (reason.endsWith(\"cap\")) entry.flags.push(\"truncated\");\n return;\n }\n try {\n const result = await this.send(tabId, \"Network.getResponseBody\", { requestId: params.requestId });\n const body = typeof result.body === \"string\" ? result.body : \"\";\n const capturedBytes = result.base64Encoded ? Math.ceil(body.length * 0.75) : new TextEncoder().encode(body).byteLength;\n if (capturedBytes > capture.perBodyBytes || (this.networkBodyBytes.get(tabId) || 0) + capturedBytes > capture.totalBytes) {\n entry.flags.push(\"truncated\");\n entry.bodyCapture = { mode: capture.mode, complete: false, reason: capturedBytes > capture.perBodyBytes ? \"per-body-cap\" : \"session-cap\" };\n return;\n }\n if (result.base64Encoded && capture.mode === \"all\") {\n entry.responseBody = body;\n entry.responseBodyEncoding = \"base64\";\n } else if (result.base64Encoded) {\n try { entry.responseBody = atob(body); } catch { entry.bodyCapture = { mode: capture.mode, complete: false, reason: \"decode-failed\" }; return; }\n } else entry.responseBody = body;\n this.networkBodyBytes.set(tabId, (this.networkBodyBytes.get(tabId) || 0) + capturedBytes);\n entry.bodyCapture = { mode: capture.mode, complete: true, capturedBytes };\n if (existing) existing.responseBody = entry.responseBody;\n } catch {\n entry.bodyCapture = { mode: capture.mode, complete: false, reason: \"unavailable\" };\n }\n }\n\n // Helper: Extract origin from URL\n private extractOrigin(url: string): string {\n try {\n const parsed = new URL(url);\n return parsed.origin;\n } catch {\n return '';\n }\n }\n\n // Helper: Check if MIME type is a static asset (skip body fetch)\n private isStaticAsset(mimeType?: string): boolean {\n if (!mimeType) return false;\n return CDPController.STATIC_ASSET_TYPES.has(mimeType);\n }\n\n // Helper: Check if MIME type is binary\n private isBinaryType(mimeType?: string): boolean {\n if (!mimeType) return false;\n return CDPController.BINARY_TYPES.has(mimeType);\n }\n\n async enableConsoleTracking(tabId: number): Promise<void> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Runtime.enable\");\n } catch (e) {}\n }\n\n async enableNetworkTracking(\n tabId: number,\n options: { bodyMode?: \"none\" | \"text\" | \"all\"; perBodyBytes?: number; totalBytes?: number } = {},\n ): Promise<void> {\n await this.ensureAttached(tabId);\n const mode = options.bodyMode || \"text\";\n const perBodyBytes = options.perBodyBytes ?? CDPController.DEFAULT_PER_BODY_BYTES;\n const totalBytes = options.totalBytes ?? CDPController.DEFAULT_TOTAL_BODY_BYTES;\n if (!Number.isInteger(perBodyBytes) || perBodyBytes < 0 || !Number.isInteger(totalBytes) || totalBytes < 0) {\n throw new Error(\"network body caps must be non-negative integers\");\n }\n this.networkCapture.set(tabId, { mode, perBodyBytes, totalBytes });\n if (!this.networkBodyBytes.has(tabId)) this.networkBodyBytes.set(tabId, 0);\n try {\n await this.send(tabId, \"Network.enable\", { maxPostDataSize: 65536 });\n } catch (e) {}\n }\n\n async disableNetworkTracking(tabId: number): Promise<void> {\n await this.drainNetworkEvents(tabId);\n this.networkCapture.delete(tabId);\n this.networkBodyBytes.delete(tabId);\n if (this.networkCallbacks.get(tabId)?.size) return;\n try {\n await this.send(tabId, \"Network.disable\");\n } catch (e) {}\n }\n\n async handleDialog(tabId: number, accept: boolean, promptText?: string): Promise<{ success: boolean; error?: string }> {\n try {\n await this.send(tabId, \"Page.handleJavaScriptDialog\", {\n accept,\n promptText,\n });\n this.pendingDialogs.delete(tabId);\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n getDialogInfo(tabId: number): PendingDialog | null {\n return this.pendingDialogs.get(tabId) || null;\n }\n\n async emulateNetwork(tabId: number, preset: string): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n const presets: Record<string, { offline: boolean; latency: number; downloadThroughput: number; uploadThroughput: number }> = {\n \"offline\": { offline: true, latency: 0, downloadThroughput: 0, uploadThroughput: 0 },\n \"slow-3g\": { offline: false, latency: 2000, downloadThroughput: 50000, uploadThroughput: 50000 },\n \"fast-3g\": { offline: false, latency: 562.5, downloadThroughput: 180000, uploadThroughput: 84375 },\n \"4g\": { offline: false, latency: 100, downloadThroughput: 4000000, uploadThroughput: 3000000 },\n \"reset\": { offline: false, latency: 0, downloadThroughput: -1, uploadThroughput: -1 },\n };\n const config = presets[preset.toLowerCase().replace(/\\s+/g, \"-\")];\n if (!config) {\n return { success: false, error: `Unknown preset: ${preset}. Available: ${Object.keys(presets).join(\", \")}` };\n }\n try {\n await this.send(tabId, \"Network.enable\");\n await this.send(tabId, \"Network.emulateNetworkConditions\", config);\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateCPU(tabId: number, rate: number): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n if (rate < 1) {\n return { success: false, error: \"CPU throttling rate must be >= 1 (1 = no throttle, 4 = 4x slower)\" };\n }\n try {\n await this.send(tabId, \"Emulation.setCPUThrottlingRate\", { rate });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateGeolocation(tabId: number, latitude: number, longitude: number, accuracy?: number): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Emulation.setGeolocationOverride\", {\n latitude,\n longitude,\n accuracy: accuracy || 100,\n });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async clearGeolocation(tabId: number): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Emulation.clearGeolocationOverride\");\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateDevice(\n tabId: number, \n device: { width: number; height: number; deviceScaleFactor: number; mobile: boolean; touch?: boolean; userAgent?: string }\n ): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n // Set device metrics\n await this.send(tabId, \"Emulation.setDeviceMetricsOverride\", {\n width: device.width,\n height: device.height,\n deviceScaleFactor: device.deviceScaleFactor,\n mobile: device.mobile,\n });\n \n // Set user agent if provided\n if (device.userAgent) {\n await this.send(tabId, \"Emulation.setUserAgentOverride\", {\n userAgent: device.userAgent,\n });\n }\n \n // Enable touch if specified\n if (device.touch) {\n await this.send(tabId, \"Emulation.setTouchEmulationEnabled\", {\n enabled: true,\n maxTouchPoints: 5,\n });\n }\n \n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async clearDeviceEmulation(tabId: number): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Emulation.clearDeviceMetricsOverride\");\n await this.send(tabId, \"Emulation.setUserAgentOverride\", { userAgent: \"\" });\n await this.send(tabId, \"Emulation.setTouchEmulationEnabled\", { enabled: false });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateViewport(\n tabId: number, \n options: { width?: number; height?: number; deviceScaleFactor?: number; mobile?: boolean }\n ): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n // Get current viewport size as defaults\n const viewport = await this.getViewportSize(tabId);\n \n await this.send(tabId, \"Emulation.setDeviceMetricsOverride\", {\n width: options.width || viewport.width,\n height: options.height || viewport.height,\n deviceScaleFactor: options.deviceScaleFactor || 1,\n mobile: options.mobile || false,\n });\n \n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateTouch(tabId: number, enabled: boolean): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Emulation.setTouchEmulationEnabled\", {\n enabled,\n maxTouchPoints: enabled ? 5 : 0,\n });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async startPerformanceTrace(tabId: number, categories?: string[]): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Performance.enable\");\n await this.send(tabId, \"Tracing.start\", {\n categories: categories?.join(\",\") || \"devtools.timeline,v8.execute,disabled-by-default-devtools.timeline\",\n transferMode: \"ReturnAsStream\",\n });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async stopPerformanceTrace(tabId: number): Promise<{ success: boolean; metrics?: any; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Performance.enable\");\n const metricsResult = await this.send(tabId, \"Performance.getMetrics\");\n await this.send(tabId, \"Tracing.end\");\n await this.send(tabId, \"Performance.disable\");\n const metrics: Record<string, number> = {};\n for (const m of metricsResult.metrics || []) {\n metrics[m.name] = m.value;\n }\n return { success: true, metrics };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async getPerformanceMetrics(tabId: number): Promise<{ success: boolean; metrics?: Record<string, number>; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Performance.enable\");\n const result = await this.send(tabId, \"Performance.getMetrics\");\n await this.send(tabId, \"Performance.disable\");\n const metrics: Record<string, number> = {};\n for (const m of result.metrics || []) {\n metrics[m.name] = m.value;\n }\n return { success: true, metrics };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async setFileInputBySelector(tabId: number, selector: string, files: string[]): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"DOM.enable\");\n const doc = await this.send(tabId, \"DOM.getDocument\");\n const queryResult = await this.send(tabId, \"DOM.querySelector\", {\n nodeId: doc.root.nodeId,\n selector,\n });\n if (!queryResult.nodeId) {\n return { success: false, error: \"Could not find element by selector\" };\n }\n await this.send(tabId, \"DOM.setFileInputFiles\", {\n nodeId: queryResult.nodeId,\n files,\n });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async waitForLoad(tabId: number, timeout: number = 30000): Promise<{ success: boolean; readyState?: string; error?: string }> {\n await this.ensureAttached(tabId);\n const startTime = Date.now();\n try {\n while (Date.now() - startTime < timeout) {\n const result = await this.send(tabId, \"Runtime.evaluate\", {\n expression: \"document.readyState\",\n returnByValue: true,\n });\n const readyState = result.result?.value;\n if (readyState === \"complete\") {\n return { success: true, readyState };\n }\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n return { success: false, error: `Timeout waiting for page load (${timeout}ms)` };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async getFrames(tabId: number): Promise<{ success: boolean; frames?: Array<{ frameId: string; url: string; name: string; parentId?: string }>; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Page.enable\");\n const result = await this.send(tabId, \"Page.getFrameTree\");\n const frames: Array<{ frameId: string; url: string; name: string; parentId?: string }> = [];\n const extractFrames = (frame: any, parentId?: string) => {\n frames.push({\n frameId: frame.frame.id,\n url: frame.frame.url,\n name: frame.frame.name || \"\",\n parentId,\n });\n if (frame.childFrames) {\n for (const child of frame.childFrames) {\n extractFrames(child, frame.frame.id);\n }\n }\n };\n extractFrames(result.frameTree);\n return { success: true, frames };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async evaluateInFrame(tabId: number, frameId: string, expression: string): Promise<{ success: boolean; result?: any; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n const contextResult = await this.send(tabId, \"Page.createIsolatedWorld\", {\n frameId,\n worldName: \"surf-isolated\",\n });\n const wrappedExpression = `JSON.stringify((function() { ${expression} })())`;\n const result = await this.send(tabId, \"Runtime.evaluate\", {\n expression: wrappedExpression,\n contextId: contextResult.executionContextId,\n returnByValue: true,\n awaitPromise: true,\n });\n if (result.exceptionDetails) {\n return { success: false, error: result.exceptionDetails.text || result.exceptionDetails.exception?.description || \"Evaluation failed\" };\n }\n try {\n return { success: true, result: JSON.parse(result.result?.value) };\n } catch {\n return { success: true, result: result.result?.value };\n }\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n getConsoleMessages(\n tabId: number,\n options?: {\n onlyErrors?: boolean;\n pattern?: string;\n limit?: number;\n }\n ): ConsoleMessage[] {\n let messages = this.consoleMessages.get(tabId) || [];\n\n if (options?.onlyErrors) {\n messages = messages.filter((m) => m.type === \"error\" || m.type === \"exception\");\n }\n if (options?.pattern) {\n try {\n const regex = new RegExp(options.pattern, \"i\");\n messages = messages.filter((m) => regex.test(m.text));\n } catch (e) {\n messages = messages.filter((m) => m.text.includes(options.pattern!));\n }\n }\n if (options?.limit) {\n messages = messages.slice(-options.limit);\n }\n\n return [...messages];\n }\n\n clearConsoleMessages(tabId: number): void {\n this.consoleMessages.set(tabId, []);\n }\n\n getNetworkRequests(\n tabId: number,\n options?: {\n urlPattern?: string;\n limit?: number;\n }\n ): NetworkRequest[] {\n let requests = this.networkRequests.get(tabId) || [];\n\n if (options?.urlPattern) {\n requests = requests.filter((r) => r.url.includes(options.urlPattern!));\n }\n if (options?.limit) {\n requests = requests.slice(-options.limit);\n }\n\n return [...requests];\n }\n\n clearNetworkRequests(tabId: number): void {\n this.networkRequests.set(tabId, []);\n this.networkEntries.set(tabId, new Map());\n this.networkBodyBytes.set(tabId, 0);\n }\n\n /**\n * Get all full network entries for a tab\n */\n getNetworkEntries(\n tabId: number,\n options?: {\n urlPattern?: string;\n limit?: number;\n includeStatic?: boolean;\n }\n ): NetworkEntry[] {\n // First try the full entries map\n const entriesMap = this.networkEntries.get(tabId);\n let entries: NetworkEntry[] = [];\n \n if (entriesMap && entriesMap.size > 0) {\n entries = Array.from(entriesMap.values());\n } else {\n // Fallback to basic networkRequests and convert to NetworkEntry format\n const requests = this.networkRequests.get(tabId) || [];\n entries = requests.map((req, idx) => ({\n id: `r_${req.timestamp}_${idx}`,\n ts: req.timestamp,\n method: req.method,\n url: req.url,\n origin: this.extractOrigin(req.url),\n requestHeaders: {},\n tabId: tabId,\n type: req.type,\n status: req.status,\n flags: [],\n bodyCapture: { mode: \"none\", complete: false, reason: \"legacy\" },\n _requestId: req.requestId,\n _responseReceived: true,\n _loadingFinished: true,\n } as NetworkEntry));\n }\n\n // Filter out static assets by default\n if (!options?.includeStatic) {\n entries = entries.filter(e => !this.isStaticAsset(e.mimeType));\n }\n\n if (options?.urlPattern) {\n entries = entries.filter((e) => e.url.includes(options.urlPattern!));\n }\n\n if (options?.limit) {\n entries = entries.slice(-options.limit);\n }\n\n return entries;\n }\n\n /**\n * Get a single network entry by request ID\n */\n getNetworkEntry(tabId: number, requestId: string): NetworkEntry | null {\n const entriesMap = this.networkEntries.get(tabId);\n return entriesMap?.get(requestId) || null;\n }\n\n /**\n * Fetch response body on demand via CDP\n * Use this for bodies that weren't fetched inline (large or binary)\n */\n async getResponseBody(tabId: number, requestId: string): Promise<{\n success: boolean;\n body?: string;\n base64Encoded?: boolean;\n error?: string;\n }> {\n await this.ensureAttached(tabId);\n \n try {\n const result = await this.send(tabId, \"Network.getResponseBody\", {\n requestId,\n });\n \n return {\n success: true,\n body: result.body,\n base64Encoded: result.base64Encoded,\n };\n } catch (e) {\n return {\n success: false,\n error: e instanceof Error ? e.message : String(e),\n };\n }\n }\n\n subscribeToConsole(tabId: number, streamId: number, callback: ConsoleEventCallback): void {\n if (!this.consoleCallbacks.has(tabId)) {\n this.consoleCallbacks.set(tabId, new Map());\n }\n this.consoleCallbacks.get(tabId)!.set(streamId, callback);\n }\n\n unsubscribeFromConsole(tabId: number, streamId: number): void {\n const callbacks = this.consoleCallbacks.get(tabId);\n if (callbacks) {\n callbacks.delete(streamId);\n if (callbacks.size === 0) {\n this.consoleCallbacks.delete(tabId);\n }\n }\n }\n\n subscribeToNetwork(tabId: number, streamId: number, callback: NetworkEventCallback): void {\n if (!this.networkCallbacks.has(tabId)) {\n this.networkCallbacks.set(tabId, new Map());\n }\n this.networkCallbacks.get(tabId)!.set(streamId, callback);\n }\n\n unsubscribeFromNetwork(tabId: number, streamId: number): void {\n const callbacks = this.networkCallbacks.get(tabId);\n if (callbacks) {\n callbacks.delete(streamId);\n if (callbacks.size === 0) {\n this.networkCallbacks.delete(tabId);\n }\n }\n }\n\n async evaluateScript(tabId: number, expression: string): Promise<{\n result?: { value?: any; type?: string; description?: string };\n exceptionDetails?: { text?: string; exception?: { description?: string } };\n }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Runtime.enable\");\n } catch (e) {}\n \n return this.send(tabId, \"Runtime.evaluate\", {\n expression,\n returnByValue: true,\n awaitPromise: true,\n timeout: 30000,\n });\n }\n\n private async send(\n tabId: number,\n method: string,\n params?: { [key: string]: unknown },\n ): Promise<any> {\n await this.ensureAttached(tabId);\n const target = this.targets.get(tabId)!;\n return chrome.debugger.sendCommand(target, method, params);\n }\n\n async sendCommand(\n tabId: number,\n method: string,\n params?: { [key: string]: unknown },\n ): Promise<any> {\n return this.send(tabId, method, params);\n }\n\n private async ensureAttached(tabId: number): Promise<void> {\n const detachReason = this.detachReasons.get(tabId);\n if (detachReason) {\n this.detachReasons.delete(tabId);\n throw new CDPControllerError(\n \"debugger_detached\",\n `Debugger detached from tab ${tabId}: ${detachReason}. Retry after closing any competing debugger.`,\n { tabId, reason: detachReason },\n );\n }\n if (!this.targets.has(tabId)) await this.attach(tabId);\n }\n\n async getViewportSize(tabId: number): Promise<{ width: number; height: number }> {\n const layoutMetrics = await this.send(tabId, \"Page.getLayoutMetrics\");\n const viewport = layoutMetrics.visualViewport || layoutMetrics.layoutViewport;\n return {\n width: Math.round(viewport.clientWidth),\n height: Math.round(viewport.clientHeight),\n };\n }\n\n async captureScreenshot(tabId: number): Promise<{\n base64: string;\n width: number;\n height: number;\n }> {\n const result = await this.send(tabId, \"Page.captureScreenshot\", {\n format: \"png\",\n captureBeyondViewport: false,\n });\n const { width, height } = await this.getViewportSize(tabId);\n return { base64: result.data, width, height };\n }\n\n async captureRegion(tabId: number, x: number, y: number, width: number, height: number): Promise<{\n base64: string;\n width: number;\n height: number;\n }> {\n const result = await this.send(tabId, \"Page.captureScreenshot\", {\n format: \"png\",\n clip: { x, y, width, height, scale: 1 },\n });\n return { base64: result.data, width, height };\n }\n\n private async dispatchMouseEvent(\n tabId: number,\n type: \"mousePressed\" | \"mouseReleased\" | \"mouseMoved\" | \"mouseWheel\",\n x: number,\n y: number,\n options: {\n button?: MouseButton;\n buttons?: number;\n clickCount?: number;\n modifiers?: number;\n deltaX?: number;\n deltaY?: number;\n } = {}\n ): Promise<void> {\n const params: Record<string, any> = {\n type,\n x: Math.round(x),\n y: Math.round(y),\n modifiers: options.modifiers || 0,\n };\n\n if (type === \"mousePressed\" || type === \"mouseReleased\" || type === \"mouseMoved\") {\n params.button = options.button || \"none\";\n if (type === \"mousePressed\" || type === \"mouseReleased\") {\n params.clickCount = options.clickCount || 1;\n }\n }\n\n if (type !== \"mouseWheel\") {\n params.buttons = options.buttons ?? 0;\n }\n\n if (type === \"mouseWheel\") {\n params.deltaX = options.deltaX || 0;\n params.deltaY = options.deltaY || 0;\n }\n\n await this.send(tabId, \"Input.dispatchMouseEvent\", params);\n }\n\n async click(\n tabId: number,\n x: number,\n y: number,\n button: MouseButton = \"left\",\n clickCount = 1,\n modifiers = 0\n ): Promise<void> {\n const buttonValue = button === \"left\" ? 1 : button === \"right\" ? 2 : button === \"middle\" ? 4 : 0;\n\n await this.dispatchMouseEvent(tabId, \"mouseMoved\", x, y, { button: \"none\", buttons: 0, modifiers });\n await new Promise(resolve => setTimeout(resolve, 100));\n\n for (let i = 1; i <= clickCount; i++) {\n await this.dispatchMouseEvent(tabId, \"mousePressed\", x, y, {\n button,\n buttons: buttonValue,\n clickCount: i,\n modifiers,\n });\n await new Promise(resolve => setTimeout(resolve, 12));\n await this.dispatchMouseEvent(tabId, \"mouseReleased\", x, y, {\n button,\n buttons: 0,\n clickCount: i,\n modifiers,\n });\n if (i < clickCount) {\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n }\n }\n\n async rightClick(tabId: number, x: number, y: number, modifiers = 0): Promise<void> {\n await this.click(tabId, x, y, \"right\", 1, modifiers);\n }\n\n async doubleClick(tabId: number, x: number, y: number, modifiers = 0): Promise<void> {\n await this.click(tabId, x, y, \"left\", 2, modifiers);\n }\n\n async tripleClick(tabId: number, x: number, y: number, modifiers = 0): Promise<void> {\n await this.click(tabId, x, y, \"left\", 3, modifiers);\n }\n\n async hover(tabId: number, x: number, y: number): Promise<void> {\n await this.dispatchMouseEvent(tabId, \"mouseMoved\", x, y, { button: \"none\", buttons: 0 });\n }\n\n async drag(\n tabId: number,\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n modifiers = 0\n ): Promise<void> {\n await this.dispatchMouseEvent(tabId, \"mouseMoved\", startX, startY, { button: \"none\", buttons: 0 });\n await new Promise(resolve => setTimeout(resolve, 50));\n\n await this.dispatchMouseEvent(tabId, \"mousePressed\", startX, startY, {\n button: \"left\",\n buttons: 1,\n clickCount: 1,\n modifiers,\n });\n await new Promise(resolve => setTimeout(resolve, 50));\n\n await this.dispatchMouseEvent(tabId, \"mouseMoved\", endX, endY, { button: \"left\", buttons: 1, modifiers });\n await new Promise(resolve => setTimeout(resolve, 50));\n\n await this.dispatchMouseEvent(tabId, \"mouseReleased\", endX, endY, {\n button: \"left\",\n buttons: 0,\n clickCount: 1,\n modifiers,\n });\n }\n\n async scroll(tabId: number, x: number, y: number, deltaX: number, deltaY: number): Promise<void> {\n await this.dispatchMouseEvent(tabId, \"mouseWheel\", x, y, { deltaX, deltaY });\n }\n\n async type(tabId: number, text: string): Promise<void> {\n for (const char of text) {\n if (char === \"\\n\" || char === \"\\r\") {\n await this.pressKey(tabId, \"Enter\");\n } else {\n const keyDef = this.getKeyDefinition(char);\n if (keyDef) {\n const needsShift = this.requiresShift(char);\n await this.pressKey(tabId, char, needsShift ? MODIFIERS.shift : 0);\n } else {\n await this.send(tabId, \"Input.insertText\", { text: char });\n }\n }\n }\n }\n\n private requiresShift(char: string): boolean {\n return /[A-Z!@#$%^&*()_+{}|:\"<>?~]/.test(char);\n }\n\n private async dispatchKeyEvent(\n tabId: number,\n type: \"keyDown\" | \"keyUp\" | \"rawKeyDown\" | \"char\",\n keyDef: KeyDefinition,\n modifiers = 0\n ): Promise<void> {\n await this.send(tabId, \"Input.dispatchKeyEvent\", {\n type: keyDef.text ? type : (type === \"keyDown\" ? \"rawKeyDown\" : type),\n key: keyDef.key,\n code: keyDef.code,\n windowsVirtualKeyCode: keyDef.keyCode,\n modifiers,\n text: keyDef.text ?? \"\",\n unmodifiedText: keyDef.text ?? \"\",\n location: keyDef.location ?? 0,\n });\n }\n\n async pressKey(tabId: number, key: string, modifiers = 0): Promise<void> {\n const keyDef = this.getKeyDefinition(key);\n if (!keyDef) {\n throw new Error(`Unknown key: ${key}`);\n }\n\n await this.dispatchKeyEvent(tabId, \"keyDown\", keyDef, modifiers);\n await this.dispatchKeyEvent(tabId, \"keyUp\", keyDef, modifiers);\n }\n\n async pressKeyChord(tabId: number, chord: string): Promise<void> {\n const parts = chord.toLowerCase().split(\"+\");\n const modifierKeys: string[] = [];\n let mainKey = \"\";\n\n for (const part of parts) {\n if (part in MODIFIERS) {\n modifierKeys.push(part);\n } else {\n mainKey = part;\n }\n }\n\n let modifiers = 0;\n for (const mod of modifierKeys) {\n modifiers |= MODIFIERS[mod as keyof typeof MODIFIERS] || 0;\n }\n\n if (mainKey) {\n await this.pressKey(tabId, mainKey, modifiers);\n }\n }\n\n private getKeyDefinition(key: string): KeyDefinition | null {\n const lowerKey = key.toLowerCase();\n \n if (KEY_DEFINITIONS[lowerKey]) {\n return KEY_DEFINITIONS[lowerKey];\n }\n\n if (key.length === 1) {\n const code = key.toUpperCase().charCodeAt(0);\n return {\n key,\n code: `Key${key.toUpperCase()}`,\n keyCode: code,\n text: key,\n };\n }\n\n return null;\n }\n\n parseModifiers(modifierString?: string): number {\n if (!modifierString) return 0;\n \n let result = 0;\n const parts = modifierString.toLowerCase().split(\"+\");\n for (const part of parts) {\n const trimmed = part.trim();\n if (trimmed in MODIFIERS) {\n result |= MODIFIERS[trimmed as keyof typeof MODIFIERS];\n }\n }\n return result;\n }\n}\n","let debugMode = false;\nlet initialized = false;\nconst pendingLogs: unknown[][] = [];\n\nchrome.storage.local.get(\"debugMode\").then(({ debugMode: stored }) => {\n debugMode = !!stored;\n initialized = true;\n if (debugMode) {\n for (const args of pendingLogs) {\n console.log(\"[Surf]\", ...args);\n }\n }\n pendingLogs.length = 0;\n});\n\nchrome.storage.onChanged.addListener((changes, areaName) => {\n if (areaName === \"local\" && changes.debugMode) {\n debugMode = !!changes.debugMode.newValue;\n }\n});\n\nexport function debugLog(...args: unknown[]): void {\n if (!initialized) {\n pendingLogs.push(args);\n return;\n }\n if (debugMode) {\n console.log(\"[Surf]\", ...args);\n }\n}\n","import { debugLog } from \"../utils/debug\";\n\nlet nativePort: chrome.runtime.Port | null = null;\nlet messageHandler: ((msg: any) => Promise<any>) | null = null;\nlet reconnectTimeout: ReturnType<typeof setTimeout> | null = null;\nlet pendingNativeRequests = new Map<number, { resolve: (value: any) => void; reject: (err: Error) => void }>();\nlet nativeRequestId = 0;\n\nconst INSTANCE_ID_KEY = \"surfBrowserInstanceId\";\nconst EPOCH_KEY = \"surfBrowserEpoch\";\n\nfunction randomId(): string {\n if (globalThis.crypto?.randomUUID) return globalThis.crypto.randomUUID();\n const bytes = new Uint8Array(16);\n globalThis.crypto.getRandomValues(bytes);\n return Array.from(bytes, (value) => value.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nasync function getBrowserIdentity(): Promise<{ browserInstanceId: string; browserEpoch: string }> {\n const local = await chrome.storage.local.get(INSTANCE_ID_KEY);\n let browserInstanceId = local[INSTANCE_ID_KEY] as string | undefined;\n if (!browserInstanceId) {\n browserInstanceId = randomId();\n await chrome.storage.local.set({ [INSTANCE_ID_KEY]: browserInstanceId });\n }\n\n const session = await chrome.storage.session.get(EPOCH_KEY);\n let browserEpoch = session[EPOCH_KEY] as string | undefined;\n if (!browserEpoch) {\n browserEpoch = randomId();\n await chrome.storage.session.set({ [EPOCH_KEY]: browserEpoch });\n }\n return { browserInstanceId, browserEpoch };\n}\n\nasync function postExtensionHello(port: chrome.runtime.Port): Promise<void> {\n const identity = await getBrowserIdentity();\n if (nativePort !== port) return;\n port.postMessage({\n type: \"EXTENSION_HELLO\",\n protocolVersion: 2,\n extensionVersion: chrome.runtime.getManifest().version,\n capabilities: [\"browser-sessions\", \"strict-targets\", \"keyed-lanes\"],\n ...identity,\n });\n}\n\nexport function initNativeMessaging(\n handler: (msg: any) => Promise<any>\n): void {\n messageHandler = handler;\n connect();\n}\n\nexport function sendToNativeHost(msg: any): Promise<any> {\n return new Promise((resolve, reject) => {\n if (!nativePort) {\n reject(new Error(\"Native host not connected\"));\n return;\n }\n\n if (msg.type === \"API_REQUEST\") {\n nativePort.postMessage(msg);\n resolve({ sent: true });\n return;\n }\n\n const id = ++nativeRequestId;\n pendingNativeRequests.set(id, { resolve, reject });\n nativePort.postMessage({ ...msg, id });\n\n setTimeout(() => {\n if (pendingNativeRequests.has(id)) {\n pendingNativeRequests.delete(id);\n reject(new Error(\"Native host request timeout\"));\n }\n }, 10000);\n });\n}\n\nexport function postToNativeHost(msg: any): void {\n if (nativePort) nativePort.postMessage(msg);\n}\n\nfunction connect(): void {\n if (reconnectTimeout) {\n clearTimeout(reconnectTimeout);\n reconnectTimeout = null;\n }\n\n try {\n const port = chrome.runtime.connectNative(\"surf.browser.host\");\n nativePort = port;\n debugLog(\"Connecting to native host...\");\n postExtensionHello(port).catch((error) => debugLog(\"Failed to send extension hello:\", error));\n\n port.onMessage.addListener(async (msg) => {\n debugLog(\"Received from native host:\", msg.type || msg.id);\n\n if (msg.type === \"HOST_READY\") {\n debugLog(\"Native host ready\");\n postExtensionHello(port).catch((error) => debugLog(\"Failed to refresh extension hello:\", error));\n return;\n }\n\n if (msg.type?.startsWith(\"API_RESPONSE_\")) {\n chrome.runtime.sendMessage(msg).catch(() => {});\n return;\n }\n\n if (msg.id && pendingNativeRequests.has(msg.id)) {\n const { resolve } = pendingNativeRequests.get(msg.id)!;\n pendingNativeRequests.delete(msg.id);\n resolve(msg);\n return;\n }\n\n if (!messageHandler) return;\n\n try {\n const result = await messageHandler(msg);\n if (nativePort !== port) {\n debugLog(\"Cannot send response - native host disconnected:\", msg.id);\n return;\n }\n port.postMessage({ id: msg.id, ...result });\n } catch (err) {\n if (nativePort !== port) {\n debugLog(\"Cannot send error - native host disconnected:\", msg.id);\n return;\n }\n const error = err as Error & { code?: string; details?: Record<string, unknown> };\n port.postMessage({\n id: msg.id,\n error: error instanceof Error ? error.message : \"Unknown error\",\n errorCode: typeof error?.code === \"string\" ? error.code : undefined,\n errorDetails: error?.details,\n });\n }\n });\n\n port.onDisconnect.addListener(() => {\n const error = chrome.runtime.lastError;\n debugLog(\"Native host disconnected:\", error?.message || \"unknown reason\");\n if (nativePort === port) nativePort = null;\n for (const pending of pendingNativeRequests.values()) {\n pending.reject(new Error(\"Native host disconnected\"));\n }\n pendingNativeRequests.clear();\n\n if (!error?.message?.includes(\"not found\")) {\n reconnectTimeout = setTimeout(connect, 5000);\n }\n });\n } catch (err) {\n debugLog(\"Failed to connect to native host:\", err);\n reconnectTimeout = setTimeout(connect, 10000);\n }\n}\n","import { CDPController } from \"../cdp/controller\";\nimport { debugLog } from \"../utils/debug\";\nimport { initNativeMessaging, postToNativeHost } from \"../native/port-manager\";\n\ndebugLog(\"Service worker loaded\");\n\nconst cdp = new CDPController();\nconst activeStreamTabs = new Map<number, number>();\n\nfunction getFrameIdForTab(_tabId: number, message?: { frameId?: unknown }): number {\n const frameId = Number(message?.frameId);\n return Number.isInteger(frameId) && frameId > 0 ? frameId : 0;\n}\n\nasync function validateRequestedFrame(tabId: number, value: unknown): Promise<void> {\n const frameId = Number(value);\n if (!Number.isInteger(frameId) || frameId <= 0) return;\n const frames = await chrome.webNavigation.getAllFrames({ tabId });\n if (frames?.some((frame) => frame.frameId === frameId)) return;\n postToNativeHost({\n type: \"TARGET_EVENT\",\n event: \"frame-reset\",\n tabId,\n frameId,\n reason: \"missing-frame\",\n });\n throw new BrowserCommandError(\n \"frame_context_reset\",\n `Frame context ${frameId} is no longer available in tab ${tabId}`,\n { tabId, frameId, reason: \"missing-frame\", recoveryCommand: \"surf frame.list\" },\n );\n}\n\nfunction isRestrictedTabUrl(url?: string): boolean {\n if (!url) return true;\n return /^(?:about|arc|brave|chrome|chrome-extension|devtools|edge|extension|helium|moz-extension):/i.test(url);\n}\n\nclass BrowserCommandError extends Error {\n code: string;\n details?: Record<string, unknown>;\n\n constructor(code: string, message: string, details?: Record<string, unknown>) {\n super(message);\n this.name = \"BrowserCommandError\";\n this.code = code;\n this.details = details;\n }\n}\n\nasync function inspectTarget(tabId: number): Promise<{\n tabId: number;\n windowId: number;\n url?: string;\n title?: string;\n active: boolean;\n status?: string;\n restricted: boolean;\n groupId: number;\n}> {\n let tab: chrome.tabs.Tab;\n try {\n tab = await chrome.tabs.get(tabId);\n } catch {\n throw new BrowserCommandError(\"tab_gone\", `Tab ${tabId} no longer exists`, { tabId });\n }\n if (!tab.id || tab.windowId === undefined) {\n throw new BrowserCommandError(\"tab_gone\", `Tab ${tabId} no longer has a browser window`, { tabId });\n }\n return {\n tabId: tab.id,\n windowId: tab.windowId,\n url: tab.url,\n title: tab.title,\n active: Boolean(tab.active),\n status: tab.status,\n restricted: isRestrictedTabUrl(tab.url),\n groupId: tab.groupId,\n };\n}\n\nasync function resolveDefaultTarget(windowId?: number, allowCreate = true): Promise<{ tab: chrome.tabs.Tab; autoCreated: boolean }> {\n let tabs: chrome.tabs.Tab[];\n let tab: chrome.tabs.Tab | undefined;\n let autoCreated = false;\n\n if (windowId) {\n tabs = await chrome.tabs.query({ active: true, windowId });\n tab = tabs[0];\n if (!tab || isRestrictedTabUrl(tab.url)) {\n tabs = await chrome.tabs.query({ windowId });\n tab = tabs.find((candidate) => !isRestrictedTabUrl(candidate.url));\n }\n if (!tab?.id && allowCreate) {\n const created = await chrome.tabs.create({\n windowId,\n url: \"data:text/html,<html><head><title>Surf</title></head><body></body></html>\",\n active: true,\n });\n if (!created.id) throw new BrowserCommandError(\"target_create_failed\", `Failed to create tab in window ${windowId}`);\n await sleep(100);\n tab = created;\n autoCreated = true;\n }\n } else {\n tabs = await chrome.tabs.query({ active: true, lastFocusedWindow: true });\n tab = tabs[0];\n if (!tab || isRestrictedTabUrl(tab.url)) {\n tabs = await chrome.tabs.query({ active: true, currentWindow: true });\n tab = tabs[0];\n }\n if (!tab || isRestrictedTabUrl(tab.url)) {\n tabs = await chrome.tabs.query({ active: true });\n tab = tabs.find((candidate) => !isRestrictedTabUrl(candidate.url));\n }\n }\n\n if (!tab?.id) {\n throw new BrowserCommandError(\n \"target_required\",\n \"No active tab found. Use 'surf session.ensure <name> about:blank' or 'surf tab.new <url>'.\",\n );\n }\n return { tab, autoCreated };\n}\n\nasync function labelSessionTab(tabId: number, name: string): Promise<number | undefined> {\n try {\n const groupId = await chrome.tabs.group({ tabIds: tabId });\n await chrome.tabGroups.update(groupId, {\n title: `Surf: ${name}`,\n color: \"blue\",\n collapsed: false,\n });\n return groupId;\n } catch {\n return undefined;\n }\n}\n\nconst screenshotCache = new Map<string, { base64: string; width: number; height: number }>();\nlet screenshotCounter = 0;\n\nfunction generateScreenshotId(): string {\n return `screenshot_${++screenshotCounter}_${Date.now()}`;\n}\n\nfunction cacheScreenshot(id: string, data: { base64: string; width: number; height: number }): void {\n screenshotCache.set(id, data);\n if (screenshotCache.size > 10) {\n const oldest = screenshotCache.keys().next().value;\n if (oldest) screenshotCache.delete(oldest);\n }\n}\n\nfunction getScreenshot(id: string): { base64: string; width: number; height: number } | null {\n return screenshotCache.get(id) || null;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nconst providerUploadStrategies = {\n gemini: {\n openerSelector: 'button[aria-label=\"Upload & tools\"], button[aria-label=\"Open upload file menu\"]',\n closeSelector: 'button[aria-label=\"Close upload file menu\"]',\n uploadItemSelector: '[data-test-id=\"local-images-files-uploader-button\"], [data-testid=\"local-images-files-uploader-button\"], button[aria-label^=\"Upload files\"]',\n },\n chatgpt: {\n directInputSelector: 'form input[type=\"file\"]:not([accept*=\"image\"]), input[type=\"file\"]:not([accept*=\"image\"]), input[type=\"file\"]',\n openerSelector: 'button[data-testid=\"composer-plus-btn\"], button[aria-label=\"Add files and more\"]',\n },\n};\n\nasync function setFileInputFilesBySelector(\n tabId: number,\n filePaths: string[],\n selector: string,\n): Promise<boolean> {\n const result = await cdp.sendCommand(tabId, \"Runtime.evaluate\", {\n expression: `(() => {\n const input = document.querySelector(${JSON.stringify(selector)});\n if (!input || input.tagName !== 'INPUT' || input.type !== 'file') return null;\n return input;\n })()`,\n userGesture: true,\n });\n const objectId = result?.result?.objectId;\n if (!objectId) return false;\n await cdp.sendCommand(tabId, \"DOM.setFileInputFiles\", { files: filePaths, objectId });\n return true;\n}\n\nasync function uploadFilesWithChooser(\n tabId: number,\n filePaths: string[],\n provider: \"gemini\" | \"chatgpt\",\n): Promise<void> {\n await cdp.sendCommand(tabId, \"Page.setInterceptFileChooserDialog\", { enabled: true });\n\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let handler: ((source: chrome.debugger.Debuggee, method: string, params: any) => void) | null = null;\n const cleanup = () => {\n if (timeoutId) { clearTimeout(timeoutId); timeoutId = null; }\n if (handler) { chrome.debugger.onEvent.removeListener(handler); handler = null; }\n };\n\n const attemptFileChooser = (attemptNum: number, timeoutMs: number): Promise<void> => {\n return new Promise<void>((resolve, reject) => {\n timeoutId = setTimeout(() => {\n cleanup();\n reject(new Error(`${provider} file chooser did not open within ${timeoutMs / 1000}s (attempt ${attemptNum})`));\n }, timeoutMs);\n handler = (source: chrome.debugger.Debuggee, method: string, params: any) => {\n if (source.tabId === tabId && method === \"Page.fileChooserOpened\") {\n cleanup();\n cdp.sendCommand(tabId, \"DOM.setFileInputFiles\", {\n files: filePaths,\n backendNodeId: params.backendNodeId,\n }).then(() => resolve()).catch(reject);\n }\n };\n chrome.debugger.onEvent.addListener(handler);\n });\n };\n\n const clickUploadSequence = async () => {\n if (provider === \"gemini\") {\n await cdp.sendCommand(tabId, \"Runtime.evaluate\", {\n expression: `document.querySelector(${JSON.stringify(providerUploadStrategies.gemini.closeSelector)})?.click()`,\n userGesture: true,\n });\n await sleep(300);\n await cdp.sendCommand(tabId, \"Runtime.evaluate\", {\n expression: `document.querySelector(${JSON.stringify(providerUploadStrategies.gemini.openerSelector)})?.click()`,\n userGesture: true,\n });\n await sleep(500);\n await cdp.sendCommand(tabId, \"Runtime.evaluate\", {\n expression: `document.querySelector(${JSON.stringify(providerUploadStrategies.gemini.uploadItemSelector)})?.click()`,\n userGesture: true,\n });\n return;\n }\n\n await cdp.sendCommand(tabId, \"Runtime.evaluate\", {\n expression: `document.querySelector(${JSON.stringify(providerUploadStrategies.chatgpt.openerSelector)})?.click()`,\n userGesture: true,\n });\n };\n\n const maxAttempts = 3;\n const timeouts = [10000, 15000, 20000];\n let lastError: Error | null = null;\n\n try {\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const fileSetPromise = attemptFileChooser(attempt, timeouts[attempt - 1]);\n await clickUploadSequence();\n await fileSetPromise;\n return;\n } catch (err) {\n lastError = err as Error;\n cleanup();\n if (attempt < maxAttempts) await sleep(1000);\n }\n }\n throw new Error(`${provider} file upload failed after ${maxAttempts} attempts: ${lastError?.message}`);\n } finally {\n cleanup();\n try { await cdp.sendCommand(tabId, \"Page.setInterceptFileChooserDialog\", { enabled: false }); } catch {}\n }\n}\n\nasync function uploadFilesToProviderTab(\n provider: \"gemini\" | \"chatgpt\",\n tabId: number,\n filePaths: string[],\n): Promise<{ success: true }> {\n await cdp.attach(tabId);\n await cdp.sendCommand(tabId, \"DOM.enable\", {});\n\n if (provider === \"chatgpt\") {\n const directUpload = await setFileInputFilesBySelector(\n tabId,\n filePaths,\n providerUploadStrategies.chatgpt.directInputSelector,\n );\n if (directUpload) return { success: true };\n }\n\n await uploadFilesWithChooser(tabId, filePaths, provider);\n return { success: true };\n}\n\nconst ELEMENT_COLORS: Record<string, string> = {\n button: '#FF6B6B',\n input: '#4ECDC4',\n select: '#45B7D1',\n a: '#96CEB4',\n textarea: '#FF8C42',\n default: '#DDA0DD',\n};\n\nasync function annotateScreenshot(\n screenshot: { base64: string; width: number; height: number },\n elements: Array<{ ref: string; tag: string; bounds: { x: number; y: number; width: number; height: number } }>,\n scale: { scaleX: number; scaleY: number }\n): Promise<{ base64: string; width: number; height: number }> {\n const blob = base64ToBlob(screenshot.base64);\n const bitmap = await createImageBitmap(blob);\n\n const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) throw new Error(\"Failed to get canvas context\");\n\n ctx.drawImage(bitmap, 0, 0);\n bitmap.close();\n\n const scaleFactor = Math.min(scale.scaleX, scale.scaleY);\n\n for (const element of elements) {\n const color = ELEMENT_COLORS[element.tag] || ELEMENT_COLORS.default;\n\n const x = Math.round(element.bounds.x * scaleFactor);\n const y = Math.round(element.bounds.y * scaleFactor);\n const w = Math.round(element.bounds.width * scaleFactor);\n const h = Math.round(element.bounds.height * scaleFactor);\n\n if (w < 1 || h < 1) continue;\n\n ctx.strokeStyle = color;\n ctx.lineWidth = 2;\n ctx.setLineDash([4, 4]);\n ctx.strokeRect(x, y, w, h);\n ctx.setLineDash([]);\n\n const labelText = element.ref;\n const fontSize = Math.max(10, Math.min(16, Math.round(canvas.width * 0.01)));\n ctx.font = `bold ${fontSize}px sans-serif`;\n const textWidth = ctx.measureText(labelText).width;\n const padding = 4;\n const labelWidth = textWidth + padding * 2;\n const labelHeight = fontSize + padding * 2;\n\n let labelX = x + Math.floor((w - labelWidth) / 2);\n let labelY = y + 2;\n if (w < 60 || h < 30) {\n labelY = y - labelHeight - 2 < 0 ? y + h + 2 : y - labelHeight - 2;\n }\n\n labelX = Math.max(0, Math.min(canvas.width - labelWidth, labelX));\n labelY = Math.max(0, Math.min(canvas.height - labelHeight, labelY));\n\n ctx.fillStyle = color;\n ctx.fillRect(labelX, labelY, labelWidth, labelHeight);\n ctx.strokeStyle = \"white\";\n ctx.lineWidth = 1;\n ctx.strokeRect(labelX, labelY, labelWidth, labelHeight);\n\n ctx.fillStyle = \"white\";\n ctx.textBaseline = \"top\";\n ctx.fillText(labelText, labelX + padding, labelY + padding);\n }\n\n const resultBlob = await canvas.convertToBlob({ type: \"image/png\" });\n const base64 = await blobToBase64(resultBlob);\n\n return { base64, width: canvas.width, height: canvas.height };\n}\n\nfunction blobToBase64(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => {\n const dataUrl = reader.result as string;\n const base64 = dataUrl.split(\",\")[1];\n resolve(base64);\n };\n reader.onerror = () => reject(new Error(\"Failed to convert blob to base64\"));\n reader.readAsDataURL(blob);\n });\n}\n\nfunction base64ToBlob(base64: string, mimeType = \"image/png\"): Blob {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return new Blob([bytes], { type: mimeType });\n}\n\nfunction codeWithExpressionReturn(code: string): string {\n return `return (\\n${code}\\n);`;\n}\n\nfunction scriptParses(code: string): boolean {\n try {\n new Function(code);\n return true;\n } catch (err) {\n return !(err instanceof SyntaxError);\n }\n}\n\nasync function captureFullPage(tabId: number, maxHeight: number): Promise<{ base64: string; width: number; height: number }> {\n const dimensionsResult = await cdp.evaluateScript(tabId, `(() => ({\n viewportHeight: window.innerHeight,\n totalHeight: Math.min(document.documentElement.scrollHeight, ${maxHeight}),\n width: window.innerWidth,\n devicePixelRatio: window.devicePixelRatio || 1,\n originalScrollY: window.scrollY,\n }))()`);\n\n const dimensions = dimensionsResult.result?.value;\n if (!dimensions) throw new Error(\"Failed to get page dimensions\");\n\n const { viewportHeight, totalHeight, width, devicePixelRatio, originalScrollY } = dimensions;\n const chunks: ImageBitmap[] = [];\n let currentY = 0;\n\n while (currentY < totalHeight) {\n await cdp.evaluateScript(tabId, `window.scrollTo(0, ${currentY})`);\n await new Promise(r => setTimeout(r, 300));\n\n const chunk = await cdp.captureScreenshot(tabId);\n const chunkBlob = base64ToBlob(chunk.base64);\n chunks.push(await createImageBitmap(chunkBlob));\n\n currentY += viewportHeight;\n }\n\n await cdp.evaluateScript(tabId, `window.scrollTo(0, ${originalScrollY})`);\n\n const canvasWidth = Math.round(width * devicePixelRatio);\n const canvasHeight = Math.round(totalHeight * devicePixelRatio);\n const canvas = new OffscreenCanvas(canvasWidth, canvasHeight);\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) throw new Error(\"Failed to get canvas context\");\n\n let y = 0;\n const chunkHeight = Math.round(viewportHeight * devicePixelRatio);\n for (let i = 0; i < chunks.length; i++) {\n const chunk = chunks[i];\n const remainingHeight = canvasHeight - y;\n const drawHeight = Math.min(chunkHeight, remainingHeight);\n ctx.drawImage(chunk, 0, 0, chunk.width, drawHeight, 0, y, chunk.width, drawHeight);\n y += drawHeight;\n chunk.close();\n }\n\n const resultBlob = await canvas.convertToBlob({ type: \"image/png\" });\n const base64 = await blobToBase64(resultBlob);\n\n return { base64, width: canvasWidth, height: canvasHeight };\n}\n\nconst navigationResolvers = new Map<number, () => void>();\nconst tabNameRegistry = new Map<string, number>();\n\nchrome.webNavigation.onCompleted.addListener((details) => {\n if (details.frameId === 0) {\n // Clear frame context on main frame navigation (iframes may have changed)\n chrome.tabs.get(details.tabId)\n .then((tab) => postToNativeHost({\n type: \"TARGET_EVENT\",\n event: \"navigation\",\n tabId: details.tabId,\n url: details.url,\n title: tab.title,\n }))\n .catch(() => postToNativeHost({ type: \"TARGET_EVENT\", event: \"navigation\", tabId: details.tabId, url: details.url }));\n const resolver = navigationResolvers.get(details.tabId);\n if (resolver) {\n resolver();\n navigationResolvers.delete(details.tabId);\n }\n }\n});\n\nchrome.webNavigation.onErrorOccurred.addListener((details) => {\n if (details.frameId === 0) {\n const resolver = navigationResolvers.get(details.tabId);\n if (resolver) {\n resolver();\n navigationResolvers.delete(details.tabId);\n }\n }\n});\n\n\n\nchrome.tabs.onRemoved.addListener((tabId) => {\n postToNativeHost({ type: \"TARGET_EVENT\", event: \"tab-removed\", tabId });\n cdp.detach(tabId);\n for (const [name, id] of tabNameRegistry) {\n if (id === tabId) {\n tabNameRegistry.delete(name);\n }\n }\n for (const [streamId, streamTabId] of activeStreamTabs) {\n if (streamTabId === tabId) {\n activeStreamTabs.delete(streamId);\n }\n }\n});\n\nchrome.windows.onRemoved.addListener((windowId) => {\n postToNativeHost({ type: \"TARGET_EVENT\", event: \"window-removed\", windowId });\n});\n\n/**\n * Wait for JavaScript runtime to be ready in a newly created/attached tab.\n * This is needed because document.readyState === 'complete' doesn't mean\n * React/Vue/etc frameworks have finished hydrating.\n */\nasync function waitForRuntimeReady(tabId: number, timeoutMs = 10000): Promise<void> {\n const deadline = Date.now() + timeoutMs;\n\n // Poll until we can successfully evaluate JS\n while (Date.now() < deadline) {\n try {\n const result = await cdp.evaluateScript(tabId, \"document.readyState\");\n if (result?.result?.value === \"complete\") {\n // Extra delay for framework hydration (React, Vue, etc.)\n await sleep(1500);\n return;\n }\n } catch {\n // CDP not ready yet, continue polling\n }\n await sleep(200);\n }\n\n // Timeout but proceed anyway - the page might still work\n console.warn(`waitForRuntimeReady timed out for tab ${tabId}`);\n}\n\n// Helper for locate.* commands with actions\nasync function performLocateAction(\n tabId: number,\n ref: string,\n action: string,\n value: string | undefined,\n cdp: CDPController,\n frameId: number = 0\n): Promise<any> {\n switch (action) {\n case \"click\": {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"CLICK_ELEMENT\",\n ref,\n button: \"left\",\n }, { frameId });\n return result.error ? result : { success: true, action: \"click\", ref };\n }\n case \"fill\": {\n if (!value) return { error: \"fill action requires --value\" };\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"FORM_INPUT\",\n ref,\n value,\n }, { frameId });\n return result.error ? result : { success: true, action: \"fill\", ref, value };\n }\n case \"hover\": {\n const coords = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_COORDINATES\",\n ref,\n }, { frameId });\n if (coords.error) return coords;\n await cdp.hover(tabId, coords.x, coords.y);\n return { success: true, action: \"hover\", ref };\n }\n case \"text\": {\n const textResult = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_TEXT\",\n ref,\n }, { frameId });\n return textResult;\n }\n default:\n return { error: `Unknown action: ${action}. Use click|fill|hover|text` };\n }\n}\n\nchrome.runtime.onMessage.addListener((message, sender, sendResponse) => {\n handleMessage(message, sender)\n .then(sendResponse)\n .catch((err) => sendResponse({ error: err.message }));\n return true;\n});\n\nexport async function handleMessage(\n message: any,\n sender: chrome.runtime.MessageSender\n): Promise<any> {\n const tabId = message.tabId;\n\n switch (message.type) {\n case \"GET_CURRENT_TAB_ID\": {\n const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });\n return { tabId: tab?.id };\n }\n\n case \"TARGET_INSPECT\": {\n const targetTabId = Number(message.tabId);\n if (!Number.isInteger(targetTabId) || targetTabId <= 0) {\n throw new BrowserCommandError(\"target_required\", \"TARGET_INSPECT requires a valid tabId\");\n }\n return inspectTarget(targetTabId);\n }\n\n case \"TARGET_RESOLVE\": {\n const requestedWindowId = message.windowId === undefined ? undefined : Number(message.windowId);\n if (requestedWindowId !== undefined && (!Number.isInteger(requestedWindowId) || requestedWindowId <= 0)) {\n throw new BrowserCommandError(\"target_invalid\", \"windowId must be a positive integer\");\n }\n const { tab, autoCreated } = await resolveDefaultTarget(requestedWindowId, message.allowCreate !== false);\n const inspected = await inspectTarget(tab.id!);\n return { ...inspected, autoCreated };\n }\n\n case \"SESSION_CREATE_TARGET\": {\n const name = String(message.name || \"\");\n const url = typeof message.url === \"string\" && message.url ? message.url : \"about:blank\";\n const mode = message.mode === \"tab\" ? \"tab\" : \"window\";\n const focused = message.focused === true;\n let createdTab: chrome.tabs.Tab | undefined;\n let createdWindowId: number | undefined;\n\n if (mode === \"tab\") {\n const createOptions: chrome.tabs.CreateProperties = { url, active: focused };\n if (message.windowId !== undefined) {\n const targetWindowId = Number(message.windowId);\n if (!Number.isInteger(targetWindowId) || targetWindowId <= 0) {\n throw new BrowserCommandError(\"target_invalid\", \"--window-id must be a positive integer\");\n }\n createOptions.windowId = targetWindowId;\n }\n createdTab = await chrome.tabs.create(createOptions);\n createdWindowId = createdTab.windowId;\n } else {\n const createdWindow = await chrome.windows.create({\n url,\n focused,\n type: \"normal\",\n });\n if (!createdWindow) {\n throw new BrowserCommandError(\"target_create_failed\", `Failed to create target for session ${name}`);\n }\n createdWindowId = createdWindow.id;\n createdTab = createdWindow.tabs?.[0];\n if (!createdTab && createdWindowId !== undefined) {\n const tabs = await chrome.tabs.query({ windowId: createdWindowId });\n createdTab = tabs[0];\n }\n }\n\n if (!createdTab?.id || createdWindowId === undefined) {\n throw new BrowserCommandError(\"target_create_failed\", `Failed to create target for session ${name}`);\n }\n const groupId = await labelSessionTab(createdTab.id, name);\n const inspected = await inspectTarget(createdTab.id);\n return { ...inspected, mode, groupId };\n }\n\n case \"SESSION_CLOSE_TARGET\": {\n const targetTabId = Number(message.tabId);\n if (!Number.isInteger(targetTabId) || targetTabId <= 0) {\n throw new BrowserCommandError(\"target_required\", \"SESSION_CLOSE_TARGET requires a valid tabId\");\n }\n try {\n await chrome.tabs.remove(targetTabId);\n } catch {\n return { success: true, tabId: targetTabId, alreadyGone: true };\n }\n return { success: true, tabId: targetTabId };\n }\n\n case \"EXECUTE_SCREENSHOT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n\n try {\n let result: { base64: string; width: number; height: number };\n let scaleInfo = { scaleX: 1, scaleY: 1 };\n let usedFallback = false;\n\n if (message.fullpage) {\n result = await captureFullPage(tabId, message.maxHeight || 4000);\n try {\n const viewport = await cdp.getViewportSize(tabId);\n const dpr = result.width / viewport.width;\n scaleInfo = { scaleX: dpr, scaleY: dpr };\n } catch {}\n } else {\n try {\n const rawResult = await cdp.captureScreenshot(tabId);\n result = rawResult;\n try {\n const viewport = await cdp.getViewportSize(tabId);\n scaleInfo = {\n scaleX: rawResult.width / viewport.width,\n scaleY: rawResult.height / viewport.height,\n };\n } catch {}\n } catch (cdpError) {\n const tab = await chrome.tabs.get(tabId);\n if (!tab.windowId) throw cdpError;\n if (message.strictTarget) {\n const [activeTab] = await chrome.tabs.query({ active: true, windowId: tab.windowId });\n if (activeTab?.id !== tabId) {\n throw new BrowserCommandError(\n \"screenshot_target_not_visible\",\n `Cannot use screenshot fallback because tab ${tabId} is not visible in window ${tab.windowId}`,\n { tabId, windowId: tab.windowId, activeTabId: activeTab?.id },\n );\n }\n }\n const dataUrl = await chrome.tabs.captureVisibleTab(tab.windowId, { format: \"png\" });\n const base64 = dataUrl.replace(/^data:image\\/png;base64,/, \"\");\n const binaryString = atob(base64);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n const blob = new Blob([bytes], { type: \"image/png\" });\n const bitmap = await createImageBitmap(blob);\n result = { base64, width: bitmap.width, height: bitmap.height };\n bitmap.close();\n usedFallback = true;\n }\n }\n\n if (message.annotate && !usedFallback) {\n try {\n const treeResult = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_BOUNDS_FOR_ANNOTATION\",\n }, { frameId: 0 });\n\n if (treeResult?.elements && treeResult.elements.length > 0) {\n result = await annotateScreenshot(result, treeResult.elements, scaleInfo);\n }\n } catch {}\n }\n\n const screenshotId = generateScreenshotId();\n cacheScreenshot(screenshotId, result);\n return { ...result, screenshotId };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n }\n }\n\n case \"EXECUTE_CLICK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.click(tabId, message.x, message.y, \"left\", 1, mods);\n return { success: true };\n }\n\n case \"EXECUTE_RIGHT_CLICK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.rightClick(tabId, message.x, message.y, mods);\n return { success: true };\n }\n\n case \"EXECUTE_DOUBLE_CLICK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.doubleClick(tabId, message.x, message.y, mods);\n return { success: true };\n }\n\n case \"EXECUTE_TRIPLE_CLICK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.tripleClick(tabId, message.x, message.y, mods);\n return { success: true };\n }\n\n case \"EXECUTE_DRAG\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.drag(tabId, message.startX, message.startY, message.endX, message.endY, mods);\n return { success: true };\n }\n\n case \"EXECUTE_HOVER\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await cdp.hover(tabId, message.x, message.y);\n return { success: true };\n }\n\n case \"EXECUTE_TYPE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.text === undefined || message.text === null) throw new Error(\"No text provided\");\n await cdp.type(tabId, message.text);\n return { success: true };\n }\n\n case \"TYPE_SUBMIT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n await cdp.type(tabId, message.text);\n await cdp.pressKey(tabId, message.submitKey || \"Enter\");\n return { success: true };\n }\n\n case \"CLICK_TYPE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n const clickTypeFrameId = getFrameIdForTab(tabId, message);\n let clicked = false;\n if (message.ref) {\n try {\n const result = await chrome.tabs.sendMessage(tabId, { type: \"CLICK_ELEMENT\", ref: message.ref, button: \"left\" }, { frameId: clickTypeFrameId });\n if (!result.error) clicked = true;\n } catch {}\n }\n if (!clicked && message.coordinate) {\n await cdp.click(tabId, message.coordinate[0], message.coordinate[1], \"left\", 1, 0);\n clicked = true;\n }\n if (!clicked) {\n const result = await cdp.evaluateScript(tabId, `(() => {\n const el = document.querySelector('textarea, input[type=\"text\"], input[type=\"search\"], input:not([type]), [contenteditable=\"true\"]');\n if (!el) return null;\n const r = el.getBoundingClientRect();\n return { x: r.left + r.width/2, y: r.top + r.height/2 };\n })()`);\n if (result.result?.value) {\n await cdp.click(tabId, result.result.value.x, result.result.value.y, \"left\", 1, 0);\n clicked = true;\n }\n }\n if (!clicked) return { error: \"Could not find input element\" };\n await cdp.type(tabId, message.text);\n return { success: true };\n }\n\n case \"CLICK_TYPE_SUBMIT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n const clickTypeSubmitFrameId = getFrameIdForTab(tabId, message);\n let clicked = false;\n if (message.ref) {\n try {\n const result = await chrome.tabs.sendMessage(tabId, { type: \"CLICK_ELEMENT\", ref: message.ref, button: \"left\" }, { frameId: clickTypeSubmitFrameId });\n if (!result.error) clicked = true;\n } catch {}\n }\n if (!clicked && message.coordinate) {\n await cdp.click(tabId, message.coordinate[0], message.coordinate[1], \"left\", 1, 0);\n clicked = true;\n }\n if (!clicked) {\n const result = await cdp.evaluateScript(tabId, `(() => {\n const el = document.querySelector('textarea, input[type=\"text\"], input[type=\"search\"], input:not([type]), [contenteditable=\"true\"]');\n if (!el) return null;\n const r = el.getBoundingClientRect();\n return { x: r.left + r.width/2, y: r.top + r.height/2 };\n })()`);\n if (result.result?.value) {\n await cdp.click(tabId, result.result.value.x, result.result.value.y, \"left\", 1, 0);\n clicked = true;\n }\n }\n if (!clicked) return { error: \"Could not find input element\" };\n await cdp.type(tabId, message.text);\n await cdp.pressKey(tabId, message.submitKey || \"Enter\");\n return { success: true };\n }\n\n case \"FIND_AND_TYPE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n const findResult = await cdp.evaluateScript(tabId, `(() => {\n const selectors = [\n 'textarea:not([readonly]):not([disabled])',\n 'input[type=\"text\"]:not([readonly]):not([disabled])',\n 'input[type=\"search\"]:not([readonly]):not([disabled])',\n 'input:not([type]):not([readonly]):not([disabled])',\n '[contenteditable=\"true\"]',\n '[role=\"textbox\"]'\n ];\n for (const sel of selectors) {\n const el = document.querySelector(sel);\n if (el) {\n const r = el.getBoundingClientRect();\n if (r.width > 0 && r.height > 0) {\n el.focus();\n return { x: r.left + r.width/2, y: r.top + r.height/2, found: true };\n }\n }\n }\n return { found: false };\n })()`);\n const coords = findResult.result?.value;\n if (!coords?.found) return { error: \"No input field found on page\" };\n await cdp.click(tabId, coords.x, coords.y, \"left\", 1, 0);\n await cdp.type(tabId, message.text);\n if (message.submit) {\n await cdp.pressKey(tabId, message.submitKey || \"Enter\");\n }\n return { success: true, coordinates: { x: coords.x, y: coords.y } };\n }\n\n case \"AUTOCOMPLETE_SELECT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n const autocompleteFrameId = getFrameIdForTab(tabId, message);\n let clicked = false;\n if (message.ref) {\n try {\n const result = await chrome.tabs.sendMessage(tabId, { type: \"CLICK_ELEMENT\", ref: message.ref, button: \"left\" }, { frameId: autocompleteFrameId });\n if (!result.error) clicked = true;\n } catch {}\n }\n if (!clicked && message.coordinate) {\n await cdp.click(tabId, message.coordinate[0], message.coordinate[1], \"left\", 1, 0);\n clicked = true;\n }\n if (!clicked) return { error: \"ref or coordinate required\" };\n await new Promise(r => setTimeout(r, 100));\n await cdp.type(tabId, message.text);\n const waitMs = message.waitMs || 500;\n await new Promise(r => setTimeout(r, waitMs));\n if (message.index && message.index > 0) {\n for (let i = 0; i < message.index; i++) {\n await cdp.pressKey(tabId, \"ArrowDown\");\n await new Promise(r => setTimeout(r, 50));\n }\n }\n await cdp.pressKey(tabId, \"Enter\");\n return { success: true };\n }\n\n case \"SET_INPUT_VALUE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.value === undefined) throw new Error(\"No value provided\");\n const selector = message.selector;\n const ref = message.ref;\n if (!selector && !ref) throw new Error(\"selector or ref required\");\n\n const script = ref\n ? `(() => {\n const el = document.querySelector('[data-pi-ref=\"${ref}\"]') ||\n [...document.querySelectorAll('*')].find(e => e.getAttribute?.('data-ref') === '${ref}');\n if (!el) return { error: 'Element not found' };\n el.focus();\n const isContentEditable = el.isContentEditable || el.getAttribute('contenteditable') === 'true';\n const target = isContentEditable ? (el.querySelector('p') || el) : el;\n if (isContentEditable) {\n target.textContent = ${JSON.stringify(message.value)};\n } else {\n el.value = ${JSON.stringify(message.value)};\n }\n el.dispatchEvent(new Event('input', { bubbles: true }));\n el.dispatchEvent(new Event('change', { bubbles: true }));\n return { success: true, contentEditable: isContentEditable };\n })()`\n : `(() => {\n const el = document.querySelector(${JSON.stringify(selector)});\n if (!el) return { error: 'Element not found: ' + ${JSON.stringify(selector)} };\n el.focus();\n const isContentEditable = el.isContentEditable || el.getAttribute('contenteditable') === 'true';\n const target = isContentEditable ? (el.querySelector('p') || el) : el;\n if (isContentEditable) {\n target.textContent = ${JSON.stringify(message.value)};\n } else {\n el.value = ${JSON.stringify(message.value)};\n }\n el.dispatchEvent(new Event('input', { bubbles: true }));\n el.dispatchEvent(new Event('change', { bubbles: true }));\n return { success: true, contentEditable: isContentEditable };\n })()`;\n\n const result = await cdp.evaluateScript(tabId, script);\n return result.result?.value || { error: \"Script failed\" };\n }\n\n case \"SMART_TYPE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const { selector, text, clear = true, submit = false } = message;\n if (!selector) throw new Error(\"selector required\");\n if (text === undefined) throw new Error(\"text required\");\n\n try {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"SMART_TYPE\",\n selector,\n text,\n clear,\n submit,\n }, { frameId: getFrameIdForTab(tabId, message) });\n } catch (err) {\n throw new Error(`Could not type into selector: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n case \"CLOSE_DIALOGS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const maxAttempts = message.maxAttempts || 3;\n for (let i = 0; i < maxAttempts; i++) {\n await cdp.pressKey(tabId, \"Escape\");\n await new Promise(r => setTimeout(r, 100));\n }\n return { success: true };\n }\n\n case \"PAGE_STATE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const stateScript = `(() => {\n const hasModal = !!(\n document.querySelector('[role=\"dialog\"]') ||\n document.querySelector('[role=\"alertdialog\"]') ||\n document.querySelector('.modal:not([hidden])') ||\n document.querySelector('[aria-modal=\"true\"]') ||\n document.querySelector('.MuiModal-root') ||\n document.querySelector('.MuiDialog-root')\n );\n const hasDropdown = !!(\n document.querySelector('[role=\"listbox\"]') ||\n document.querySelector('[role=\"menu\"]:not([hidden])') ||\n document.querySelector('.dropdown-menu.show') ||\n document.querySelector('[aria-expanded=\"true\"]')\n );\n const hasDatePicker = !!(\n document.querySelector('[role=\"grid\"][aria-label*=\"calendar\" i]') ||\n document.querySelector('.react-datepicker') ||\n document.querySelector('.flatpickr-calendar.open') ||\n document.querySelector('[class*=\"DatePicker\"]')\n );\n const focusedEl = document.activeElement;\n const focusedTag = focusedEl?.tagName?.toLowerCase();\n const focusedType = focusedEl?.getAttribute?.('type');\n return {\n hasModal,\n hasDropdown,\n hasDatePicker,\n hasOverlay: hasModal || hasDropdown || hasDatePicker,\n focusedElement: focusedTag ? { tag: focusedTag, type: focusedType } : null,\n url: location.href,\n title: document.title\n };\n })()`;\n const stateResult = await cdp.evaluateScript(tabId, stateScript);\n return stateResult.result?.value || { error: \"Failed to get page state\" };\n }\n\n case \"EXECUTE_SCROLL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const deltaX = message.deltaX || 0;\n const deltaY = message.deltaY || 0;\n\n const scrollScript = (dx: number, dy: number) => {\n const before = { x: window.scrollX, y: window.scrollY };\n window.scrollBy(dx, dy);\n const after = { x: window.scrollX, y: window.scrollY };\n return {\n scrollX: after.x,\n scrollY: after.y,\n pageHeight: document.documentElement.scrollHeight,\n viewportHeight: window.innerHeight,\n scrolled: before.x !== after.x || before.y !== after.y\n };\n };\n\n try {\n const result = await cdp.evaluateScript(tabId,\n `(${scrollScript.toString()})(${deltaX}, ${deltaY})`\n );\n return result.result?.value || { error: \"Script failed\" };\n } catch {\n try {\n const results = await chrome.scripting.executeScript({\n target: { tabId },\n func: scrollScript,\n args: [deltaX, deltaY],\n });\n return results[0]?.result || { error: \"Script failed\" };\n } catch {\n return { error: \"Cannot scroll on this page (restricted)\" };\n }\n }\n }\n\n case \"EXECUTE_KEY\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const key = message.key;\n if (!key) throw new Error(\"No key provided\");\n if (key.includes(\"+\")) {\n await cdp.pressKeyChord(tabId, key);\n } else {\n await cdp.pressKey(tabId, key);\n }\n return { success: true };\n }\n\n case \"EXECUTE_NAVIGATE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.url) throw new Error(\"No url provided\");\n\n const navigationPromise = new Promise<void>((resolve) => {\n navigationResolvers.set(tabId, resolve);\n setTimeout(() => {\n if (navigationResolvers.has(tabId)) {\n navigationResolvers.delete(tabId);\n resolve();\n }\n }, 30000);\n });\n\n await chrome.tabs.update(tabId, { url: message.url });\n await navigationPromise;\n\n await new Promise(resolve => setTimeout(resolve, 500));\n\n return { success: true };\n }\n\n case \"GET_VIEWPORT_SIZE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n return await cdp.getViewportSize(tabId);\n }\n\n case \"READ_PAGE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const readFrameId = getFrameIdForTab(tabId, message);\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n\n let result;\n try {\n result = await chrome.tabs.sendMessage(tabId, {\n type: \"GENERATE_ACCESSIBILITY_TREE\",\n options: message.options || {},\n }, { frameId: readFrameId });\n } catch (err) {\n return {\n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n }\n\n // Include visible text content if requested\n if (message.options?.includeText) {\n try {\n const textResult = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_PAGE_TEXT\",\n options: {\n compact: message.options?.compact === true,\n maxBytes: message.options?.maxBytes,\n },\n }, { frameId: readFrameId });\n if (textResult?.text) {\n result.text = textResult.text;\n }\n } catch (err) {\n // Ignore text extraction errors\n }\n }\n\n if (message.options?.includeScreenshot) {\n try {\n const screenshot = await cdp.captureScreenshot(tabId);\n return { ...result, screenshot };\n } catch (err) {\n return { ...result, screenshotError: \"Failed to capture screenshot\" };\n }\n }\n return result;\n }\n\n case \"GET_ELEMENT_COORDINATES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_COORDINATES\",\n ref: message.ref,\n }, { frameId: getFrameIdForTab(tabId, message) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"FORM_INPUT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"FORM_INPUT\",\n ref: message.ref,\n value: message.value,\n }, { frameId: getFrameIdForTab(tabId, message) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"EVAL_IN_PAGE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.code) throw new Error(\"No code provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"EVAL_IN_PAGE\",\n code: message.code,\n }, { frameId: getFrameIdForTab(tabId, message) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"SCROLL_TO_ELEMENT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"SCROLL_TO_ELEMENT\",\n ref: message.ref,\n }, { frameId: getFrameIdForTab(tabId, message) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"SCROLL_TO_POSITION\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const position = message.position;\n if (position === undefined) throw new Error(\"position required (\\\"top\\\", \\\"bottom\\\", or number)\");\n const selector = message.selector;\n\n const scrollScript = (pos: string | number, sel: string | null) => {\n const findScrollable = (): Element => {\n const candidates = [...document.querySelectorAll(\"*\")].filter(el =>\n el.scrollHeight > el.clientHeight && el.clientHeight > 200\n ).sort((a,b) => b.scrollHeight - a.scrollHeight);\n return candidates[0] || document.documentElement;\n };\n\n const container = sel ? document.querySelector(sel) || findScrollable() : findScrollable();\n if (!container) return { error: \"No scrollable container found\" };\n\n if (pos === \"bottom\") {\n container.scrollTop = container.scrollHeight;\n } else if (pos === \"top\") {\n container.scrollTop = 0;\n } else if (typeof pos === \"number\") {\n container.scrollTop = pos;\n }\n\n return {\n scrollTop: container.scrollTop,\n scrollHeight: container.scrollHeight,\n clientHeight: container.clientHeight,\n atBottom: container.scrollTop + container.clientHeight >= container.scrollHeight - 10,\n atTop: container.scrollTop < 10\n };\n };\n\n try {\n const script = `(${scrollScript.toString()})(${JSON.stringify(position)}, ${JSON.stringify(selector)})`;\n const result = await cdp.evaluateScript(tabId, script);\n return result.result?.value || { error: \"Script failed\" };\n } catch {\n try {\n const results = await chrome.scripting.executeScript({\n target: { tabId },\n func: scrollScript,\n args: [position, selector],\n });\n return results[0]?.result || { error: \"Script failed\" };\n } catch {\n return { error: \"Cannot scroll on this page (restricted)\" };\n }\n }\n }\n\n case \"GET_SCROLL_INFO\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const selector = message.selector;\n\n const scrollInfoScript = (sel: string | null) => {\n const findScrollable = (): Element => {\n const candidates = [...document.querySelectorAll(\"*\")].filter(el =>\n el.scrollHeight > el.clientHeight && el.clientHeight > 200\n ).sort((a,b) => b.scrollHeight - a.scrollHeight);\n return candidates[0] || document.documentElement;\n };\n\n const container = sel ? document.querySelector(sel) || findScrollable() : findScrollable();\n if (!container) return { error: \"No scrollable container found\" };\n\n const maxScroll = container.scrollHeight - container.clientHeight;\n return {\n scrollTop: container.scrollTop,\n scrollHeight: container.scrollHeight,\n clientHeight: container.clientHeight,\n atBottom: container.scrollTop + container.clientHeight >= container.scrollHeight - 10,\n atTop: container.scrollTop < 10,\n scrollPercentage: maxScroll > 0 ? Math.round((container.scrollTop / maxScroll) * 100) : 100\n };\n };\n\n try {\n const script = `(${scrollInfoScript.toString()})(${JSON.stringify(selector)})`;\n const result = await cdp.evaluateScript(tabId, script);\n return result.result?.value || { error: \"Script failed\" };\n } catch {\n try {\n const results = await chrome.scripting.executeScript({\n target: { tabId },\n func: scrollInfoScript,\n args: [selector],\n });\n return results[0]?.result || { error: \"Script failed\" };\n } catch {\n return { error: \"Cannot get scroll info on this page (restricted)\" };\n }\n }\n }\n\n case \"GET_PAGE_TEXT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, { type: \"GET_PAGE_TEXT\" }, { frameId: getFrameIdForTab(tabId, message) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"GET_PAGE_HTML\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const results = await chrome.scripting.executeScript({\n target: { tabId, frameIds: [getFrameIdForTab(tabId, message)] },\n func: (selector?: unknown, stripScripts?: boolean) => {\n if (selector !== undefined && (typeof selector !== \"string\" || selector.length === 0)) {\n throw new Error(\"selector must be a non-empty string\");\n }\n const root = selector === undefined ? document.documentElement : document.querySelector(selector);\n if (!root) throw new Error(`No element matches selector \"${selector}\"`);\n const exportRoot = stripScripts ? root.cloneNode(true) as Element : root;\n if (stripScripts) {\n if (exportRoot.matches(\"script\")) return \"\";\n exportRoot.querySelectorAll(\"script\").forEach((script) => script.remove());\n }\n const doctype = selector === undefined && document.doctype ? `<!doctype ${document.doctype.name}>\\n` : \"\";\n return doctype + exportRoot.outerHTML;\n },\n args: [message.selector, message.stripScripts],\n });\n const html = results[0]?.result;\n if (typeof html !== \"string\") throw new Error(\"Page HTML extraction returned an invalid result\");\n return { html };\n }\n\n case \"LOCATE_ROLE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.role) throw new Error(\"role required\");\n const locateFrameId = getFrameIdForTab(tabId, message);\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"LOCATE_ROLE\",\n role: message.role,\n name: message.name,\n all: message.all,\n }, { frameId: locateFrameId });\n\n if (result.error) return result;\n\n // Perform action if specified\n if (message.action && result.ref) {\n return await performLocateAction(tabId, result.ref, message.action, message.value, cdp, locateFrameId);\n }\n\n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"LOCATE_TEXT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"text required\");\n const textFrameId = getFrameIdForTab(tabId, message);\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"LOCATE_TEXT\",\n text: message.text,\n exact: message.exact,\n }, { frameId: textFrameId });\n\n if (result.error) return result;\n\n // Perform action if specified\n if (message.action && result.ref) {\n return await performLocateAction(tabId, result.ref, message.action, message.value, cdp, textFrameId);\n }\n\n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"LOCATE_LABEL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.label) throw new Error(\"label required\");\n const labelFrameId = getFrameIdForTab(tabId, message);\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"LOCATE_LABEL\",\n label: message.label,\n }, { frameId: labelFrameId });\n\n if (result.error) return result;\n\n // Perform action if specified\n if (message.action && result.ref) {\n return await performLocateAction(tabId, result.ref, message.action, message.value, cdp, labelFrameId);\n }\n\n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"GET_ELEMENT_STYLES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.selector) throw new Error(\"selector required\");\n const stylesFrameId = getFrameIdForTab(tabId, message);\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_STYLES\",\n selector: message.selector,\n }, { frameId: stylesFrameId });\n\n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"SELECT_OPTION\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.selector) throw new Error(\"selector required\");\n if (!message.values) throw new Error(\"values required\");\n const selectFrameId = getFrameIdForTab(tabId, message);\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"SELECT_OPTION\",\n selector: message.selector,\n values: message.values,\n by: message.by || \"value\",\n }, { frameId: selectFrameId });\n\n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"SHOW_AGENT_INDICATORS\":\n case \"HIDE_AGENT_INDICATORS\":\n case \"SHOW_STATIC_INDICATOR\":\n case \"HIDE_STATIC_INDICATOR\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, { type: message.type }, { frameId: 0 });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"STOP_AGENT\": {\n const fromTabId = message.fromTabId;\n let targetTabId: number | undefined;\n\n if (fromTabId === \"CURRENT_TAB\" && sender.tab?.id) {\n targetTabId = sender.tab.id;\n } else if (typeof fromTabId === \"number\") {\n targetTabId = fromTabId;\n }\n\n if (targetTabId) {\n chrome.runtime.sendMessage({ type: \"STOP_AGENT\", targetTabId });\n }\n return { success: true };\n }\n\n case \"DISMISS_STATIC_INDICATOR\": {\n return { success: true };\n }\n\n case \"STATIC_INDICATOR_HEARTBEAT\": {\n return { success: true };\n }\n\n case \"CLICK_REF\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"CLICK_ELEMENT\",\n ref: message.ref,\n button: message.button || \"left\",\n }, { frameId: getFrameIdForTab(tabId, message) });\n if (result.error) return { error: result.error };\n return { success: true };\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"HOVER_REF\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n const coords = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_COORDINATES\",\n ref: message.ref,\n }, { frameId: getFrameIdForTab(tabId, message) });\n if (coords.error) return { error: coords.error };\n await cdp.hover(tabId, coords.x, coords.y);\n return { success: true };\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"PING\": {\n return { success: true, status: \"connected\" };\n }\n\n case \"HEALTH_CHECK_URL\": {\n if (!message.url) throw new Error(\"No url provided\");\n const timeout = message.timeout || 30000;\n const expect = message.expect || 200;\n const startTime = Date.now();\n const pollInterval = 500;\n\n let lastError: string | null = null;\n while (Date.now() - startTime < timeout) {\n try {\n const response = await fetch(message.url, { method: \"GET\" });\n await response.text();\n if (response.status === expect) {\n return { success: true, status: response.status, time: Date.now() - startTime };\n }\n lastError = `Got status ${response.status}`;\n } catch (e) {\n lastError = e instanceof Error ? e.message : String(e);\n }\n await new Promise((r) => setTimeout(r, pollInterval));\n }\n return {\n error: `Timeout waiting for ${message.url} to return ${expect}`,\n lastError,\n time: Date.now() - startTime\n };\n }\n\n case \"SMOKE_TEST\": {\n const urls: string[] = message.urls || [];\n const captureScreenshots: boolean = message.savePath !== undefined;\n const failFast: boolean = message.failFast || false;\n\n if (urls.length === 0) {\n return { error: \"No URLs provided for smoke test\" };\n }\n\n const results: Array<{\n url: string;\n status: \"pass\" | \"fail\";\n time: number;\n errors: string[];\n screenshotBase64?: string;\n hostname?: string;\n }> = [];\n\n let pass = 0;\n let fail = 0;\n\n for (const url of urls) {\n const startTime = Date.now();\n const errors: string[] = [];\n let screenshotBase64: string | undefined;\n let hostname: string | undefined;\n let testTabId: number | undefined;\n\n try {\n hostname = new URL(url).hostname.replace(/[^a-zA-Z0-9.-]/g, \"_\");\n const testTab = await chrome.tabs.create({ url, active: false });\n if (!testTab.id) throw new Error(\"Failed to create tab\");\n testTabId = testTab.id;\n\n try {\n await cdp.enableConsoleTracking(testTabId);\n } catch (e) {}\n\n await new Promise<void>((resolve) => {\n const onComplete = (details: chrome.webNavigation.WebNavigationFramedCallbackDetails) => {\n if (details.tabId === testTabId && details.frameId === 0) {\n chrome.webNavigation.onCompleted.removeListener(onComplete);\n chrome.webNavigation.onErrorOccurred.removeListener(onError);\n resolve();\n }\n };\n const onError = (details: chrome.webNavigation.WebNavigationFramedErrorCallbackDetails) => {\n if (details.tabId === testTabId && details.frameId === 0) {\n chrome.webNavigation.onCompleted.removeListener(onComplete);\n chrome.webNavigation.onErrorOccurred.removeListener(onError);\n errors.push(`Navigation error: ${details.error}`);\n resolve();\n }\n };\n chrome.webNavigation.onCompleted.addListener(onComplete);\n chrome.webNavigation.onErrorOccurred.addListener(onError);\n setTimeout(() => {\n chrome.webNavigation.onCompleted.removeListener(onComplete);\n chrome.webNavigation.onErrorOccurred.removeListener(onError);\n errors.push(\"Navigation timeout (30s)\");\n resolve();\n }, 30000);\n });\n\n await new Promise(r => setTimeout(r, 2000));\n\n const consoleMessages = cdp.getConsoleMessages(testTabId, { onlyErrors: true, limit: 50 });\n for (const msg of consoleMessages) {\n errors.push(`[${msg.type}] ${msg.text}`);\n }\n\n if (captureScreenshots) {\n try {\n const screenshot = await cdp.captureScreenshot(testTabId);\n screenshotBase64 = screenshot.base64;\n } catch (e) {}\n }\n } catch (e) {\n errors.push(e instanceof Error ? e.message : String(e));\n } finally {\n if (testTabId) {\n try { await chrome.tabs.remove(testTabId); } catch {}\n }\n }\n\n const elapsed = Date.now() - startTime;\n const status = errors.length === 0 ? \"pass\" : \"fail\";\n if (status === \"pass\") pass++;\n else fail++;\n\n results.push({\n url,\n status,\n time: elapsed,\n errors,\n ...(screenshotBase64 && { screenshotBase64, hostname }),\n });\n\n if (failFast && status === \"fail\") {\n break;\n }\n }\n\n return {\n results,\n summary: { pass, fail, total: results.length },\n savePath: message.savePath,\n };\n }\n\n case \"WAIT_FOR_ELEMENT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.selector) throw new Error(\"No selector provided\");\n const waitFrameId = getFrameIdForTab(tabId, message);\n\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"WAIT_FOR_ELEMENT\",\n selector: message.selector,\n state: message.state || \"visible\",\n timeout: message.timeout || 20000,\n }, { frameId: waitFrameId });\n return result;\n } catch (err) {\n return {\n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n }\n }\n\n case \"WAIT_FOR_URL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.pattern) throw new Error(\"No URL pattern provided\");\n\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"WAIT_FOR_URL\",\n pattern: message.pattern,\n timeout: message.timeout || 20000,\n }, { frameId: 0 });\n return result;\n } catch (err) {\n return {\n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n }\n }\n\n case \"WAIT_FOR_NETWORK_IDLE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"WAIT_FOR_NETWORK_IDLE\",\n timeout: message.timeout || 10000,\n }, { frameId: 0 });\n return result;\n } catch (err) {\n return {\n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n }\n }\n\n case \"WAIT_FOR_DOM_STABLE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"WAIT_FOR_DOM_STABLE\",\n stable: message.stable || 100,\n timeout: message.timeout || 5000,\n }, { frameId: 0 });\n return result;\n } catch (err) {\n return {\n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n }\n }\n\n case \"DIALOG_ACCEPT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.handleDialog(tabId, true, message.text);\n return result;\n }\n\n case \"DIALOG_DISMISS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.handleDialog(tabId, false);\n return result;\n }\n\n case \"DIALOG_INFO\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const dialog = cdp.getDialogInfo(tabId);\n if (!dialog) {\n return { hasDialog: false };\n }\n return {\n hasDialog: true,\n type: dialog.type,\n message: dialog.message,\n defaultPrompt: dialog.defaultPrompt,\n };\n }\n\n case \"EMULATE_NETWORK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.preset) throw new Error(\"No preset provided\");\n const result = await cdp.emulateNetwork(tabId, message.preset);\n if (!result.success) throw new Error(result.error);\n return { success: true, preset: message.preset };\n }\n\n case \"EMULATE_CPU\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.rate === undefined) throw new Error(\"No rate provided\");\n const result = await cdp.emulateCPU(tabId, message.rate);\n if (!result.success) throw new Error(result.error);\n return { success: true, rate: message.rate };\n }\n\n case \"EMULATE_GEO\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.clear) {\n const result = await cdp.clearGeolocation(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, cleared: true };\n }\n if (message.latitude === undefined || message.longitude === undefined) {\n throw new Error(\"Latitude and longitude required\");\n }\n const result = await cdp.emulateGeolocation(tabId, message.latitude, message.longitude, message.accuracy);\n if (!result.success) throw new Error(result.error);\n return { success: true, latitude: message.latitude, longitude: message.longitude };\n }\n\n case \"EMULATE_DEVICE_LIST\": {\n // Return list of available devices - handled in CLI\n const devices = [\n \"iPhone 12\", \"iPhone 13\", \"iPhone 14\", \"iPhone 14 Pro\", \"iPhone 14 Pro Max\", \"iPhone SE\",\n \"iPad\", \"iPad Pro\", \"iPad Mini\",\n \"Pixel 5\", \"Pixel 6\", \"Pixel 7\", \"Pixel 7 Pro\",\n \"Galaxy S21\", \"Galaxy S22\", \"Galaxy S23\", \"Galaxy Tab S7\",\n \"Nest Hub\", \"Nest Hub Max\"\n ];\n return { devices };\n }\n\n case \"EMULATE_DEVICE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const deviceName = message.device;\n\n // Handle reset\n if (deviceName.toLowerCase() === \"reset\") {\n const result = await cdp.clearDeviceEmulation(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, message: \"Device emulation reset\" };\n }\n\n // Device presets (synced with device-presets.cjs)\n const presets: Record<string, { width: number; height: number; deviceScaleFactor: number; mobile: boolean; touch: boolean; userAgent: string }> = {\n // Apple devices\n \"iPhone 12\": { width: 390, height: 844, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone 13\": { width: 390, height: 844, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone 14\": { width: 390, height: 844, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone 14 Pro\": { width: 393, height: 852, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone 14 Pro Max\": { width: 430, height: 932, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone SE\": { width: 375, height: 667, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1\" },\n \"iPad\": { width: 768, height: 1024, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1\" },\n \"iPad Pro\": { width: 1024, height: 1366, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1\" },\n \"iPad Mini\": { width: 768, height: 1024, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1\" },\n // Google devices\n \"Pixel 5\": { width: 393, height: 851, deviceScaleFactor: 2.75, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36\" },\n \"Pixel 6\": { width: 412, height: 915, deviceScaleFactor: 2.625, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 12; Pixel 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36\" },\n \"Pixel 7\": { width: 412, height: 915, deviceScaleFactor: 2.625, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36\" },\n \"Pixel 7 Pro\": { width: 412, height: 892, deviceScaleFactor: 3.5, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 13; Pixel 7 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36\" },\n // Samsung devices\n \"Galaxy S21\": { width: 360, height: 800, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 11; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.210 Mobile Safari/537.36\" },\n \"Galaxy S22\": { width: 360, height: 780, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 12; SM-S901B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36\" },\n \"Galaxy S23\": { width: 360, height: 780, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 13; SM-S911B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Mobile Safari/537.36\" },\n \"Galaxy Tab S7\": { width: 800, height: 1280, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 10; SM-T870) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Safari/537.36\" },\n // Other\n \"Nest Hub\": { width: 1024, height: 600, deviceScaleFactor: 2, mobile: false, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666\" },\n \"Nest Hub Max\": { width: 1280, height: 800, deviceScaleFactor: 2, mobile: false, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666\" },\n };\n\n // Find matching device (case-insensitive partial match, prefer longest match)\n type DevicePreset = { width: number; height: number; deviceScaleFactor: number; mobile: boolean; touch: boolean; userAgent: string };\n const aliases: Record<string, string> = {\n iphone: \"iPhone 14\",\n iphone14: \"iPhone 14\",\n iphone13: \"iPhone 13\",\n iphone12: \"iPhone 12\",\n iphonese: \"iPhone SE\",\n pixel: \"Pixel 7\",\n pixel7: \"Pixel 7\",\n pixel6: \"Pixel 6\",\n galaxy: \"Galaxy S23\",\n galaxys23: \"Galaxy S23\",\n ipad: \"iPad\",\n ipadpro: \"iPad Pro\",\n };\n let device: DevicePreset | undefined = presets[deviceName];\n if (!device) {\n const lowerName = deviceName.toLowerCase();\n device = presets[aliases[lowerName.replace(/\\s+/g, \"\")]];\n }\n if (!device) {\n const lowerName = deviceName.toLowerCase();\n let bestMatch: { name: string; preset: DevicePreset } | null = null;\n\n for (const [name, preset] of Object.entries(presets)) {\n const presetLower = name.toLowerCase();\n const presetNoSpaces = presetLower.replace(/\\s+/g, \"\");\n\n // Check if it's a match\n if (presetLower.includes(lowerName) || lowerName.includes(presetNoSpaces)) {\n // Prefer longer matches (more specific devices)\n if (!bestMatch || name.length > bestMatch.name.length) {\n bestMatch = { name, preset };\n }\n }\n }\n\n if (bestMatch) {\n device = bestMatch.preset;\n }\n }\n\n if (!device) {\n throw new Error(`Unknown device: ${deviceName}. Use --list to see available devices.`);\n }\n\n const result = await cdp.emulateDevice(tabId, device);\n if (!result.success) throw new Error(result.error);\n return { success: true, device: deviceName };\n }\n\n case \"EMULATE_VIEWPORT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.width && !message.height) {\n throw new Error(\"--width or --height required\");\n }\n const result = await cdp.emulateViewport(tabId, {\n width: message.width,\n height: message.height,\n deviceScaleFactor: message.deviceScaleFactor,\n mobile: message.mobile,\n });\n if (!result.success) throw new Error(result.error);\n return { success: true, width: message.width, height: message.height };\n }\n\n case \"EMULATE_TOUCH\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.emulateTouch(tabId, message.enabled);\n if (!result.success) throw new Error(result.error);\n return { success: true, enabled: message.enabled };\n }\n\n case \"FORM_FILL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.data) throw new Error(\"No data provided\");\n const response = await chrome.tabs.sendMessage(tabId, {\n type: \"FORM_FILL\",\n data: message.data,\n }, { frameId: getFrameIdForTab(tabId, message) });\n return response;\n }\n\n case \"PERF_START\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.startPerformanceTrace(tabId, message.categories);\n if (!result.success) throw new Error(result.error);\n return { success: true, message: \"Performance tracing started\" };\n }\n\n case \"PERF_STOP\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.stopPerformanceTrace(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, metrics: result.metrics };\n }\n\n case \"PERF_METRICS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.getPerformanceMetrics(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, metrics: result.metrics };\n }\n\n case \"UPLOAD_FILE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.ref) throw new Error(\"No ref provided\");\n if (!message.files || !message.files.length) throw new Error(\"No files provided\");\n const selectorResult = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_FILE_INPUT_SELECTOR\",\n ref: message.ref,\n }, { frameId: getFrameIdForTab(tabId, message) });\n if (selectorResult.error) throw new Error(selectorResult.error);\n const setResult = await cdp.setFileInputBySelector(tabId, selectorResult.selector, message.files);\n if (!setResult.success) throw new Error(setResult.error);\n return { success: true, filesSet: message.files.length };\n }\n\n case \"WAIT_FOR_LOAD\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.waitForLoad(tabId, message.timeout || 30000);\n if (!result.success) throw new Error(result.error);\n return { success: true, readyState: result.readyState };\n }\n\n case \"GET_FRAMES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.getFrames(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, frames: result.frames };\n }\n\n case \"FRAME_SWITCH\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const { selector, name, index } = message;\n\n if (!selector && !name && index === undefined) {\n throw new Error(\"--selector, --name, or --index required\");\n }\n\n // Get all frames using Chrome's webNavigation API (gives us correct frameIds for messaging)\n const chromeFrames = await chrome.webNavigation.getAllFrames({ tabId });\n if (!chromeFrames || chromeFrames.length === 0) {\n throw new Error(\"No frames found in tab\");\n }\n\n // Filter to child frames only (frameId !== 0)\n const childFrames = chromeFrames.filter(f => f.frameId !== 0);\n\n if (childFrames.length === 0) {\n throw new Error(\"No iframes found on this page\");\n }\n\n let targetFrame: chrome.webNavigation.GetAllFrameResultDetails | null = null;\n\n if (index !== undefined) {\n if (index < 0 || index >= childFrames.length) {\n throw new Error(`Frame index ${index} out of range. Found ${childFrames.length} frame(s).`);\n }\n targetFrame = childFrames[index];\n } else if (name) {\n // Try to find frame by name using content script in each frame\n for (const frame of childFrames) {\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_FRAME_NAME\",\n }, { frameId: frame.frameId });\n if (result?.name === name) {\n targetFrame = frame;\n break;\n }\n } catch {\n // Frame may not have content script loaded\n }\n }\n if (!targetFrame) {\n throw new Error(`Frame with name \"${name}\" not found`);\n }\n } else if (selector) {\n // Find frame by selector - ask main frame for iframe element's info\n try {\n const selectorResult = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_FRAME_BY_SELECTOR\",\n selector,\n }, { frameId: 0 });\n\n if (selectorResult?.error) throw new Error(selectorResult.error);\n\n // Match by URL since that's what we can reliably get\n if (selectorResult?.url) {\n targetFrame = childFrames.find(f => f.url === selectorResult.url) || null;\n }\n\n // If no URL match and only one child frame, use it\n if (!targetFrame && childFrames.length === 1) {\n targetFrame = childFrames[0];\n }\n } catch (e) {\n throw new Error(`Could not find frame with selector \"${selector}\"`);\n }\n }\n\n if (!targetFrame) {\n throw new Error(\"Frame not found\");\n }\n\n return {\n success: true,\n frameId: targetFrame.frameId,\n url: targetFrame.url,\n };\n }\n\n case \"FRAME_MAIN\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n\n // Clear frame context - go back to main frame (frameId 0)\n\n return { success: true, message: \"Returned to main frame\" };\n }\n\n case \"EVALUATE_IN_FRAME\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.frameId) throw new Error(\"No frameId provided\");\n if (!message.code) throw new Error(\"No code provided\");\n const result = await cdp.evaluateInFrame(tabId, message.frameId, message.code);\n if (!result.success) throw new Error(result.error);\n return { value: result.result };\n }\n\n case \"EXECUTE_JAVASCRIPT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.code) throw new Error(\"No code provided\");\n\n try {\n const piHelpersCode = `if(!window.piHelpers){const piHelpers={wait(ms){return new Promise(r=>setTimeout(r,ms))},async waitForSelector(sel,opts={}){const{state='visible',timeout=20000}=opts;const isVis=el=>el&&getComputedStyle(el).display!=='none'&&getComputedStyle(el).visibility!=='hidden'&&getComputedStyle(el).opacity!=='0'&&el.offsetWidth>0&&el.offsetHeight>0;const chk=()=>{const el=document.querySelector(sel);switch(state){case'attached':return el;case'detached':return el?null:document.body;case'hidden':return(!el||!isVis(el))?(el||document.body):null;default:return isVis(el)?el:null}};return new Promise((res,rej)=>{const r=chk();if(r){res(state==='detached'||state==='hidden'?null:r);return}const obs=new MutationObserver(()=>{const r=chk();if(r){obs.disconnect();clearTimeout(tid);res(state==='detached'||state==='hidden'?null:r)}});const tid=setTimeout(()=>{obs.disconnect();rej(new Error('Timeout'))},timeout);obs.observe(document.documentElement,{childList:true,subtree:true,attributes:true,attributeFilter:['style','class','hidden']})})},async waitForText(text,opts={}){const{selector,timeout=20000}=opts;const chk=()=>{const root=selector?document.querySelector(selector):document.body;if(!root)return null;const w=document.createTreeWalker(root,NodeFilter.SHOW_TEXT);while(w.nextNode())if(w.currentNode.textContent?.includes(text))return w.currentNode.parentElement;return null};return new Promise((res,rej)=>{const r=chk();if(r){res(r);return}const obs=new MutationObserver(()=>{const r=chk();if(r){obs.disconnect();clearTimeout(tid);res(r)}});const tid=setTimeout(()=>{obs.disconnect();rej(new Error('Timeout'))},timeout);obs.observe(document.documentElement,{childList:true,subtree:true,characterData:true})})},async waitForHidden(sel,t=20000){await piHelpers.waitForSelector(sel,{state:'hidden',timeout:t})},getByRole(role,opts={}){const{name}=opts;const roles={button:['button','input[type=button]','input[type=submit]','input[type=reset]'],link:['a[href]'],textbox:['input:not([type])','input[type=text]','input[type=email]','input[type=password]','textarea'],checkbox:['input[type=checkbox]'],radio:['input[type=radio]'],combobox:['select'],heading:['h1','h2','h3','h4','h5','h6']};const cands=[...document.querySelectorAll('[role='+role+']')];if(roles[role])roles[role].forEach(s=>cands.push(...document.querySelectorAll(s+':not([role])')));if(!name)return cands[0]||null;const n=name.toLowerCase().trim();for(const el of cands){const l=el.getAttribute('aria-label')?.toLowerCase().trim();const t=el.textContent?.toLowerCase().trim();if(l===n||t===n||l?.includes(n)||t?.includes(n))return el}return null}};window.__piHelpers=piHelpers;window.piHelpers=piHelpers}`;\n await cdp.evaluateScript(tabId, piHelpersCode);\n\n const body = codeWithExpressionReturn(message.code);\n const expression = `(async () => { 'use strict'; ${body} })()`;\n\n let result = await cdp.evaluateScript(tabId, expression);\n\n if (result.exceptionDetails && !scriptParses(body)) {\n result = await cdp.evaluateScript(tabId, `(async () => { 'use strict'; ${message.code} })()`);\n }\n\n if (result.exceptionDetails) {\n const err = result.exceptionDetails.exception?.description ||\n result.exceptionDetails.text ||\n \"Script execution failed\";\n return { error: err };\n }\n\n const value = result.result?.value;\n const output = value === undefined ? \"undefined\" : JSON.stringify(value, null, 2);\n return { output: output?.substring(0, 50000) || \"undefined\" };\n } catch (err) {\n const msg = err instanceof Error ? err.message : \"Script execution failed\";\n if (msg.includes(\"Cannot access\") || msg.includes(\"Cannot attach\")) {\n return { error: \"Cannot execute JavaScript on this page (restricted URL)\" };\n }\n return { error: msg };\n }\n }\n\n case \"ANIMATE_AUDIT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.selector || typeof message.selector !== \"string\") throw new Error(\"selector required\");\n\n if (typeof message.durationMs === \"boolean\") throw new Error(\"duration must be a number\");\n if (typeof message.fps === \"boolean\") throw new Error(\"fps must be a number\");\n const durationMs = message.durationMs !== undefined ? Number(message.durationMs) : 2000;\n const fps = message.fps !== undefined ? Number(message.fps) : 10;\n if (!Number.isFinite(durationMs) || durationMs < 100 || durationMs > 10000) {\n throw new Error(\"duration must be between 100 and 10000 ms\");\n }\n if (!Number.isFinite(fps) || fps < 1 || fps > 30) {\n throw new Error(\"fps must be between 1 and 30\");\n }\n\n try {\n const expression = `(async () => {\n const selector = ${JSON.stringify(message.selector)};\n const durationMs = ${Math.round(durationMs)};\n const fps = ${Math.round(fps)};\n const intervalMs = Math.max(1, Math.round(1000 / fps));\n const maxElements = 25;\n const maxSamples = Math.min(Math.floor(durationMs / intervalMs) + 1, 301);\n const startedAt = Date.now();\n const start = performance.now();\n const samples = [];\n const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\n const sample = () => {\n const now = performance.now();\n const elements = Array.from(document.querySelectorAll(selector)).slice(0, maxElements).map((el, index) => {\n const rect = el.getBoundingClientRect();\n const style = getComputedStyle(el);\n const text = (el.textContent || \"\").replace(/\\\\s+/g, \" \").trim().slice(0, 120);\n return {\n selector,\n index,\n rect: {\n x: Math.round(rect.x * 100) / 100,\n y: Math.round(rect.y * 100) / 100,\n width: Math.round(rect.width * 100) / 100,\n height: Math.round(rect.height * 100) / 100,\n top: Math.round(rect.top * 100) / 100,\n right: Math.round(rect.right * 100) / 100,\n bottom: Math.round(rect.bottom * 100) / 100,\n left: Math.round(rect.left * 100) / 100,\n },\n opacity: style.opacity,\n transform: style.transform,\n visibility: style.visibility,\n display: style.display,\n text,\n };\n });\n samples.push({ t: Math.round((now - start) * 100) / 100, timestamp: Date.now(), elements });\n };\n\n for (let i = 0; i < maxSamples; i++) {\n sample();\n const elapsed = performance.now() - start;\n if (elapsed >= durationMs || i === maxSamples - 1) break;\n await wait(Math.max(0, Math.min(intervalMs, durationMs - elapsed)));\n }\n\n return {\n selector,\n durationMs,\n fps,\n intervalMs,\n maxElementsPerSample: maxElements,\n startedAt,\n endedAt: Date.now(),\n sampleCount: samples.length,\n samples,\n };\n })()`;\n\n const result = await cdp.evaluateScript(tabId, expression);\n if (result.exceptionDetails) {\n const err = result.exceptionDetails.exception?.description ||\n result.exceptionDetails.text ||\n \"Animation audit failed\";\n return { error: err };\n }\n return result.result?.value ?? { error: \"Animation audit returned no data\" };\n } catch (err) {\n const msg = err instanceof Error ? err.message : \"Animation audit failed\";\n if (msg.includes(\"Cannot access\") || msg.includes(\"Cannot attach\")) {\n return { error: \"Cannot execute animation audit on this page (restricted URL)\" };\n }\n return { error: msg };\n }\n }\n\n case \"PERF_AUDIT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (typeof message.durationMs === \"boolean\") throw new Error(\"duration must be a number\");\n if (message.trigger !== undefined && typeof message.trigger !== \"string\") {\n throw new Error(\"trigger must be action:target\");\n }\n const durationMs = message.durationMs !== undefined ? Number(message.durationMs) : 3000;\n if (!Number.isFinite(durationMs) || durationMs < 100 || durationMs > 10000) {\n throw new Error(\"duration must be between 100 and 10000 ms\");\n }\n\n try {\n const expression = `(async () => {\n const durationMs = ${Math.round(durationMs)};\n const trigger = ${JSON.stringify(message.trigger || null)};\n const startedAt = Date.now();\n const startedAtPerformance = performance.now();\n const supportedEntryTypes = typeof PerformanceObserver !== \"undefined\" && Array.isArray(PerformanceObserver.supportedEntryTypes) ? PerformanceObserver.supportedEntryTypes : [];\n const requestedTypes = [\"layout-shift\", \"long-animation-frame\", \"event\", \"longtask\", \"paint\"];\n const observedEntryTypes = [];\n const entries = {\n layoutShifts: [],\n longAnimationFrames: [],\n events: [],\n longTasks: [],\n paints: [],\n };\n const round = (value) => Math.round(value * 100) / 100;\n const auditEndsAtPerformance = startedAtPerformance + durationMs;\n const inAuditWindow = (entry) => entry.startTime >= startedAtPerformance && entry.startTime <= auditEndsAtPerformance;\n const nodeSummary = (node) => {\n if (!node || node.nodeType !== Node.ELEMENT_NODE) return null;\n const el = node;\n return {\n tag: el.tagName?.toLowerCase(),\n id: el.id || undefined,\n className: typeof el.className === \"string\" ? el.className.slice(0, 120) : undefined,\n };\n };\n const rectSummary = (rect) => rect ? {\n x: round(rect.x),\n y: round(rect.y),\n width: round(rect.width),\n height: round(rect.height),\n top: round(rect.top),\n right: round(rect.right),\n bottom: round(rect.bottom),\n left: round(rect.left),\n } : null;\n const pushEntry = (entry) => {\n if (!inAuditWindow(entry)) return;\n if (entry.entryType === \"layout-shift\") {\n entries.layoutShifts.push({\n name: entry.name,\n startTime: round(entry.startTime),\n duration: round(entry.duration || 0),\n value: round(entry.value || 0),\n hadRecentInput: Boolean(entry.hadRecentInput),\n sources: Array.from(entry.sources || []).slice(0, 10).map((source) => ({\n node: nodeSummary(source.node),\n previousRect: rectSummary(source.previousRect),\n currentRect: rectSummary(source.currentRect),\n })),\n });\n return;\n }\n if (entry.entryType === \"long-animation-frame\") {\n entries.longAnimationFrames.push({\n name: entry.name,\n startTime: round(entry.startTime),\n duration: round(entry.duration || 0),\n renderStart: round(entry.renderStart || 0),\n styleAndLayoutStart: round(entry.styleAndLayoutStart || 0),\n blockingDuration: round(entry.blockingDuration || 0),\n firstUIEventTimestamp: round(entry.firstUIEventTimestamp || 0),\n scripts: Array.from(entry.scripts || []).slice(0, 10).map((script) => ({\n name: script.name,\n sourceURL: script.sourceURL,\n sourceFunctionName: script.sourceFunctionName,\n duration: round(script.duration || 0),\n invoker: script.invoker,\n invokerType: script.invokerType,\n })),\n });\n return;\n }\n if (entry.entryType === \"event\") {\n entries.events.push({\n name: entry.name,\n startTime: round(entry.startTime),\n duration: round(entry.duration || 0),\n processingStart: round(entry.processingStart || 0),\n processingEnd: round(entry.processingEnd || 0),\n interactionId: entry.interactionId || 0,\n cancelable: Boolean(entry.cancelable),\n });\n return;\n }\n if (entry.entryType === \"longtask\") {\n entries.longTasks.push({\n name: entry.name,\n startTime: round(entry.startTime),\n duration: round(entry.duration || 0),\n });\n return;\n }\n if (entry.entryType === \"paint\") {\n entries.paints.push({\n name: entry.name,\n startTime: round(entry.startTime),\n duration: round(entry.duration || 0),\n });\n }\n };\n const observers = [];\n for (const type of requestedTypes) {\n if (!supportedEntryTypes.includes(type)) continue;\n try {\n const observer = new PerformanceObserver((list) => {\n for (const entry of list.getEntries()) pushEntry(entry);\n });\n const options = type === \"event\"\n ? { type, buffered: true, durationThreshold: 16 }\n : { type, buffered: true };\n observer.observe(options);\n observers.push(observer);\n observedEntryTypes.push(type);\n } catch {}\n }\n const fireTrigger = () => {\n if (!trigger) return null;\n const separator = trigger.indexOf(\":\");\n if (separator === -1) throw new Error(\"trigger must be action:target\");\n const action = trigger.slice(0, separator).trim();\n const target = trigger.slice(separator + 1).trim();\n if (!action || !target) throw new Error(\"trigger must be action:target\");\n if (action === \"click\") {\n const el = document.querySelector(target);\n if (!el) return { action, selector: target, fired: false };\n el.click();\n return { action, selector: target, fired: true };\n }\n if (action === \"scroll\") {\n if ([\"up\", \"down\", \"left\", \"right\"].includes(target)) {\n const deltas = { up: [0, -500], down: [0, 500], left: [-500, 0], right: [500, 0] };\n const [left, top] = deltas[target];\n window.scrollBy({ left, top, behavior: \"instant\" });\n return { action, target, fired: true };\n }\n if (target === \"top\" || target === \"bottom\") {\n window.scrollTo({ top: target === \"top\" ? 0 : document.documentElement.scrollHeight, behavior: \"instant\" });\n return { action, target, fired: true };\n }\n const el = document.querySelector(target);\n if (!el) return { action, selector: target, fired: false };\n el.scrollTop = el.scrollHeight;\n el.dispatchEvent(new Event(\"scroll\", { bubbles: true }));\n return { action, selector: target, fired: true };\n }\n throw new Error(\"trigger action must be click or scroll\");\n };\n const triggerResult = fireTrigger();\n await new Promise((resolve) => setTimeout(resolve, durationMs));\n for (const observer of observers) observer.disconnect();\n const cls = entries.layoutShifts\n .filter((entry) => !entry.hadRecentInput)\n .reduce((sum, entry) => sum + entry.value, 0);\n const maxDuration = (items) => items.reduce((max, entry) => Math.max(max, entry.duration || 0), 0);\n const longTaskTotalDuration = entries.longTasks.reduce((sum, entry) => sum + (entry.duration || 0), 0);\n\n return {\n durationMs,\n startedAt,\n endedAt: Date.now(),\n elapsedMs: round(performance.now() - startedAtPerformance),\n supportedEntryTypes,\n observedEntryTypes,\n trigger: triggerResult,\n summary: {\n cumulativeLayoutShift: round(cls),\n maxEventDuration: round(maxDuration(entries.events)),\n maxLongAnimationFrame: round(maxDuration(entries.longAnimationFrames)),\n longTaskTotalDuration: round(longTaskTotalDuration),\n counts: {\n layoutShifts: entries.layoutShifts.length,\n longAnimationFrames: entries.longAnimationFrames.length,\n events: entries.events.length,\n longTasks: entries.longTasks.length,\n paints: entries.paints.length,\n },\n },\n entries,\n };\n })()`;\n\n const result = await cdp.evaluateScript(tabId, expression);\n if (result.exceptionDetails) {\n const err = result.exceptionDetails.exception?.description ||\n result.exceptionDetails.text ||\n \"Performance audit failed\";\n return { error: err };\n }\n return result.result?.value ?? { error: \"Performance audit returned no data\" };\n } catch (err) {\n const msg = err instanceof Error ? err.message : \"Performance audit failed\";\n if (msg.includes(\"Cannot access\") || msg.includes(\"Cannot attach\")) {\n return { error: \"Cannot execute performance audit on this page (restricted URL)\" };\n }\n return { error: msg };\n }\n }\n\n case \"READ_CONSOLE_MESSAGES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n\n try {\n await cdp.enableConsoleTracking(tabId);\n } catch (e) {}\n\n const messages = cdp.getConsoleMessages(tabId, {\n onlyErrors: message.onlyErrors,\n pattern: message.pattern,\n limit: message.limit || 100,\n });\n\n if (message.clear) {\n cdp.clearConsoleMessages(tabId);\n }\n\n return { messages };\n }\n\n case \"CLEAR_CONSOLE_MESSAGES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n cdp.clearConsoleMessages(tabId);\n return { success: true };\n }\n\n case \"START_NETWORK_CAPTURE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n cdp.clearNetworkRequests(tabId);\n await cdp.enableNetworkTracking(tabId, {\n bodyMode: message.bodyMode || \"text\",\n perBodyBytes: message.perBodyBytes,\n totalBytes: message.totalBodyBytes,\n });\n return { success: true };\n }\n\n case \"STOP_NETWORK_CAPTURE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await cdp.disableNetworkTracking(tabId);\n return { success: true };\n }\n\n case \"GET_PLAYBOOK_RECORD_CONTEXT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n let origin: string | undefined;\n try {\n if (tab.url) {\n const parsed = new URL(tab.url);\n if (parsed.protocol === \"http:\" || parsed.protocol === \"https:\") origin = parsed.origin;\n }\n } catch {}\n return { success: true, origin, url: tab.url };\n }\n\n case \"START_PLAYBOOK_WATCH\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await chrome.tabs.sendMessage(tabId, { type: \"PLAYBOOK_WATCH_START\", includeInputValues: message.includeInputValues === true }, { frameId: 0 });\n return { success: true };\n }\n\n case \"STOP_PLAYBOOK_WATCH\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await chrome.tabs.sendMessage(tabId, { type: \"PLAYBOOK_WATCH_STOP\" }, { frameId: 0 }).catch(() => {});\n return { success: true };\n }\n\n case \"PLAYBOOK_WATCH_EVENT\": {\n postToNativeHost({ ...message, tabId: sender.tab?.id, type: \"PLAYBOOK_WATCH_EVENT\" });\n return { success: true };\n }\n\n case \"READ_NETWORK_REQUESTS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n\n try {\n if (message.bodyMode !== undefined || message.perBodyBytes !== undefined || message.totalBodyBytes !== undefined) {\n await cdp.enableNetworkTracking(tabId, { bodyMode: message.bodyMode, perBodyBytes: message.perBodyBytes, totalBytes: message.totalBodyBytes });\n } else await cdp.enableNetworkTracking(tabId);\n } catch (e) {}\n await cdp.drainNetworkEvents(tabId);\n\n // If full flag is passed, use getNetworkEntries for rich data\n if (message.full) {\n let entries = cdp.getNetworkEntries(tabId, {\n urlPattern: message.urlPattern,\n });\n\n // Apply filters\n if (message.method) {\n entries = entries.filter(e => e.method === message.method);\n }\n if (message.status) {\n entries = entries.filter(e => e.status === message.status);\n }\n if (message.contentType) {\n entries = entries.filter(e => e.type === message.contentType);\n }\n\n if (message.clear) {\n cdp.clearNetworkRequests(tabId);\n }\n\n // Return entries sliced to limit\n const limit = message.limit || 100;\n return {\n entries: entries.slice(0, limit),\n format: message.format,\n verbose: message.verbose\n };\n }\n\n let requests = cdp.getNetworkRequests(tabId, {\n urlPattern: message.urlPattern,\n limit: message.limit || 100,\n });\n\n // Apply filters\n if (message.method) {\n requests = requests.filter(r => r.method === message.method);\n }\n if (message.status) {\n requests = requests.filter(r => r.status === message.status);\n }\n if (message.contentType) {\n requests = requests.filter(r => r.type === message.contentType);\n }\n\n if (message.clear) {\n cdp.clearNetworkRequests(tabId);\n }\n\n return {\n requests,\n format: message.format,\n verbose: message.verbose\n };\n }\n\n case \"EXPORT_NETWORK_REQUESTS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.har && message.jsonl) throw new Error(\"network export cannot combine HAR and JSONL\");\n try {\n if (message.bodyMode !== undefined || message.perBodyBytes !== undefined || message.totalBodyBytes !== undefined) {\n await cdp.enableNetworkTracking(tabId, { bodyMode: message.bodyMode, perBodyBytes: message.perBodyBytes, totalBytes: message.totalBodyBytes });\n } else await cdp.enableNetworkTracking(tabId);\n } catch (e) {}\n await cdp.drainNetworkEvents(tabId);\n const entries = cdp.getNetworkEntries(tabId, {});\n const serializedSize = new TextEncoder().encode(JSON.stringify(entries)).byteLength;\n if (serializedSize > 16 * 1024 * 1024) {\n throw new Error(\"network export source exceeds the 16 MiB native-message limit\");\n }\n return { entries, har: Boolean(message.har), jsonl: Boolean(message.jsonl) };\n }\n\n case \"CLEAR_NETWORK_REQUESTS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n cdp.clearNetworkRequests(tabId);\n return { success: true };\n }\n\n case \"GET_NETWORK_ENTRIES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n\n try {\n await cdp.enableNetworkTracking(tabId);\n } catch (e) {}\n await cdp.drainNetworkEvents(tabId);\n\n let entries = cdp.getNetworkEntries(tabId, {\n urlPattern: message.urlPattern,\n includeStatic: !message.excludeStatic,\n });\n\n // Apply additional filters\n if (message.origin) {\n entries = entries.filter(e => e.origin === message.origin);\n }\n if (message.method) {\n entries = entries.filter(e => e.method === message.method);\n }\n if (message.status) {\n entries = entries.filter(e => e.status === message.status);\n }\n if (message.type) {\n entries = entries.filter(e => e.type === message.type);\n }\n if (message.since) {\n entries = entries.filter(e => e.ts >= message.since);\n }\n if (message.hasBody !== undefined) {\n entries = entries.filter(e => message.hasBody ? (e.responseBodySize && e.responseBodySize > 0) : !e.responseBodySize);\n }\n if (message.last) {\n entries = entries.slice(-message.last);\n }\n\n if (message.clear) {\n cdp.clearNetworkRequests(tabId);\n }\n\n return { entries };\n }\n\n case \"GET_NETWORK_ENTRY\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.requestId) throw new Error(\"No requestId provided\");\n await cdp.drainNetworkEvents(tabId);\n\n // First try direct lookup by CDP requestId\n let entry = cdp.getNetworkEntry(tabId, message.requestId);\n\n // If not found, try lookup by entry.id (r_xxx format)\n if (!entry) {\n const entries = cdp.getNetworkEntries(tabId, {});\n entry = entries.find(e => e.id === message.requestId) || null;\n }\n\n // Also try lookup by _requestId for entries that use the generated id\n if (!entry) {\n const entries = cdp.getNetworkEntries(tabId, {});\n entry = entries.find(e => e._requestId === message.requestId) || null;\n }\n\n if (!entry) {\n return { error: `Entry not found: ${message.requestId}` };\n }\n return { entry };\n }\n\n case \"GET_RESPONSE_BODY\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.requestId) throw new Error(\"No requestId provided\");\n await cdp.drainNetworkEvents(tabId);\n\n // If requestId looks like entry.id format (r_xxx), look up the CDP requestId\n let cdpRequestId = message.requestId;\n if (message.requestId.startsWith('r_')) {\n const entries = cdp.getNetworkEntries(tabId, {});\n const entry = entries.find(e => e.id === message.requestId);\n if (entry) {\n cdpRequestId = entry._requestId;\n }\n }\n\n const result = await cdp.getResponseBody(tabId, cdpRequestId);\n return result;\n }\n\n case \"GET_NETWORK_ORIGINS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await cdp.drainNetworkEvents(tabId);\n\n const entries = cdp.getNetworkEntries(tabId, {});\n const origins: Record<string, { count: number; lastSeen: number; size: number }> = {};\n\n for (const entry of entries) {\n if (!origins[entry.origin]) {\n origins[entry.origin] = { count: 0, lastSeen: 0, size: 0 };\n }\n origins[entry.origin].count++;\n origins[entry.origin].lastSeen = Math.max(origins[entry.origin].lastSeen, entry.ts);\n origins[entry.origin].size += (entry.responseBodySize || 0);\n }\n\n return { origins };\n }\n\n case \"GET_NETWORK_STATS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await cdp.drainNetworkEvents(tabId);\n\n const entries = cdp.getNetworkEntries(tabId, {});\n const origins: Record<string, number> = {};\n const byMethod: Record<string, number> = {};\n const byStatus: Record<string, number> = {};\n let totalSize = 0;\n let oldestEntry = Infinity;\n let newestEntry = 0;\n\n for (const entry of entries) {\n // Count by origin\n if (!origins[entry.origin]) {\n origins[entry.origin] = 0;\n }\n origins[entry.origin]++;\n\n // Count by method\n const method = entry.method || 'GET';\n byMethod[method] = (byMethod[method] || 0) + 1;\n\n // Count by status\n if (entry.status) {\n const statusGroup = `${Math.floor(entry.status / 100)}xx`;\n byStatus[statusGroup] = (byStatus[statusGroup] || 0) + 1;\n }\n\n // Sum size\n totalSize += (entry.responseBodySize || 0);\n\n // Track time range\n if (entry.ts < oldestEntry) oldestEntry = entry.ts;\n if (entry.ts > newestEntry) newestEntry = entry.ts;\n }\n\n return {\n stats: {\n totalRequests: entries.length,\n totalSize,\n uniqueOrigins: Object.keys(origins).length,\n startTime: oldestEntry === Infinity ? null : oldestEntry,\n duration: (newestEntry && oldestEntry !== Infinity) ? newestEntry - oldestEntry : 0,\n byMethod,\n byStatus,\n }\n };\n }\n\n case \"RESIZE_WINDOW\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.width === undefined && message.height === undefined) {\n throw new Error(\"width or height required\");\n }\n\n const tab = await chrome.tabs.get(tabId);\n if (!tab.windowId) throw new Error(\"Tab has no window\");\n\n const currentWindow =\n message.width === undefined || message.height === undefined\n ? await chrome.windows.get(tab.windowId)\n : null;\n const width = message.width === undefined ? currentWindow?.width : message.width;\n const height = message.height === undefined ? currentWindow?.height : message.height;\n if (width === undefined || height === undefined) {\n throw new Error(\"current window size unavailable\");\n }\n\n await chrome.windows.update(tab.windowId, {\n width: Math.floor(width),\n height: Math.floor(height),\n });\n\n return { success: true, width, height };\n }\n\n case \"TABS_CREATE\": {\n const activeTab = tabId ? await chrome.tabs.get(tabId) : null;\n\n const newTab = await chrome.tabs.create({\n url: message.url || \"about:blank\",\n active: false,\n });\n\n if (!newTab.id) throw new Error(\"Failed to create tab\");\n\n if (activeTab?.groupId && activeTab.groupId !== chrome.tabGroups.TAB_GROUP_ID_NONE) {\n await chrome.tabs.group({ tabIds: newTab.id, groupId: activeTab.groupId });\n }\n\n return {\n success: true,\n tabId: newTab.id,\n url: newTab.url || message.url || \"about:blank\"\n };\n }\n\n case \"UPLOAD_IMAGE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.screenshotId) throw new Error(\"screenshotId required\");\n if (!message.ref && !message.coordinate) throw new Error(\"ref or coordinate required\");\n\n const screenshot = getScreenshot(message.screenshotId);\n if (!screenshot) throw new Error(`Screenshot not found: ${message.screenshotId}`);\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"UPLOAD_IMAGE\",\n base64: screenshot.base64,\n ref: message.ref,\n coordinate: message.coordinate,\n filename: message.filename || \"screenshot.png\",\n }, { frameId: getFrameIdForTab(tabId, message) });\n\n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"GET_TABS\": {\n const tabs = await chrome.tabs.query({});\n return {\n tabs: tabs.map((t) => ({ id: t.id, title: t.title, url: t.url })),\n };\n }\n\n case \"LIST_TABS\": {\n const queryOptions: chrome.tabs.QueryInfo = {};\n // Support filtering by window\n if (message.windowId) {\n queryOptions.windowId = message.windowId;\n }\n const tabs = await chrome.tabs.query(queryOptions);\n return {\n tabs: tabs.map((t) => ({\n id: t.id,\n title: t.title,\n url: t.url,\n active: t.active,\n windowId: t.windowId,\n })),\n };\n }\n\n case \"NEW_TAB\": {\n const urls = message.urls || (message.url ? [message.url] : [\"about:blank\"]);\n const createdTabs = [];\n for (let i = 0; i < urls.length; i++) {\n const createOptions: chrome.tabs.CreateProperties = {\n url: urls[i],\n active: i === 0,\n };\n // Support creating tab in specific window\n if (message.windowId) {\n createOptions.windowId = message.windowId;\n }\n const newTab = await chrome.tabs.create(createOptions);\n if (newTab.id) createdTabs.push({ tabId: newTab.id, url: urls[i] });\n }\n if (createdTabs.length === 1) {\n return { success: true, tabId: createdTabs[0].tabId, url: createdTabs[0].url };\n }\n return { success: true, tabs: createdTabs };\n }\n\n case \"SWITCH_TAB\": {\n const targetTabId = message.tabId;\n if (!targetTabId) throw new Error(\"No tabId provided\");\n const tab = (await chrome.tabs.update(targetTabId, { active: true })) as chrome.tabs.Tab;\n if (tab.windowId) {\n await chrome.windows.update(tab.windowId, { focused: true });\n }\n return { success: true, tabId: targetTabId, url: tab.url, title: tab.title };\n }\n\n case \"CLOSE_TAB\": {\n const tabIds = message.tabIds || (message.tabId ? [message.tabId] : []);\n if (tabIds.length === 0) throw new Error(\"No tabId(s) provided\");\n await chrome.tabs.remove(tabIds);\n if (tabIds.length === 1) {\n return { success: true, tabId: tabIds[0] };\n }\n return { success: true, closed: tabIds };\n }\n\n case \"TAB_MOVE\": {\n const rawTabIds = message.tabIds || (message.tabId ? [message.tabId] : []);\n const tabIds = (Array.isArray(rawTabIds) ? rawTabIds : String(rawTabIds).split(\",\"))\n .map((id) => Number(id));\n if (tabIds.length === 0) throw new Error(\"No tabId(s) provided\");\n if (tabIds.some((id) => !Number.isInteger(id) || id <= 0)) {\n throw new Error(\"Invalid tabId(s)\");\n }\n\n const windowId = Number(message.windowId);\n if (!Number.isInteger(windowId) || windowId <= 0) {\n throw new Error(\"No destination windowId provided\");\n }\n\n const index = message.index !== undefined ? Number(message.index) : -1;\n if (!Number.isInteger(index) || index < -1) throw new Error(\"Invalid tab index\");\n\n const moveProperties = { windowId, index };\n const movedTabs = tabIds.length === 1\n ? await chrome.tabs.move(tabIds[0], moveProperties)\n : await chrome.tabs.move(tabIds, moveProperties);\n\n return {\n success: true,\n moved: tabIds,\n destinationWindowId: windowId,\n index,\n tabs: Array.isArray(movedTabs) ? movedTabs : [movedTabs],\n };\n }\n\n case \"TABS_REGISTER\": {\n let targetTabId = tabId;\n if (!targetTabId) {\n const queryOptions: chrome.tabs.QueryInfo = message.windowId\n ? { active: true, windowId: message.windowId }\n : { active: true, lastFocusedWindow: true };\n const [activeTab] = await chrome.tabs.query(queryOptions);\n if (activeTab && !isRestrictedTabUrl(activeTab.url)) {\n targetTabId = activeTab.id;\n } else {\n throw new Error(\n \"Cannot register a restricted browser or extension page. Focus a regular web page, or pass an explicit tabId.\"\n );\n }\n }\n if (!targetTabId) throw new Error(\"No active tab found\");\n if (!message.name) throw new Error(\"No name provided\");\n tabNameRegistry.set(message.name, targetTabId);\n return { success: true, name: message.name, tabId: targetTabId };\n }\n\n case \"TABS_GET_BY_NAME\": {\n if (!message.name) throw new Error(\"No name provided\");\n const registeredTabId = tabNameRegistry.get(message.name);\n if (!registeredTabId) {\n return { error: `No tab registered with name \"${message.name}\"` };\n }\n try {\n const tab = await chrome.tabs.get(registeredTabId);\n return { tabId: registeredTabId, url: tab.url, title: tab.title };\n } catch (e) {\n tabNameRegistry.delete(message.name);\n return { error: `Tab \"${message.name}\" no longer exists` };\n }\n }\n\n case \"TABS_LIST_NAMED\": {\n const namedTabs: { name: string; tabId: number; url?: string; title?: string }[] = [];\n for (const [name, id] of tabNameRegistry) {\n try {\n const tab = await chrome.tabs.get(id);\n namedTabs.push({ name, tabId: id, url: tab.url, title: tab.title });\n } catch (e) {\n tabNameRegistry.delete(name);\n }\n }\n return { tabs: namedTabs };\n }\n\n case \"TABS_UNREGISTER\": {\n if (!message.name) throw new Error(\"No name provided\");\n const deleted = tabNameRegistry.delete(message.name);\n if (!deleted) {\n return { success: false, error: `No tab registered with name \"${message.name}\"` };\n }\n return { success: true };\n }\n\n case \"GET_AUTH\": {\n const { sendToNativeHost } = await import(\"../native/port-manager\");\n try {\n const result = await sendToNativeHost({ type: \"GET_AUTH\" });\n return result;\n } catch (err) {\n return {\n auth: null,\n hint: \"Native host not connected. Make sure surf native host is installed.\"\n };\n }\n }\n\n case \"NATIVE_API_REQUEST\": {\n const { sendToNativeHost } = await import(\"../native/port-manager\");\n try {\n await sendToNativeHost({\n type: \"API_REQUEST\",\n streamId: message.streamId,\n url: message.url,\n method: message.method,\n headers: message.headers,\n body: message.body,\n });\n return { sent: true };\n } catch (err) {\n return { error: err instanceof Error ? err.message : \"Unknown error\" };\n }\n }\n\n case \"STREAM_CONSOLE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const streamId = message.streamId;\n\n try {\n await cdp.enableConsoleTracking(tabId);\n activeStreamTabs.set(streamId, tabId);\n\n cdp.subscribeToConsole(tabId, streamId, (event) => {\n postToNativeHost({\n type: \"STREAM_EVENT\",\n streamId,\n event: {\n type: \"console_event\",\n level: event.type === \"exception\" ? \"error\" : event.type,\n text: event.text,\n timestamp: event.timestamp,\n url: event.url,\n line: event.line,\n },\n });\n });\n\n return { success: true, streaming: true };\n } catch (err) {\n postToNativeHost({\n type: \"STREAM_ERROR\",\n streamId,\n error: err instanceof Error ? err.message : \"Failed to start console stream\",\n });\n return { error: err instanceof Error ? err.message : \"Failed to start console stream\" };\n }\n }\n\n case \"STREAM_NETWORK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const streamId = message.streamId;\n\n try {\n await cdp.enableNetworkTracking(tabId);\n activeStreamTabs.set(streamId, tabId);\n\n cdp.subscribeToNetwork(tabId, streamId, (event) => {\n postToNativeHost({\n type: \"STREAM_EVENT\",\n streamId,\n event: {\n type: \"network_event\",\n method: event.method,\n url: event.url,\n status: event.status,\n duration: event.duration,\n timestamp: event.timestamp,\n },\n });\n });\n\n return { success: true, streaming: true };\n } catch (err) {\n postToNativeHost({\n type: \"STREAM_ERROR\",\n streamId,\n error: err instanceof Error ? err.message : \"Failed to start network stream\",\n });\n return { error: err instanceof Error ? err.message : \"Failed to start network stream\" };\n }\n }\n\n case \"STREAM_STOP\": {\n const streamId = message.streamId;\n const streamTabId = activeStreamTabs.get(streamId);\n\n if (streamTabId !== undefined) {\n cdp.unsubscribeFromConsole(streamTabId, streamId);\n cdp.unsubscribeFromNetwork(streamTabId, streamId);\n activeStreamTabs.delete(streamId);\n }\n\n return { success: true };\n }\n\n case \"SEARCH_PAGE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.term) throw new Error(\"Search term required\");\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"SEARCH_PAGE\",\n term: message.term,\n caseSensitive: message.caseSensitive || false,\n limit: message.limit || 10,\n }, { frameId: getFrameIdForTab(tabId, message) });\n return result;\n } catch {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"TAB_GROUP_CREATE\": {\n const tabIds: number[] = [...(message.tabIds || [])];\n const name = message.name || \"Surf\";\n const validColors = [\"grey\", \"blue\", \"red\", \"yellow\", \"green\", \"pink\", \"purple\", \"cyan\", \"orange\"];\n const color = validColors.includes(message.color) ? message.color : \"blue\";\n\n if (tabIds.length === 0 && tabId) {\n tabIds.push(tabId);\n }\n\n if (tabIds.length === 0) throw new Error(\"No tabs specified\");\n const groupTabIds = tabIds.length === 1 ? tabIds[0] : (tabIds as [number, ...number[]]);\n\n const existingGroups = await chrome.tabGroups.query({ title: name });\n let groupId: number;\n\n if (existingGroups.length > 0) {\n groupId = existingGroups[0].id;\n await chrome.tabs.group({ tabIds: groupTabIds, groupId });\n } else {\n groupId = await chrome.tabs.group({ tabIds: groupTabIds });\n await chrome.tabGroups.update(groupId, {\n title: name,\n color: color as `${chrome.tabGroups.Color}`,\n collapsed: false,\n });\n }\n\n return { success: true, groupId, name, tabIds };\n }\n\n case \"TAB_GROUP_REMOVE\": {\n const tabIds: number[] = [...(message.tabIds || [])];\n if (tabIds.length === 0 && tabId) {\n tabIds.push(tabId);\n }\n\n if (tabIds.length === 0) throw new Error(\"No tabs specified\");\n const ungroupTabIds = tabIds.length === 1 ? tabIds[0] : (tabIds as [number, ...number[]]);\n\n await chrome.tabs.ungroup(ungroupTabIds);\n return { success: true, ungrouped: tabIds };\n }\n\n case \"TAB_GROUPS_LIST\": {\n const groups = await chrome.tabGroups.query({});\n const result = [];\n\n for (const group of groups) {\n const tabs = await chrome.tabs.query({ groupId: group.id });\n result.push({\n id: group.id,\n name: group.title || \"(unnamed)\",\n color: group.color,\n collapsed: group.collapsed,\n tabs: tabs.map(t => ({ id: t.id, title: t.title, url: t.url })),\n });\n }\n\n return { groups: result };\n }\n\n case \"CLICK_SELECTOR\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const selector = message.selector;\n const index = message.index || 0;\n const frameId = getFrameIdForTab(tabId, message);\n\n if (frameId > 0) {\n const [result] = await chrome.scripting.executeScript({\n target: { tabId, frameIds: [frameId] },\n func: (selector: string, index: number) => {\n const elements = document.querySelectorAll(selector);\n if (elements.length === 0) return { error: \"No elements match selector\" };\n if (index >= elements.length) return { error: `Index ${index} out of range (found ${elements.length} elements)` };\n\n (elements[index] as HTMLElement).click();\n return { success: true, selector, index, matchCount: elements.length };\n },\n args: [selector, index],\n });\n return result?.result || { error: \"Failed to click element\" };\n }\n\n const script = `(() => {\n const elements = document.querySelectorAll(${JSON.stringify(selector)});\n if (elements.length === 0) return { error: \"No elements match selector\" };\n if (${index} >= elements.length) return { error: \"Index \" + ${index} + \" out of range (found \" + elements.length + \" elements)\" };\n\n const el = elements[${index}];\n const rect = el.getBoundingClientRect();\n return {\n x: rect.left + rect.width / 2,\n y: rect.top + rect.height / 2,\n count: elements.length\n };\n })()`;\n\n const result = await cdp.evaluateScript(tabId, script);\n const coords = result.result?.value;\n\n if (coords?.error) return { error: coords.error };\n if (!coords) return { error: \"Failed to get element coordinates\" };\n\n await cdp.click(tabId, coords.x, coords.y, \"left\", 1, 0);\n return { success: true, selector, index, matchCount: coords.count };\n }\n\n case \"COOKIE_LIST\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n const cookies = await chrome.cookies.getAll({ url });\n return { cookies };\n }\n\n case \"COOKIE_GET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n if (!message.name) throw new Error(\"Cookie name required\");\n const cookie = await chrome.cookies.get({ url, name: message.name });\n if (!cookie) return { error: `Cookie \"${message.name}\" not found` };\n return { cookie };\n }\n\n case \"COOKIE_SET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n if (!message.name) throw new Error(\"Cookie name required\");\n if (message.value === undefined) throw new Error(\"Cookie value required\");\n\n const cookieDetails: chrome.cookies.SetDetails = {\n url,\n name: message.name,\n value: message.value,\n };\n\n if (message.expires) {\n const expirationDate = new Date(message.expires).getTime() / 1000;\n if (isNaN(expirationDate)) {\n throw new Error(`Invalid expiration date: ${message.expires}`);\n }\n cookieDetails.expirationDate = expirationDate;\n }\n\n const result = await chrome.cookies.set(cookieDetails);\n return { success: true, cookie: result };\n }\n\n case \"COOKIE_CLEAR\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n if (!message.name) throw new Error(\"Cookie name required\");\n\n await chrome.cookies.remove({ url, name: message.name });\n return { success: true, cleared: message.name };\n }\n\n case \"COOKIE_CLEAR_ALL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n\n const cookies = await chrome.cookies.getAll({ url });\n for (const cookie of cookies) {\n await chrome.cookies.remove({ url, name: cookie.name });\n }\n return { success: true, cleared: cookies.length };\n }\n\n case \"TAB_RELOAD\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await chrome.tabs.reload(tabId, { bypassCache: message.hard || false });\n return { success: true };\n }\n\n case \"ZOOM_GET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const zoom = await chrome.tabs.getZoom(tabId);\n return { zoom };\n }\n\n case \"ZOOM_SET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const level = message.level;\n if (level < 0.25 || level > 5) throw new Error(\"Zoom level must be between 0.25 and 5\");\n await chrome.tabs.setZoom(tabId, level);\n return { success: true, zoom: level };\n }\n\n case \"ZOOM_RESET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await chrome.tabs.setZoom(tabId, 0);\n return { success: true, zoom: 1.0 };\n }\n\n case \"BOOKMARK_ADD\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const createProps: { title: string; url?: string; parentId?: string } = {\n title: tab.title || \"Untitled\",\n url: tab.url,\n };\n if (message.folder) {\n const search = await chrome.bookmarks.search({ title: message.folder });\n const folder = search.find(b => !b.url);\n if (folder) {\n createProps.parentId = folder.id;\n }\n }\n const bookmark = await chrome.bookmarks.create(createProps);\n return { success: true, bookmark: { id: bookmark.id, title: bookmark.title, url: bookmark.url } };\n }\n\n case \"BOOKMARK_REMOVE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n if (!tab.url) throw new Error(\"Tab has no URL\");\n const bookmarks = await chrome.bookmarks.search({ url: tab.url });\n if (bookmarks.length === 0) throw new Error(\"No bookmark found for this URL\");\n await chrome.bookmarks.remove(bookmarks[0].id);\n return { success: true };\n }\n\n case \"BOOKMARK_LIST\": {\n const limit = typeof message.limit === 'number' ? message.limit : 50;\n let bookmarks: chrome.bookmarks.BookmarkTreeNode[] = [];\n\n if (message.folder) {\n const search = await chrome.bookmarks.search({ title: message.folder });\n const folder = search.find(b => !b.url);\n if (folder) {\n const children = await chrome.bookmarks.getChildren(folder.id);\n bookmarks = children.filter(b => b.url).slice(0, limit);\n }\n } else {\n const recent = await chrome.bookmarks.getRecent(limit);\n bookmarks = recent;\n }\n\n return {\n bookmarks: bookmarks.map(b => ({\n id: b.id,\n title: b.title,\n url: b.url,\n dateAdded: b.dateAdded\n }))\n };\n }\n\n case \"HISTORY_LIST\": {\n const limit = typeof message.limit === 'number' ? message.limit : 20;\n const items = await chrome.history.search({\n text: \"\",\n maxResults: limit,\n startTime: 0\n });\n return {\n history: items.map(h => ({\n url: h.url,\n title: h.title,\n lastVisitTime: h.lastVisitTime,\n visitCount: h.visitCount\n }))\n };\n }\n\n case \"HISTORY_SEARCH\": {\n const query = message.query;\n const limit = typeof message.limit === 'number' ? message.limit : 20;\n const items = await chrome.history.search({\n text: query,\n maxResults: limit,\n startTime: 0\n });\n return {\n history: items.map(h => ({\n url: h.url,\n title: h.title,\n lastVisitTime: h.lastVisitTime,\n visitCount: h.visitCount\n }))\n };\n }\n\n case \"GET_CHATGPT_COOKIES\": {\n const cookies = await chrome.cookies.getAll({ domain: \".chatgpt.com\" });\n const openaiCookies = await chrome.cookies.getAll({ domain: \".openai.com\" });\n return { cookies: [...cookies, ...openaiCookies] };\n }\n\n case \"CHATGPT_NEW_TAB\": {\n const tab = await chrome.tabs.create({\n url: \"https://chatgpt.com/\",\n active: true,\n });\n if (!tab.id) throw new Error(\"Failed to create tab\");\n const currentTab = await chrome.tabs.get(tab.id);\n if (currentTab.status !== \"complete\") {\n await new Promise<void>((resolve) => {\n const listener = (tabId: number, info: chrome.tabs.OnUpdatedInfo) => {\n if (tabId === tab.id && info.status === \"complete\") {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }\n };\n chrome.tabs.onUpdated.addListener(listener);\n setTimeout(() => {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }, 30000);\n });\n }\n await cdp.attach(tab.id);\n // Wait for JS runtime to be ready after CDP attach\n await waitForRuntimeReady(tab.id, 10000);\n return { tabId: tab.id };\n }\n\n case \"CHATGPT_CLOSE_TAB\": {\n const chatTabId = message.tabId;\n if (chatTabId) {\n try {\n await cdp.detach(chatTabId);\n } catch {}\n try {\n await chrome.tabs.remove(chatTabId);\n } catch {}\n }\n return { success: true };\n }\n\n case \"CHATGPT_CDP_COMMAND\": {\n const { method, params } = message;\n const result = await cdp.sendCommand(message.tabId, method, params || {});\n return result;\n }\n\n case \"CHATGPT_EVALUATE\": {\n const result = await cdp.evaluateScript(message.tabId, message.expression);\n return result;\n }\n\n case \"PERPLEXITY_NEW_TAB\": {\n const tab = await chrome.tabs.create({\n url: \"https://www.perplexity.ai/\",\n active: true,\n });\n if (!tab.id) throw new Error(\"Failed to create tab\");\n const currentTab = await chrome.tabs.get(tab.id);\n if (currentTab.status !== \"complete\") {\n await new Promise<void>((resolve) => {\n const listener = (tabId: number, info: chrome.tabs.OnUpdatedInfo) => {\n if (tabId === tab.id && info.status === \"complete\") {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }\n };\n chrome.tabs.onUpdated.addListener(listener);\n setTimeout(() => {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }, 30000);\n });\n }\n await cdp.attach(tab.id);\n // Wait for JS runtime to be ready after CDP attach\n await waitForRuntimeReady(tab.id, 10000);\n return { tabId: tab.id };\n }\n\n case \"PERPLEXITY_CLOSE_TAB\": {\n const pplxTabId = message.tabId;\n if (pplxTabId) {\n try {\n await cdp.detach(pplxTabId);\n } catch {}\n try {\n await chrome.tabs.remove(pplxTabId);\n } catch {}\n }\n return { success: true };\n }\n\n case \"PERPLEXITY_CDP_COMMAND\": {\n const { method, params } = message;\n const result = await cdp.sendCommand(message.tabId, method, params || {});\n return result;\n }\n\n case \"PERPLEXITY_EVALUATE\": {\n const result = await cdp.evaluateScript(message.tabId, message.expression);\n return result;\n }\n\n case \"GET_TWITTER_COOKIES\": {\n // Grok requires X.com cookies for authentication\n const domains = [\".x.com\", \".twitter.com\", \"x.com\", \"twitter.com\"];\n const allCookies: chrome.cookies.Cookie[] = [];\n\n for (const domain of domains) {\n try {\n const cookies = await chrome.cookies.getAll({ domain });\n allCookies.push(...cookies);\n } catch {}\n }\n\n // Also try by URL\n const urls = [\"https://x.com\", \"https://twitter.com\"];\n for (const url of urls) {\n try {\n const cookies = await chrome.cookies.getAll({ url });\n allCookies.push(...cookies);\n } catch {}\n }\n\n // Dedupe by name\n const seen = new Map<string, chrome.cookies.Cookie>();\n for (const cookie of allCookies) {\n const existing = seen.get(cookie.name);\n if (!existing || cookie.domain?.includes(\"x.com\")) {\n seen.set(cookie.name, cookie);\n }\n }\n\n return { cookies: Array.from(seen.values()) };\n }\n\n case \"GROK_NEW_TAB\": {\n const tab = await chrome.tabs.create({\n url: \"https://x.com/i/grok\",\n active: true,\n });\n if (!tab.id) throw new Error(\"Failed to create tab\");\n const currentTab = await chrome.tabs.get(tab.id);\n if (currentTab.status !== \"complete\") {\n await new Promise<void>((resolve) => {\n const listener = (tabId: number, info: chrome.tabs.OnUpdatedInfo) => {\n if (tabId === tab.id && info.status === \"complete\") {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }\n };\n chrome.tabs.onUpdated.addListener(listener);\n setTimeout(() => {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }, 30000);\n });\n }\n await cdp.attach(tab.id);\n // Wait for JS runtime to be ready after CDP attach\n await waitForRuntimeReady(tab.id, 10000);\n return { tabId: tab.id };\n }\n\n case \"GROK_CLOSE_TAB\": {\n const grokTabId = message.tabId;\n if (grokTabId) {\n try {\n await cdp.detach(grokTabId);\n } catch {}\n try {\n await chrome.tabs.remove(grokTabId);\n } catch {}\n }\n return { success: true };\n }\n\n case \"GROK_CDP_COMMAND\": {\n const { method, params } = message;\n const result = await cdp.sendCommand(message.tabId, method, params || {});\n return result;\n }\n\n case \"GROK_EVALUATE\": {\n const result = await cdp.evaluateScript(message.tabId, message.expression);\n return result;\n }\n\n case \"GEMINI_NEW_TAB\": {\n const tab = await chrome.tabs.create({\n url: \"https://gemini.google.com/app\",\n active: true,\n });\n if (!tab.id) throw new Error(\"Failed to create tab\");\n return { tabId: tab.id };\n }\n\n case \"GEMINI_CLOSE_TAB\": {\n const geminiTabId = message.tabId;\n if (geminiTabId) {\n try {\n await cdp.detach(geminiTabId);\n } catch {}\n try {\n await chrome.tabs.remove(geminiTabId);\n } catch {}\n }\n return { success: true };\n }\n\n case \"AI_UPLOAD_FILE_TO_TAB\":\n case \"UPLOAD_FILE_TO_TAB\": {\n const { tabId: uploadTabId, filePaths } = message;\n const provider = message.type === \"UPLOAD_FILE_TO_TAB\" ? \"gemini\" : message.provider;\n if (!uploadTabId || !filePaths?.length) {\n throw new Error(`${message.type} requires tabId and filePaths`);\n }\n if (provider !== \"gemini\" && provider !== \"chatgpt\") {\n throw new Error(`Unsupported upload provider: ${provider}`);\n }\n return uploadFilesToProviderTab(provider, uploadTabId, filePaths);\n }\n\n case \"GEMINI_FETCH_URL\": {\n const imageUrl = message.url;\n if (!imageUrl) throw new Error(\"No URL provided\");\n const resp = await fetch(imageUrl, { credentials: \"include\" });\n if (!resp.ok) throw new Error(`Fetch failed: ${resp.status}`);\n const blob = await resp.blob();\n const reader = new FileReader();\n const b64: string = await new Promise((resolve, reject) => {\n reader.onload = () => resolve((reader.result as string).split(\",\")[1]);\n reader.onerror = () => reject(new Error(\"FileReader failed\"));\n reader.readAsDataURL(blob);\n });\n return { b64, size: blob.size, type: blob.type };\n }\n\n case \"AISTUDIO_NEW_TAB\": {\n const url = message.url || \"https://aistudio.google.com/prompts/new_chat\";\n const tab = await chrome.tabs.create({ url, active: true });\n if (!tab.id) throw new Error(\"Failed to create tab\");\n const currentTab = await chrome.tabs.get(tab.id);\n if (currentTab.status !== \"complete\") {\n await new Promise<void>((resolve) => {\n const listener = (tabId: number, info: chrome.tabs.OnUpdatedInfo) => {\n if (tabId === tab.id && info.status === \"complete\") {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }\n };\n chrome.tabs.onUpdated.addListener(listener);\n setTimeout(() => {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }, 30000);\n });\n }\n await cdp.attach(tab.id);\n await waitForRuntimeReady(tab.id, 10000);\n return { tabId: tab.id };\n }\n\n case \"AISTUDIO_CLOSE_TAB\": {\n const aiStudioTabId = message.tabId;\n if (aiStudioTabId) {\n try { await cdp.detach(aiStudioTabId); } catch {}\n try { await chrome.tabs.remove(aiStudioTabId); } catch {}\n }\n return { success: true };\n }\n\n case \"AISTUDIO_CDP_COMMAND\": {\n const { method, params } = message;\n return await cdp.sendCommand(message.tabId, method, params || {});\n }\n\n case \"AISTUDIO_EVALUATE\": {\n return await cdp.evaluateScript(message.tabId, message.expression);\n }\n\n case \"DOWNLOADS_SEARCH\": {\n const results = await chrome.downloads.search(message.searchParams || {});\n return {\n downloads: results.map(d => ({\n id: d.id,\n filename: d.filename,\n state: d.state,\n error: d.error,\n }))\n };\n }\n\n case \"GET_GOOGLE_COOKIES\": {\n // Gemini requires cookies from multiple Google domains\n const domains = [\".google.com\", \".gemini.google.com\", \"accounts.google.com\", \"www.google.com\"];\n const allCookies: chrome.cookies.Cookie[] = [];\n\n for (const domain of domains) {\n try {\n const cookies = await chrome.cookies.getAll({ domain });\n allCookies.push(...cookies);\n } catch {}\n }\n\n // Also try by URL for better coverage\n const urls = [\"https://gemini.google.com\", \"https://aistudio.google.com\", \"https://accounts.google.com\", \"https://www.google.com\"];\n for (const url of urls) {\n try {\n const cookies = await chrome.cookies.getAll({ url });\n allCookies.push(...cookies);\n } catch {}\n }\n\n // Dedupe by name, preferring google.com domain with root path\n const seen = new Map<string, chrome.cookies.Cookie>();\n for (const cookie of allCookies) {\n const existing = seen.get(cookie.name);\n if (!existing ||\n (cookie.domain === \".google.com\" && cookie.path === \"/\") ||\n (!existing.domain?.includes(\"google.com\") && cookie.domain?.includes(\"google.com\"))) {\n seen.set(cookie.name, cookie);\n }\n }\n\n return { cookies: Array.from(seen.values()) };\n }\n\n case \"WINDOW_NEW\": {\n // Default to a usable blank page if no URL provided\n const url = message.url || 'data:text/html,<html><head><title>Surf Agent</title></head><body style=\"font-family:system-ui;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;color:%23666\"><div style=\"text-align:center\"><h2>Agent Window</h2><p>Ready for automation</p></div></body></html>';\n\n const createOptions: chrome.windows.CreateData = {\n focused: message.focused !== false,\n type: \"normal\",\n url,\n };\n\n if (message.width && message.height) {\n createOptions.width = message.width;\n createOptions.height = message.height;\n }\n\n if (message.incognito) {\n createOptions.incognito = true;\n }\n\n const window = (await chrome.windows.create(createOptions)) as chrome.windows.Window;\n\n if (!window.id) throw new Error(\"Failed to create window\");\n\n // Get the tab that was created with the window\n const tabs = await chrome.tabs.query({ windowId: window.id });\n const firstTab = tabs[0];\n\n // Wait for tab to be ready\n if (firstTab?.id) {\n await new Promise(r => setTimeout(r, 150));\n }\n\n return {\n success: true,\n windowId: window.id,\n tabId: firstTab?.id,\n hint: `Use --window-id ${window.id} to target this window`,\n };\n }\n\n case \"WINDOW_LIST\": {\n const windows = await chrome.windows.getAll({ populate: true });\n\n return {\n windows: windows.map(w => ({\n id: w.id,\n focused: w.focused,\n type: w.type,\n state: w.state,\n width: w.width,\n height: w.height,\n tabCount: w.tabs?.length || 0,\n tabs: message.includeTabs ? w.tabs?.map(t => ({\n id: t.id,\n title: t.title,\n url: t.url,\n active: t.active,\n })) : undefined,\n }))\n };\n }\n\n case \"WINDOW_FOCUS\": {\n if (!message.windowId) throw new Error(\"No windowId provided\");\n\n await chrome.windows.update(message.windowId, { focused: true });\n return { success: true, windowId: message.windowId };\n }\n\n case \"WINDOW_CLOSE\": {\n if (!message.windowId) throw new Error(\"No windowId provided\");\n\n await chrome.windows.remove(message.windowId);\n return { success: true, windowId: message.windowId };\n }\n\n case \"WINDOW_RESIZE\": {\n if (!message.windowId) throw new Error(\"No windowId provided\");\n\n const updateInfo: chrome.windows.UpdateInfo = {};\n if (message.width) updateInfo.width = message.width;\n if (message.height) updateInfo.height = message.height;\n if (message.left !== undefined) updateInfo.left = message.left;\n if (message.top !== undefined) updateInfo.top = message.top;\n if (message.state) updateInfo.state = message.state as `${chrome.windows.WindowState}`;\n\n const window = (await chrome.windows.update(message.windowId, updateInfo)) as chrome.windows.Window;\n return {\n success: true,\n windowId: message.windowId,\n width: window.width,\n height: window.height,\n };\n }\n\n default:\n throw new Error(`Unknown message type: ${message.type}`);\n }\n}\n\nchrome.runtime.onInstalled.addListener((details) => {\n debugLog(\"Extension installed/updated:\", details.reason);\n});\n\nconst COMMANDS_WITHOUT_TAB = new Set([\n \"LIST_TABS\", \"NEW_TAB\", \"TABS_NEW\", \"CLOSE_TAB\", \"CLOSE_TABS\", \"TAB_MOVE\", \"SWITCH_TAB\", \"TABS_SWITCH\",\n \"TABS_REGISTER\", \"TABS_UNREGISTER\", \"TABS_LIST_NAMED\", \"TABS_GET_BY_NAME\",\n \"CREATE_TAB_GROUP\", \"UNGROUP_TABS\", \"LIST_TAB_GROUPS\", \"GET_HISTORY\", \"SEARCH_HISTORY\",\n \"GET_COOKIES\", \"SET_COOKIE\", \"DELETE_COOKIES\", \"GET_BOOKMARKS\", \"ADD_BOOKMARK\",\n \"DELETE_BOOKMARK\", \"DIALOG_DISMISS\", \"DIALOG_ACCEPT\", \"DIALOG_INFO\",\n \"CHATGPT_NEW_TAB\", \"CHATGPT_CLOSE_TAB\", \"CHATGPT_EVALUATE\", \"CHATGPT_CDP_COMMAND\",\n \"GET_CHATGPT_COOKIES\", \"GET_GOOGLE_COOKIES\", \"GET_TWITTER_COOKIES\",\n \"PERPLEXITY_NEW_TAB\", \"PERPLEXITY_CLOSE_TAB\", \"PERPLEXITY_EVALUATE\", \"PERPLEXITY_CDP_COMMAND\",\n \"GROK_NEW_TAB\", \"GROK_CLOSE_TAB\", \"GROK_EVALUATE\", \"GROK_CDP_COMMAND\",\n \"GEMINI_NEW_TAB\", \"GEMINI_CLOSE_TAB\", \"GEMINI_FETCH_URL\", \"AI_UPLOAD_FILE_TO_TAB\", \"UPLOAD_FILE_TO_TAB\",\n \"AISTUDIO_NEW_TAB\", \"AISTUDIO_CLOSE_TAB\", \"AISTUDIO_EVALUATE\", \"AISTUDIO_CDP_COMMAND\",\n \"DOWNLOADS_SEARCH\",\n \"WINDOW_NEW\", \"WINDOW_LIST\", \"WINDOW_FOCUS\", \"WINDOW_CLOSE\", \"WINDOW_RESIZE\",\n \"TARGET_INSPECT\", \"TARGET_RESOLVE\", \"SESSION_CREATE_TARGET\", \"SESSION_CLOSE_TARGET\",\n \"EMULATE_DEVICE_LIST\"\n]);\n\ninitNativeMessaging(async (msg) => {\n let tabId = msg.tabId;\n const windowId = msg.windowId;\n const isDialogCommand = msg.type?.startsWith(\"DIALOG_\");\n const needsTab = !COMMANDS_WITHOUT_TAB.has(msg.type);\n let autoCreatedTab = false;\n\n if (tabId && !isDialogCommand && !COMMANDS_WITHOUT_TAB.has(msg.type)) {\n try {\n await chrome.tabs.get(tabId);\n } catch {\n throw new BrowserCommandError(\"tab_gone\", `Tab ${tabId} no longer exists`, { tabId });\n }\n } else if (!tabId && needsTab) {\n if (msg.strictTarget) {\n throw new BrowserCommandError(\"target_required\", \"Strict browser command requires an explicit tab binding\");\n }\n const resolved = await resolveDefaultTarget(windowId, true);\n tabId = resolved.tab.id;\n autoCreatedTab = resolved.autoCreated;\n }\n\n if (tabId && msg.frameId !== undefined) await validateRequestedFrame(tabId, msg.frameId);\n const result = await handleMessage({ ...msg, tabId }, {} as chrome.runtime.MessageSender);\n const hints: string[] = [];\n if (autoCreatedTab) {\n hints.push(`Auto-created tab in window ${windowId} (no usable tabs existed). Navigate to your target URL.`);\n }\n let resolvedWindowId: number | undefined;\n if (tabId) {\n try { resolvedWindowId = (await chrome.tabs.get(tabId)).windowId; } catch {}\n }\n\n return {\n ...result,\n _resolvedTabId: tabId,\n _resolvedWindowId: resolvedWindowId,\n _hint: hints.length > 0 ? hints.join(\" \") : undefined,\n };\n});\n"],"file":"index.js"}
1
+ {"version":3,"mappings":"oJAGM,EAAN,cAAiC,KAAM,CACrC,KACA,QAEA,YAAY,EAAc,EAAiB,EAAmC,CAC5E,MAAM,CAAO,EACb,KAAK,KAAO,qBACZ,KAAK,KAAO,EACZ,KAAK,QAAU,CACjB,CACF,EAgBA,SAAgB,EAAsB,EAAc,EAAwB,CAC1E,IAAM,EAAM,aAAe,MAAQ,EAAI,QAAU,OAAO,CAAG,EACrD,EAAU,EAAI,KAAK,EACzB,GAAI,EAAQ,WAAW,GAAG,GAAK,EAAQ,SAAS,GAAG,EACjD,GAAI,CACF,IAAM,EAAS,KAAK,MAAM,CAAO,EACjC,GAAI,GAAU,OAAO,EAAO,SAAY,UAAY,EAAO,QAAQ,OAAS,EAAG,CAC7E,IAAM,EAAY,MAAM,EAAO,QAAS,CAAE,MAAO,CAAI,CAAC,EAGtD,OAFI,OAAO,EAAO,MAAS,WAAU,EAAM,QAAU,EAAO,MACxD,IAAQ,EAAM,UAAY,GACvB,CACT,CACF,MAAQ,CAER,CAEF,OAAO,aAAe,MAAQ,EAAU,MAAM,CAAG,CACnD,CAuFA,IAAM,EAAY,CAChB,IAAK,EACL,KAAM,EACN,QAAS,EACT,KAAM,EACN,IAAK,EACL,QAAS,EACT,IAAK,EACL,QAAS,EACT,MAAO,CACT,EAUM,EAAiD,CACrD,MAAO,CAAE,IAAK,QAAS,KAAM,QAAS,QAAS,GAAI,KAAM,IAAK,EAC9D,IAAK,CAAE,IAAK,MAAO,KAAM,MAAO,QAAS,CAAE,EAC3C,OAAQ,CAAE,IAAK,SAAU,KAAM,SAAU,QAAS,EAAG,EACrD,UAAW,CAAE,IAAK,YAAa,KAAM,YAAa,QAAS,CAAE,EAC7D,OAAQ,CAAE,IAAK,SAAU,KAAM,SAAU,QAAS,EAAG,EACrD,QAAS,CAAE,IAAK,UAAW,KAAM,UAAW,QAAS,EAAG,EACxD,UAAW,CAAE,IAAK,YAAa,KAAM,YAAa,QAAS,EAAG,EAC9D,UAAW,CAAE,IAAK,YAAa,KAAM,YAAa,QAAS,EAAG,EAC9D,WAAY,CAAE,IAAK,aAAc,KAAM,aAAc,QAAS,EAAG,EACjE,KAAM,CAAE,IAAK,OAAQ,KAAM,OAAQ,QAAS,EAAG,EAC/C,IAAK,CAAE,IAAK,MAAO,KAAM,MAAO,QAAS,EAAG,EAC5C,OAAQ,CAAE,IAAK,SAAU,KAAM,SAAU,QAAS,EAAG,EACrD,SAAU,CAAE,IAAK,WAAY,KAAM,WAAY,QAAS,EAAG,EAC3D,MAAO,CAAE,IAAK,IAAK,KAAM,QAAS,QAAS,GAAI,KAAM,GAAI,EACzD,GAAI,CAAE,IAAK,KAAM,KAAM,KAAM,QAAS,GAAI,EAC1C,GAAI,CAAE,IAAK,KAAM,KAAM,KAAM,QAAS,GAAI,EAC1C,GAAI,CAAE,IAAK,KAAM,KAAM,KAAM,QAAS,GAAI,EAC1C,GAAI,CAAE,IAAK,KAAM,KAAM,KAAM,QAAS,GAAI,EAC1C,GAAI,CAAE,IAAK,KAAM,KAAM,KAAM,QAAS,GAAI,EAC1C,GAAI,CAAE,IAAK,KAAM,KAAM,KAAM,QAAS,GAAI,EAC1C,GAAI,CAAE,IAAK,KAAM,KAAM,KAAM,QAAS,GAAI,EAC1C,GAAI,CAAE,IAAK,KAAM,KAAM,KAAM,QAAS,GAAI,EAC1C,GAAI,CAAE,IAAK,KAAM,KAAM,KAAM,QAAS,GAAI,EAC1C,IAAK,CAAE,IAAK,MAAO,KAAM,MAAO,QAAS,GAAI,EAC7C,IAAK,CAAE,IAAK,MAAO,KAAM,MAAO,QAAS,GAAI,EAC7C,IAAK,CAAE,IAAK,MAAO,KAAM,MAAO,QAAS,GAAI,CAC/C,EAEa,EAAb,MAAa,CAAc,CACzB,OAAwB,sBAAwB,IAChD,QAAkB,IAAI,IACtB,gBAAyD,IAAI,IAC7D,gBAAyD,IAAI,IAC7D,eAAiE,IAAI,IACrE,iBAA2E,IAAI,IAC/E,iBAA2E,IAAI,IAC/E,oBAAgI,IAAI,IACpI,yBAAwD,IAAI,IAC5D,eAAqD,IAAI,IACzD,cAA6C,IAAI,IACjD,gBAA0B,EAC1B,iBAAgD,IAAI,IACpD,eAAmH,IAAI,IACvH,kBAAwD,IAAI,IAC5D,OAAe,2BAA6B,GAG5C,OAAwB,uBAAyB,MACjD,OAAwB,yBAA2B,QACnD,OAAwB,mBAAqB,IAAI,IAAI,CACnD,YAAa,aAAc,YAAa,aAAc,gBAAiB,eACvE,YAAa,aAAc,WAAY,WAAY,wBAAyB,yBAC5E,WAAY,yBAA0B,kBAAmB,0BAC3D,CAAC,EACD,OAAwB,aAAe,IAAI,IAAI,CAC7C,YAAa,aAAc,YAAa,aAAc,eACtD,YAAa,aAAc,WAAY,WAAY,wBAAyB,yBAC5E,2BAA4B,kBAAmB,kBAC/C,aAAc,YAAa,YAC3B,YAAa,aAAc,WAC7B,CAAC,EAED,MAAM,OAAO,EAA8B,CACzC,GAAI,KAAK,QAAQ,IAAI,CAAK,EAAG,OAE7B,IAAM,EAAmB,CAAE,OAAM,EACjC,GAAI,CACF,MAAM,OAAO,SAAS,OAAO,EAAQ,KAAK,CAC5C,OAAS,EAAK,CACZ,IAAM,EAAU,aAAe,MAAQ,EAAI,QAAU,OAAO,CAAG,EAe/D,KAdI,oBAAoB,KAAK,CAAO,EAC5B,IAAI,EACR,gBACA,yCAAyC,EAAM,uDAC/C,CAAE,OAAM,CACV,EAEE,EAAQ,SAAS,eAAe,GAAK,EAAQ,SAAS,eAAe,EACjE,IAAI,EACR,oBACA,uGACA,CAAE,OAAM,CACV,EAEI,IAAI,EAAmB,yBAA0B,8BAA8B,IAAW,CAAE,OAAM,CAAC,CAC3G,CACA,KAAK,QAAQ,IAAI,EAAO,CAAM,EAC9B,KAAK,cAAc,OAAO,CAAK,EAE/B,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,IAAI,EAAO,CAAC,CAAC,EAClC,KAAK,gBAAgB,IAAI,EAAO,CAAC,CAAC,EAElC,GAAI,CACF,MAAM,KAAK,KAAK,EAAO,aAAa,CACtC,MAAY,CAAC,CACf,CAEA,WAAW,EAAwB,CACjC,OAAO,KAAK,QAAQ,IAAI,CAAK,CAC/B,CAEA,MAAM,OAAO,EAA8D,CACzE,IAAM,EAAS,KAAK,QAAQ,IAAI,CAAK,EACjC,EACJ,GAAI,EAAQ,CACV,GAAI,CACF,MAAM,OAAO,SAAS,OAAO,CAAM,CACrC,OAAS,EAAG,CACV,EAAQ,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,EACjD,QAAQ,KAAK,mCAAoC,CAAC,CACpD,CACA,KAAK,QAAQ,OAAO,CAAK,EACzB,KAAK,gBAAgB,OAAO,CAAK,EACjC,KAAK,gBAAgB,OAAO,CAAK,EACjC,KAAK,eAAe,OAAO,CAAK,EAChC,KAAK,iBAAiB,OAAO,CAAK,EAClC,KAAK,eAAe,OAAO,CAAK,EAChC,KAAK,iBAAiB,OAAO,CAAK,EAClC,KAAK,iBAAiB,OAAO,CAAK,EAClC,KAAK,sBAAsB,EAAO,IAAI,EACpC,oBACA,8BAA8B,IAC9B,CAAE,OAAM,CACV,CAAC,EACD,KAAK,oBAAoB,OAAO,CAAK,EACrC,KAAK,eAAe,OAAO,CAAK,EAChC,KAAK,uBAAuB,CAAK,EACjC,KAAK,cAAc,OAAO,CAAK,CACjC,CACA,OAAO,EAAQ,CAAE,QAAS,GAAO,OAAM,EAAI,CAAE,QAAS,EAAK,CAC7D,CAEA,MAAM,WAA2B,CAC/B,IAAK,IAAM,KAAS,KAAK,QAAQ,KAAK,EACpC,MAAM,KAAK,OAAO,CAAK,CAE3B,CAEA,oBAAmC,CAC7B,EAAc,6BAClB,EAAc,2BAA6B,GAE3C,OAAO,SAAS,QAAQ,aAAa,EAAQ,EAAQ,IAAW,CAC9D,IAAM,EAAQ,EAAO,MAChB,GAAU,KAAK,QAAQ,IAAI,CAAK,GAErC,KAAK,gBAAgB,EAAO,EAAQ,CAAM,CAC5C,CAAC,EAED,OAAO,SAAS,SAAS,aAAa,EAAQ,IAAW,CACvD,IAAM,EAAQ,EAAO,MACjB,GAAS,KAAK,QAAQ,IAAI,CAAK,IACjC,KAAK,cAAc,IAAI,EAAO,GAAU,SAAS,EACjD,KAAK,QAAQ,OAAO,CAAK,EACzB,KAAK,gBAAgB,OAAO,CAAK,EACjC,KAAK,gBAAgB,OAAO,CAAK,EACjC,KAAK,eAAe,OAAO,CAAK,EAChC,KAAK,iBAAiB,OAAO,CAAK,EAClC,KAAK,eAAe,OAAO,CAAK,EAChC,KAAK,iBAAiB,OAAO,CAAK,EAClC,KAAK,iBAAiB,OAAO,CAAK,EAClC,KAAK,sBAAsB,EAAO,IAAI,EACpC,oBACA,8BAA8B,EAAM,IAAI,GAAU,mBAClD,CAAE,QAAO,OAAQ,GAAU,SAAU,CACvC,CAAC,EACD,KAAK,oBAAoB,OAAO,CAAK,EACrC,KAAK,eAAe,OAAO,CAAK,EAChC,KAAK,uBAAuB,CAAK,EAErC,CAAC,EACH,CAEA,gBAAwB,EAAe,EAA2B,CAChE,MAAO,GAAG,EAAM,GAAG,GACrB,CAEA,uBAA+B,EAAqB,CAClD,IAAM,EAAS,GAAG,EAAM,GACxB,IAAK,IAAM,KAAO,KAAK,yBAAyB,KAAK,EAC/C,EAAI,WAAW,CAAM,GAAG,KAAK,yBAAyB,OAAO,CAAG,CAExE,CAEA,gBAAwB,EAAe,EAAgB,EAAmB,CAExE,IAAM,GADW,KAAK,kBAAkB,IAAI,CAAK,GAAK,QAAQ,QAAQ,GAEnE,UAAY,MAAS,CAAC,CACtB,SAAW,KAAK,eAAe,EAAO,EAAQ,CAAM,CAAC,CAAC,CACtD,UAAY,MAAS,EACxB,KAAK,kBAAkB,IAAI,EAAO,CAAI,EACtC,EAAK,YAAc,CACb,KAAK,kBAAkB,IAAI,CAAK,IAAM,GAAM,KAAK,kBAAkB,OAAO,CAAK,CACrF,CAAC,CACH,CAEA,MAAM,mBAAmB,EAA8B,CACrD,MAAM,KAAK,kBAAkB,IAAI,CAAK,CACxC,CAEA,MAAc,eAAe,EAAe,EAAgB,EAA4B,CACtF,OAAQ,EAAR,CACE,IAAK,2BACH,KAAK,qBAAqB,EAAO,CAAM,EACvC,MACF,IAAK,0BACH,KAAK,uBAAuB,EAAO,CAAM,EACzC,MACF,IAAK,4BACH,KAAK,qBAAqB,EAAO,CAAM,EACvC,MACF,IAAK,2BACH,KAAK,sBAAsB,EAAO,CAAM,EACxC,MACF,IAAK,wBACH,KAAK,oBAAoB,EAAO,CAAM,EACtC,MACF,IAAK,0BACH,MAAM,KAAK,sBAAsB,EAAO,CAAM,EAC9C,MACF,IAAK,+BACH,KAAK,oBAAoB,EAAO,CAAM,EACtC,MACF,IAAK,8BACH,KAAK,eAAe,OAAO,CAAK,EAChC,MACF,IAAK,uBACH,MAAM,KAAK,sBAAsB,EAAO,CAAM,CAElD,CACF,CAEA,MAAc,sBAAsB,EAAe,EAA4B,CAC7E,IAAM,EAAY,OAAO,GAAQ,SAAS,EAC1C,GAAI,CAAC,OAAO,UAAU,CAAS,EAAG,OAKlC,GAAI,CACF,MAAM,KAAK,KAAK,EAAO,0BAA2B,CAAE,WAAU,CAAC,CACjE,OAAS,EAAO,CACd,KAAK,sBAAsB,EAAO,aAAiB,MAAQ,EAAY,MAAM,OAAO,CAAK,CAAC,CAAC,EAC3F,MACF,CAEA,IAAM,EAAY,KAAK,oBAAoB,IAAI,CAAK,EACpD,GAAI,CAAC,EAAW,OAChB,IAAM,EAAQ,CACZ,KAAM,OAAO,GAAQ,MAAS,SAAW,EAAO,KAAO,GACvD,SAAU,GAAQ,SAClB,WACF,EACA,IAAK,IAAM,KAAY,EAAU,OAAO,EACtC,GAAI,CAAE,EAAS,QAAQ,CAAK,CAAG,MAAQ,CAAC,CAE5C,CAEA,sBAA8B,EAAe,EAAoB,CAC/D,IAAM,EAAY,KAAK,oBAAoB,IAAI,CAAK,EAC/C,KACL,IAAK,IAAM,KAAY,EAAU,OAAO,EACtC,GAAI,CAAE,EAAS,QAAQ,CAAK,CAAG,MAAQ,CAAC,CAE5C,CAEA,qBAA6B,EAAe,EAAmB,CAC7D,IAAM,EAAW,KAAK,gBAAgB,IAAI,CAAK,GAAK,CAAC,EAG/C,GAFO,EAAO,MAAQ,CAAC,GAG1B,IAAK,GACA,EAAE,QAAU,OACZ,EAAE,YAAoB,EAAE,YACrB,GAF2B,OAAO,EAAE,KAAK,CAGjD,CAAC,CACD,KAAK,GAAG,EAEL,EAAY,EAAO,YAAY,aAAa,GAE5C,EAAsB,CAC1B,KAAM,EAAO,MAAQ,MACrB,OACA,UAAW,EAAO,WAAa,KAAK,IAAI,EACxC,IAAK,GAAW,IAChB,KAAM,GAAW,UACnB,EAEA,EAAS,KAAK,CAAG,EACb,EAAS,OAAS,KAAM,EAAS,MAAM,EAC3C,KAAK,gBAAgB,IAAI,EAAO,CAAQ,EAExC,IAAM,EAAY,KAAK,iBAAiB,IAAI,CAAK,EACjD,GAAI,EACF,IAAK,IAAM,KAAM,EAAU,OAAO,EAChC,EAAG,CAAG,CAGZ,CAEA,uBAA+B,EAAe,EAAmB,CAC/D,IAAM,EAAW,KAAK,gBAAgB,IAAI,CAAK,GAAK,CAAC,EAC/C,EAAU,EAAO,iBACvB,GAAI,CAAC,EAAS,OAEd,IAAM,EAAsB,CAC1B,KAAM,YACN,KAAM,EAAQ,WAAW,aAAe,EAAQ,MAAQ,oBACxD,UAAW,EAAQ,WAAa,KAAK,IAAI,EACzC,IAAK,EAAQ,IACb,KAAM,EAAQ,UAChB,EAEA,EAAS,KAAK,CAAG,EACb,EAAS,OAAS,KAAM,EAAS,MAAM,EAC3C,KAAK,gBAAgB,IAAI,EAAO,CAAQ,EAExC,IAAM,EAAY,KAAK,iBAAiB,IAAI,CAAK,EACjD,GAAI,EACF,IAAK,IAAM,KAAM,EAAU,OAAO,EAChC,EAAG,CAAG,CAGZ,CAEA,qBAA6B,EAAe,EAAmB,CAC7D,IAAM,EAAW,KAAK,gBAAgB,IAAI,CAAK,GAAK,CAAC,EAC/C,EAAM,EAAO,QACnB,GAAI,CAAC,EAAK,OAEV,IAAM,EAAY,EAAO,UAAY,EAAO,UAAY,IAAO,KAAK,IAAI,EACxE,KAAK,yBAAyB,IAAI,KAAK,gBAAgB,EAAO,EAAO,SAAS,EAAG,CAAS,EAG1F,IAAM,EAAqC,CAAC,EAC5C,GAAI,EAAI,QACN,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAI,OAAO,EACnD,EAAW,GAAO,OAAO,CAAK,EAIlC,EAAS,KAAK,CACZ,UAAW,EAAO,UAClB,IAAK,EAAI,IACT,OAAQ,EAAI,OACZ,KAAM,EAAO,KACb,YACA,eAAgB,EAChB,YAAa,EAAI,QACnB,CAAC,EAEG,EAAS,OAAS,KAAK,EAAS,MAAM,EAC1C,KAAK,gBAAgB,IAAI,EAAO,CAAQ,EAGnC,KAAK,eAAe,IAAI,CAAK,GAChC,KAAK,eAAe,IAAI,EAAO,IAAI,GAAK,EAE1C,IAAM,EAAa,KAAK,eAAe,IAAI,CAAK,EAI1C,EAAU,KAAK,EAAU,GAAG,EADpB,KAAK,kBAIb,EAAyC,CAAC,EAChD,GAAI,EAAI,QACN,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAI,OAAO,EACnD,EAAe,GAAO,OAAO,CAAK,EAKtC,IAAM,EAAc,EAAI,SAClB,EAAkB,EAAc,EAAY,OAAS,OAErD,EAAsB,CAC1B,GAAI,EACJ,GAAI,EACJ,OAAQ,EAAI,OACZ,IAAK,EAAI,IACT,OAAQ,KAAK,cAAc,EAAI,GAAG,EAClC,iBACA,cACA,kBACA,QACA,OAAQ,EAAO,YACf,KAAM,EAAO,KACb,MAAO,CAAC,EACR,YAAa,CAAE,KAAM,KAAK,eAAe,IAAI,CAAK,CAAC,EAAE,MAAQ,OAAQ,SAAU,GAAO,OAAQ,SAAU,EACxG,WAAY,EAAO,UACnB,kBAAmB,GACnB,iBAAkB,EACpB,EAGA,GAAI,EAAW,KAAO,IAAK,CACzB,IAAM,EAAY,EAAW,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,MACvC,GAAW,EAAW,OAAO,CAAS,CAC5C,CAEA,EAAW,IAAI,EAAO,UAAW,CAAK,CACxC,CAEA,sBAA8B,EAAe,EAAmB,CAE9D,IAAM,GADW,KAAK,gBAAgB,IAAI,CAAK,GAAK,CAAC,GAC3B,KAAM,GAAM,EAAE,YAAc,EAAO,SAAS,EACtE,GAAI,EAAU,CAKZ,GAJA,EAAS,OAAS,EAAO,UAAU,OACnC,EAAS,SAAW,EAAO,UAAU,SAGjC,EAAO,UAAU,QAAS,CAC5B,IAAM,EAAsC,CAAC,EAC7C,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAO,SAAS,OAAO,EAC/D,EAAY,GAAO,OAAO,CAAK,EAEjC,EAAS,gBAAkB,CAC7B,CAEA,IAAM,EAAY,KAAK,iBAAiB,IAAI,CAAK,EACjD,GAAI,EAAW,CACb,IAAM,EAAY,KAAK,yBAAyB,IAAI,KAAK,gBAAgB,EAAO,EAAO,SAAS,CAAC,EAC3F,EAAM,KAAK,IAAI,EACf,EAAW,EAAY,KAAK,MAAM,EAAM,CAAS,EAAI,OAI3D,IAAK,IAAM,KAAM,EAAU,OAAO,EAChC,EAAG,CACD,OAAQ,EAAS,OACjB,IAAK,EAAS,IACd,OAAQ,EAAS,OACjB,WACA,UAAW,CACb,CAAC,CAEL,CACF,CAIA,IAAM,EADa,KAAK,eAAe,IAAI,CAC7B,GAAY,IAAI,EAAO,SAAS,EAC9C,GAAI,GAAS,EAAO,SAAU,CAC5B,IAAM,EAAW,EAAO,SAGlB,EAAY,KAAK,yBAAyB,IAAI,KAAK,gBAAgB,EAAO,EAAO,SAAS,CAAC,EAC3F,EAAM,EAAO,UAAY,EAAO,UAAY,IAAO,KAAK,IAAI,EAC9D,IACF,EAAM,KAAO,KAAK,MAAM,EAAM,CAAS,GAGzC,EAAM,OAAS,EAAS,OACxB,EAAM,WAAa,EAAS,WAC5B,EAAM,SAAW,EAAS,SAG1B,IAAM,EAA0C,CAAC,EACjD,GAAI,EAAS,QACX,IAAK,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAS,OAAO,EACxD,EAAgB,GAAO,OAAO,CAAK,EAGvC,EAAM,gBAAkB,EAGpB,KAAK,aAAa,EAAS,QAAQ,GACrC,EAAM,MAAM,KAAK,QAAQ,GAIvB,EAAS,UAAU,SAAS,UAAU,GACtC,EAAS,UAAU,SAAS,YAAY,GACxC,EAAS,UAAU,SAAS,kBAAkB,IAChD,EAAM,MAAM,KAAK,UAAU,EAG7B,EAAM,kBAAoB,EAC5B,CACF,CAEA,oBAA4B,EAAe,EAAmB,CAE5D,IAAM,GADW,KAAK,gBAAgB,IAAI,CAAK,GAAK,CAAC,GAC3B,KAAM,GAAM,EAAE,YAAc,EAAO,SAAS,EACtE,GAAI,GAAY,CAAC,EAAS,OAAQ,CAChC,EAAS,OAAS,EAElB,IAAM,EAAY,KAAK,iBAAiB,IAAI,CAAK,EACjD,GAAI,EAAW,CACb,IAAM,EAAY,KAAK,yBAAyB,IAAI,KAAK,gBAAgB,EAAO,EAAO,SAAS,CAAC,EAC3F,EAAM,KAAK,IAAI,EACf,EAAW,EAAY,KAAK,MAAM,EAAM,CAAS,EAAI,OAC3D,KAAK,yBAAyB,OAAO,KAAK,gBAAgB,EAAO,EAAO,SAAS,CAAC,EAElF,IAAK,IAAM,KAAM,EAAU,OAAO,EAChC,EAAG,CACD,OAAQ,EAAS,OACjB,IAAK,EAAS,IACd,OAAQ,EACR,WACA,UAAW,CACb,CAAC,CAEL,CACF,CAIA,IAAM,EADa,KAAK,eAAe,IAAI,CAC7B,GAAY,IAAI,EAAO,SAAS,EAC9C,GAAI,EAAO,CACT,IAAM,EAAY,KAAK,yBAAyB,IAAI,KAAK,gBAAgB,EAAO,EAAO,SAAS,CAAC,EAC3F,EAAM,EAAO,UAAY,EAAO,UAAY,IAAO,KAAK,IAAI,EAC9D,IACF,EAAM,SAAW,KAAK,MAAM,EAAM,CAAS,GAE7C,KAAK,yBAAyB,OAAO,KAAK,gBAAgB,EAAO,EAAO,SAAS,CAAC,EAElF,EAAM,OAAS,EACf,EAAM,MAAM,KAAK,QAAQ,EACzB,EAAM,iBAAmB,EAC3B,CACF,CAEA,oBAA4B,EAAe,EAAmB,CAC5D,KAAK,eAAe,IAAI,EAAO,CAC7B,KAAM,EAAO,KACb,QAAS,EAAO,QAChB,cAAe,EAAO,cACtB,UAAW,KAAK,IAAI,CACtB,CAAC,CACH,CAEA,MAAc,sBAAsB,EAAe,EAA4B,CAG7E,IAAM,GADW,KAAK,gBAAgB,IAAI,CAAK,GAAK,CAAC,GAC3B,KAAM,GAAM,EAAE,YAAc,EAAO,SAAS,EACtE,GAAI,EAAU,CAEZ,IAAM,EAAY,KAAK,yBAAyB,IAAI,KAAK,gBAAgB,EAAO,EAAO,SAAS,CAAC,EAC3F,EAAM,EAAO,UAAY,EAAO,UAAY,IAAO,KAAK,IAAI,EAC9D,IACF,EAAS,SAAW,KAAK,MAAM,EAAM,CAAS,EAGlD,CAIA,IAAM,EADa,KAAK,eAAe,IAAI,CAC7B,GAAY,IAAI,EAAO,SAAS,EAC9C,GAAI,CAAC,EAAO,OAGZ,IAAM,EAAY,KAAK,yBAAyB,IAAI,KAAK,gBAAgB,EAAO,EAAO,SAAS,CAAC,EAC3F,EAAM,EAAO,UAAY,EAAO,UAAY,IAAO,KAAK,IAAI,EAC9D,IACF,EAAM,SAAW,KAAK,MAAM,EAAM,CAAS,GAE7C,KAAK,yBAAyB,OAAO,KAAK,gBAAgB,EAAO,EAAO,SAAS,CAAC,EAGlF,EAAM,iBAAmB,EAAO,kBAChC,EAAM,iBAAmB,GACzB,IAAM,EAAU,KAAK,eAAe,IAAI,CAAK,GAAK,CAAE,KAAM,OAAiB,aAAc,EAAG,WAAY,CAAE,EACpG,EAAe,KAAK,IAAI,EAAG,OAAO,EAAO,iBAAiB,GAAK,CAAC,EAClE,EAAwB,KAK5B,GAJI,EAAQ,OAAS,OAAQ,EAAS,WAC7B,EAAQ,OAAS,SAAW,KAAK,cAAc,EAAM,QAAQ,GAAK,KAAK,aAAa,EAAM,QAAQ,GAAI,EAAS,eAC/G,EAAe,EAAQ,aAAc,EAAS,gBAC7C,KAAK,iBAAiB,IAAI,CAAK,GAAK,GAAK,EAAe,EAAQ,aAAY,EAAS,eAC3F,EAAQ,CACV,EAAM,YAAc,CAAE,KAAM,EAAQ,KAAM,SAAU,GAAO,QAAO,EAC9D,EAAO,SAAS,KAAK,GAAG,EAAM,MAAM,KAAK,WAAW,EACxD,MACF,CACA,GAAI,CACF,IAAM,EAAS,MAAM,KAAK,KAAK,EAAO,0BAA2B,CAAE,UAAW,EAAO,SAAU,CAAC,EAC1F,EAAO,OAAO,EAAO,MAAS,SAAW,EAAO,KAAO,GACvD,EAAgB,EAAO,cAAgB,KAAK,KAAK,EAAK,OAAS,GAAI,EAAI,IAAI,YAAY,CAAC,CAAC,OAAO,CAAI,CAAC,CAAC,WAC5G,GAAI,EAAgB,EAAQ,eAAiB,KAAK,iBAAiB,IAAI,CAAK,GAAK,GAAK,EAAgB,EAAQ,WAAY,CACxH,EAAM,MAAM,KAAK,WAAW,EAC5B,EAAM,YAAc,CAAE,KAAM,EAAQ,KAAM,SAAU,GAAO,OAAQ,EAAgB,EAAQ,aAAe,eAAiB,aAAc,EACzI,MACF,CACA,GAAI,EAAO,eAAiB,EAAQ,OAAS,MAC3C,EAAM,aAAe,EACrB,EAAM,qBAAuB,cACxB,GAAI,EAAO,cAChB,GAAI,CAAE,EAAM,aAAe,KAAK,CAAI,CAAG,MAAQ,CAAE,EAAM,YAAc,CAAE,KAAM,EAAQ,KAAM,SAAU,GAAO,OAAQ,eAAgB,EAAG,MAAQ,KAC1I,GAAM,aAAe,EAC5B,KAAK,iBAAiB,IAAI,GAAQ,KAAK,iBAAiB,IAAI,CAAK,GAAK,GAAK,CAAa,EACxF,EAAM,YAAc,CAAE,KAAM,EAAQ,KAAM,SAAU,GAAM,eAAc,EACpE,IAAU,EAAS,aAAe,EAAM,aAC9C,MAAQ,CACN,EAAM,YAAc,CAAE,KAAM,EAAQ,KAAM,SAAU,GAAO,OAAQ,aAAc,CACnF,CACF,CAGA,cAAsB,EAAqB,CACzC,GAAI,CAEF,OAAO,IADY,IAAI,CAChB,EAAO,MAChB,MAAQ,CACN,MAAO,EACT,CACF,CAGA,cAAsB,EAA4B,CAEhD,OADK,EACE,EAAc,mBAAmB,IAAI,CAAQ,EAD9B,EAExB,CAGA,aAAqB,EAA4B,CAE/C,OADK,EACE,EAAc,aAAa,IAAI,CAAQ,EADxB,EAExB,CAEA,MAAM,sBAAsB,EAA8B,CACxD,MAAM,KAAK,eAAe,CAAK,EAC/B,GAAI,CACF,MAAM,KAAK,KAAK,EAAO,gBAAgB,CACzC,MAAY,CAAC,CACf,CAEA,MAAM,sBACJ,EACA,EAA8F,CAAC,EAChF,CACf,MAAM,KAAK,eAAe,CAAK,EAC/B,IAAM,EAAO,EAAQ,UAAY,OAC3B,EAAe,EAAQ,cAAgB,EAAc,uBACrD,EAAa,EAAQ,YAAc,EAAc,yBACvD,GAAI,CAAC,OAAO,UAAU,CAAY,GAAK,EAAe,GAAK,CAAC,OAAO,UAAU,CAAU,GAAK,EAAa,EACvG,MAAU,MAAM,iDAAiD,EAEnE,KAAK,eAAe,IAAI,EAAO,CAAE,OAAM,eAAc,YAAW,CAAC,EAC5D,KAAK,iBAAiB,IAAI,CAAK,GAAG,KAAK,iBAAiB,IAAI,EAAO,CAAC,EACzE,GAAI,CACF,MAAM,KAAK,KAAK,EAAO,iBAAkB,CAAE,gBAAiB,KAAM,CAAC,CACrE,MAAY,CAAC,CACf,CAEA,MAAM,uBAAuB,EAA8B,CACzD,SAAM,KAAK,mBAAmB,CAAK,EACnC,KAAK,eAAe,OAAO,CAAK,EAChC,KAAK,iBAAiB,OAAO,CAAK,EAC9B,MAAK,iBAAiB,IAAI,CAAK,CAAC,EAAE,KACtC,GAAI,CACF,MAAM,KAAK,KAAK,EAAO,iBAAiB,CAC1C,MAAY,CAAC,CACf,CAEA,MAAM,aAAa,EAAe,EAAiB,EAAoE,CACrH,GAAI,CAMF,OALA,MAAM,KAAK,KAAK,EAAO,8BAA+B,CACpD,SACA,YACF,CAAC,EACD,KAAK,eAAe,OAAO,CAAK,EACzB,CAAE,QAAS,EAAK,CACzB,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CAAE,CAC7E,CACF,CAEA,cAAc,EAAqC,CACjD,OAAO,KAAK,eAAe,IAAI,CAAK,GAAK,IAC3C,CAEA,MAAM,eAAe,EAAe,EAA+D,CACjG,MAAM,KAAK,eAAe,CAAK,EAC/B,IAAM,EAAuH,CAC3H,QAAW,CAAE,QAAS,GAAM,QAAS,EAAG,mBAAoB,EAAG,iBAAkB,CAAE,EACnF,UAAW,CAAE,QAAS,GAAO,QAAS,IAAM,mBAAoB,IAAO,iBAAkB,GAAM,EAC/F,UAAW,CAAE,QAAS,GAAO,QAAS,MAAO,mBAAoB,KAAQ,iBAAkB,KAAM,EACjG,KAAM,CAAE,QAAS,GAAO,QAAS,IAAK,mBAAoB,IAAS,iBAAkB,GAAQ,EAC7F,MAAS,CAAE,QAAS,GAAO,QAAS,EAAG,mBAAoB,GAAI,iBAAkB,EAAG,CACtF,EACM,EAAS,EAAQ,EAAO,YAAY,CAAC,CAAC,QAAQ,OAAQ,GAAG,GAC/D,GAAI,CAAC,EACH,MAAO,CAAE,QAAS,GAAO,MAAO,mBAAmB,EAAO,eAAe,OAAO,KAAK,CAAO,CAAC,CAAC,KAAK,IAAI,GAAI,EAE7G,GAAI,CAGF,OAFA,MAAM,KAAK,KAAK,EAAO,gBAAgB,EACvC,MAAM,KAAK,KAAK,EAAO,mCAAoC,CAAM,EAC1D,CAAE,QAAS,EAAK,CACzB,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CAAE,CAC7E,CACF,CAEA,MAAM,WAAW,EAAe,EAA6D,CAE3F,GADA,MAAM,KAAK,eAAe,CAAK,EAC3B,EAAO,EACT,MAAO,CAAE,QAAS,GAAO,MAAO,mEAAoE,EAEtG,GAAI,CAEF,OADA,MAAM,KAAK,KAAK,EAAO,iCAAkC,CAAE,MAAK,CAAC,EAC1D,CAAE,QAAS,EAAK,CACzB,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CAAE,CAC7E,CACF,CAEA,MAAM,mBAAmB,EAAe,EAAkB,EAAmB,EAAkE,CAC7I,MAAM,KAAK,eAAe,CAAK,EAC/B,GAAI,CAMF,OALA,MAAM,KAAK,KAAK,EAAO,mCAAoC,CACzD,WACA,YACA,SAAU,GAAY,GACxB,CAAC,EACM,CAAE,QAAS,EAAK,CACzB,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CAAE,CAC7E,CACF,CAEA,MAAM,iBAAiB,EAA8D,CACnF,MAAM,KAAK,eAAe,CAAK,EAC/B,GAAI,CAEF,OADA,MAAM,KAAK,KAAK,EAAO,oCAAoC,EACpD,CAAE,QAAS,EAAK,CACzB,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CAAE,CAC7E,CACF,CAEA,MAAM,cACJ,EACA,EAC+C,CAC/C,MAAM,KAAK,eAAe,CAAK,EAC/B,GAAI,CAwBF,OAtBA,MAAM,KAAK,KAAK,EAAO,qCAAsC,CAC3D,MAAO,EAAO,MACd,OAAQ,EAAO,OACf,kBAAmB,EAAO,kBAC1B,OAAQ,EAAO,MACjB,CAAC,EAGG,EAAO,WACT,MAAM,KAAK,KAAK,EAAO,iCAAkC,CACvD,UAAW,EAAO,SACpB,CAAC,EAIC,EAAO,OACT,MAAM,KAAK,KAAK,EAAO,qCAAsC,CAC3D,QAAS,GACT,eAAgB,CAClB,CAAC,EAGI,CAAE,QAAS,EAAK,CACzB,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CAAE,CAC7E,CACF,CAEA,MAAM,qBAAqB,EAA8D,CACvF,MAAM,KAAK,eAAe,CAAK,EAC/B,GAAI,CAIF,OAHA,MAAM,KAAK,KAAK,EAAO,sCAAsC,EAC7D,MAAM,KAAK,KAAK,EAAO,iCAAkC,CAAE,UAAW,EAAG,CAAC,EAC1E,MAAM,KAAK,KAAK,EAAO,qCAAsC,CAAE,QAAS,EAAM,CAAC,EACxE,CAAE,QAAS,EAAK,CACzB,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CAAE,CAC7E,CACF,CAEA,MAAM,gBACJ,EACA,EAC+C,CAC/C,MAAM,KAAK,eAAe,CAAK,EAC/B,GAAI,CAEF,IAAM,EAAW,MAAM,KAAK,gBAAgB,CAAK,EASjD,OAPA,MAAM,KAAK,KAAK,EAAO,qCAAsC,CAC3D,MAAO,EAAQ,OAAS,EAAS,MACjC,OAAQ,EAAQ,QAAU,EAAS,OACnC,kBAAmB,EAAQ,mBAAqB,EAChD,OAAQ,EAAQ,QAAU,EAC5B,CAAC,EAEM,CAAE,QAAS,EAAK,CACzB,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CAAE,CAC7E,CACF,CAEA,MAAM,aAAa,EAAe,EAAiE,CACjG,MAAM,KAAK,eAAe,CAAK,EAC/B,GAAI,CAKF,OAJA,MAAM,KAAK,KAAK,EAAO,qCAAsC,CAC3D,UACA,eAAgB,EAAU,EAAI,CAChC,CAAC,EACM,CAAE,QAAS,EAAK,CACzB,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CAAE,CAC7E,CACF,CAEA,MAAM,sBAAsB,EAAe,EAAsE,CAC/G,MAAM,KAAK,eAAe,CAAK,EAC/B,GAAI,CAMF,OALA,MAAM,KAAK,KAAK,EAAO,oBAAoB,EAC3C,MAAM,KAAK,KAAK,EAAO,gBAAiB,CACtC,WAAY,GAAY,KAAK,GAAG,GAAK,qEACrC,aAAc,gBAChB,CAAC,EACM,CAAE,QAAS,EAAK,CACzB,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CAAE,CAC7E,CACF,CAEA,MAAM,qBAAqB,EAA6E,CACtG,MAAM,KAAK,eAAe,CAAK,EAC/B,GAAI,CACF,MAAM,KAAK,KAAK,EAAO,oBAAoB,EAC3C,IAAM,EAAgB,MAAM,KAAK,KAAK,EAAO,wBAAwB,EACrE,MAAM,KAAK,KAAK,EAAO,aAAa,EACpC,MAAM,KAAK,KAAK,EAAO,qBAAqB,EAC5C,IAAM,EAAkC,CAAC,EACzC,IAAK,IAAM,KAAK,EAAc,SAAW,CAAC,EACxC,EAAQ,EAAE,MAAQ,EAAE,MAEtB,MAAO,CAAE,QAAS,GAAM,SAAQ,CAClC,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CAAE,CAC7E,CACF,CAEA,MAAM,sBAAsB,EAAgG,CAC1H,MAAM,KAAK,eAAe,CAAK,EAC/B,GAAI,CACF,MAAM,KAAK,KAAK,EAAO,oBAAoB,EAC3C,IAAM,EAAS,MAAM,KAAK,KAAK,EAAO,wBAAwB,EAC9D,MAAM,KAAK,KAAK,EAAO,qBAAqB,EAC5C,IAAM,EAAkC,CAAC,EACzC,IAAK,IAAM,KAAK,EAAO,SAAW,CAAC,EACjC,EAAQ,EAAE,MAAQ,EAAE,MAEtB,MAAO,CAAE,QAAS,GAAM,SAAQ,CAClC,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CAAE,CAC7E,CACF,CAEA,MAAM,uBAAuB,EAAe,EAAkB,EAAgE,CAC5H,MAAM,KAAK,eAAe,CAAK,EAC/B,GAAI,CACF,MAAM,KAAK,KAAK,EAAO,YAAY,EACnC,IAAM,EAAM,MAAM,KAAK,KAAK,EAAO,iBAAiB,EAC9C,EAAc,MAAM,KAAK,KAAK,EAAO,oBAAqB,CAC9D,OAAQ,EAAI,KAAK,OACjB,UACF,CAAC,EAQD,OAPK,EAAY,QAGjB,MAAM,KAAK,KAAK,EAAO,wBAAyB,CAC9C,OAAQ,EAAY,OACpB,OACF,CAAC,EACM,CAAE,QAAS,EAAK,GANd,CAAE,QAAS,GAAO,MAAO,oCAAqC,CAOzE,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CAAE,CAC7E,CACF,CAEA,MAAM,YAAY,EAAe,EAAkB,IAA2E,CAC5H,MAAM,KAAK,eAAe,CAAK,EAC/B,IAAM,EAAY,KAAK,IAAI,EAC3B,GAAI,CACF,KAAO,KAAK,IAAI,EAAI,EAAY,GAAS,CAKvC,IAAM,GAAa,MAJE,KAAK,KAAK,EAAO,mBAAoB,CACxD,WAAY,sBACZ,cAAe,EACjB,CAAC,GACyB,QAAQ,MAClC,GAAI,IAAe,WACjB,MAAO,CAAE,QAAS,GAAM,YAAW,EAErC,MAAM,IAAI,QAAQ,GAAW,WAAW,EAAS,GAAG,CAAC,CACvD,CACA,MAAO,CAAE,QAAS,GAAO,MAAO,kCAAkC,EAAQ,IAAK,CACjF,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CAAE,CAC7E,CACF,CAEA,MAAM,UAAU,EAAiJ,CAC/J,MAAM,KAAK,eAAe,CAAK,EAC/B,GAAI,CACF,MAAM,KAAK,KAAK,EAAO,aAAa,EACpC,IAAM,EAAS,MAAM,KAAK,KAAK,EAAO,mBAAmB,EACnD,EAAmF,CAAC,EACpF,GAAiB,EAAY,IAAsB,CAOvD,GANA,EAAO,KAAK,CACV,QAAS,EAAM,MAAM,GACrB,IAAK,EAAM,MAAM,IACjB,KAAM,EAAM,MAAM,MAAQ,GAC1B,UACF,CAAC,EACG,EAAM,YACR,IAAK,IAAM,KAAS,EAAM,YACxB,EAAc,EAAO,EAAM,MAAM,EAAE,CAGzC,EAEA,OADA,EAAc,EAAO,SAAS,EACvB,CAAE,QAAS,GAAM,QAAO,CACjC,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CAAE,CAC7E,CACF,CAEA,MAAM,gBAAgB,EAAe,EAAiB,EAAiF,CACrI,MAAM,KAAK,eAAe,CAAK,EAC/B,GAAI,CACF,IAAM,EAAgB,MAAM,KAAK,KAAK,EAAO,2BAA4B,CACvE,UACA,UAAW,eACb,CAAC,EACK,EAAoB,gCAAgC,EAAW,QAC/D,EAAS,MAAM,KAAK,KAAK,EAAO,mBAAoB,CACxD,WAAY,EACZ,UAAW,EAAc,mBACzB,cAAe,GACf,aAAc,EAChB,CAAC,EACD,GAAI,EAAO,iBACT,MAAO,CAAE,QAAS,GAAO,MAAO,EAAO,iBAAiB,MAAQ,EAAO,iBAAiB,WAAW,aAAe,mBAAoB,EAExI,GAAI,CACF,MAAO,CAAE,QAAS,GAAM,OAAQ,KAAK,MAAM,EAAO,QAAQ,KAAK,CAAE,CACnE,MAAQ,CACN,MAAO,CAAE,QAAS,GAAM,OAAQ,EAAO,QAAQ,KAAM,CACvD,CACF,OAAS,EAAG,CACV,MAAO,CAAE,QAAS,GAAO,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CAAE,CAC7E,CACF,CAEA,mBACE,EACA,EAKkB,CAClB,IAAI,EAAW,KAAK,gBAAgB,IAAI,CAAK,GAAK,CAAC,EAKnD,GAHI,GAAS,aACX,EAAW,EAAS,OAAQ,GAAM,EAAE,OAAS,SAAW,EAAE,OAAS,WAAW,GAE5E,GAAS,QACX,GAAI,CACF,IAAM,EAAQ,IAAI,OAAO,EAAQ,QAAS,GAAG,EAC7C,EAAW,EAAS,OAAQ,GAAM,EAAM,KAAK,EAAE,IAAI,CAAC,CACtD,MAAY,CACV,EAAW,EAAS,OAAQ,GAAM,EAAE,KAAK,SAAS,EAAQ,OAAQ,CAAC,CACrE,CAMF,OAJI,GAAS,QACX,EAAW,EAAS,MAAM,CAAC,EAAQ,KAAK,GAGnC,CAAC,GAAG,CAAQ,CACrB,CAEA,qBAAqB,EAAqB,CACxC,KAAK,gBAAgB,IAAI,EAAO,CAAC,CAAC,CACpC,CAEA,mBACE,EACA,EAIkB,CAClB,IAAI,EAAW,KAAK,gBAAgB,IAAI,CAAK,GAAK,CAAC,EASnD,OAPI,GAAS,aACX,EAAW,EAAS,OAAQ,GAAM,EAAE,IAAI,SAAS,EAAQ,UAAW,CAAC,GAEnE,GAAS,QACX,EAAW,EAAS,MAAM,CAAC,EAAQ,KAAK,GAGnC,CAAC,GAAG,CAAQ,CACrB,CAEA,qBAAqB,EAAqB,CACxC,KAAK,gBAAgB,IAAI,EAAO,CAAC,CAAC,EAClC,KAAK,eAAe,IAAI,EAAO,IAAI,GAAK,EACxC,KAAK,iBAAiB,IAAI,EAAO,CAAC,CACpC,CAKA,kBACE,EACA,EAKgB,CAEhB,IAAM,EAAa,KAAK,eAAe,IAAI,CAAK,EAC5C,EAA0B,CAAC,EAsC/B,MApCA,CAKE,EALE,GAAc,EAAW,KAAO,EACxB,MAAM,KAAK,EAAW,OAAO,CAAC,GAGvB,KAAK,gBAAgB,IAAI,CAAK,GAAK,CAAC,GAClC,KAAK,EAAK,KAAS,CACpC,GAAI,KAAK,EAAI,UAAU,GAAG,IAC1B,GAAI,EAAI,UACR,OAAQ,EAAI,OACZ,IAAK,EAAI,IACT,OAAQ,KAAK,cAAc,EAAI,GAAG,EAClC,eAAgB,CAAC,EACV,QACP,KAAM,EAAI,KACV,OAAQ,EAAI,OACZ,MAAO,CAAC,EACR,YAAa,CAAE,KAAM,OAAQ,SAAU,GAAO,OAAQ,QAAS,EAC/D,WAAY,EAAI,UAChB,kBAAmB,GACnB,iBAAkB,EACpB,EAAkB,EAIf,GAAS,gBACZ,EAAU,EAAQ,OAAO,GAAK,CAAC,KAAK,cAAc,EAAE,QAAQ,CAAC,GAG3D,GAAS,aACX,EAAU,EAAQ,OAAQ,GAAM,EAAE,IAAI,SAAS,EAAQ,UAAW,CAAC,GAGjE,GAAS,QACX,EAAU,EAAQ,MAAM,CAAC,EAAQ,KAAK,GAGjC,CACT,CAKA,gBAAgB,EAAe,EAAwC,CAErE,OADmB,KAAK,eAAe,IAAI,CACpC,GAAY,IAAI,CAAS,GAAK,IACvC,CAMA,MAAM,gBAAgB,EAAe,EAKlC,CACD,MAAM,KAAK,eAAe,CAAK,EAE/B,GAAI,CACF,IAAM,EAAS,MAAM,KAAK,KAAK,EAAO,0BAA2B,CAC/D,WACF,CAAC,EAED,MAAO,CACL,QAAS,GACT,KAAM,EAAO,KACb,cAAe,EAAO,aACxB,CACF,OAAS,EAAG,CACV,MAAO,CACL,QAAS,GACT,MAAO,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CAClD,CACF,CACF,CAEA,mBAAmB,EAAe,EAAkB,EAAsC,CACnF,KAAK,iBAAiB,IAAI,CAAK,GAClC,KAAK,iBAAiB,IAAI,EAAO,IAAI,GAAK,EAE5C,KAAK,iBAAiB,IAAI,CAAK,CAAC,CAAE,IAAI,EAAU,CAAQ,CAC1D,CAEA,uBAAuB,EAAe,EAAwB,CAC5D,IAAM,EAAY,KAAK,iBAAiB,IAAI,CAAK,EAC7C,IACF,EAAU,OAAO,CAAQ,EACrB,EAAU,OAAS,GACrB,KAAK,iBAAiB,OAAO,CAAK,EAGxC,CAEA,mBAAmB,EAAe,EAAkB,EAAsC,CACnF,KAAK,iBAAiB,IAAI,CAAK,GAClC,KAAK,iBAAiB,IAAI,EAAO,IAAI,GAAK,EAE5C,KAAK,iBAAiB,IAAI,CAAK,CAAC,CAAE,IAAI,EAAU,CAAQ,CAC1D,CAEA,uBAAuB,EAAe,EAAwB,CAC5D,IAAM,EAAY,KAAK,iBAAiB,IAAI,CAAK,EAC7C,IACF,EAAU,OAAO,CAAQ,EACrB,EAAU,OAAS,GACrB,KAAK,iBAAiB,OAAO,CAAK,EAGxC,CAEA,sBACE,EACA,EACA,EACA,MAAyC,CAAC,EACpC,CACD,KAAK,oBAAoB,IAAI,CAAK,GAAG,KAAK,oBAAoB,IAAI,EAAO,IAAI,GAAK,EACvF,KAAK,oBAAoB,IAAI,CAAK,CAAC,CAAE,IAAI,EAAY,CAAE,UAAS,SAAQ,CAAC,CAC3E,CAEA,0BAA0B,EAAe,EAA0B,CACjE,IAAM,EAAY,KAAK,oBAAoB,IAAI,CAAK,EAC/C,IACL,EAAU,OAAO,CAAU,EACvB,EAAU,OAAS,GAAG,KAAK,oBAAoB,OAAO,CAAK,EACjE,CAEA,MAAM,gBACJ,EACA,EAAiF,CAAC,EACpE,CACd,OAAO,KAAK,KAAK,EAAO,uBAAwB,CAC9C,OAAQ,EAAQ,QAAU,OAC1B,QAAS,EAAQ,SAAW,GAC5B,cAAe,EAAQ,eAAiB,CAC1C,CAAC,CACH,CAEA,MAAM,eAAe,EAA6B,CAChD,OAAO,KAAK,KAAK,EAAO,qBAAqB,CAC/C,CAMA,MAAM,cAAc,EAAe,EAAkE,CACnG,MAAM,KAAK,eAAe,CAAK,EAC/B,GAAI,CACF,MAAM,KAAK,KAAK,EAAO,gBAAgB,CACzC,MAAY,CAAC,CACb,IAAM,EAAS,MAAM,KAAK,KAAK,EAAO,wBAAyB,CAC7D,aACA,UAAW,GACX,cAAe,EACjB,CAAC,EAOD,OANI,GAAQ,iBACH,CACL,OAAQ,GACR,MAAO,EAAO,iBAAiB,WAAW,aAAe,EAAO,iBAAiB,MAAQ,aAC3F,EAEK,CAAE,OAAQ,EAAK,CACxB,CAEA,MAAM,eAAe,EAAe,EAGjC,CACD,MAAM,KAAK,eAAe,CAAK,EAC/B,GAAI,CACF,MAAM,KAAK,KAAK,EAAO,gBAAgB,CACzC,MAAY,CAAC,CAEb,OAAO,KAAK,KAAK,EAAO,mBAAoB,CAC1C,aACA,cAAe,GACf,aAAc,GACd,QAAS,GACX,CAAC,CACH,CAEA,MAAc,KACZ,EACA,EACA,EACc,CACd,MAAM,KAAK,eAAe,CAAK,EAC/B,IAAM,EAAS,KAAK,QAAQ,IAAI,CAAK,EACrC,GAAI,CACF,OAAO,MAAM,OAAO,SAAS,YAAY,EAAQ,EAAQ,CAAM,CACjE,OAAS,EAAK,CACZ,MAAM,EAAsB,EAAK,CAAM,CACzC,CACF,CAEA,MAAM,YACJ,EACA,EACA,EACc,CACd,OAAO,KAAK,KAAK,EAAO,EAAQ,CAAM,CACxC,CAEA,MAAc,eAAe,EAA8B,CACzD,IAAM,EAAe,KAAK,cAAc,IAAI,CAAK,EACjD,GAAI,EAEF,MADA,KAAK,cAAc,OAAO,CAAK,EACzB,IAAI,EACR,oBACA,8BAA8B,EAAM,IAAI,EAAa,+CACrD,CAAE,QAAO,OAAQ,CAAa,CAChC,EAEG,KAAK,QAAQ,IAAI,CAAK,GAAG,MAAM,KAAK,OAAO,CAAK,CACvD,CAEA,MAAM,gBAAgB,EAA2D,CAC/E,IAAM,EAAgB,MAAM,KAAK,KAAK,EAAO,uBAAuB,EAC9D,EAAW,EAAc,gBAAkB,EAAc,eAC/D,MAAO,CACL,MAAO,KAAK,MAAM,EAAS,WAAW,EACtC,OAAQ,KAAK,MAAM,EAAS,YAAY,CAC1C,CACF,CAEA,MAAM,kBAAkB,EAIrB,CACD,OAAO,KAAK,uBAAuB,GAAQ,SAAY,CACrD,IAAM,EAA2B,MAAM,KAAK,KAAK,EAAO,yBAA0B,CAChF,OAAQ,MACR,sBAAuB,EACzB,CAAC,EACK,CAAE,QAAO,UAAW,MAAM,KAAK,gBAAgB,CAAK,EAC1D,MAAO,CAAE,OAAQ,EAAO,KAAM,QAAO,QAAO,CAC9C,GAAG,CAAC,CACN,CAEA,MAAc,uBAA0B,EAAe,EAA8B,CACnF,IAAI,EACE,EAAU,IAAI,SAAgB,EAAG,IAAW,CAChD,EAAY,eAAiB,EAAO,IAAI,EACtC,qBACA,sCAAsC,EAAc,sBAAsB,IAC1E,CAAE,QAAO,UAAW,EAAc,qBAAsB,CAC1D,CAAC,EAAG,EAAc,qBAAqB,CACzC,CAAC,EACD,GAAI,CACF,OAAO,MAAM,QAAQ,KAAK,CAAC,EAAM,CAAO,CAAC,CAC3C,QAAU,CACJ,IAAc,QAAW,aAAa,CAAS,CACrD,CACF,CAEA,MAAM,cAAc,EAAe,EAAW,EAAW,EAAe,EAIrE,CAQD,MAAO,CAAE,QAAQ,MAPsB,KAAK,uBAC1C,EACA,KAAK,KAAK,EAAO,yBAA0B,CACzC,OAAQ,MACR,KAAM,CAAE,IAAG,IAAG,QAAO,SAAQ,MAAO,CAAE,CACxC,CAAC,CACH,GACwB,KAAM,QAAO,QAAO,CAC9C,CAEA,MAAc,mBACZ,EACA,EACA,EACA,EACA,EAOI,CAAC,EACU,CACf,IAAM,EAA8B,CAClC,OACA,EAAG,KAAK,MAAM,CAAC,EACf,EAAG,KAAK,MAAM,CAAC,EACf,UAAW,EAAQ,WAAa,CAClC,GAEI,IAAS,gBAAkB,IAAS,iBAAmB,IAAS,gBAClE,EAAO,OAAS,EAAQ,QAAU,QAC9B,IAAS,gBAAkB,IAAS,mBACtC,EAAO,WAAa,EAAQ,YAAc,IAI1C,IAAS,eACX,EAAO,QAAU,EAAQ,SAAW,GAGlC,IAAS,eACX,EAAO,OAAS,EAAQ,QAAU,EAClC,EAAO,OAAS,EAAQ,QAAU,GAGpC,MAAM,KAAK,KAAK,EAAO,2BAA4B,CAAM,CAC3D,CAEA,MAAM,MACJ,EACA,EACA,EACA,EAAsB,OACtB,EAAa,EACb,EAAY,EACG,CACf,IAAM,EAAc,IAAW,OAAS,EAAI,IAAW,QAAU,EAAI,IAAW,SAAW,EAAI,EAE/F,MAAM,KAAK,mBAAmB,EAAO,aAAc,EAAG,EAAG,CAAE,OAAQ,OAAQ,QAAS,EAAG,WAAU,CAAC,EAClG,MAAM,IAAI,QAAQ,GAAW,WAAW,EAAS,GAAG,CAAC,EAErD,IAAK,IAAI,EAAI,EAAG,GAAK,EAAY,IAC/B,MAAM,KAAK,mBAAmB,EAAO,eAAgB,EAAG,EAAG,CACzD,SACA,QAAS,EACT,WAAY,EACZ,WACF,CAAC,EACD,MAAM,IAAI,QAAQ,GAAW,WAAW,EAAS,EAAE,CAAC,EACpD,MAAM,KAAK,mBAAmB,EAAO,gBAAiB,EAAG,EAAG,CAC1D,SACA,QAAS,EACT,WAAY,EACZ,WACF,CAAC,EACG,EAAI,GACN,MAAM,IAAI,QAAQ,GAAW,WAAW,EAAS,GAAG,CAAC,CAG3D,CAEA,MAAM,WAAW,EAAe,EAAW,EAAW,EAAY,EAAkB,CAClF,MAAM,KAAK,MAAM,EAAO,EAAG,EAAG,QAAS,EAAG,CAAS,CACrD,CAEA,MAAM,YAAY,EAAe,EAAW,EAAW,EAAY,EAAkB,CACnF,MAAM,KAAK,MAAM,EAAO,EAAG,EAAG,OAAQ,EAAG,CAAS,CACpD,CAEA,MAAM,YAAY,EAAe,EAAW,EAAW,EAAY,EAAkB,CACnF,MAAM,KAAK,MAAM,EAAO,EAAG,EAAG,OAAQ,EAAG,CAAS,CACpD,CAEA,MAAM,MAAM,EAAe,EAAW,EAA0B,CAC9D,MAAM,KAAK,mBAAmB,EAAO,aAAc,EAAG,EAAG,CAAE,OAAQ,OAAQ,QAAS,CAAE,CAAC,CACzF,CAEA,MAAM,KACJ,EACA,EACA,EACA,EACA,EACA,EAAY,EACG,CACf,MAAM,KAAK,mBAAmB,EAAO,aAAc,EAAQ,EAAQ,CAAE,OAAQ,OAAQ,QAAS,CAAE,CAAC,EACjG,MAAM,IAAI,QAAQ,GAAW,WAAW,EAAS,EAAE,CAAC,EAEpD,MAAM,KAAK,mBAAmB,EAAO,eAAgB,EAAQ,EAAQ,CACnE,OAAQ,OACR,QAAS,EACT,WAAY,EACZ,WACF,CAAC,EACD,MAAM,IAAI,QAAQ,GAAW,WAAW,EAAS,EAAE,CAAC,EAEpD,MAAM,KAAK,mBAAmB,EAAO,aAAc,EAAM,EAAM,CAAE,OAAQ,OAAQ,QAAS,EAAG,WAAU,CAAC,EACxG,MAAM,IAAI,QAAQ,GAAW,WAAW,EAAS,EAAE,CAAC,EAEpD,MAAM,KAAK,mBAAmB,EAAO,gBAAiB,EAAM,EAAM,CAChE,OAAQ,OACR,QAAS,EACT,WAAY,EACZ,WACF,CAAC,CACH,CAEA,MAAM,OAAO,EAAe,EAAW,EAAW,EAAgB,EAA+B,CAC/F,MAAM,KAAK,mBAAmB,EAAO,aAAc,EAAG,EAAG,CAAE,SAAQ,QAAO,CAAC,CAC7E,CAEA,MAAM,KAAK,EAAe,EAA6B,CACrD,IAAK,IAAM,KAAQ,EACjB,GAAI,IAAS;GAAQ,IAAS,KAC5B,MAAM,KAAK,SAAS,EAAO,OAAO,OAGlC,GADe,KAAK,iBAAiB,CACjC,EAAQ,CACV,IAAM,EAAa,KAAK,cAAc,CAAI,EAC1C,MAAM,KAAK,SAAS,EAAO,EAAM,EAAa,EAAU,MAAQ,CAAC,CACnE,MACE,MAAM,KAAK,KAAK,EAAO,mBAAoB,CAAE,KAAM,CAAK,CAAC,CAIjE,CAEA,cAAsB,EAAuB,CAC3C,MAAO,6BAA6B,KAAK,CAAI,CAC/C,CAEA,MAAc,iBACZ,EACA,EACA,EACA,EAAY,EACG,CACf,MAAM,KAAK,KAAK,EAAO,yBAA0B,CAC/C,KAAM,EAAO,KAAO,EAAQ,IAAS,UAAY,aAAe,EAChE,IAAK,EAAO,IACZ,KAAM,EAAO,KACb,sBAAuB,EAAO,QAC9B,YACA,KAAM,EAAO,MAAQ,GACrB,eAAgB,EAAO,MAAQ,GAC/B,SAAU,EAAO,UAAY,CAC/B,CAAC,CACH,CAEA,MAAM,SAAS,EAAe,EAAa,EAAY,EAAkB,CACvE,IAAM,EAAS,KAAK,iBAAiB,CAAG,EACxC,GAAI,CAAC,EACH,MAAU,MAAM,gBAAgB,GAAK,EAGvC,MAAM,KAAK,iBAAiB,EAAO,UAAW,EAAQ,CAAS,EAC/D,MAAM,KAAK,iBAAiB,EAAO,QAAS,EAAQ,CAAS,CAC/D,CAEA,MAAM,cAAc,EAAe,EAA8B,CAC/D,IAAM,EAAQ,EAAM,YAAY,CAAC,CAAC,MAAM,GAAG,EACrC,EAAyB,CAAC,EAC5B,EAAU,GAEd,IAAK,IAAM,KAAQ,EACb,KAAQ,EACV,EAAa,KAAK,CAAI,EAEtB,EAAU,EAId,IAAI,EAAY,EAChB,IAAK,IAAM,KAAO,EAChB,GAAa,EAAU,IAAkC,EAGvD,GACF,MAAM,KAAK,SAAS,EAAO,EAAS,CAAS,CAEjD,CAEA,iBAAyB,EAAmC,CAC1D,IAAM,EAAW,EAAI,YAAY,EAEjC,GAAI,EAAgB,GAClB,OAAO,EAAgB,GAGzB,GAAI,EAAI,SAAW,EAAG,CACpB,IAAM,EAAO,EAAI,YAAY,CAAC,CAAC,WAAW,CAAC,EAC3C,MAAO,CACL,MACA,KAAM,MAAM,EAAI,YAAY,IAC5B,QAAS,EACT,KAAM,CACR,CACF,CAEA,OAAO,IACT,CAEA,eAAe,EAAiC,CAC9C,GAAI,CAAC,EAAgB,MAAO,GAE5B,IAAI,EAAS,EACP,EAAQ,EAAe,YAAY,CAAC,CAAC,MAAM,GAAG,EACpD,IAAK,IAAM,KAAQ,EAAO,CACxB,IAAM,EAAU,EAAK,KAAK,EACtB,KAAW,IACb,GAAU,EAAU,GAExB,CACA,OAAO,CACT,CACF,ECnpDI,EAAY,GACZ,EAAc,GACZ,EAA2B,CAAC,EAElC,OAAO,QAAQ,MAAM,IAAI,WAAW,CAAC,CAAC,MAAM,CAAE,UAAW,KAAa,CAGpE,GAFA,EAAY,CAAC,CAAC,EACd,EAAc,GACV,EACF,IAAK,IAAM,KAAQ,EACjB,QAAQ,IAAI,SAAU,GAAG,CAAI,EAGjC,EAAY,OAAS,CACvB,CAAC,EAED,OAAO,QAAQ,UAAU,aAAa,EAAS,IAAa,CACtD,IAAa,SAAW,EAAQ,YAClC,EAAY,CAAC,CAAC,EAAQ,UAAU,SAEpC,CAAC,EAED,SAAgB,EAAS,GAAG,EAAuB,CACjD,GAAI,CAAC,EAAa,CAChB,EAAY,KAAK,CAAI,EACrB,MACF,CACI,GACF,QAAQ,IAAI,SAAU,GAAG,CAAI,CAEjC,CC6EA,SAAgB,EAAS,EAA4B,CACnD,GAAI,CACF,IAAM,EAAS,IAAI,IAAI,CAAG,EAC1B,OAAO,EAAO,SAAW,OAAS,KAAO,EAAO,MAClD,MAAQ,CACN,OAAO,IACT,CACF,CAEA,SAAgB,EAAgB,EAAsB,CACpD,OAAO,IAAQ,IAAM,IAAQ,eAAiB,EAAI,WAAW,cAAc,GAAK,IAAQ,cAC1F,CAEA,SAAgB,EAAqB,EAAiC,CAEpE,OADI,IAAY,MACT,CAAC,EAAQ,MAAM,KAAK,CAAC,CAAC,SAAS,eAAe,CACvD,CAEA,SAAS,EAAQ,EAAW,EAAoB,CAE9C,OADI,EAAgB,CAAC,GAAK,EAAgB,CAAC,EAAU,GAC9C,IAAM,CACf,CAEA,SAAS,EAAM,EAAa,EAAM,GAAY,CAE5C,OADI,EAAI,QAAU,EAAY,EACvB,GAAG,EAAI,MAAM,EAAG,EAAM,CAAC,EAAE,IAClC,CAEA,SAAS,GAAU,EAAgC,CACjD,OAAO,EAAO,MAAQ,EAAO,IAAM,EACrC,CAEA,SAAgB,GAAoB,EAA4C,CAC9E,IAAM,EAAa,EAAS,EAAM,SAAS,IAAI,EACzC,EAAqB,EAAM,qBAAuB,GAClD,EAAuB,EAAM,gBAAgB,OAAQ,GAAU,EAAM,gBAAkB,EAAE,EACzF,EAAqB,CAAC,EAEtB,EAA6C,EAAM,gBAAgB,IAAK,GAAU,CACtF,IAAM,EAAS,EAAS,EAAM,GAAG,EAC3B,EAAS,EAAM,gBAAkB,GACvC,MAAO,CACL,GAAG,EACH,SACA,YAAa,EACT,KACA,EAAqB,UAAW,GAAc,EAAU,UAAY,EAAM,OAAO,EACrF,SACA,YAAa,IAAW,MAAQ,IAAe,MAAQ,IAAW,CACpE,CACF,CAAC,EAEK,EAAiC,EAAM,UAAU,IAAK,GAAU,CACpE,IAAM,EAAS,EAAS,EAAM,GAAG,EACjC,MAAO,CACL,GAAG,EACH,OAAQ,EAAM,WAAa,OAC3B,SACA,YAAa,IAAW,MAAQ,IAAe,MAAQ,IAAW,EAClE,kBAAmB,EAChB,OACE,GACC,EAAM,WAAa,QACnB,CAAC,EAAgB,EAAM,GAAG,GAC1B,EAAQ,EAAU,IAAK,EAAM,GAAG,CACpC,CAAC,CACA,IAAK,GAAc,EAAU,OAAO,CACzC,CACF,CAAC,EAEK,EAAmC,EAAM,WAAW,IAAK,GAAW,CACxE,IAAM,EAAQ,EAAO,QAAU,EAAgB,EAAO,GAAG,EACnD,EAAS,EAAQ,KAAO,EAAS,EAAO,GAAG,EAC3C,EAAc,GAAyB,CAAC,GAAS,EAAQ,EAAK,EAAO,GAAG,EACxE,EAAO,GAAU,CAAM,EAGvB,EAAc,GAClB,EAAM,WAAa,SAAc,EAAW,EAAM,GAAG,GAAM,IAAS,IAAM,EAAM,OAAS,GAC3F,MAAO,CACL,GAAG,EACH,WAAY,EAAO,YAAc,KACjC,SACA,YAAa,IAAW,MAAQ,IAAe,MAAQ,IAAW,EAClE,QACA,SAAU,EAAO,KAAK,OAAS,GAAK,EAAO,KAAK,QAAU,EAC1D,eAAgB,EAAqB,EAAO,OAAO,EACnD,kBAAmB,EAAqB,OAAQ,GAAU,EAAW,EAAM,GAAG,CAAC,CAAC,CAAC,IAAK,GAAU,EAAM,OAAO,EAC7G,YAAa,EAAM,UAAU,OAAO,CAAU,CAAC,CAAC,IAAK,GAAU,EAAM,OAAO,CAC9E,CACF,CAAC,EAEK,EAAiB,EACnB,EAAW,OAAQ,GAAW,EAAO,OAAS,EAAO,YAAY,SAAW,CAAC,EAC7E,CAAC,EACD,EAAe,OAAS,GAC1B,EAAS,KACP,GAAG,EAAe,OAAO,8DAA8D,EAAe,IAAK,GAAW,EAAO,QAAQ,CAAC,CAAC,KAAK,IAAI,EAAE,iLACpJ,EAGF,IAAK,IAAM,KAAU,EAgBnB,GAfI,EAAO,gBACT,EAAS,KAAK,UAAU,EAAO,SAAS,IAAI,EAAM,EAAO,GAAG,GAAK,SAAS,uFAAuF,EAE/J,EAAO,UACT,EAAS,KAAK,UAAU,EAAO,SAAS,IAAI,EAAM,EAAO,GAAG,GAAK,SAAS,mBAAmB,EAAO,KAAK,MAAM,GAAG,EAAO,KAAK,OAAO,0CAA0C,EAE7K,CAAC,EAAO,OAAS,EAAO,kBAAkB,SAAW,GACvD,EAAS,KAAK,UAAU,EAAO,SAAS,IAAI,EAAM,EAAO,GAAG,EAAE,qGAAqG,EAEjK,EAAO,kBAAkB,OAAS,GACpC,EAAS,KAAK,UAAU,EAAO,SAAS,IAAI,EAAM,EAAO,GAAG,EAAE,YAAY,EAAO,kBAAkB,OAAO,4BAA4B,EAAO,kBAAkB,KAAK,IAAI,EAAE,yCAAyC,EAEjN,EAAO,YAAY,OAAS,GAC9B,EAAS,KAAK,UAAU,EAAO,SAAS,IAAI,EAAM,EAAO,GAAG,EAAE,YAAY,EAAO,YAAY,OAAO,eAAe,EAAO,YAAY,KAAK,IAAI,EAAE,4EAA4E,EAE3N,GAAsB,CAAC,EAAO,OAAS,EAAO,kBAAkB,OAAS,GAAK,EAAO,YAAY,SAAW,EAAG,CACjH,IAAM,EAAY,EAAO,kBAAkB,MACxC,GAAO,EAAM,gBAAgB,KAAM,GAAU,EAAM,UAAY,CAAE,CAAC,EAAE,yBAA2B,EAClG,EACI,EAAO,YACT,EAAS,KACP,UAAU,EAAO,SAAS,IAAI,EAAM,EAAO,GAAG,EAAE,kGAC9C,EACI,sFACA,+EAER,EAEA,EAAS,KACP,UAAU,EAAO,SAAS,IAAI,EAAM,EAAO,GAAG,EAAE,+HAClD,CAEJ,CAGF,IAAK,IAAM,KAAS,EAAsB,CACxC,IAAM,EAAa,EAAW,OAAQ,GAAW,EAAO,kBAAkB,SAAS,EAAM,OAAO,CAAC,EAC7F,EAAW,OAAS,GACtB,EAAS,KAAK,mBAAmB,EAAM,QAAQ,IAAI,EAAM,EAAM,GAAG,EAAE,YAAY,EAAW,OAAO,gBAAgB,EAAW,IAAK,GAAW,EAAO,QAAQ,CAAC,CAAC,KAAK,IAAI,EAAE,6BAA6B,EAExM,IAAM,EAAa,EAAU,OAAQ,GAAc,EAAU,kBAAkB,SAAS,EAAM,OAAO,CAAC,EAClG,EAAW,OAAS,GACtB,EAAS,KAAK,mBAAmB,EAAM,QAAQ,IAAI,EAAM,EAAM,GAAG,EAAE,YAAY,EAAW,OAAO,eAAe,EAAW,IAAK,GAAc,EAAU,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,oCAAoC,CAErN,CAEA,IAAK,IAAM,KAAS,EAAW,CAC7B,GAAI,EAAM,OAAQ,SAClB,IAAM,EAAa,EAAW,OAAQ,GAAW,EAAO,YAAY,SAAS,EAAM,OAAO,CAAC,EACvF,EAAW,OAAS,GACtB,EAAS,KAAK,aAAa,EAAM,QAAQ,IAAI,EAAM,EAAM,GAAG,EAAE,YAAY,EAAW,OAAO,gBAAgB,EAAW,IAAK,GAAW,EAAO,QAAQ,CAAC,CAAC,KAAK,IAAI,EAAE,6BAA6B,EAE9L,EAAM,kBAAkB,OAAS,GACnC,EAAS,KAAK,aAAa,EAAM,QAAQ,IAAI,EAAM,EAAM,GAAG,EAAE,YAAY,EAAM,kBAAkB,OAAO,4BAA4B,EAAM,kBAAkB,KAAK,IAAI,EAAE,6BAA6B,CAEzM,CAEA,IAAK,IAAM,KAAS,EACd,MAAM,OACV,IAAI,CAAC,EAAM,uBAAwB,CACjC,IAAM,EAAS,EAAM,mBAAqB,KAAK,EAAM,mBAAmB,GAAK,GAC7E,EAAS,KAAK,mBAAmB,EAAM,QAAQ,IAAI,EAAM,EAAM,GAAG,EAAE,mCAAmC,EAAO,wGAAwG,CACxN,CACI,EAAM,eACR,EAAS,KAAK,mBAAmB,EAAM,QAAQ,IAAI,EAAM,EAAM,GAAG,EAAE,+BAA+B,CAFrG,CAMF,IAAM,EAAoB,EAAU,OACjC,GAAU,CAAC,EAAM,QAAU,CAAC,EAAgB,EAAM,GAAG,GAAK,EAAM,kBAAkB,SAAW,CAChG,EACA,IAAK,IAAM,KAAS,EAClB,EAAS,KAAK,aAAa,EAAM,QAAQ,IAAI,EAAM,EAAM,GAAG,EAAE,0GAA0G,EAG1K,IAAM,EAAmB,EAAW,OAAQ,GAAW,EAAO,WAAW,CAAC,CAAC,OAK3E,GAJI,EAAmB,GACrB,EAAS,KAAK,GAAG,EAAiB,yGAAyG,EAGzI,EAAW,SAAW,EAAqB,OAAQ,CACrD,IAAM,EAAS,EAAqB,OAAQ,GAAU,EAAM,gBAAkB,CAAC,CAAC,CAAC,OAC3E,EAAW,EAAW,OAAQ,GAAW,EAAO,UAAU,CAAC,CAAC,OAC5D,EAAY,EAAW,SAAW,EAAqB,OAAS,EACtE,EAAS,KACP,aAAa,EAAW,OAAO,YAAY,EAAW,EAAI,KAAK,EAAS,4BAA8B,GAAG,0BAA0B,EAAqB,OAAO,iBAAiB,EAAS,EAAI,KAAK,EAAO,qCAAuC,GAAG,IACjP,EACI,gDACA,2FAER,CACF,CAEA,MAAO,CACL,SAAU,CAAE,GAAG,EAAM,SAAU,OAAQ,CAAW,EAClD,OAAQ,CACN,WAAY,EAAW,OACvB,gBAAiB,EAAgB,OACjC,UAAW,EAAU,MACvB,EACA,aACA,kBACA,YACA,UACF,CACF,CAGA,IAAa,GAAkC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MC5SlC,EAAuD,CAClE,YACA,QACA,YACA,OACF,EAEa,GAAsD,CAAC,QAAS,OAAO,EAEpF,SAAgB,GAAmB,EAAsC,CACvE,OAAQ,EAAR,CACE,IAAK,YACH,MAAO,iBACT,IAAK,QACH,MAAO,aACT,IAAK,YACH,MAAO,iBACT,IAAK,QACH,MAAO,aACT,QACE,OAAO,IACX,CACF,CAEA,SAAgB,GAAiB,EAAyC,CACxE,OACE,IAAU,SACV,IAAU,SACV,IAAU,WACV,EAA0B,SAAS,CAAuB,CAE9D,CAEA,SAAgB,GAAkB,EAAkC,CAClE,IAAM,EAAiB,MAAM,QAAQ,CAAK,EACtC,EACA,OAAO,GAAU,SACf,EAAM,MAAM,GAAG,EACf,CAAC,EACD,EAA2B,CAAC,EAClC,IAAK,IAAM,KAAS,EAAK,CACvB,IAAM,EAAU,OAAO,GAAU,SAAW,EAAM,KAAK,EAAI,GAC3D,GAAI,CAAC,GAAiB,CAAO,GAAK,CAAC,EAA0B,SAAS,CAAO,EAC3E,MAAU,MACR,2BAA2B,OAAO,CAAK,EAAE,uDAC3C,EAEG,EAAO,SAAS,CAAO,GAAG,EAAO,KAAK,CAAO,CACpD,CACA,OAAO,CACT,CAgBA,IAAa,GAA+B,IAC/B,GAA2B,KAIxC,SAAgB,GAAqB,EAAuE,CAC1G,IAAM,EAAa,OAAO,EAAM,SAAS,EACnC,EAAc,OAAO,EAAM,UAAU,EACrC,EAAY,OAAO,SAAS,CAAU,GAAK,EAAa,EAC1D,KAAK,IAAI,EAAY,EAAwB,EAC7C,GAGJ,MAAO,CAAE,YAAW,WADD,KAAK,IAAI,KAAK,IADZ,OAAO,SAAS,CAAW,GAAK,EAAc,EAAI,QACK,EAAG,CAC3D,CAAW,CACjC,CAqBA,IAAM,GAAgB,GAA8B,IAAI,QAAS,GAAY,WAAW,EAAS,CAAE,CAAC,EAOpG,eAAsB,GAAc,EAA8D,CAChG,IAAM,EAAQ,EAAQ,OAAS,GACzB,EAAM,EAAQ,KAAO,KAAK,IAC1B,EAAS,EAAQ,QAAU,CAAC,EAC5B,EAAY,EAAI,EAClB,EAAQ,EACR,EAA6B,CAAE,MAAO,UAAW,SAAU,CAAC,oBAAoB,CAAE,EAEtF,OAAS,CACP,EAAO,MAAM,EAAQ,MAAM,EAC3B,GAAS,EACT,IAAM,EAAW,EAAI,EAAI,EAGzB,GAFA,EAAQ,SAAS,EAAM,EAAO,CAAQ,EAElC,GAAyB,SAAS,EAAK,KAAK,EAC9C,MAAO,CAAE,KAAM,UAAW,OAAQ,EAAM,QAAO,UAAS,EAE1D,GAAI,EAA0B,SAAS,EAAK,KAAK,EAC/C,MAAO,CAAE,KAAM,EAAO,SAAS,EAAK,KAAK,EAAI,WAAa,WAAY,OAAQ,EAAM,QAAO,UAAS,EAEtG,IAAM,EAAY,EAAQ,WAAa,EAAI,EAAI,GAC/C,GAAI,GAAa,EACf,MAAO,CAAE,KAAM,UAAW,OAAQ,EAAM,QAAO,SAAU,EAAI,EAAI,CAAU,EAE7E,MAAM,EAAM,KAAK,IAAI,EAAQ,WAAY,CAAS,CAAC,CACrD,CACF,qFCpJI,EAAyC,KACzC,EAAsD,KACtD,EAAyD,KACzD,EAAwB,IAAI,IAC5B,GAAkB,EAClB,EAAmE,KAEjE,EAAkB,wBAClB,EAAY,mBAElB,SAAS,GAAmB,CAC1B,GAAI,WAAW,QAAQ,WAAY,OAAO,WAAW,OAAO,WAAW,EACvE,IAAM,EAAQ,IAAI,WAAW,EAAE,EAE/B,OADA,WAAW,OAAO,gBAAgB,CAAK,EAChC,MAAM,KAAK,EAAQ,GAAU,EAAM,SAAS,EAAE,CAAC,CAAC,SAAS,EAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAClF,CAEA,eAAe,IAAmF,CAEhG,IAAI,GAAoB,MADJ,OAAO,QAAQ,MAAM,IAAI,CAAe,GAC9B,GACzB,IACH,EAAoB,EAAS,EAC7B,MAAM,OAAO,QAAQ,MAAM,IAAI,EAAG,GAAkB,CAAkB,CAAC,GAIzE,IAAI,GAAe,MADG,OAAO,QAAQ,QAAQ,IAAI,CAAS,GAC/B,GAK3B,OAJK,IACH,EAAe,EAAS,EACxB,MAAM,OAAO,QAAQ,QAAQ,IAAI,EAAG,GAAY,CAAa,CAAC,GAEzD,CAAE,oBAAmB,cAAa,CAC3C,CAEA,eAAe,EAAmB,EAA0C,CAC1E,IAAM,EAAW,MAAM,GAAmB,EACtC,IAAe,GACnB,EAAK,YAAY,CACf,KAAM,kBACN,gBAAiB,EACjB,iBAAkB,OAAO,QAAQ,YAAY,CAAC,CAAC,QAC/C,aAAc,CAAC,mBAAoB,iBAAkB,cAAe,iBAAiB,EACrF,GAAG,CACL,CAAC,CACH,CAEA,SAAgB,EACd,EACA,EACM,CACN,EAAiB,EACjB,EAA8B,GAAgB,KAC9C,EAAQ,CACV,CAEA,SAAgB,GAAiB,EAAwB,CACvD,OAAO,IAAI,SAAS,EAAS,IAAW,CACtC,GAAI,CAAC,EAAY,CACf,EAAW,MAAM,2BAA2B,CAAC,EAC7C,MACF,CAEA,GAAI,EAAI,OAAS,cAAe,CAC9B,EAAW,YAAY,CAAG,EAC1B,EAAQ,CAAE,KAAM,EAAK,CAAC,EACtB,MACF,CAEA,IAAM,EAAK,EAAE,GACb,EAAsB,IAAI,EAAI,CAAE,UAAS,QAAO,CAAC,EACjD,EAAW,YAAY,CAAE,GAAG,EAAK,IAAG,CAAC,EAErC,eAAiB,CACX,EAAsB,IAAI,CAAE,IAC9B,EAAsB,OAAO,CAAE,EAC/B,EAAW,MAAM,6BAA6B,CAAC,EAEnD,EAAG,GAAK,CACV,CAAC,CACH,CAEA,SAAgB,EAAiB,EAAgB,CAC3C,GAAY,EAAW,YAAY,CAAG,CAC5C,CAEA,SAAS,GAAgB,CACvB,CAEE,IADA,aAAa,CAAgB,EACV,MAGrB,GAAI,CACF,IAAM,EAAO,OAAO,QAAQ,cAAc,mBAAmB,EAC7D,EAAa,EACb,EAAS,8BAA8B,EACvC,EAAmB,CAAI,CAAC,CAAC,MAAO,GAAU,EAAS,kCAAmC,CAAK,CAAC,EAE5F,EAAK,UAAU,YAAY,KAAO,IAAQ,CAGxC,GAFA,EAAS,6BAA8B,EAAI,MAAQ,EAAI,EAAE,EAErD,EAAI,OAAS,aAAc,CAC7B,EAAS,mBAAmB,EAC5B,EAAmB,CAAI,CAAC,CAAC,MAAO,GAAU,EAAS,qCAAsC,CAAK,CAAC,EAC/F,MACF,CAEA,GAAI,EAAI,MAAM,WAAW,eAAe,EAAG,CACzC,OAAO,QAAQ,YAAY,CAAG,CAAC,CAAC,UAAY,CAAC,CAAC,EAC9C,MACF,CAEA,GAAI,EAAI,IAAM,EAAsB,IAAI,EAAI,EAAE,EAAG,CAC/C,GAAM,CAAE,WAAY,EAAsB,IAAI,EAAI,EAAE,EACpD,EAAsB,OAAO,EAAI,EAAE,EACnC,EAAQ,CAAG,EACX,MACF,CAEK,KAEL,GAAI,CACF,IAAM,EAAS,MAAM,EAAe,CAAG,EACvC,GAAI,IAAe,EAAM,CACvB,EAAS,mDAAoD,EAAI,EAAE,EACnE,MACF,CACA,EAAK,YAAY,CAAE,GAAI,EAAI,GAAI,GAAG,CAAO,CAAC,CAC5C,OAAS,EAAK,CACZ,GAAI,IAAe,EAAM,CACvB,EAAS,gDAAiD,EAAI,EAAE,EAChE,MACF,CACA,IAAM,EAAQ,EACd,EAAK,YAAY,CACf,GAAI,EAAI,GACR,MAAO,aAAiB,MAAQ,EAAM,QAAU,gBAChD,UAAW,OAAO,GAAO,MAAS,SAAW,EAAM,KAAO,OAC1D,aAAc,GAAO,OACvB,CAAC,CACH,CACF,CAAC,EAED,EAAK,aAAa,gBAAkB,CAClC,IAAM,EAAQ,OAAO,QAAQ,UAG7B,GAFA,EAAS,4BAA6B,GAAO,SAAW,gBAAgB,EACjD,IAAe,EAClB,CAClB,EAAa,KACb,GAAI,CACF,QAAQ,QAAQ,IAA8B,CAAC,CAAC,CAAC,MAAO,GAAiB,CACvE,EAAS,yCAA0C,CAAY,CACjE,CAAC,CACH,OAAS,EAAc,CACrB,EAAS,yCAA0C,CAAY,CACjE,CACF,CACA,IAAK,IAAM,KAAW,EAAsB,OAAO,EACjD,EAAQ,OAAW,MAAM,0BAA0B,CAAC,EAEtD,EAAsB,MAAM,EAEvB,GAAO,SAAS,SAAS,WAAW,IACvC,EAAmB,WAAW,EAAS,GAAI,EAE/C,CAAC,CACH,OAAS,EAAK,CACZ,EAAS,oCAAqC,CAAG,EACjD,EAAmB,WAAW,EAAS,GAAK,CAC9C,CACF,4rCCvJA,EAAS,uBAAuB,EAEhC,IAAM,EAAM,IAAI,EACV,EAAmB,IAAI,IACzB,EAAoE,KAExE,eAAe,IAA4C,CACzD,IAAM,EAAS,EACV,KAEL,GAAI,CACF,MAAM,EAAI,eAAe,EAAO,KAAK,CACvC,OAAS,EAAO,CACd,EAAS,gEAAiE,CAAK,CACjF,QAAU,CACR,EAAI,0BAA0B,EAAO,MAAO,EAAO,UAAU,EACzD,GAAqB,aAAe,EAAO,aAAY,EAAsB,KACnF,CACF,CAEA,SAAS,EAAiB,EAAgB,EAAyC,CACjF,IAAM,EAAU,OAAO,GAAS,OAAO,EACvC,OAAO,OAAO,UAAU,CAAO,GAAK,EAAU,EAAI,EAAU,CAC9D,CAEA,eAAe,GAAuB,EAAe,EAA+B,CAClF,IAAM,EAAU,OAAO,CAAK,EACxB,MAAC,OAAO,UAAU,CAAO,GAAK,GAAW,IAE7C,EAAI,MADiB,OAAO,cAAc,aAAa,CAAE,OAAM,CAAC,IACpD,KAAM,GAAU,EAAM,UAAY,CAAO,EAQrD,MAPA,EAAiB,CACf,KAAM,eACN,MAAO,cACP,QACA,UACA,OAAQ,eACV,CAAC,EACK,IAAI,EACR,sBACA,iBAAiB,EAAQ,iCAAiC,IAC1D,CAAE,QAAO,UAAS,OAAQ,gBAAiB,gBAAiB,iBAAkB,CAChF,CACF,CAEA,SAAS,EAAmB,EAAuB,CAEjD,MADA,CAAK,GACE,8FAA8F,KAAK,CAAG,CAC/G,CAEA,IAAM,EAAN,cAAkC,KAAM,CACtC,KACA,QAEA,YAAY,EAAc,EAAiB,EAAmC,CAC5E,MAAM,CAAO,EACb,KAAK,KAAO,sBACZ,KAAK,KAAO,EACZ,KAAK,QAAU,CACjB,CACF,EAEA,eAAe,EAAc,EAS1B,CACD,IAAI,EACJ,GAAI,CACF,EAAM,MAAM,OAAO,KAAK,IAAI,CAAK,CACnC,MAAQ,CACN,MAAM,IAAI,EAAoB,WAAY,OAAO,EAAM,mBAAoB,CAAE,OAAM,CAAC,CACtF,CACA,GAAI,CAAC,EAAI,IAAM,EAAI,WAAa,OAC9B,MAAM,IAAI,EAAoB,WAAY,OAAO,EAAM,iCAAkC,CAAE,OAAM,CAAC,EAEpG,MAAO,CACL,MAAO,EAAI,GACX,SAAU,EAAI,SACd,IAAK,EAAI,IACT,MAAO,EAAI,MACX,OAAQ,EAAQ,EAAI,OACpB,OAAQ,EAAI,OACZ,WAAY,EAAmB,EAAI,GAAG,EACtC,QAAS,EAAI,OACf,CACF,CAEA,eAAe,EAAqB,EAAmB,EAAc,GAA+D,CAClI,IAAI,EACA,EACA,EAAc,GAElB,GAAI,EAOF,IANA,EAAO,MAAM,OAAO,KAAK,MAAM,CAAE,OAAQ,GAAM,UAAS,CAAC,EACzD,EAAM,EAAK,IACP,CAAC,GAAO,EAAmB,EAAI,GAAG,KACpC,EAAO,MAAM,OAAO,KAAK,MAAM,CAAE,UAAS,CAAC,EAC3C,EAAM,EAAK,KAAM,GAAc,CAAC,EAAmB,EAAU,GAAG,CAAC,GAE/D,CAAC,GAAK,IAAM,EAAa,CAC3B,IAAM,EAAU,MAAM,OAAO,KAAK,OAAO,CACvC,WACA,IAAK,4EACL,OAAQ,EACV,CAAC,EACD,GAAI,CAAC,EAAQ,GAAI,MAAM,IAAI,EAAoB,uBAAwB,kCAAkC,GAAU,EACnH,MAAM,EAAM,GAAG,EACf,EAAM,EACN,EAAc,EAChB,MAEA,GAAO,MAAM,OAAO,KAAK,MAAM,CAAE,OAAQ,GAAM,kBAAmB,EAAK,CAAC,EACxE,EAAM,EAAK,IACP,CAAC,GAAO,EAAmB,EAAI,GAAG,KACpC,EAAO,MAAM,OAAO,KAAK,MAAM,CAAE,OAAQ,GAAM,cAAe,EAAK,CAAC,EACpE,EAAM,EAAK,KAET,CAAC,GAAO,EAAmB,EAAI,GAAG,KACpC,EAAO,MAAM,OAAO,KAAK,MAAM,CAAE,OAAQ,EAAK,CAAC,EAC/C,EAAM,EAAK,KAAM,GAAc,CAAC,EAAmB,EAAU,GAAG,CAAC,GAIrE,GAAI,CAAC,GAAK,GACR,MAAM,IAAI,EACR,kBACA,4FACF,EAEF,MAAO,CAAE,MAAK,aAAY,CAC5B,CAEA,eAAe,GAAgB,EAAe,EAA2C,CACvF,GAAI,CACF,IAAM,EAAU,MAAM,OAAO,KAAK,MAAM,CAAE,OAAQ,CAAM,CAAC,EAMzD,OALA,MAAM,OAAO,UAAU,OAAO,EAAS,CACrC,MAAO,SAAS,IAChB,MAAO,OACP,UAAW,EACb,CAAC,EACM,CACT,MAAQ,CACN,MACF,CACF,CAEA,SAAS,EAA0B,EAAuC,CACxE,IAAM,EAAM,GAAS,OAAO,GAAU,SAAY,EAAoC,CAAC,EACjF,EAAgC,CAAC,EACvC,IAAK,IAAM,IAAO,CAAC,WAAY,OAAQ,YAAa,WAAW,EAAY,CACzE,IAAM,EAAQ,EAAI,GACd,OAAO,GAAU,UAAY,EAAM,KAAK,IAAM,KAAI,EAAO,GAAO,EACtE,CACA,OAAO,CACT,CAQA,eAAe,EAAkB,EAAe,EAA8D,CAC5G,IAAI,EACA,EACA,EACJ,GAAI,CACF,IAAM,EAAM,MAAM,OAAO,KAAK,IAAI,CAAK,EACvC,EAAY,EAAI,OAChB,EAAa,EAAI,WACjB,EAAS,GAAc,EAAI,GAC7B,MAAQ,CAAC,CACT,GAAI,CAAC,GAAU,IAAW,cACxB,MAAO,CAAE,MAAO,UAAW,SAAU,CAAC,cAAc,GAAU,SAAS,EAAG,KAAM,EAAQ,WAAU,EAEpG,GAAI,EAAmB,CAAM,EAC3B,MAAO,CAAE,MAAO,QAAS,SAAU,CAAC,wCAAwC,GAAQ,EAAG,KAAM,EAAQ,WAAU,EAEjH,IAAI,EACJ,GAAI,CACF,EAAS,MAAM,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,iBAAkB,QAAO,EAAG,CAAE,QAAS,CAAE,CAAC,CAClG,OAAS,EAAK,CAEZ,MAAO,CAAE,MAAO,UAAW,SAAU,CAAC,+BADvB,aAAe,MAAQ,EAAI,QAAU,OAAO,CAAG,GACe,EAAG,KAAM,EAAQ,WAAU,CAC1G,CACA,GAAI,GAAQ,MASV,OARI,GAAc,EAAO,OAAS,EACzB,CACL,MAAO,UACP,SAAU,CAAC,iBAAiB,EAAW,2BAA2B,EAAO,MAAM,EAC/E,KAAM,EAAO,KACb,WACF,EAEK,CAAE,GAAG,EAAQ,WAAU,EAEhC,GAAI,GAAQ,OAAS,mBACnB,MAAM,IAAI,EAAoB,mBAAoB,OAAO,EAAO,OAAS,sBAAsB,EAAG,CAChG,SAAU,EAAO,SACjB,OACF,CAAC,EAGH,MAAO,CAAE,MAAO,UAAW,SAAU,CADtB,GAAQ,MAAQ,OAAO,EAAO,KAAK,EAAI,oCACV,EAAG,KAAM,EAAQ,WAAU,CACzE,CAEA,SAAS,EAAkB,EAAsC,CAC/D,IAAM,EAAQ,EAAO,KAAO,OAAO,EAAO,OAAS,GAC7C,EAAW,EAAO,SAAS,OAAS,EAAI,KAAK,EAAO,SAAS,KAAK,IAAI,EAAE,GAAK,GACnF,MAAO,GAAG,EAAO,QAAQ,IAAQ,GACnC,CAEA,eAAe,GACb,EACqE,CACrE,IAAM,EAAS,MAAM,EAAI,eAAe,EAAO,EAA+B,EAC9E,GAAI,EAAO,iBACT,MAAU,MACR,EAAO,iBAAiB,WAAW,aACjC,EAAO,iBAAiB,MACxB,4CACJ,EAEF,IAAM,EAAQ,EAAO,QAAQ,MAC7B,GAAI,CAAC,GAAS,OAAO,GAAU,UAAY,CAAC,MAAM,QAAQ,EAAM,OAAO,EACrE,MAAU,MAAM,8CAA8C,EAEhE,OAAO,CACT,CAGA,eAAe,GAAuB,EAA+C,CACnF,IAAM,EAAU,MAAM,OAAO,cAAc,aAAa,CAAE,OAAM,CAAC,GAAM,CAAC,EAClE,EAAiC,CAAC,EACxC,IAAK,IAAM,KAAS,EAAQ,CAC1B,IAAM,EAA6B,CACjC,QAAS,EAAM,QACf,cAAe,EAAM,cACrB,IAAK,EAAM,IACX,cAAe,EAAM,gBAAkB,GACvC,uBAAwB,EAC1B,EACA,GAAI,CACF,IAAM,EAAO,MAAM,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,MAAO,EAAG,CAAE,QAAS,EAAM,OAAQ,CAAC,EAC1F,GAAM,SACR,EAAM,uBAAyB,GAC/B,EAAM,cAAgB,CAAE,KAAM,EAAK,KAAM,WAAY,EAAK,UAAW,GAErE,EAAM,mBAAqB,GAAM,MAAQ,OAAO,EAAK,KAAK,EAAI,aAElE,OAAS,EAAK,CACZ,EAAM,mBAAqB,aAAe,MAAQ,EAAI,QAAU,OAAO,CAAG,CAC5E,CACA,EAAQ,KAAK,CAAK,CACpB,CACA,OAAO,CACT,CAEA,IAAM,EAAkB,IAAI,IACxB,GAAoB,EAExB,SAAS,IAA+B,CACtC,MAAO,cAAc,EAAE,GAAkB,GAAG,KAAK,IAAI,GACvD,CAEA,SAAS,GAAgB,EAAY,EAA+D,CAElG,GADA,EAAgB,IAAI,EAAI,CAAI,EACxB,EAAgB,KAAO,GAAI,CAC7B,IAAM,EAAS,EAAgB,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,MACzC,GAAQ,EAAgB,OAAO,CAAM,CAC3C,CACF,CAEA,SAAS,GAAc,EAAsE,CAC3F,OAAO,EAAgB,IAAI,CAAE,GAAK,IACpC,CAEA,SAAS,EAAM,EAA2B,CACxC,OAAO,IAAI,QAAS,GAAY,WAAW,EAAS,CAAE,CAAC,CACzD,CAEA,IAAM,GAAN,cAAkC,KAAM,CACtC,KAEA,YAAY,EAAc,EAAiB,CACzC,MAAM,CAAO,EACb,KAAK,KAAO,sBACZ,KAAK,KAAO,CACd,CACF,EAEA,SAAS,EAAY,EAAkB,EAA8C,EAAsC,CAOzH,OAAO,IAAI,GANE,IAAU,WACnB,4BACA,IAAU,UAAY,kCAAoC,wBAIzB,GAAG,EAAS,cAHnC,IAAU,WACpB,oBACA,IAAU,UAAY,uBAAyB,aACkB,IAAI,GAAS,CACpF,CAEA,IAAM,EAA2B,CAC/B,OAAQ,CACN,eAAgB,kFAChB,cAAe,8CACf,mBAAoB,6IACtB,EACA,QAAS,CACP,oBAAqB,gHACrB,eAAgB,kFAClB,CACF,EAEA,eAAe,GACb,EACA,EACA,EACkB,CAClB,IAAI,EACJ,GAAI,CACF,EAAS,MAAM,EAAI,YAAY,EAAO,mBAAoB,CACxD,WAAY;+CAC6B,KAAK,UAAU,CAAQ,EAAE;;;YAIlE,YAAa,EACf,CAAC,CACH,OAAS,EAAO,CACd,MAAM,EAAY,UAAW,WAAY,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,CAAC,CACjG,CACA,GAAI,GAAQ,iBACV,MAAM,EAAY,UAAW,WAAY,uCAAuC,EAElF,IAAM,EAAW,GAAQ,QAAQ,SACjC,GAAI,CAAC,EAAU,MAAO,GACtB,GAAI,CACF,MAAM,EAAI,YAAY,EAAO,wBAAyB,CAAE,MAAO,EAAW,UAAS,CAAC,CACtF,OAAS,EAAO,CACd,MAAM,EAAY,UAAW,aAAc,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,CAAC,CACnG,CACA,MAAO,EACT,CAEA,eAAe,GACb,EACA,EACA,EACe,CACf,GAAI,CACF,MAAM,EAAI,YAAY,EAAO,qCAAsC,CAAE,QAAS,EAAK,CAAC,CACtF,OAAS,EAAO,CACd,MAAM,EAAY,EAAU,UAAW,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,CAAC,CAC/F,CAEA,IAAI,EAAkD,KAClD,EAA4F,KAC1F,MAAgB,CACpB,CAA0C,IAAzB,aAAa,CAAS,EAAe,MACtD,CAAgE,IAAjD,OAAO,SAAS,QAAQ,eAAe,CAAO,EAAa,KAC5E,EAEM,GAAsB,EAAoB,IACvC,IAAI,SAAe,EAAS,IAAW,CAC5C,EAAY,eAAiB,CAC3B,EAAQ,EACR,EAAW,MAAM,GAAG,EAAS,oCAAoC,EAAY,IAAK,aAAa,EAAW,EAAE,CAAC,CAC/G,EAAG,CAAS,EACZ,GAAW,EAAkC,EAAgB,IAAgB,CAC3E,GAAI,EAAO,QAAU,GAAS,IAAW,yBAA0B,CAEjE,GADA,EAAQ,EACJ,CAAC,GAAQ,cAAe,CAC1B,EAAO,EAAY,EAAU,UAAW,6CAA6C,CAAC,EACtF,MACF,CACA,EAAI,YAAY,EAAO,wBAAyB,CAC9C,MAAO,EACP,cAAe,EAAO,aACxB,CAAC,CAAC,CAAC,SAAW,EAAQ,CAAC,CAAC,CAAC,MAAO,GAAU,EAAO,EAC/C,EACA,aACA,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,CACvD,CAAC,CAAC,CACJ,CACF,EACA,OAAO,SAAS,QAAQ,YAAY,CAAO,CAC7C,CAAC,EAGG,EAAsB,SAAY,CACtC,GAAI,IAAa,SAAU,CACzB,MAAM,EAAI,YAAY,EAAO,mBAAoB,CAC/C,WAAY,0BAA0B,KAAK,UAAU,EAAyB,OAAO,aAAa,EAAE,YACpG,YAAa,EACf,CAAC,EACD,MAAM,EAAM,GAAG,EACf,MAAM,EAAI,YAAY,EAAO,mBAAoB,CAC/C,WAAY,0BAA0B,KAAK,UAAU,EAAyB,OAAO,cAAc,EAAE,YACrG,YAAa,EACf,CAAC,EACD,MAAM,EAAM,GAAG,EACf,MAAM,EAAI,YAAY,EAAO,mBAAoB,CAC/C,WAAY,0BAA0B,KAAK,UAAU,EAAyB,OAAO,kBAAkB,EAAE,YACzG,YAAa,EACf,CAAC,EACD,MACF,CAEA,IAAI,EACJ,GAAI,CACF,EAAS,MAAM,EAAI,YAAY,EAAO,mBAAoB,CACxD,WAAY,kDAAkD,KAAK,UAAU,EAAyB,QAAQ,cAAc,EAAE,iEAC9H,YAAa,EACf,CAAC,CACH,OAAS,EAAO,CACd,MAAM,EAAY,UAAW,WAAY,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,CAAC,CACjG,CACA,GAAI,GAAQ,iBACV,MAAM,EAAY,UAAW,WAAY,sCAAsC,EAEjF,GAAI,GAAQ,QAAQ,QAAU,IAAS,GAAQ,QAAQ,QAAU,KAC/D,MAAM,EAAY,UAAW,WAAY,iCAAiC,CAE9E,EAGM,EAAW,CAAC,IAAO,KAAO,GAAK,EACjC,EAA0B,KAE9B,GAAI,CACF,IAAK,IAAI,EAAU,EAAG,GAAW,EAAa,IAC5C,GAAI,CACF,IAAM,EAAiB,EAAmB,EAAS,EAAS,EAAU,EAAE,EACxE,MAAM,EAAoB,EAC1B,MAAM,EACN,MACF,OAAS,EAAK,CACZ,EAAY,EACZ,EAAQ,EACR,IAAM,EAAa,GAAyC,KAC5D,GAAI,GAAa,IAAc,kCAAmC,MAAM,EACpE,EAAU,GAAa,MAAM,EAAM,GAAI,CAC7C,CAEF,MAAM,GAAa,EAAY,EAAU,UAAW,2BAA2B,CACjF,QAAU,CACR,EAAQ,EACR,GAAI,CAAE,MAAM,EAAI,YAAY,EAAO,qCAAsC,CAAE,QAAS,EAAM,CAAC,CAAG,MAAQ,CAAC,CACzG,CACF,CAEA,eAAe,GACb,EACA,EACA,EAC4B,CAC5B,GAAI,CACF,MAAM,EAAI,OAAO,CAAK,EACtB,MAAM,EAAI,YAAY,EAAO,aAAc,CAAC,CAAC,CAC/C,OAAS,EAAO,CACd,MAAM,EAAY,IAAa,UAAY,UAAY,SAAU,WAAY,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,CAAC,CACrI,CAYA,OAVI,IAAa,WAMX,MALuB,GACzB,EACA,EACA,EAAyB,QAAQ,mBACnC,GAIF,MAAM,GAAuB,EAAO,EAAW,CAAQ,EAH5B,CAAE,QAAS,EAAK,CAK7C,CAEA,IAAM,EAAyC,CAC7C,OAAQ,UACR,MAAO,UACP,OAAQ,UACR,EAAG,UACH,SAAU,UACV,QAAS,SACX,EAEA,eAAe,GACb,EACA,EACA,EAC4D,CAC5D,IAAM,EAAO,EAAa,EAAW,MAAM,EACrC,EAAS,MAAM,kBAAkB,CAAI,EAErC,EAAS,IAAI,gBAAgB,EAAO,MAAO,EAAO,MAAM,EACxD,EAAM,EAAO,WAAW,IAAI,EAClC,GAAI,CAAC,EAAK,MAAU,MAAM,8BAA8B,EAExD,EAAI,UAAU,EAAQ,EAAG,CAAC,EAC1B,EAAO,MAAM,EAEb,IAAM,EAAc,KAAK,IAAI,EAAM,OAAQ,EAAM,MAAM,EAEvD,IAAK,IAAM,KAAW,EAAU,CAC9B,IAAM,EAAQ,EAAe,EAAQ,MAAQ,EAAe,QAEtD,EAAI,KAAK,MAAM,EAAQ,OAAO,EAAI,CAAW,EAC7C,EAAI,KAAK,MAAM,EAAQ,OAAO,EAAI,CAAW,EAC7C,EAAI,KAAK,MAAM,EAAQ,OAAO,MAAQ,CAAW,EACjD,EAAI,KAAK,MAAM,EAAQ,OAAO,OAAS,CAAW,EAExD,GAAI,EAAI,GAAK,EAAI,EAAG,SAEpB,EAAI,YAAc,EAClB,EAAI,UAAY,EAChB,EAAI,YAAY,CAAC,EAAG,CAAC,CAAC,EACtB,EAAI,WAAW,EAAG,EAAG,EAAG,CAAC,EACzB,EAAI,YAAY,CAAC,CAAC,EAElB,IAAM,EAAY,EAAQ,IACpB,EAAW,KAAK,IAAI,GAAI,KAAK,IAAI,GAAI,KAAK,MAAM,EAAO,MAAQ,GAAI,CAAC,CAAC,EAC3E,EAAI,KAAO,QAAQ,EAAS,eAC5B,IAEM,EAFY,EAAI,YAAY,CAAS,CAAC,CAAC,MAEd,EACzB,EAAc,EAAW,EAE3B,EAAS,EAAI,KAAK,OAAO,EAAI,GAAc,CAAC,EAC5C,EAAS,EAAI,GACb,EAAI,IAAM,EAAI,MAChB,EAAS,EAAI,EAAc,EAAI,EAAI,EAAI,EAAI,EAAI,EAAI,EAAc,GAGnE,EAAS,KAAK,IAAI,EAAG,KAAK,IAAI,EAAO,MAAQ,EAAY,CAAM,CAAC,EAChE,EAAS,KAAK,IAAI,EAAG,KAAK,IAAI,EAAO,OAAS,EAAa,CAAM,CAAC,EAElE,EAAI,UAAY,EAChB,EAAI,SAAS,EAAQ,EAAQ,EAAY,CAAW,EACpD,EAAI,YAAc,QAClB,EAAI,UAAY,EAChB,EAAI,WAAW,EAAQ,EAAQ,EAAY,CAAW,EAEtD,EAAI,UAAY,QAChB,EAAI,aAAe,MACnB,EAAI,SAAS,EAAW,EAAS,EAAS,EAAS,CAAO,CAC5D,CAKA,MAAO,CAAE,aAFY,EAAa,MADT,EAAO,cAAc,CAAE,KAAM,WAAY,CAAC,CACvB,EAE3B,MAAO,EAAO,MAAO,OAAQ,EAAO,MAAO,CAC9D,CAEA,SAAS,EAAa,EAA6B,CACjD,OAAO,IAAI,SAAS,EAAS,IAAW,CACtC,IAAM,EAAS,IAAI,WACnB,EAAO,WAAe,CAEpB,IAAM,EADU,EAAO,OACA,MAAM,GAAG,CAAC,CAAC,GAClC,EAAQ,CAAM,CAChB,EACA,EAAO,YAAgB,EAAW,MAAM,kCAAkC,CAAC,EAC3E,EAAO,cAAc,CAAI,CAC3B,CAAC,CACH,CAEA,SAAS,EAAa,EAAgB,EAAW,YAAmB,CAClE,IAAM,EAAS,KAAK,CAAM,EACpB,EAAQ,IAAI,WAAW,EAAO,MAAM,EAC1C,IAAK,IAAI,EAAI,EAAG,EAAI,EAAO,OAAQ,IACjC,EAAM,GAAK,EAAO,WAAW,CAAC,EAEhC,OAAO,IAAI,KAAK,CAAC,CAAK,EAAG,CAAE,KAAM,CAAS,CAAC,CAC7C,CAEA,SAAS,GAAyB,EAAsB,CACtD,MAAO,aAAa,EAAK,KAC3B,CAQA,eAAe,GAAoB,EAAe,EAAgC,CAChF,GAAI,CAEF,OADI,SAAS,CAAI,EACV,EACT,OAAS,EAAK,CACZ,GAAI,aAAe,YAAa,MAAO,EACzC,CAEA,OAAO,MADgB,EAAI,cAAc,EAAO,gCAAgC,EAAK,MAAM,GAC3E,MAClB,CAEA,eAAe,GAAgB,EAAe,EAA+E,CAS3H,IAAM,GAAa,MARY,EAAI,eAAe,EAAO;;mEAEQ,EAAU;;;;QAIrE,GAE8B,QAAQ,MAC5C,GAAI,CAAC,EAAY,MAAU,MAAM,+BAA+B,EAEhE,GAAM,CAAE,iBAAgB,cAAa,QAAO,mBAAkB,mBAAoB,EAC5E,EAAwB,CAAC,EAC3B,EAAW,EAEf,KAAO,EAAW,GAAa,CAC7B,MAAM,EAAI,eAAe,EAAO,sBAAsB,EAAS,EAAE,EACjE,MAAM,IAAI,QAAQ,GAAK,WAAW,EAAG,GAAG,CAAC,EAGzC,IAAM,EAAY,GAAa,MADX,EAAI,kBAAkB,CAAK,GACV,MAAM,EAC3C,EAAO,KAAK,MAAM,kBAAkB,CAAS,CAAC,EAE9C,GAAY,CACd,CAEA,MAAM,EAAI,eAAe,EAAO,sBAAsB,EAAgB,EAAE,EAExE,IAAM,EAAc,KAAK,MAAM,EAAQ,CAAgB,EACjD,EAAe,KAAK,MAAM,EAAc,CAAgB,EACxD,EAAS,IAAI,gBAAgB,EAAa,CAAY,EACtD,EAAM,EAAO,WAAW,IAAI,EAClC,GAAI,CAAC,EAAK,MAAU,MAAM,8BAA8B,EAExD,IAAI,EAAI,EACF,EAAc,KAAK,MAAM,EAAiB,CAAgB,EAChE,IAAK,IAAI,EAAI,EAAG,EAAI,EAAO,OAAQ,IAAK,CACtC,IAAM,EAAQ,EAAO,GACf,EAAkB,EAAe,EACjC,EAAa,KAAK,IAAI,EAAa,CAAe,EACxD,EAAI,UAAU,EAAO,EAAG,EAAG,EAAM,MAAO,EAAY,EAAG,EAAG,EAAM,MAAO,CAAU,EACjF,GAAK,EACL,EAAM,MAAM,CACd,CAKA,MAAO,CAAE,aAFY,EAAa,MADT,EAAO,cAAc,CAAE,KAAM,WAAY,CAAC,CACvB,EAE3B,MAAO,EAAa,OAAQ,CAAa,CAC5D,CAEA,IAAM,EAAsB,IAAI,IAC1B,EAAkB,IAAI,IAE5B,OAAO,cAAc,YAAY,YAAa,GAAY,CACxD,GAAI,EAAQ,UAAY,EAAG,CAEzB,OAAO,KAAK,IAAI,EAAQ,KAAK,CAAC,CAC3B,KAAM,GAAQ,EAAiB,CAC9B,KAAM,eACN,MAAO,aACP,MAAO,EAAQ,MACf,IAAK,EAAQ,IACb,MAAO,EAAI,KACb,CAAC,CAAC,CAAC,CACF,UAAY,EAAiB,CAAE,KAAM,eAAgB,MAAO,aAAc,MAAO,EAAQ,MAAO,IAAK,EAAQ,GAAI,CAAC,CAAC,EACtH,IAAM,EAAW,EAAoB,IAAI,EAAQ,KAAK,EAClD,IACF,EAAS,EACT,EAAoB,OAAO,EAAQ,KAAK,EAE5C,CACF,CAAC,EAED,OAAO,cAAc,gBAAgB,YAAa,GAAY,CAC5D,GAAI,EAAQ,UAAY,EAAG,CACzB,IAAM,EAAW,EAAoB,IAAI,EAAQ,KAAK,EAClD,IACF,EAAS,EACT,EAAoB,OAAO,EAAQ,KAAK,EAE5C,CACF,CAAC,EAID,OAAO,KAAK,UAAU,YAAa,GAAU,CAC3C,EAAiB,CAAE,KAAM,eAAgB,MAAO,cAAe,OAAM,CAAC,EACtE,EAAI,OAAO,CAAK,EAChB,IAAK,GAAM,CAAC,EAAM,KAAO,EACnB,IAAO,GACT,EAAgB,OAAO,CAAI,EAG/B,IAAK,GAAM,CAAC,EAAU,KAAgB,EAChC,IAAgB,GAClB,EAAiB,OAAO,CAAQ,EAGhC,GAAqB,QAAU,IAAO,EAAsB,KAClE,CAAC,EAED,OAAO,QAAQ,UAAU,YAAa,GAAa,CACjD,EAAiB,CAAE,KAAM,eAAgB,MAAO,iBAAkB,UAAS,CAAC,CAC9E,CAAC,EAOD,eAAe,EAAoB,EAAe,EAAY,IAAsB,CAClF,IAAM,EAAW,KAAK,IAAI,EAAI,EAG9B,KAAO,KAAK,IAAI,EAAI,GAAU,CAC5B,GAAI,CAEF,IAAI,MADiB,EAAI,eAAe,EAAO,qBAAqB,IACxD,QAAQ,QAAU,WAAY,CAExC,MAAM,EAAM,IAAI,EAChB,MACF,CACF,MAAQ,CAER,CACA,MAAM,EAAM,GAAG,CACjB,CAGA,QAAQ,KAAK,yCAAyC,GAAO,CAC/D,CAGA,eAAe,EACb,EACA,EACA,EACA,EACA,EACA,EAAkB,EACJ,CACd,OAAQ,EAAR,CACE,IAAK,QAAS,CACZ,IAAM,EAAS,MAAM,OAAO,KAAK,YAAY,EAAO,CAClD,KAAM,gBACN,MACA,OAAQ,MACV,EAAG,CAAE,SAAQ,CAAC,EACd,OAAO,EAAO,MAAQ,EAAS,CAAE,QAAS,GAAM,OAAQ,QAAS,KAAI,CACvE,CACA,IAAK,OAAQ,CACX,GAAI,CAAC,EAAO,MAAO,CAAE,MAAO,8BAA+B,EAC3D,IAAM,EAAS,MAAM,OAAO,KAAK,YAAY,EAAO,CAClD,KAAM,aACN,MACA,OACF,EAAG,CAAE,SAAQ,CAAC,EACd,OAAO,EAAO,MAAQ,EAAS,CAAE,QAAS,GAAM,OAAQ,OAAQ,MAAK,OAAM,CAC7E,CACA,IAAK,QAAS,CACZ,IAAM,EAAS,MAAM,OAAO,KAAK,YAAY,EAAO,CAClD,KAAM,0BACN,KACF,EAAG,CAAE,SAAQ,CAAC,EAGd,OAFI,EAAO,MAAc,GACzB,MAAM,EAAI,MAAM,EAAO,EAAO,EAAG,EAAO,CAAC,EAClC,CAAE,QAAS,GAAM,OAAQ,QAAS,KAAI,EAC/C,CACA,IAAK,OAKH,OAAO,MAJkB,OAAO,KAAK,YAAY,EAAO,CACtD,KAAM,mBACN,KACF,EAAG,CAAE,SAAQ,CAAC,EAGhB,QACE,MAAO,CAAE,MAAO,mBAAmB,EAAO,4BAA6B,CAC3E,CACF,CAEA,OAAO,QAAQ,UAAU,aAAa,EAAS,EAAQ,KACrD,GAAc,EAAS,CAAM,CAAC,CAC3B,KAAK,CAAY,CAAC,CAClB,MAAO,GAAQ,EAAa,CAAE,MAAO,EAAI,OAAQ,CAAC,CAAC,EAC/C,GACR,EAED,eAAsB,GACpB,EACA,EACc,CACd,IAAM,EAAQ,EAAQ,MAEtB,OAAQ,EAAQ,KAAhB,CACE,IAAK,qBAAsB,CACzB,GAAM,CAAC,GAAO,MAAM,OAAO,KAAK,MAAM,CAAE,OAAQ,GAAM,cAAe,EAAK,CAAC,EAC3E,MAAO,CAAE,MAAO,GAAK,EAAG,CAC1B,CAEA,IAAK,iBAAkB,CACrB,IAAM,EAAc,OAAO,EAAQ,KAAK,EACxC,GAAI,CAAC,OAAO,UAAU,CAAW,GAAK,GAAe,EACnD,MAAM,IAAI,EAAoB,kBAAmB,uCAAuC,EAE1F,OAAO,EAAc,CAAW,CAClC,CAEA,IAAK,iBAAkB,CACrB,IAAM,EAAoB,EAAQ,WAAa,OAAY,OAAY,OAAO,EAAQ,QAAQ,EAC9F,GAAI,IAAsB,SAAc,CAAC,OAAO,UAAU,CAAiB,GAAK,GAAqB,GACnG,MAAM,IAAI,EAAoB,iBAAkB,qCAAqC,EAEvF,GAAM,CAAE,MAAK,eAAgB,MAAM,EAAqB,EAAmB,EAAQ,cAAgB,EAAK,EAExG,MAAO,CAAE,GAAG,MADY,EAAc,EAAI,EAAG,EACtB,aAAY,CACrC,CAEA,IAAK,wBAAyB,CAC5B,IAAM,EAAO,OAAO,EAAQ,MAAQ,EAAE,EAChC,EAAM,OAAO,EAAQ,KAAQ,UAAY,EAAQ,IAAM,EAAQ,IAAM,cACrE,EAAO,EAAQ,OAAS,MAAQ,MAAQ,SACxC,EAAU,EAAQ,UAAY,GAChC,EACA,EAEJ,GAAI,IAAS,MAAO,CAClB,IAAM,EAA8C,CAAE,MAAK,OAAQ,CAAQ,EAC3E,GAAI,EAAQ,WAAa,OAAW,CAClC,IAAM,EAAiB,OAAO,EAAQ,QAAQ,EAC9C,GAAI,CAAC,OAAO,UAAU,CAAc,GAAK,GAAkB,EACzD,MAAM,IAAI,EAAoB,iBAAkB,wCAAwC,EAE1F,EAAc,SAAW,CAC3B,CACA,EAAa,MAAM,OAAO,KAAK,OAAO,CAAa,EACnD,EAAkB,EAAW,QAC/B,KAAO,CACL,IAAM,EAAgB,MAAM,OAAO,QAAQ,OAAO,CAChD,MACA,UACA,KAAM,QACR,CAAC,EACD,GAAI,CAAC,EACH,MAAM,IAAI,EAAoB,uBAAwB,uCAAuC,GAAM,EAErG,EAAkB,EAAc,GAChC,EAAa,EAAc,OAAO,GAC9B,CAAC,GAAc,IAAoB,SAErC,GAAa,MADM,OAAO,KAAK,MAAM,CAAE,SAAU,CAAgB,CAAC,GAChD,GAEtB,CAEA,GAAI,CAAC,GAAY,IAAM,IAAoB,OACzC,MAAM,IAAI,EAAoB,uBAAwB,uCAAuC,GAAM,EAErG,IAAM,EAAU,MAAM,GAAgB,EAAW,GAAI,CAAI,EAEzD,MAAO,CAAE,GAAG,MADY,EAAc,EAAW,EAAE,EAC5B,OAAM,SAAQ,CACvC,CAEA,IAAK,uBAAwB,CAC3B,IAAM,EAAc,OAAO,EAAQ,KAAK,EACxC,GAAI,CAAC,OAAO,UAAU,CAAW,GAAK,GAAe,EACnD,MAAM,IAAI,EAAoB,kBAAmB,6CAA6C,EAEhG,GAAI,CACF,MAAM,OAAO,KAAK,OAAO,CAAW,CACtC,MAAQ,CACN,MAAO,CAAE,QAAS,GAAM,MAAO,EAAa,YAAa,EAAK,CAChE,CACA,MAAO,CAAE,QAAS,GAAM,MAAO,CAAY,CAC7C,CAEA,IAAK,qBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,GAAI,CACF,MAAM,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,mBAAoB,EAAG,CAAE,QAAS,CAAE,CAAC,CACpF,MAAY,CAAC,CACb,MAAM,IAAI,QAAQ,GAAW,WAAW,EAAS,EAAE,CAAC,EAEpD,GAAI,CACF,IAAI,EACA,EAAY,CAAE,OAAQ,EAAG,OAAQ,CAAE,EACnC,EAAe,GAEnB,GAAI,EAAQ,SAAU,CACpB,EAAS,MAAM,GAAgB,EAAO,EAAQ,WAAa,GAAI,EAC/D,GAAI,CACF,IAAM,EAAW,MAAM,EAAI,gBAAgB,CAAK,EAC1C,EAAM,EAAO,MAAQ,EAAS,MACpC,EAAY,CAAE,OAAQ,EAAK,OAAQ,CAAI,CACzC,MAAQ,CAAC,CACX,MACE,GAAI,CACF,IAAM,EAAY,MAAM,EAAI,kBAAkB,CAAK,EACnD,EAAS,EACT,GAAI,CACF,IAAM,EAAW,MAAM,EAAI,gBAAgB,CAAK,EAChD,EAAY,CACV,OAAQ,EAAU,MAAQ,EAAS,MACnC,OAAQ,EAAU,OAAS,EAAS,MACtC,CACF,MAAQ,CAAC,CACX,OAAS,EAAU,CACjB,IAAM,EAAM,MAAM,OAAO,KAAK,IAAI,CAAK,EACvC,GAAI,CAAC,EAAI,SAAU,MAAM,EACzB,GAAI,EAAQ,aAAc,CACxB,GAAM,CAAC,GAAa,MAAM,OAAO,KAAK,MAAM,CAAE,OAAQ,GAAM,SAAU,EAAI,QAAS,CAAC,EACpF,GAAI,GAAW,KAAO,EACpB,MAAM,IAAI,EACR,gCACA,8CAA8C,EAAM,4BAA4B,EAAI,WACpF,CAAE,QAAO,SAAU,EAAI,SAAU,YAAa,GAAW,EAAG,CAC9D,CAEJ,CAEA,IAAM,GAAS,MADO,OAAO,KAAK,kBAAkB,EAAI,SAAU,CAAE,OAAQ,KAAM,CAAC,GAC5D,QAAQ,2BAA4B,EAAE,EACvD,EAAe,KAAK,CAAM,EAC1B,EAAQ,IAAI,WAAW,EAAa,MAAM,EAChD,IAAK,IAAI,EAAI,EAAG,EAAI,EAAa,OAAQ,IACvC,EAAM,GAAK,EAAa,WAAW,CAAC,EAEtC,IAAM,EAAO,IAAI,KAAK,CAAC,CAAK,EAAG,CAAE,KAAM,WAAY,CAAC,EAC9C,EAAS,MAAM,kBAAkB,CAAI,EAC3C,EAAS,CAAE,SAAQ,MAAO,EAAO,MAAO,OAAQ,EAAO,MAAO,EAC9D,EAAO,MAAM,EACb,EAAe,EACjB,CAGF,GAAI,EAAQ,UAAY,CAAC,EACvB,GAAI,CACF,IAAM,EAAa,MAAM,OAAO,KAAK,YAAY,EAAO,CACtD,KAAM,mCACR,EAAG,CAAE,QAAS,CAAE,CAAC,EAEb,GAAY,UAAY,EAAW,SAAS,OAAS,IACvD,EAAS,MAAM,GAAmB,EAAQ,EAAW,SAAU,CAAS,EAE5E,MAAQ,CAAC,CAGX,IAAM,EAAe,GAAqB,EAE1C,OADA,GAAgB,EAAc,CAAM,EAC7B,CAAE,GAAG,EAAQ,cAAa,CACnC,QAAU,CACR,GAAI,CACF,MAAM,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,qBAAsB,EAAG,CAAE,QAAS,CAAE,CAAC,CACtF,MAAY,CAAC,CACf,CAGF,IAAK,gBAAiB,CACpB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAO,EAAQ,UAAY,EAAI,eAAe,EAAQ,SAAS,EAAI,EAEzE,OADA,MAAM,EAAI,MAAM,EAAO,EAAQ,EAAG,EAAQ,EAAG,OAAQ,EAAG,CAAI,EACrD,CAAE,QAAS,EAAK,CACzB,CAEA,IAAK,sBAAuB,CAC1B,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAO,EAAQ,UAAY,EAAI,eAAe,EAAQ,SAAS,EAAI,EAEzE,OADA,MAAM,EAAI,WAAW,EAAO,EAAQ,EAAG,EAAQ,EAAG,CAAI,EAC/C,CAAE,QAAS,EAAK,CACzB,CAEA,IAAK,uBAAwB,CAC3B,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAO,EAAQ,UAAY,EAAI,eAAe,EAAQ,SAAS,EAAI,EAEzE,OADA,MAAM,EAAI,YAAY,EAAO,EAAQ,EAAG,EAAQ,EAAG,CAAI,EAChD,CAAE,QAAS,EAAK,CACzB,CAEA,IAAK,uBAAwB,CAC3B,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAO,EAAQ,UAAY,EAAI,eAAe,EAAQ,SAAS,EAAI,EAEzE,OADA,MAAM,EAAI,YAAY,EAAO,EAAQ,EAAG,EAAQ,EAAG,CAAI,EAChD,CAAE,QAAS,EAAK,CACzB,CAEA,IAAK,eAAgB,CACnB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAO,EAAQ,UAAY,EAAI,eAAe,EAAQ,SAAS,EAAI,EAEzE,OADA,MAAM,EAAI,KAAK,EAAO,EAAQ,OAAQ,EAAQ,OAAQ,EAAQ,KAAM,EAAQ,KAAM,CAAI,EAC/E,CAAE,QAAS,EAAK,CACzB,CAEA,IAAK,gBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,OADA,MAAM,EAAI,MAAM,EAAO,EAAQ,EAAG,EAAQ,CAAC,EACpC,CAAE,QAAS,EAAK,EAGzB,IAAK,eACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,EAAQ,OAAS,QAAa,EAAQ,OAAS,KAAM,MAAU,MAAM,kBAAkB,EAE3F,OADA,MAAM,EAAI,KAAK,EAAO,EAAQ,IAAI,EAC3B,CAAE,QAAS,EAAK,EAGzB,IAAK,cACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,KAAM,MAAU,MAAM,kBAAkB,EAGrD,OAFA,MAAM,EAAI,KAAK,EAAO,EAAQ,IAAI,EAClC,MAAM,EAAI,SAAS,EAAO,EAAQ,WAAa,OAAO,EAC/C,CAAE,QAAS,EAAK,EAGzB,IAAK,aAAc,CACjB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,KAAM,MAAU,MAAM,kBAAkB,EACrD,IAAM,EAAmB,EAAiB,EAAO,CAAO,EACpD,EAAU,GACd,GAAI,EAAQ,IACV,GAAI,EAEG,MADgB,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,gBAAiB,IAAK,EAAQ,IAAK,OAAQ,MAAO,EAAG,CAAE,QAAS,CAAiB,CAAC,GAClI,QAAO,EAAU,GAC/B,MAAQ,CAAC,CAMX,GAJI,CAAC,GAAW,EAAQ,aACtB,MAAM,EAAI,MAAM,EAAO,EAAQ,WAAW,GAAI,EAAQ,WAAW,GAAI,OAAQ,EAAG,CAAC,EACjF,EAAU,IAER,CAAC,EAAS,CACZ,IAAM,EAAS,MAAM,EAAI,eAAe,EAAO;;;;;aAK1C,EACD,EAAO,QAAQ,QACjB,MAAM,EAAI,MAAM,EAAO,EAAO,OAAO,MAAM,EAAG,EAAO,OAAO,MAAM,EAAG,OAAQ,EAAG,CAAC,EACjF,EAAU,GAEd,CAGA,OAFK,GACL,MAAM,EAAI,KAAK,EAAO,EAAQ,IAAI,EAC3B,CAAE,QAAS,EAAK,GAFF,CAAE,MAAO,8BAA+B,CAG/D,CAEA,IAAK,oBAAqB,CACxB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,KAAM,MAAU,MAAM,kBAAkB,EACrD,IAAM,EAAyB,EAAiB,EAAO,CAAO,EAC1D,EAAU,GACd,GAAI,EAAQ,IACV,GAAI,EAEG,MADgB,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,gBAAiB,IAAK,EAAQ,IAAK,OAAQ,MAAO,EAAG,CAAE,QAAS,CAAuB,CAAC,GACxI,QAAO,EAAU,GAC/B,MAAQ,CAAC,CAMX,GAJI,CAAC,GAAW,EAAQ,aACtB,MAAM,EAAI,MAAM,EAAO,EAAQ,WAAW,GAAI,EAAQ,WAAW,GAAI,OAAQ,EAAG,CAAC,EACjF,EAAU,IAER,CAAC,EAAS,CACZ,IAAM,EAAS,MAAM,EAAI,eAAe,EAAO;;;;;aAK1C,EACD,EAAO,QAAQ,QACjB,MAAM,EAAI,MAAM,EAAO,EAAO,OAAO,MAAM,EAAG,EAAO,OAAO,MAAM,EAAG,OAAQ,EAAG,CAAC,EACjF,EAAU,GAEd,CAIA,OAHK,GACL,MAAM,EAAI,KAAK,EAAO,EAAQ,IAAI,EAClC,MAAM,EAAI,SAAS,EAAO,EAAQ,WAAa,OAAO,EAC/C,CAAE,QAAS,EAAK,GAHF,CAAE,MAAO,8BAA+B,CAI/D,CAEA,IAAK,gBAAiB,CACpB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,KAAM,MAAU,MAAM,kBAAkB,EAsBrD,IAAM,GAAS,MArBU,EAAI,eAAe,EAAO;;;;;;;;;;;;;;;;;;;;WAoB9C,GACqB,QAAQ,MAOlC,OANK,GAAQ,OACb,MAAM,EAAI,MAAM,EAAO,EAAO,EAAG,EAAO,EAAG,OAAQ,EAAG,CAAC,EACvD,MAAM,EAAI,KAAK,EAAO,EAAQ,IAAI,EAC9B,EAAQ,QACV,MAAM,EAAI,SAAS,EAAO,EAAQ,WAAa,OAAO,EAEjD,CAAE,QAAS,GAAM,YAAa,CAAE,EAAG,EAAO,EAAG,EAAG,EAAO,CAAE,CAAE,GANvC,CAAE,MAAO,8BAA+B,CAOrE,CAEA,IAAK,sBAAuB,CAC1B,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,KAAM,MAAU,MAAM,kBAAkB,EACrD,IAAM,EAAsB,EAAiB,EAAO,CAAO,EACvD,EAAU,GACd,GAAI,EAAQ,IACV,GAAI,EAEG,MADgB,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,gBAAiB,IAAK,EAAQ,IAAK,OAAQ,MAAO,EAAG,CAAE,QAAS,CAAoB,CAAC,GACrI,QAAO,EAAU,GAC/B,MAAQ,CAAC,CAMX,GAJI,CAAC,GAAW,EAAQ,aACtB,MAAM,EAAI,MAAM,EAAO,EAAQ,WAAW,GAAI,EAAQ,WAAW,GAAI,OAAQ,EAAG,CAAC,EACjF,EAAU,IAER,CAAC,EAAS,MAAO,CAAE,MAAO,4BAA6B,EAC3D,MAAM,IAAI,QAAQ,GAAK,WAAW,EAAG,GAAG,CAAC,EACzC,MAAM,EAAI,KAAK,EAAO,EAAQ,IAAI,EAClC,IAAM,EAAS,EAAQ,QAAU,IAEjC,GADA,MAAM,IAAI,QAAQ,GAAK,WAAW,EAAG,CAAM,CAAC,EACxC,EAAQ,OAAS,EAAQ,MAAQ,EACnC,IAAK,IAAI,EAAI,EAAG,EAAI,EAAQ,MAAO,IACjC,MAAM,EAAI,SAAS,EAAO,WAAW,EACrC,MAAM,IAAI,QAAQ,GAAK,WAAW,EAAG,EAAE,CAAC,EAI5C,OADA,MAAM,EAAI,SAAS,EAAO,OAAO,EAC1B,CAAE,QAAS,EAAK,CACzB,CAEA,IAAK,kBAAmB,CACtB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,EAAQ,QAAU,OAAW,MAAU,MAAM,mBAAmB,EACpE,IAAM,EAAW,EAAQ,SACnB,EAAM,EAAQ,IACpB,GAAI,CAAC,GAAY,CAAC,EAAK,MAAU,MAAM,0BAA0B,EAEjE,IAAM,EAAS,EACX;+DACqD,EAAI;yGACsC,EAAI;;;;;;qCAMxE,KAAK,UAAU,EAAQ,KAAK,EAAE;;2BAExC,KAAK,UAAU,EAAQ,KAAK,EAAE;;;;;gBAM/C;gDACsC,KAAK,UAAU,CAAQ,EAAE;+DACV,KAAK,UAAU,CAAQ,EAAE;;;;;qCAKnD,KAAK,UAAU,EAAQ,KAAK,EAAE;;2BAExC,KAAK,UAAU,EAAQ,KAAK,EAAE;;;;;gBAQnD,OAAO,MADc,EAAI,eAAe,EAAO,CAAM,GACvC,QAAQ,OAAS,CAAE,MAAO,eAAgB,CAC1D,CAEA,IAAK,aAAc,CACjB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAM,CAAE,WAAU,OAAM,QAAQ,GAAM,SAAS,IAAU,EACzD,GAAI,CAAC,EAAU,MAAU,MAAM,mBAAmB,EAClD,GAAI,IAAS,OAAW,MAAU,MAAM,eAAe,EAEvD,GAAI,CACF,OAAO,MAAM,OAAO,KAAK,YAAY,EAAO,CAC1C,KAAM,aACN,WACA,OACA,QACA,QACF,EAAG,CAAE,QAAS,EAAiB,EAAO,CAAO,CAAE,CAAC,CAClD,OAAS,EAAK,CACZ,MAAU,MAAM,iCAAiC,aAAe,MAAQ,EAAI,QAAU,OAAO,CAAG,GAAG,CACrG,CACF,CAEA,IAAK,gBAAiB,CACpB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAc,EAAQ,aAAe,EAC3C,IAAK,IAAI,EAAI,EAAG,EAAI,EAAa,IAC/B,MAAM,EAAI,SAAS,EAAO,QAAQ,EAClC,MAAM,IAAI,QAAQ,GAAK,WAAW,EAAG,GAAG,CAAC,EAE3C,MAAO,CAAE,QAAS,EAAK,CACzB,CAEA,IAAK,aACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAoC/C,OAAO,MADmB,EAAI,eAAe,EAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAAW,GAC5C,QAAQ,OAAS,CAAE,MAAO,0BAA2B,EAG1E,IAAK,yBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,OAAO,MAAM,OAAO,KAAK,YAAY,EAAO,CAC1C,KAAM,yBACN,IAAK,EAAQ,IACb,UAAW,EAAQ,UACnB,iBAAkB,EAAQ,gBAC5B,EAAG,CAAE,QAAS,EAAiB,EAAO,CAAO,CAAE,CAAC,EAGlD,IAAK,wBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,OAAO,MAAM,OAAO,KAAK,YAAY,EAAO,CAC1C,KAAM,wBACN,OAAQ,EAAQ,OAChB,WAAY,EAAQ,WACpB,iBAAkB,EAAQ,gBAC5B,EAAG,CAAE,QAAS,EAAiB,EAAO,CAAO,CAAE,CAAC,EAGlD,IAAK,iBAAkB,CACrB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAS,EAAQ,QAAU,EAC3B,EAAS,EAAQ,QAAU,EACjC,GAAI,EAAQ,iBACV,OAAO,MAAM,OAAO,KAAK,YAAY,EAAO,CAC1C,KAAM,kBACN,SACA,SACA,iBAAkB,EAAQ,gBAC5B,EAAG,CAAE,QAAS,EAAiB,EAAO,CAAO,CAAE,CAAC,EAGlD,IAAM,GAAgB,EAAY,IAAe,CAC/C,IAAM,EAAS,CAAE,EAAG,OAAO,QAAS,EAAG,OAAO,OAAQ,EACtD,OAAO,SAAS,EAAI,CAAE,EACtB,IAAM,EAAQ,CAAE,EAAG,OAAO,QAAS,EAAG,OAAO,OAAQ,EACrD,MAAO,CACL,QAAS,EAAM,EACf,QAAS,EAAM,EACf,WAAY,SAAS,gBAAgB,aACrC,eAAgB,OAAO,YACvB,SAAU,EAAO,IAAM,EAAM,GAAK,EAAO,IAAM,EAAM,CACvD,CACF,EAEA,GAAI,CAIF,OAAO,MAHc,EAAI,eAAe,EACtC,IAAI,EAAa,SAAS,EAAE,IAAI,EAAO,IAAI,EAAO,EACpD,GACc,QAAQ,OAAS,CAAE,MAAO,eAAgB,CAC1D,MAAQ,CACN,GAAI,CAMF,OAAO,MALe,OAAO,UAAU,cAAc,CACnD,OAAQ,CAAE,OAAM,EAChB,KAAM,EACN,KAAM,CAAC,EAAQ,CAAM,CACvB,CAAC,GACc,EAAE,EAAE,QAAU,CAAE,MAAO,eAAgB,CACxD,MAAQ,CACN,MAAO,CAAE,MAAO,yCAA0C,CAC5D,CACF,CACF,CAEA,IAAK,cAAe,CAClB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAM,EAAQ,IACpB,GAAI,CAAC,EAAK,MAAU,MAAM,iBAAiB,EAM3C,OALI,EAAI,SAAS,GAAG,EAClB,MAAM,EAAI,cAAc,EAAO,CAAG,EAElC,MAAM,EAAI,SAAS,EAAO,CAAG,EAExB,CAAE,QAAS,EAAK,CACzB,CAEA,IAAK,mBAAoB,CACvB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,IAAK,MAAU,MAAM,iBAAiB,EACnD,GAAI,EAAQ,iBACV,OAAO,MAAM,OAAO,KAAK,YAAY,EAAO,CAC1C,KAAM,oBACN,IAAK,EAAQ,IACb,iBAAkB,EAAQ,gBAC5B,EAAG,CAAE,QAAS,EAAiB,EAAO,CAAO,CAAE,CAAC,EAGlD,IAAM,EAAoB,IAAI,QAAe,GAAY,CACvD,EAAoB,IAAI,EAAO,CAAO,EACtC,eAAiB,CACX,EAAoB,IAAI,CAAK,IAC/B,EAAoB,OAAO,CAAK,EAChC,EAAQ,EAEZ,EAAG,GAAK,CACV,CAAC,EAOD,OALA,MAAM,OAAO,KAAK,OAAO,EAAO,CAAE,IAAK,EAAQ,GAAI,CAAC,EACpD,MAAM,EAEN,MAAM,IAAI,QAAQ,GAAW,WAAW,EAAS,GAAG,CAAC,EAE9C,CAAE,QAAS,EAAK,CACzB,CAEA,IAAK,oBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,OAAO,MAAM,EAAI,gBAAgB,CAAK,EAGxC,IAAK,YAAa,CAChB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAc,EAAiB,EAAO,CAAO,EACnD,GAAI,CACF,MAAM,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,mBAAoB,EAAG,CAAE,QAAS,CAAE,CAAC,CACpF,MAAY,CAAC,CACb,MAAM,IAAI,QAAQ,GAAW,WAAW,EAAS,EAAE,CAAC,EAEpD,IAAI,EACJ,GAAI,CACF,EAAS,MAAM,OAAO,KAAK,YAAY,EAAO,CAC5C,KAAM,8BACN,QAAS,EAAQ,SAAW,CAAC,CAC/B,EAAG,CAAE,QAAS,CAAY,CAAC,CAC7B,MAAc,CACZ,MAAO,CACL,MAAO,sDACP,YAAa,GACb,SAAU,CAAE,MAAO,EAAG,OAAQ,CAAE,CAClC,CACF,QAAU,CACR,GAAI,CACF,MAAM,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,qBAAsB,EAAG,CAAE,QAAS,CAAE,CAAC,CACtF,MAAY,CAAC,CACf,CAGA,GAAI,EAAQ,SAAS,YACnB,GAAI,CACF,IAAM,EAAa,MAAM,OAAO,KAAK,YAAY,EAAO,CACtD,KAAM,gBACN,QAAS,CACP,QAAS,EAAQ,SAAS,UAAY,GACtC,SAAU,EAAQ,SAAS,QAC7B,CACF,EAAG,CAAE,QAAS,CAAY,CAAC,EACvB,GAAY,OACd,EAAO,KAAO,EAAW,KAE7B,MAAc,CAEd,CAGF,GAAI,EAAQ,SAAS,kBACnB,GAAI,CACF,IAAM,EAAa,MAAM,EAAI,kBAAkB,CAAK,EACpD,MAAO,CAAE,GAAG,EAAQ,YAAW,CACjC,OAAS,EAAK,CACZ,MAAO,CACL,GAAG,EACH,gBAAiB,aAAe,MAAQ,EAAI,QAAU,8BACxD,CACF,CAMF,OAJI,GAAQ,qBAAqB,WAC/B,EAAO,oBAAoB,SAAS,MAAQ,EAC5C,EAAO,oBAAoB,SAAS,QAAU,GAEzC,CACT,CAEA,IAAK,0BACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CACF,OAAO,MAAM,OAAO,KAAK,YAAY,EAAO,CAC1C,KAAM,0BACN,IAAK,EAAQ,GACf,EAAG,CAAE,QAAS,EAAiB,EAAO,CAAO,CAAE,CAAC,CAClD,MAAc,CACZ,MAAO,CAAE,MAAO,qDAAsD,CACxE,CAGF,IAAK,aACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CACF,OAAO,MAAM,OAAO,KAAK,YAAY,EAAO,CAC1C,KAAM,aACN,IAAK,EAAQ,IACb,MAAO,EAAQ,KACjB,EAAG,CAAE,QAAS,EAAiB,EAAO,CAAO,CAAE,CAAC,CAClD,MAAc,CACZ,MAAO,CAAE,MAAO,qDAAsD,CACxE,CAGF,IAAK,eACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,KAAM,MAAU,MAAM,kBAAkB,EACrD,GAAI,CACF,OAAO,MAAM,OAAO,KAAK,YAAY,EAAO,CAC1C,KAAM,eACN,KAAM,EAAQ,IAChB,EAAG,CAAE,QAAS,EAAiB,EAAO,CAAO,CAAE,CAAC,CAClD,MAAc,CACZ,MAAO,CAAE,MAAO,qDAAsD,CACxE,CAGF,IAAK,oBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CACF,OAAO,MAAM,OAAO,KAAK,YAAY,EAAO,CAC1C,KAAM,oBACN,IAAK,EAAQ,GACf,EAAG,CAAE,QAAS,EAAiB,EAAO,CAAO,CAAE,CAAC,CAClD,MAAc,CACZ,MAAO,CAAE,MAAO,qDAAsD,CACxE,CAGF,IAAK,qBAAsB,CACzB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAW,EAAQ,SACzB,GAAI,IAAa,OAAW,MAAU,MAAM,gDAAoD,EAChG,IAAM,EAAW,EAAQ,SACzB,GAAI,EAAQ,iBACV,OAAO,MAAM,OAAO,KAAK,YAAY,EAAO,CAC1C,KAAM,kBACN,WACA,iBAAkB,EAAQ,gBAC5B,EAAG,CAAE,QAAS,EAAiB,EAAO,CAAO,CAAE,CAAC,EAGlD,GAAI,CACF,OAAO,MAAM,OAAO,KAAK,YAAY,EAAO,CAC1C,KAAM,qBACN,WACA,UACF,EAAG,CAAE,QAAS,EAAiB,EAAO,CAAO,CAAE,CAAC,CAClD,MAAQ,CAAC,CAET,IAAM,GAAgB,EAAsB,IAAuB,CACjE,IAOM,EAAY,GAAM,SAAS,cAAc,CAAG,GAN7B,CAAC,GAAG,SAAS,iBAAiB,GAAG,CAAC,CAAC,CAAC,OAAO,GAC5D,EAAG,aAAe,EAAG,cAAgB,EAAG,aAAe,GACzD,CAAC,CAAC,MAAM,EAAE,IAAM,EAAE,aAAe,EAAE,YAC5B,EAAW,IAAM,SAAS,gBAcnC,OAVK,GAED,IAAQ,SACV,EAAU,UAAY,EAAU,aACvB,IAAQ,MACjB,EAAU,UAAY,EACb,OAAO,GAAQ,WACxB,EAAU,UAAY,GAGjB,CACL,UAAW,EAAU,UACrB,aAAc,EAAU,aACxB,aAAc,EAAU,aACxB,SAAU,EAAU,UAAY,EAAU,cAAgB,EAAU,aAAe,GACnF,MAAO,EAAU,UAAY,EAC/B,GAhBuB,CAAE,MAAO,+BAAgC,CAiBlE,EAEA,GAAI,CACF,IAAM,EAAS,IAAI,EAAa,SAAS,EAAE,IAAI,KAAK,UAAU,CAAQ,EAAE,IAAI,KAAK,UAAU,CAAQ,EAAE,GAErG,OAAO,MADc,EAAI,eAAe,EAAO,CAAM,GACvC,QAAQ,OAAS,CAAE,MAAO,eAAgB,CAC1D,MAAQ,CACN,GAAI,CAMF,OAAO,MALe,OAAO,UAAU,cAAc,CACnD,OAAQ,CAAE,OAAM,EAChB,KAAM,EACN,KAAM,CAAC,EAAU,CAAQ,CAC3B,CAAC,GACc,EAAE,EAAE,QAAU,CAAE,MAAO,eAAgB,CACxD,MAAQ,CACN,MAAO,CAAE,MAAO,yCAA0C,CAC5D,CACF,CACF,CAEA,IAAK,kBAAmB,CACtB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAW,EAAQ,SAEnB,EAAoB,GAAuB,CAC/C,IAOM,EAAY,GAAM,SAAS,cAAc,CAAG,GAN7B,CAAC,GAAG,SAAS,iBAAiB,GAAG,CAAC,CAAC,CAAC,OAAO,GAC5D,EAAG,aAAe,EAAG,cAAgB,EAAG,aAAe,GACzD,CAAC,CAAC,MAAM,EAAE,IAAM,EAAE,aAAe,EAAE,YAC5B,EAAW,IAAM,SAAS,gBAInC,GAAI,CAAC,EAAW,MAAO,CAAE,MAAO,+BAAgC,EAEhE,IAAM,EAAY,EAAU,aAAe,EAAU,aACrD,MAAO,CACL,UAAW,EAAU,UACrB,aAAc,EAAU,aACxB,aAAc,EAAU,aACxB,SAAU,EAAU,UAAY,EAAU,cAAgB,EAAU,aAAe,GACnF,MAAO,EAAU,UAAY,GAC7B,iBAAkB,EAAY,EAAI,KAAK,MAAO,EAAU,UAAY,EAAa,GAAG,EAAI,GAC1F,CACF,EAEA,GAAI,CACF,IAAM,EAAS,IAAI,EAAiB,SAAS,EAAE,IAAI,KAAK,UAAU,CAAQ,EAAE,GAE5E,OAAO,MADc,EAAI,eAAe,EAAO,CAAM,GACvC,QAAQ,OAAS,CAAE,MAAO,eAAgB,CAC1D,MAAQ,CACN,GAAI,CAMF,OAAO,MALe,OAAO,UAAU,cAAc,CACnD,OAAQ,CAAE,OAAM,EAChB,KAAM,EACN,KAAM,CAAC,CAAQ,CACjB,CAAC,GACc,EAAE,EAAE,QAAU,CAAE,MAAO,eAAgB,CACxD,MAAQ,CACN,MAAO,CAAE,MAAO,kDAAmD,CACrE,CACF,CACF,CAEA,IAAK,gBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CACF,OAAO,MAAM,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,eAAgB,EAAG,CAAE,QAAS,EAAiB,EAAO,CAAO,CAAE,CAAC,CACtH,MAAc,CACZ,MAAO,CAAE,MAAO,qDAAsD,CACxE,CAGF,IAAK,gBAAiB,CACpB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAmB/C,IAAM,GAAO,MAlBS,OAAO,UAAU,cAAc,CACnD,OAAQ,CAAE,QAAO,SAAU,CAAC,EAAiB,EAAO,CAAO,CAAC,CAAE,EAC9D,MAAO,EAAoB,IAA2B,CACpD,GAAI,IAAa,SAAc,OAAO,GAAa,UAAY,EAAS,SAAW,GACjF,MAAU,MAAM,qCAAqC,EAEvD,IAAM,EAAO,IAAa,OAAY,SAAS,gBAAkB,SAAS,cAAc,CAAQ,EAChG,GAAI,CAAC,EAAM,MAAU,MAAM,gCAAgC,EAAS,EAAE,EACtE,IAAM,EAAa,EAAe,EAAK,UAAU,EAAI,EAAe,EACpE,GAAI,EAAc,CAChB,GAAI,EAAW,QAAQ,QAAQ,EAAG,MAAO,GACzC,EAAW,iBAAiB,QAAQ,CAAC,CAAC,QAAS,GAAW,EAAO,OAAO,CAAC,CAC3E,CAEA,OADgB,IAAa,QAAa,SAAS,QAAU,aAAa,SAAS,QAAQ,KAAK,KAAO,IACtF,EAAW,SAC9B,EACA,KAAM,CAAC,EAAQ,SAAU,EAAQ,YAAY,CAC/C,CAAC,GACoB,EAAE,EAAE,OACzB,GAAI,OAAO,GAAS,SAAU,MAAU,MAAM,iDAAiD,EAC/F,MAAO,CAAE,MAAK,CAChB,CAEA,IAAK,cAAe,CAClB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,KAAM,MAAU,MAAM,eAAe,EAClD,IAAM,EAAgB,EAAiB,EAAO,CAAO,EAErD,GAAI,CACF,IAAM,EAAS,MAAM,OAAO,KAAK,YAAY,EAAO,CAClD,KAAM,cACN,KAAM,EAAQ,KACd,KAAM,EAAQ,KACd,IAAK,EAAQ,GACf,EAAG,CAAE,QAAS,CAAc,CAAC,EAS7B,OAPI,EAAO,MAAc,EAGrB,EAAQ,QAAU,EAAO,IACpB,MAAM,EAAoB,EAAO,EAAO,IAAK,EAAQ,OAAQ,EAAQ,MAAO,EAAK,CAAa,EAGhG,CACT,MAAc,CACZ,MAAO,CAAE,MAAO,qDAAsD,CACxE,CACF,CAEA,IAAK,cAAe,CAClB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,KAAM,MAAU,MAAM,eAAe,EAClD,IAAM,EAAc,EAAiB,EAAO,CAAO,EAEnD,GAAI,CACF,IAAM,EAAS,MAAM,OAAO,KAAK,YAAY,EAAO,CAClD,KAAM,cACN,KAAM,EAAQ,KACd,MAAO,EAAQ,KACjB,EAAG,CAAE,QAAS,CAAY,CAAC,EAS3B,OAPI,EAAO,MAAc,EAGrB,EAAQ,QAAU,EAAO,IACpB,MAAM,EAAoB,EAAO,EAAO,IAAK,EAAQ,OAAQ,EAAQ,MAAO,EAAK,CAAW,EAG9F,CACT,MAAc,CACZ,MAAO,CAAE,MAAO,qDAAsD,CACxE,CACF,CAEA,IAAK,eAAgB,CACnB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,MAAO,MAAU,MAAM,gBAAgB,EACpD,IAAM,EAAe,EAAiB,EAAO,CAAO,EAEpD,GAAI,CACF,IAAM,EAAS,MAAM,OAAO,KAAK,YAAY,EAAO,CAClD,KAAM,eACN,MAAO,EAAQ,KACjB,EAAG,CAAE,QAAS,CAAa,CAAC,EAS5B,OAPI,EAAO,MAAc,EAGrB,EAAQ,QAAU,EAAO,IACpB,MAAM,EAAoB,EAAO,EAAO,IAAK,EAAQ,OAAQ,EAAQ,MAAO,EAAK,CAAY,EAG/F,CACT,MAAc,CACZ,MAAO,CAAE,MAAO,qDAAsD,CACxE,CACF,CAEA,IAAK,qBAAsB,CACzB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,SAAU,MAAU,MAAM,mBAAmB,EAC1D,IAAM,EAAgB,EAAiB,EAAO,CAAO,EAErD,GAAI,CAMF,OAAO,MALc,OAAO,KAAK,YAAY,EAAO,CAClD,KAAM,qBACN,SAAU,EAAQ,QACpB,EAAG,CAAE,QAAS,CAAc,CAAC,CAG/B,MAAc,CACZ,MAAO,CAAE,MAAO,qDAAsD,CACxE,CACF,CAEA,IAAK,gBAAiB,CACpB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,SAAU,MAAU,MAAM,mBAAmB,EAC1D,GAAI,CAAC,EAAQ,OAAQ,MAAU,MAAM,iBAAiB,EACtD,IAAM,EAAgB,EAAiB,EAAO,CAAO,EAErD,GAAI,CAQF,OAAO,MAPc,OAAO,KAAK,YAAY,EAAO,CAClD,KAAM,gBACN,SAAU,EAAQ,SAClB,OAAQ,EAAQ,OAChB,GAAI,EAAQ,IAAM,OACpB,EAAG,CAAE,QAAS,CAAc,CAAC,CAG/B,MAAc,CACZ,MAAO,CAAE,MAAO,qDAAsD,CACxE,CACF,CAEA,IAAK,wBACL,IAAK,wBACL,IAAK,wBACL,IAAK,wBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CACF,OAAO,MAAM,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,EAAQ,IAAK,EAAG,CAAE,QAAS,CAAE,CAAC,CACpF,MAAc,CACZ,MAAO,CAAE,MAAO,qDAAsD,CACxE,CAGF,IAAK,aAAc,CACjB,IAAM,EAAY,EAAQ,UACtB,EAWJ,OATI,IAAc,eAAiB,EAAO,KAAK,GAC7C,EAAc,EAAO,IAAI,GAChB,OAAO,GAAc,WAC9B,EAAc,GAGZ,GACF,OAAO,QAAQ,YAAY,CAAE,KAAM,aAAc,aAAY,CAAC,EAEzD,CAAE,QAAS,EAAK,CACzB,CAEA,IAAK,2BACH,MAAO,CAAE,QAAS,EAAK,EAGzB,IAAK,6BACH,MAAO,CAAE,QAAS,EAAK,EAGzB,IAAK,YACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CACF,IAAM,EAAS,MAAM,OAAO,KAAK,YAAY,EAAO,CAClD,KAAM,gBACN,IAAK,EAAQ,IACb,OAAQ,EAAQ,QAAU,OAC1B,iBAAkB,EAAQ,gBAC5B,EAAG,CAAE,QAAS,EAAiB,EAAO,CAAO,CAAE,CAAC,EAEhD,OADI,EAAO,MAAc,CAAE,MAAO,EAAO,MAAO,KAAM,EAAO,IAAK,EAC3D,CAAE,QAAS,EAAK,CACzB,MAAc,CACZ,MAAO,CAAE,MAAO,qDAAsD,CACxE,CAGF,IAAK,YACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CACF,IAAM,EAAS,MAAM,OAAO,KAAK,YAAY,EAAO,CAClD,KAAM,0BACN,IAAK,EAAQ,GACf,EAAG,CAAE,QAAS,EAAiB,EAAO,CAAO,CAAE,CAAC,EAGhD,OAFI,EAAO,MAAc,CAAE,MAAO,EAAO,KAAM,GAC/C,MAAM,EAAI,MAAM,EAAO,EAAO,EAAG,EAAO,CAAC,EAClC,CAAE,QAAS,EAAK,EACzB,MAAc,CACZ,MAAO,CAAE,MAAO,qDAAsD,CACxE,CAGF,IAAK,OACH,MAAO,CAAE,QAAS,GAAM,OAAQ,WAAY,EAG9C,IAAK,mBAAoB,CACvB,GAAI,CAAC,EAAQ,IAAK,MAAU,MAAM,iBAAiB,EACnD,IAAM,EAAU,EAAQ,SAAW,IAC7B,EAAS,EAAQ,QAAU,IAC3B,EAAY,KAAK,IAAI,EAGvB,EAA2B,KAC/B,KAAO,KAAK,IAAI,EAAI,EAAY,GAAS,CACvC,GAAI,CACF,IAAM,EAAW,MAAM,MAAM,EAAQ,IAAK,CAAE,OAAQ,KAAM,CAAC,EAE3D,GADA,MAAM,EAAS,KAAK,EAChB,EAAS,SAAW,EACtB,MAAO,CAAE,QAAS,GAAM,OAAQ,EAAS,OAAQ,KAAM,KAAK,IAAI,EAAI,CAAU,EAEhF,EAAY,cAAc,EAAS,QACrC,OAAS,EAAG,CACV,EAAY,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CACvD,CACA,MAAM,IAAI,QAAS,GAAM,WAAW,EAAG,GAAY,CAAC,CACtD,CACA,MAAO,CACL,MAAO,uBAAuB,EAAQ,IAAI,aAAa,IACvD,YACA,KAAM,KAAK,IAAI,EAAI,CACrB,CACF,CAEA,IAAK,aAAc,CACjB,IAAM,EAAiB,EAAQ,MAAQ,CAAC,EAClC,EAA8B,EAAQ,WAAa,OACnD,EAAoB,EAAQ,UAAY,GAE9C,GAAI,EAAK,SAAW,EAClB,MAAO,CAAE,MAAO,iCAAkC,EAGpD,IAAM,EAOD,CAAC,EAEF,EAAO,EACP,EAAO,EAEX,IAAK,IAAM,KAAO,EAAM,CACtB,IAAM,EAAY,KAAK,IAAI,EACrB,EAAmB,CAAC,EACtB,EACA,EACA,EAEJ,GAAI,CACF,EAAW,IAAI,IAAI,CAAG,CAAC,CAAC,SAAS,QAAQ,kBAAmB,GAAG,EAC/D,IAAM,EAAU,MAAM,OAAO,KAAK,OAAO,CAAE,MAAK,OAAQ,EAAM,CAAC,EAC/D,GAAI,CAAC,EAAQ,GAAI,MAAU,MAAM,sBAAsB,EACvD,EAAY,EAAQ,GAEpB,GAAI,CACF,MAAM,EAAI,sBAAsB,CAAS,CAC3C,MAAY,CAAC,CAEb,MAAM,IAAI,QAAe,GAAY,CACnC,IAAM,EAAc,GAAqE,CACnF,EAAQ,QAAU,GAAa,EAAQ,UAAY,IACrD,OAAO,cAAc,YAAY,eAAe,CAAU,EAC1D,OAAO,cAAc,gBAAgB,eAAe,CAAO,EAC3D,EAAQ,EAEZ,EACM,EAAW,GAA0E,CACrF,EAAQ,QAAU,GAAa,EAAQ,UAAY,IACrD,OAAO,cAAc,YAAY,eAAe,CAAU,EAC1D,OAAO,cAAc,gBAAgB,eAAe,CAAO,EAC3D,EAAO,KAAK,qBAAqB,EAAQ,OAAO,EAChD,EAAQ,EAEZ,EACA,OAAO,cAAc,YAAY,YAAY,CAAU,EACvD,OAAO,cAAc,gBAAgB,YAAY,CAAO,EACxD,eAAiB,CACf,OAAO,cAAc,YAAY,eAAe,CAAU,EAC1D,OAAO,cAAc,gBAAgB,eAAe,CAAO,EAC3D,EAAO,KAAK,0BAA0B,EACtC,EAAQ,CACV,EAAG,GAAK,CACV,CAAC,EAED,MAAM,IAAI,QAAQ,GAAK,WAAW,EAAG,GAAI,CAAC,EAE1C,IAAM,EAAkB,EAAI,mBAAmB,EAAW,CAAE,WAAY,GAAM,MAAO,EAAG,CAAC,EACzF,IAAK,IAAM,KAAO,EAChB,EAAO,KAAK,IAAI,EAAI,KAAK,IAAI,EAAI,MAAM,EAGzC,GAAI,EACF,GAAI,CAEF,GAAmB,MADM,EAAI,kBAAkB,CAAS,GAC1B,MAChC,MAAY,CAAC,CAEjB,OAAS,EAAG,CACV,EAAO,KAAK,aAAa,MAAQ,EAAE,QAAU,OAAO,CAAC,CAAC,CACxD,QAAU,CACR,GAAI,EACF,GAAI,CAAE,MAAM,OAAO,KAAK,OAAO,CAAS,CAAG,MAAQ,CAAC,CAExD,CAEA,IAAM,EAAU,KAAK,IAAI,EAAI,EACvB,EAAS,EAAO,SAAW,EAAI,OAAS,OAY9C,GAXI,IAAW,OAAQ,IAClB,IAEL,EAAQ,KAAK,CACX,MACA,SACA,KAAM,EACN,SACA,GAAI,GAAoB,CAAE,mBAAkB,UAAS,CACvD,CAAC,EAEG,GAAY,IAAW,OACzB,KAEJ,CAEA,MAAO,CACL,UACA,QAAS,CAAE,OAAM,OAAM,MAAO,EAAQ,MAAO,EAC7C,SAAU,EAAQ,QACpB,CACF,CAEA,IAAK,mBAAoB,CACvB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,SAAU,MAAU,MAAM,sBAAsB,EAC7D,IAAM,EAAc,EAAiB,EAAO,CAAO,EAEnD,GAAI,CACF,MAAM,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,mBAAoB,EAAG,CAAE,QAAS,CAAE,CAAC,CACpF,MAAY,CAAC,CACb,MAAM,IAAI,QAAQ,GAAW,WAAW,EAAS,EAAE,CAAC,EAEpD,GAAI,CAOF,OAAO,MANc,OAAO,KAAK,YAAY,EAAO,CAClD,KAAM,mBACN,SAAU,EAAQ,SAClB,MAAO,EAAQ,OAAS,UACxB,QAAS,EAAQ,SAAW,GAC9B,EAAG,CAAE,QAAS,CAAY,CAAC,CAE7B,MAAc,CACZ,MAAO,CACL,MAAO,sDACP,YAAa,GACb,SAAU,CAAE,MAAO,EAAG,OAAQ,CAAE,CAClC,CACF,QAAU,CACR,GAAI,CACF,MAAM,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,qBAAsB,EAAG,CAAE,QAAS,CAAE,CAAC,CACtF,MAAY,CAAC,CACf,CACF,CAEA,IAAK,eACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,QAAS,MAAU,MAAM,yBAAyB,EAE/D,GAAI,CACF,MAAM,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,mBAAoB,EAAG,CAAE,QAAS,CAAE,CAAC,CACpF,MAAY,CAAC,CACb,MAAM,IAAI,QAAQ,GAAW,WAAW,EAAS,EAAE,CAAC,EAEpD,GAAI,CAMF,OAAO,MALc,OAAO,KAAK,YAAY,EAAO,CAClD,KAAM,eACN,QAAS,EAAQ,QACjB,QAAS,EAAQ,SAAW,GAC9B,EAAG,CAAE,QAAS,CAAE,CAAC,CAEnB,MAAc,CACZ,MAAO,CACL,MAAO,sDACP,YAAa,GACb,SAAU,CAAE,MAAO,EAAG,OAAQ,CAAE,CAClC,CACF,QAAU,CACR,GAAI,CACF,MAAM,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,qBAAsB,EAAG,CAAE,QAAS,CAAE,CAAC,CACtF,MAAY,CAAC,CACf,CAGF,IAAK,wBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,GAAI,CACF,MAAM,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,mBAAoB,EAAG,CAAE,QAAS,CAAE,CAAC,CACpF,MAAY,CAAC,CACb,MAAM,IAAI,QAAQ,GAAW,WAAW,EAAS,EAAE,CAAC,EAEpD,GAAI,CAKF,OAAO,MAJc,OAAO,KAAK,YAAY,EAAO,CAClD,KAAM,wBACN,QAAS,EAAQ,SAAW,GAC9B,EAAG,CAAE,QAAS,CAAE,CAAC,CAEnB,MAAc,CACZ,MAAO,CACL,MAAO,sDACP,YAAa,GACb,SAAU,CAAE,MAAO,EAAG,OAAQ,CAAE,CAClC,CACF,QAAU,CACR,GAAI,CACF,MAAM,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,qBAAsB,EAAG,CAAE,QAAS,CAAE,CAAC,CACtF,MAAY,CAAC,CACf,CAGF,IAAK,iBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,OAAO,MAAM,EAAkB,EAAO,EAA0B,EAAQ,MAAM,CAAC,EAGjF,IAAK,iBAAkB,CACrB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAS,EAA0B,EAAQ,MAAM,EACjD,EAAS,GAAqB,CAAE,UAAW,EAAQ,QAAS,WAAY,EAAQ,QAAS,CAAC,EAC1F,EAA2B,GAAkB,EAAQ,MAAM,EAC3D,EAAU,MAAM,GAAc,CAClC,GAAG,EACH,SACA,UAAa,EAAkB,EAAO,CAAM,CAC9C,CAAC,EACK,EAAU,CACd,MAAO,EAAQ,OAAO,MACtB,SAAU,EAAQ,OAAO,SACzB,KAAM,EAAQ,OAAO,KACrB,MAAO,EAAQ,OAAO,MACtB,WAAY,EAAQ,OAAO,WAC3B,UAAW,EAAQ,OAAO,UAC1B,MAAO,EAAQ,MACf,OAAQ,EAAQ,SAChB,QAAS,EAAO,UAChB,SAAU,EAAO,UACnB,EACA,GAAI,EAAQ,OAAS,WAAa,EAAQ,OAAS,WAGjD,MAAO,CAAE,SAAU,EAAQ,OAAS,WAAY,GAAG,CAAQ,EAS7D,MAPI,EAAQ,OAAS,UACb,IAAI,EACR,eACA,oCAAoC,EAAO,UAAU,iBAAiB,EAAkB,EAAQ,MAAM,IACtG,CAAE,GAAG,EAAS,OAAM,CACtB,EAEI,IAAI,EACR,GAAmB,EAAQ,OAAO,KAAK,GAAK,iBAC5C,sBAAsB,EAAkB,EAAQ,MAAM,IACtD,CAAE,GAAG,EAAS,OAAM,CACtB,CACF,CAEA,IAAK,sBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,GAAI,CACF,MAAM,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,mBAAoB,EAAG,CAAE,QAAS,CAAE,CAAC,CACpF,MAAY,CAAC,CACb,MAAM,IAAI,QAAQ,GAAW,WAAW,EAAS,EAAE,CAAC,EAEpD,GAAI,CAMF,OAAO,MALc,OAAO,KAAK,YAAY,EAAO,CAClD,KAAM,sBACN,OAAQ,EAAQ,QAAU,IAC1B,QAAS,EAAQ,SAAW,GAC9B,EAAG,CAAE,QAAS,CAAE,CAAC,CAEnB,MAAc,CACZ,MAAO,CACL,MAAO,sDACP,YAAa,GACb,SAAU,CAAE,MAAO,EAAG,OAAQ,CAAE,CAClC,CACF,QAAU,CACR,GAAI,CACF,MAAM,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,qBAAsB,EAAG,CAAE,QAAS,CAAE,CAAC,CACtF,MAAY,CAAC,CACf,CAGF,IAAK,gBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,OAAO,MADc,EAAI,aAAa,EAAO,GAAM,EAAQ,IAAI,EAIjE,IAAK,iBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,OAAO,MADc,EAAI,aAAa,EAAO,EAAK,EAIpD,IAAK,cAAe,CAClB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAS,EAAI,cAAc,CAAK,EAItC,OAHK,EAGE,CACL,UAAW,GACX,KAAM,EAAO,KACb,QAAS,EAAO,QAChB,cAAe,EAAO,aACxB,EAPS,CAAE,UAAW,EAAM,CAQ9B,CAEA,IAAK,kBAAmB,CACtB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,OAAQ,MAAU,MAAM,oBAAoB,EACzD,IAAM,EAAS,MAAM,EAAI,eAAe,EAAO,EAAQ,MAAM,EAC7D,GAAI,CAAC,EAAO,QAAS,MAAU,MAAM,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,OAAQ,EAAQ,MAAO,CACjD,CAEA,IAAK,cAAe,CAClB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,EAAQ,OAAS,OAAW,MAAU,MAAM,kBAAkB,EAClE,IAAM,EAAS,MAAM,EAAI,WAAW,EAAO,EAAQ,IAAI,EACvD,GAAI,CAAC,EAAO,QAAS,MAAU,MAAM,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,KAAM,EAAQ,IAAK,CAC7C,CAEA,IAAK,cAAe,CAClB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,EAAQ,MAAO,CACjB,IAAM,EAAS,MAAM,EAAI,iBAAiB,CAAK,EAC/C,GAAI,CAAC,EAAO,QAAS,MAAU,MAAM,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,QAAS,EAAK,CACxC,CACA,GAAI,EAAQ,WAAa,QAAa,EAAQ,YAAc,OAC1D,MAAU,MAAM,iCAAiC,EAEnD,IAAM,EAAS,MAAM,EAAI,mBAAmB,EAAO,EAAQ,SAAU,EAAQ,UAAW,EAAQ,QAAQ,EACxG,GAAI,CAAC,EAAO,QAAS,MAAU,MAAM,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,SAAU,EAAQ,SAAU,UAAW,EAAQ,SAAU,CACnF,CAEA,IAAK,sBASH,MAAO,CAAE,SANP,YAAa,YAAa,YAAa,gBAAiB,oBAAqB,YAC7E,OAAQ,WAAY,YACpB,UAAW,UAAW,UAAW,cACjC,aAAc,aAAc,aAAc,gBAC1C,WAAY,cAEL,CAAQ,EAGnB,IAAK,iBAAkB,CACrB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAa,EAAQ,OAG3B,GAAI,EAAW,YAAY,IAAM,QAAS,CACxC,IAAM,EAAS,MAAM,EAAI,qBAAqB,CAAK,EACnD,GAAI,CAAC,EAAO,QAAS,MAAU,MAAM,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,QAAS,wBAAyB,CAC5D,CAGA,IAAM,EAA4I,CAEhJ,YAAa,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,yIAA0I,EAC9O,YAAa,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,yIAA0I,EAC9O,YAAa,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,yIAA0I,EAC9O,gBAAiB,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,yIAA0I,EAClP,oBAAqB,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,yIAA0I,EACtP,YAAa,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,yIAA0I,EAC9O,KAAQ,CAAE,MAAO,IAAK,OAAQ,KAAM,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,gIAAiI,EACjO,WAAY,CAAE,MAAO,KAAM,OAAQ,KAAM,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,gIAAiI,EACtO,YAAa,CAAE,MAAO,IAAK,OAAQ,KAAM,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,gIAAiI,EAEtO,UAAW,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,KAAM,OAAQ,GAAM,MAAO,GAAM,UAAW,0HAA2H,EAChO,UAAW,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,MAAO,OAAQ,GAAM,MAAO,GAAM,UAAW,0HAA2H,EACjO,UAAW,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,MAAO,OAAQ,GAAM,MAAO,GAAM,UAAW,uHAAwH,EAC9N,cAAe,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,IAAK,OAAQ,GAAM,MAAO,GAAM,UAAW,2HAA4H,EAEpO,aAAc,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,4HAA6H,EAClO,aAAc,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,6HAA8H,EACnO,aAAc,CAAE,MAAO,IAAK,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,wHAAyH,EAC9N,gBAAiB,CAAE,MAAO,IAAK,OAAQ,KAAM,kBAAmB,EAAG,OAAQ,GAAM,MAAO,GAAM,UAAW,mHAAoH,EAE7N,WAAY,CAAE,MAAO,KAAM,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAO,MAAO,GAAM,UAAW,0HAA2H,EAChO,eAAgB,CAAE,MAAO,KAAM,OAAQ,IAAK,kBAAmB,EAAG,OAAQ,GAAO,MAAO,GAAM,UAAW,0HAA2H,CACtO,EAIM,EAAkC,CACtC,OAAQ,YACR,SAAU,YACV,SAAU,YACV,SAAU,YACV,SAAU,YACV,MAAO,UACP,OAAQ,UACR,OAAQ,UACR,OAAQ,aACR,UAAW,aACX,KAAM,OACN,QAAS,UACX,EACI,EAAmC,EAAQ,GAK/C,GAJA,CAEE,GAAS,EAAQ,EADC,EAAW,YACJ,EAAU,QAAQ,OAAQ,EAAE,IAEnD,CAAC,EAAQ,CACX,IAAM,EAAY,EAAW,YAAY,EACrC,EAA2D,KAE/D,IAAK,GAAM,CAAC,EAAM,KAAW,OAAO,QAAQ,CAAO,EAAG,CACpD,IAAM,EAAc,EAAK,YAAY,EAC/B,EAAiB,EAAY,QAAQ,OAAQ,EAAE,GAGjD,EAAY,SAAS,CAAS,GAAK,EAAU,SAAS,CAAc,KAElE,CAAC,GAAa,EAAK,OAAS,EAAU,KAAK,UAC7C,EAAY,CAAE,OAAM,QAAO,EAGjC,CAEI,IACF,EAAS,EAAU,OAEvB,CAEA,GAAI,CAAC,EACH,MAAU,MAAM,mBAAmB,EAAW,uCAAuC,EAGvF,IAAM,EAAS,MAAM,EAAI,cAAc,EAAO,CAAM,EACpD,GAAI,CAAC,EAAO,QAAS,MAAU,MAAM,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,OAAQ,CAAW,CAC7C,CAEA,IAAK,mBAAoB,CACvB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,OAAS,CAAC,EAAQ,OAC7B,MAAU,MAAM,8BAA8B,EAEhD,IAAM,EAAS,MAAM,EAAI,gBAAgB,EAAO,CAC9C,MAAO,EAAQ,MACf,OAAQ,EAAQ,OAChB,kBAAmB,EAAQ,kBAC3B,OAAQ,EAAQ,MAClB,CAAC,EACD,GAAI,CAAC,EAAO,QAAS,MAAU,MAAM,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,MAAO,EAAQ,MAAO,OAAQ,EAAQ,MAAO,CACvE,CAEA,IAAK,gBAAiB,CACpB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAS,MAAM,EAAI,aAAa,EAAO,EAAQ,OAAO,EAC5D,GAAI,CAAC,EAAO,QAAS,MAAU,MAAM,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,QAAS,EAAQ,OAAQ,CACnD,CAEA,IAAK,YACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,KAAM,MAAU,MAAM,kBAAkB,EAMrD,OAAO,MALgB,OAAO,KAAK,YAAY,EAAO,CACpD,KAAM,YACN,KAAM,EAAQ,KACd,iBAAkB,EAAQ,gBAC5B,EAAG,CAAE,QAAS,EAAiB,EAAO,CAAO,CAAE,CAAC,EAIlD,IAAK,aAAc,CACjB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAS,MAAM,EAAI,sBAAsB,EAAO,EAAQ,UAAU,EACxE,GAAI,CAAC,EAAO,QAAS,MAAU,MAAM,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,QAAS,6BAA8B,CACjE,CAEA,IAAK,YAAa,CAChB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAS,MAAM,EAAI,qBAAqB,CAAK,EACnD,GAAI,CAAC,EAAO,QAAS,MAAU,MAAM,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,QAAS,EAAO,OAAQ,CAClD,CAEA,IAAK,eAAgB,CACnB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAS,MAAM,EAAI,sBAAsB,CAAK,EACpD,GAAI,CAAC,EAAO,QAAS,MAAU,MAAM,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,QAAS,EAAO,OAAQ,CAClD,CAEA,IAAK,cAAe,CAClB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,IAAK,MAAU,MAAM,iBAAiB,EACnD,GAAI,CAAC,EAAQ,OAAS,CAAC,EAAQ,MAAM,OAAQ,MAAU,MAAM,mBAAmB,EAChF,IAAM,EAAiB,MAAM,OAAO,KAAK,YAAY,EAAO,CAC1D,KAAM,0BACN,IAAK,EAAQ,GACf,EAAG,CAAE,QAAS,EAAiB,EAAO,CAAO,CAAE,CAAC,EAChD,GAAI,EAAe,MAAO,MAAU,MAAM,EAAe,KAAK,EAC9D,IAAM,EAAY,MAAM,EAAI,uBAAuB,EAAO,EAAe,SAAU,EAAQ,KAAK,EAChG,GAAI,CAAC,EAAU,QAAS,MAAU,MAAM,EAAU,KAAK,EACvD,MAAO,CAAE,QAAS,GAAM,SAAU,EAAQ,MAAM,MAAO,CACzD,CAEA,IAAK,gBAAiB,CACpB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAS,MAAM,EAAI,YAAY,EAAO,EAAQ,SAAW,GAAK,EACpE,GAAI,CAAC,EAAO,QAAS,MAAU,MAAM,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,WAAY,EAAO,UAAW,CACxD,CAEA,IAAK,aAAc,CACjB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAS,MAAM,EAAI,UAAU,CAAK,EACxC,GAAI,CAAC,EAAO,QAAS,MAAU,MAAM,EAAO,KAAK,EACjD,MAAO,CAAE,QAAS,GAAM,OAAQ,EAAO,MAAO,CAChD,CAEA,IAAK,iBAAkB,CACrB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAkB,MAAM,GAAuB,CAAK,EAEtD,EAAM,CAAE,KADe,EAAgB,KAAM,GAAU,EAAM,gBAAkB,EACjE,GAAoB,KAAO,GAAI,MAAO,GAAI,QAAS,CAAC,CAAsB,EACxF,EAA6B,CAAC,EAC9B,EAAqB,GACnB,EAA8B,CAAC,EAC/B,EAAkB,CAAC,EAAI,WAAW,CAAK,EAC7C,GAAI,CACF,GAAI,EACF,GAAI,CACF,MAAM,EAAI,OAAO,CAAK,CACxB,OAAS,EAAO,CACd,IAAM,EAAU,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EACrE,EAAkB,KAAK,gCAAgC,GAAS,EAChE,EAAqB,EACvB,CAEF,GAAI,EAAI,WAAW,CAAK,EAAG,CACzB,GAAI,CACF,EAAM,MAAM,GAA0B,CAAK,CAC7C,OAAS,EAAO,CACd,IAAM,EAAU,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EACrE,EAAkB,KAAK,qCAAqC,GAAS,CACvE,CACA,GAAI,CACF,IAAM,EAAY,MAAM,EAAI,UAAU,CAAK,EACvC,EAAU,QACZ,EAAY,EAAU,QAAU,CAAC,GAEjC,EAAkB,KAAK,+BAA+B,EAAU,OAAO,EACvE,EAAqB,GAEzB,OAAS,EAAO,CACd,IAAM,EAAU,aAAiB,MAAQ,EAAM,QAAU,OAAO,CAAK,EACrE,EAAkB,KAAK,+BAA+B,GAAS,EAC/D,EAAqB,EACvB,CACF,CACF,QAAU,CACR,GAAI,GAAmB,EAAI,WAAW,CAAK,EAAG,CAC5C,IAAM,EAAe,MAAM,EAAI,OAAO,CAAK,EACtC,EAAa,SAChB,EAAkB,KAAK,sBAAsB,EAAa,OAAO,CAErE,CACF,CACA,IAAM,EAAY,GAAoB,CACpC,SAAU,CAAE,KAAM,EAAI,KAAM,MAAO,EAAI,KAAM,EAC7C,WAAY,EAAI,QAChB,kBACA,YACA,oBACF,CAAC,EAID,OAHA,EAAU,SAAS,QAAQ,GAAG,CAAiB,EAGxC,CACT,CAEA,IAAK,eAAgB,CACnB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAM,CAAE,WAAU,OAAM,SAAU,EAElC,GAAI,CAAC,GAAY,CAAC,GAAQ,IAAU,OAClC,MAAU,MAAM,yCAAyC,EAI3D,IAAM,EAAe,MAAM,OAAO,cAAc,aAAa,CAAE,OAAM,CAAC,EACtE,GAAI,CAAC,GAAgB,EAAa,SAAW,EAC3C,MAAU,MAAM,wBAAwB,EAI1C,IAAM,EAAc,EAAa,OAAO,GAAK,EAAE,UAAY,CAAC,EAE5D,GAAI,EAAY,SAAW,EACzB,MAAU,MAAM,+BAA+B,EAGjD,IAAI,EAAoE,KACxE,GAAI,IAAU,OAAW,CACvB,GAAI,EAAQ,GAAK,GAAS,EAAY,OACpC,MAAU,MAAM,eAAe,EAAM,uBAAuB,EAAY,OAAO,WAAW,EAE5F,EAAc,EAAY,EAC5B,MAAO,GAAI,EAAM,CAEf,IAAK,IAAM,KAAS,EAClB,GAAI,CAIF,IAAI,MAHiB,OAAO,KAAK,YAAY,EAAO,CAClD,KAAM,gBACR,EAAG,CAAE,QAAS,EAAM,OAAQ,CAAC,IACjB,OAAS,EAAM,CACzB,EAAc,EACd,KACF,CACF,MAAQ,CAER,CAEF,GAAI,CAAC,EACH,MAAU,MAAM,oBAAoB,EAAK,YAAY,CAEzD,MAAO,GAAI,EAET,GAAI,CACF,IAAM,EAAiB,MAAM,OAAO,KAAK,YAAY,EAAO,CAC1D,KAAM,wBACN,UACF,EAAG,CAAE,QAAS,CAAE,CAAC,EAEjB,GAAI,GAAgB,MAAO,MAAU,MAAM,EAAe,KAAK,EAG3D,GAAgB,MAClB,EAAc,EAAY,KAAK,GAAK,EAAE,MAAQ,EAAe,GAAG,GAAK,MAInE,CAAC,GAAe,EAAY,SAAW,IACzC,EAAc,EAAY,GAE9B,MAAY,CACV,MAAU,MAAM,uCAAuC,EAAS,EAAE,CACpE,CAGF,GAAI,CAAC,EACH,MAAU,MAAM,iBAAiB,EAGnC,MAAO,CACL,QAAS,GACT,QAAS,EAAY,QACrB,IAAK,EAAY,GACnB,CACF,CAEA,IAAK,aACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAI/C,MAAO,CAAE,QAAS,GAAM,QAAS,wBAAyB,EAG5D,IAAK,oBAAqB,CACxB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,QAAS,MAAU,MAAM,qBAAqB,EAC3D,GAAI,CAAC,EAAQ,KAAM,MAAU,MAAM,kBAAkB,EACrD,IAAM,EAAS,MAAM,EAAI,gBAAgB,EAAO,EAAQ,QAAS,EAAQ,IAAI,EAC7E,GAAI,CAAC,EAAO,QAAS,MAAU,MAAM,EAAO,KAAK,EACjD,MAAO,CAAE,MAAO,EAAO,MAAO,CAChC,CAEA,IAAK,qBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,KAAM,MAAU,MAAM,kBAAkB,EAErD,GAAI,CAEF,MAAM,EAAI,eAAe,EAAO,27FAAa,EAE7C,IAAM,EAAO,GAAyB,EAAQ,IAAI,EAC5C,EAAa,gCAAgC,EAAK,OAEpD,EAAS,MAAM,EAAI,eAAe,EAAO,CAAU,EASvD,GAJI,EAAO,kBAAoB,CAAE,MAAM,GAAoB,EAAO,CAAI,IACpE,EAAS,MAAM,EAAI,eAAe,EAAO,gCAAgC,EAAQ,KAAK,MAAM,GAG1F,EAAO,iBAIT,MAAO,CAAE,MAHG,EAAO,iBAAiB,WAAW,aACnC,EAAO,iBAAiB,MACxB,yBACQ,EAGtB,IAAM,EAAQ,EAAO,QAAQ,MAE7B,MAAO,CAAE,QADM,IAAU,OAAY,YAAc,KAAK,UAAU,EAAO,KAAM,CAAC,IACvD,UAAU,EAAG,GAAK,GAAK,WAAY,CAC9D,OAAS,EAAK,CACZ,IAAM,EAAM,aAAe,MAAQ,EAAI,QAAU,0BAIjD,OAHI,EAAI,SAAS,eAAe,GAAK,EAAI,SAAS,eAAe,EACxD,CAAE,MAAO,yDAA0D,EAErE,CAAE,MAAO,CAAI,CACtB,CAGF,IAAK,gBAAiB,CACpB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,UAAY,OAAO,EAAQ,UAAa,SAAU,MAAU,MAAM,mBAAmB,EAElG,GAAI,OAAO,EAAQ,YAAe,UAAW,MAAU,MAAM,2BAA2B,EACxF,GAAI,OAAO,EAAQ,KAAQ,UAAW,MAAU,MAAM,sBAAsB,EAC5E,IAAM,EAAa,EAAQ,aAAe,OAAyC,IAA7B,OAAO,EAAQ,UAAU,EACzE,EAAM,EAAQ,MAAQ,OAAkC,GAAtB,OAAO,EAAQ,GAAG,EAC1D,GAAI,CAAC,OAAO,SAAS,CAAU,GAAK,EAAa,KAAO,EAAa,IACnE,MAAU,MAAM,2CAA2C,EAE7D,GAAI,CAAC,OAAO,SAAS,CAAG,GAAK,EAAM,GAAK,EAAM,GAC5C,MAAU,MAAM,8BAA8B,EAGhD,GAAI,CACF,IAAM,EAAa;6BACE,KAAK,UAAU,EAAQ,QAAQ,EAAE;+BAC/B,KAAK,MAAM,CAAU,EAAE;wBAC9B,KAAK,MAAM,CAAG,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAyD1B,EAAS,MAAM,EAAI,eAAe,EAAO,CAAU,EAOzD,OANI,EAAO,iBAIF,CAAE,MAHG,EAAO,iBAAiB,WAAW,aAC7C,EAAO,iBAAiB,MACxB,wBACkB,EAEf,EAAO,QAAQ,OAAS,CAAE,MAAO,kCAAmC,CAC7E,OAAS,EAAK,CACZ,IAAM,EAAM,aAAe,MAAQ,EAAI,QAAU,yBAIjD,OAHI,EAAI,SAAS,eAAe,GAAK,EAAI,SAAS,eAAe,EACxD,CAAE,MAAO,8DAA+D,EAE1E,CAAE,MAAO,CAAI,CACtB,CACF,CAEA,IAAK,aAAc,CACjB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,OAAO,EAAQ,YAAe,UAAW,MAAU,MAAM,2BAA2B,EACxF,GAAI,EAAQ,UAAY,QAAa,OAAO,EAAQ,SAAY,SAC9D,MAAU,MAAM,+BAA+B,EAEjD,IAAM,EAAa,EAAQ,aAAe,OAAyC,IAA7B,OAAO,EAAQ,UAAU,EAC/E,GAAI,CAAC,OAAO,SAAS,CAAU,GAAK,EAAa,KAAO,EAAa,IACnE,MAAU,MAAM,2CAA2C,EAG7D,GAAI,CACF,IAAM,EAAa;+BACI,KAAK,MAAM,CAAU,EAAE;4BAC1B,KAAK,UAAU,EAAQ,SAAW,IAAI,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAqLtD,EAAS,MAAM,EAAI,eAAe,EAAO,CAAU,EAOzD,OANI,EAAO,iBAIF,CAAE,MAHG,EAAO,iBAAiB,WAAW,aAC7C,EAAO,iBAAiB,MACxB,0BACkB,EAEf,EAAO,QAAQ,OAAS,CAAE,MAAO,oCAAqC,CAC/E,OAAS,EAAK,CACZ,IAAM,EAAM,aAAe,MAAQ,EAAI,QAAU,2BAIjD,OAHI,EAAI,SAAS,eAAe,GAAK,EAAI,SAAS,eAAe,EACxD,CAAE,MAAO,gEAAiE,EAE5E,CAAE,MAAO,CAAI,CACtB,CACF,CAEA,IAAK,wBAAyB,CAC5B,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,GAAI,CACF,MAAM,EAAI,sBAAsB,CAAK,CACvC,MAAY,CAAC,CAEb,IAAM,EAAW,EAAI,mBAAmB,EAAO,CAC7C,WAAY,EAAQ,WACpB,QAAS,EAAQ,QACjB,MAAO,EAAQ,OAAS,GAC1B,CAAC,EAMD,OAJI,EAAQ,OACV,EAAI,qBAAqB,CAAK,EAGzB,CAAE,UAAS,CACpB,CAEA,IAAK,yBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,OADA,EAAI,qBAAqB,CAAK,EACvB,CAAE,QAAS,EAAK,EAGzB,IAAK,wBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAO/C,OANA,EAAI,qBAAqB,CAAK,EAC9B,MAAM,EAAI,sBAAsB,EAAO,CACrC,SAAU,EAAQ,UAAY,OAC9B,aAAc,EAAQ,aACtB,WAAY,EAAQ,cACtB,CAAC,EACM,CAAE,QAAS,EAAK,EAGzB,IAAK,uBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,OADA,MAAM,EAAI,uBAAuB,CAAK,EAC/B,CAAE,QAAS,EAAK,EAGzB,IAAK,cAAe,CAClB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAa,OAAO,EAAQ,YAAc,EAAE,EAClD,GAAI,CAAC,EAAY,MAAU,MAAM,iCAAiC,EAClE,GAAI,EAAqB,MAAU,MAAM,qCAAqC,EAC9E,IAAM,EAAM,OAAO,EAAQ,GAAG,EAC9B,GAAI,CAAC,OAAO,SAAS,CAAG,GAAK,GAAO,GAAK,EAAM,GAAI,MAAU,MAAM,uCAAuC,EAa1G,EAAI,sBAAsB,EAAO,EAAa,GAAU,CACtD,EAAiB,CACf,KAAM,cACN,aACA,QACA,KAAM,EAAM,KACZ,SAAU,EAAM,SAChB,UAAW,EAAM,UACjB,WAAY,KAAK,IAAI,CACvB,CAAC,CACH,EArBiB,GAAiB,CAGhC,EAAiB,CACf,KAAM,cACN,aACA,QACA,UAAY,EAAoC,MAAQ,0BACxD,MAAO,EAAM,OACf,CAAC,CACH,CAWU,EACV,EAAsB,CAAE,aAAY,OAAM,EAC1C,GAAI,CAMF,GALA,MAAM,EAAI,gBAAgB,EAAO,CAC/B,OAAQ,OACR,QAAS,OAAO,SAAS,OAAO,EAAQ,OAAO,CAAC,EAAI,OAAO,EAAQ,OAAO,EAAI,GAC9E,cAAe,OAAO,SAAS,OAAO,EAAQ,aAAa,CAAC,EAAI,OAAO,EAAQ,aAAa,EAAI,CAClG,CAAC,EACG,GAAqB,aAAe,EAAY,MAAU,MAAM,yCAAyC,EAC7G,MAAO,CAAE,QAAS,GAAM,UAAW,GAAM,aAAY,QAAO,KAAI,CAClE,OAAS,EAAO,CAGd,MAFI,GAAqB,aAAe,IAAY,EAAsB,MAC1E,EAAI,0BAA0B,EAAO,CAAU,EACzC,CACR,CACF,CAEA,IAAK,aAAc,CACjB,IAAM,EAAa,EAAQ,WAAa,OAAO,EAAQ,UAAU,EAAI,OACjE,EAAS,EAGb,GAFI,GAAc,GAAQ,aAAe,IAAY,EAAS,MAC1D,CAAC,GAAc,GAAQ,QAAU,IAAO,EAAS,MACjD,CAAC,EAAQ,MAAO,CAAE,QAAS,GAAM,QAAS,EAAM,EACpD,IAAI,EACJ,GAAI,CACF,MAAM,EAAI,eAAe,EAAO,KAAK,CACvC,OAAS,EAAO,CACd,EAAY,CACd,QAAU,CACJ,GAAqB,aAAe,EAAO,aAAY,EAAsB,MACjF,EAAI,0BAA0B,EAAO,MAAO,EAAO,UAAU,CAC/D,CACA,GAAI,EAAW,MAAM,EACrB,MAAO,CAAE,QAAS,GAAM,QAAS,GAAM,WAAY,EAAO,WAAY,MAAO,EAAO,KAAM,CAC5F,CAEA,IAAK,8BAA+B,CAClC,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAM,MAAM,OAAO,KAAK,IAAI,CAAK,EACnC,EACJ,GAAI,CACF,GAAI,EAAI,IAAK,CACX,IAAM,EAAS,IAAI,IAAI,EAAI,GAAG,GAC1B,EAAO,WAAa,SAAW,EAAO,WAAa,YAAU,EAAS,EAAO,OACnF,CACF,MAAQ,CAAC,CACT,MAAO,CAAE,QAAS,GAAM,SAAQ,IAAK,EAAI,GAAI,CAC/C,CAEA,IAAK,uBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,OADA,MAAM,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,uBAAwB,mBAAoB,EAAQ,qBAAuB,EAAK,EAAG,CAAE,QAAS,CAAE,CAAC,EACvI,CAAE,QAAS,EAAK,EAGzB,IAAK,sBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,OADA,MAAM,OAAO,KAAK,YAAY,EAAO,CAAE,KAAM,qBAAsB,EAAG,CAAE,QAAS,CAAE,CAAC,CAAC,CAAC,UAAY,CAAC,CAAC,EAC7F,CAAE,QAAS,EAAK,EAGzB,IAAK,uBAEH,OADA,EAAiB,CAAE,GAAG,EAAS,MAAO,EAAO,KAAK,GAAI,KAAM,sBAAuB,CAAC,EAC7E,CAAE,QAAS,EAAK,EAGzB,IAAK,wBAAyB,CAC5B,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,GAAI,CACE,EAAQ,WAAa,QAAa,EAAQ,eAAiB,QAAa,EAAQ,iBAAmB,OACrG,MAAM,EAAI,sBAAsB,EAAO,CAAE,SAAU,EAAQ,SAAU,aAAc,EAAQ,aAAc,WAAY,EAAQ,cAAe,CAAC,EACxI,MAAM,EAAI,sBAAsB,CAAK,CAC9C,MAAY,CAAC,CAIb,GAHA,MAAM,EAAI,mBAAmB,CAAK,EAG9B,EAAQ,KAAM,CAChB,IAAI,EAAU,EAAI,kBAAkB,EAAO,CACzC,WAAY,EAAQ,UACtB,CAAC,EAGG,EAAQ,SACV,EAAU,EAAQ,OAAO,GAAK,EAAE,SAAW,EAAQ,MAAM,GAEvD,EAAQ,SACV,EAAU,EAAQ,OAAO,GAAK,EAAE,SAAW,EAAQ,MAAM,GAEvD,EAAQ,cACV,EAAU,EAAQ,OAAO,GAAK,EAAE,OAAS,EAAQ,WAAW,GAG1D,EAAQ,OACV,EAAI,qBAAqB,CAAK,EAIhC,IAAM,EAAQ,EAAQ,OAAS,IAC/B,MAAO,CACL,QAAS,EAAQ,MAAM,EAAG,CAAK,EAC/B,OAAQ,EAAQ,OAChB,QAAS,EAAQ,OACnB,CACF,CAEA,IAAI,EAAW,EAAI,mBAAmB,EAAO,CAC3C,WAAY,EAAQ,WACpB,MAAO,EAAQ,OAAS,GAC1B,CAAC,EAiBD,OAdI,EAAQ,SACV,EAAW,EAAS,OAAO,GAAK,EAAE,SAAW,EAAQ,MAAM,GAEzD,EAAQ,SACV,EAAW,EAAS,OAAO,GAAK,EAAE,SAAW,EAAQ,MAAM,GAEzD,EAAQ,cACV,EAAW,EAAS,OAAO,GAAK,EAAE,OAAS,EAAQ,WAAW,GAG5D,EAAQ,OACV,EAAI,qBAAqB,CAAK,EAGzB,CACL,WACA,OAAQ,EAAQ,OAChB,QAAS,EAAQ,OACnB,CACF,CAEA,IAAK,0BAA2B,CAC9B,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,EAAQ,KAAO,EAAQ,MAAO,MAAU,MAAM,6CAA6C,EAC/F,GAAI,CACE,EAAQ,WAAa,QAAa,EAAQ,eAAiB,QAAa,EAAQ,iBAAmB,OACrG,MAAM,EAAI,sBAAsB,EAAO,CAAE,SAAU,EAAQ,SAAU,aAAc,EAAQ,aAAc,WAAY,EAAQ,cAAe,CAAC,EACxI,MAAM,EAAI,sBAAsB,CAAK,CAC9C,MAAY,CAAC,CACb,MAAM,EAAI,mBAAmB,CAAK,EAClC,IAAM,EAAU,EAAI,kBAAkB,EAAO,CAAC,CAAC,EAE/C,GADuB,IAAI,YAAY,CAAC,CAAC,OAAO,KAAK,UAAU,CAAO,CAAC,CAAC,CAAC,WACpD,SACnB,MAAU,MAAM,+DAA+D,EAEjF,MAAO,CAAE,UAAS,IAAK,EAAQ,EAAQ,IAAM,MAAO,EAAQ,EAAQ,KAAO,CAC7E,CAEA,IAAK,yBACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,OADA,EAAI,qBAAqB,CAAK,EACvB,CAAE,QAAS,EAAK,EAGzB,IAAK,sBAAuB,CAC1B,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,GAAI,CACF,MAAM,EAAI,sBAAsB,CAAK,CACvC,MAAY,CAAC,CACb,MAAM,EAAI,mBAAmB,CAAK,EAElC,IAAI,EAAU,EAAI,kBAAkB,EAAO,CACzC,WAAY,EAAQ,WACpB,cAAe,CAAC,EAAQ,aAC1B,CAAC,EA6BD,OA1BI,EAAQ,SACV,EAAU,EAAQ,OAAO,GAAK,EAAE,SAAW,EAAQ,MAAM,GAEvD,EAAQ,SACV,EAAU,EAAQ,OAAO,GAAK,EAAE,SAAW,EAAQ,MAAM,GAEvD,EAAQ,SACV,EAAU,EAAQ,OAAO,GAAK,EAAE,SAAW,EAAQ,MAAM,GAEvD,EAAQ,OACV,EAAU,EAAQ,OAAO,GAAK,EAAE,OAAS,EAAQ,IAAI,GAEnD,EAAQ,QACV,EAAU,EAAQ,OAAO,GAAK,EAAE,IAAM,EAAQ,KAAK,GAEjD,EAAQ,UAAY,SACtB,EAAU,EAAQ,OAAO,GAAK,EAAQ,QAAW,EAAE,kBAAoB,EAAE,iBAAmB,EAAK,CAAC,EAAE,gBAAgB,GAElH,EAAQ,OACV,EAAU,EAAQ,MAAM,CAAC,EAAQ,IAAI,GAGnC,EAAQ,OACV,EAAI,qBAAqB,CAAK,EAGzB,CAAE,SAAQ,CACnB,CAEA,IAAK,oBAAqB,CACxB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,UAAW,MAAU,MAAM,uBAAuB,EAC/D,MAAM,EAAI,mBAAmB,CAAK,EAGlC,IAAI,EAAQ,EAAI,gBAAgB,EAAO,EAAQ,SAAS,EAiBxD,MAdA,CAEE,IADgB,EAAI,kBAAkB,EAAO,CAAC,CACtC,EAAQ,KAAK,GAAK,EAAE,KAAO,EAAQ,SAAS,GAAK,KAI3D,CAEE,GADgB,EAAI,kBAAkB,EAAO,CAAC,CACtC,EAAQ,KAAK,GAAK,EAAE,aAAe,EAAQ,SAAS,GAAK,KAG9D,EAGE,CAAE,OAAM,EAFN,CAAE,MAAO,oBAAoB,EAAQ,WAAY,CAG5D,CAEA,IAAK,oBAAqB,CACxB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,UAAW,MAAU,MAAM,uBAAuB,EAC/D,MAAM,EAAI,mBAAmB,CAAK,EAGlC,IAAI,EAAe,EAAQ,UAC3B,GAAI,EAAQ,UAAU,WAAW,IAAI,EAAG,CAEtC,IAAM,EADU,EAAI,kBAAkB,EAAO,CAAC,CAChC,EAAQ,KAAK,GAAK,EAAE,KAAO,EAAQ,SAAS,EACtD,IACF,EAAe,EAAM,WAEzB,CAGA,OAAO,MADc,EAAI,gBAAgB,EAAO,CAAY,CAE9D,CAEA,IAAK,sBAAuB,CAC1B,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,MAAM,EAAI,mBAAmB,CAAK,EAElC,IAAM,EAAU,EAAI,kBAAkB,EAAO,CAAC,CAAC,EACzC,EAA6E,CAAC,EAEpF,IAAK,IAAM,KAAS,EACb,EAAQ,EAAM,UACjB,EAAQ,EAAM,QAAU,CAAE,MAAO,EAAG,SAAU,EAAG,KAAM,CAAE,GAE3D,EAAQ,EAAM,OAAO,CAAC,QACtB,EAAQ,EAAM,OAAO,CAAC,SAAW,KAAK,IAAI,EAAQ,EAAM,OAAO,CAAC,SAAU,EAAM,EAAE,EAClF,EAAQ,EAAM,OAAO,CAAC,MAAS,EAAM,kBAAoB,EAG3D,MAAO,CAAE,SAAQ,CACnB,CAEA,IAAK,oBAAqB,CACxB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,MAAM,EAAI,mBAAmB,CAAK,EAElC,IAAM,EAAU,EAAI,kBAAkB,EAAO,CAAC,CAAC,EACzC,EAAkC,CAAC,EACnC,EAAmC,CAAC,EACpC,EAAmC,CAAC,EACtC,EAAY,EACZ,EAAc,IACd,EAAc,EAElB,IAAK,IAAM,KAAS,EAAS,CAEtB,EAAQ,EAAM,UACjB,EAAQ,EAAM,QAAU,GAE1B,EAAQ,EAAM,OAAO,GAGrB,IAAM,EAAS,EAAM,QAAU,MAI/B,GAHA,EAAS,IAAW,EAAS,IAAW,GAAK,EAGzC,EAAM,OAAQ,CAChB,IAAM,EAAc,GAAG,KAAK,MAAM,EAAM,OAAS,GAAG,EAAE,IACtD,EAAS,IAAgB,EAAS,IAAgB,GAAK,CACzD,CAGA,GAAc,EAAM,kBAAoB,EAGpC,EAAM,GAAK,IAAa,EAAc,EAAM,IAC5C,EAAM,GAAK,IAAa,EAAc,EAAM,GAClD,CAEA,MAAO,CACL,MAAO,CACL,cAAe,EAAQ,OACvB,YACA,cAAe,OAAO,KAAK,CAAO,CAAC,CAAC,OACpC,UAAW,IAAgB,IAAW,KAAO,EAC7C,SAAW,GAAe,IAAgB,IAAY,EAAc,EAAc,EAClF,WACA,UACF,CACF,CACF,CAEA,IAAK,gBAAiB,CACpB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,EAAQ,QAAU,QAAa,EAAQ,SAAW,OACpD,MAAU,MAAM,0BAA0B,EAG5C,IAAM,EAAM,MAAM,OAAO,KAAK,IAAI,CAAK,EACvC,GAAI,CAAC,EAAI,SAAU,MAAU,MAAM,mBAAmB,EAEtD,IAAM,EACJ,EAAQ,QAAU,QAAa,EAAQ,SAAW,OAC9C,MAAM,OAAO,QAAQ,IAAI,EAAI,QAAQ,EACrC,KACA,EAAQ,EAAQ,QAAU,OAAY,GAAe,MAAQ,EAAQ,MACrE,EAAS,EAAQ,SAAW,OAAY,GAAe,OAAS,EAAQ,OAC9E,GAAI,IAAU,QAAa,IAAW,OACpC,MAAU,MAAM,iCAAiC,EAQnD,OALA,MAAM,OAAO,QAAQ,OAAO,EAAI,SAAU,CACxC,MAAO,KAAK,MAAM,CAAK,EACvB,OAAQ,KAAK,MAAM,CAAM,CAC3B,CAAC,EAEM,CAAE,QAAS,GAAM,QAAO,QAAO,CACxC,CAEA,IAAK,cAAe,CAClB,IAAM,EAAY,EAAQ,MAAM,OAAO,KAAK,IAAI,CAAK,EAAI,KAEnD,EAAS,MAAM,OAAO,KAAK,OAAO,CACtC,IAAK,EAAQ,KAAO,cACpB,OAAQ,EACV,CAAC,EAED,GAAI,CAAC,EAAO,GAAI,MAAU,MAAM,sBAAsB,EAMtD,OAJI,GAAW,SAAW,EAAU,UAAY,OAAO,UAAU,mBAC/D,MAAM,OAAO,KAAK,MAAM,CAAE,OAAQ,EAAO,GAAI,QAAS,EAAU,OAAQ,CAAC,EAGpE,CACL,QAAS,GACT,MAAO,EAAO,GACd,IAAK,EAAO,KAAO,EAAQ,KAAO,aACpC,CACF,CAEA,IAAK,eAAgB,CACnB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,aAAc,MAAU,MAAM,uBAAuB,EAClE,GAAI,CAAC,EAAQ,KAAO,CAAC,EAAQ,WAAY,MAAU,MAAM,4BAA4B,EAErF,IAAM,EAAa,GAAc,EAAQ,YAAY,EACrD,GAAI,CAAC,EAAY,MAAU,MAAM,yBAAyB,EAAQ,cAAc,EAEhF,GAAI,CASF,OAAO,MARc,OAAO,KAAK,YAAY,EAAO,CAClD,KAAM,eACN,OAAQ,EAAW,OACnB,IAAK,EAAQ,IACb,WAAY,EAAQ,WACpB,SAAU,EAAQ,UAAY,gBAChC,EAAG,CAAE,QAAS,EAAiB,EAAO,CAAO,CAAE,CAAC,CAGlD,MAAc,CACZ,MAAO,CAAE,MAAO,qDAAsD,CACxE,CACF,CAEA,IAAK,WAEH,MAAO,CACL,MAAM,MAFW,OAAO,KAAK,MAAM,CAAC,CAAC,GAE1B,IAAK,IAAO,CAAE,GAAI,EAAE,GAAI,MAAO,EAAE,MAAO,IAAK,EAAE,GAAI,EAAE,CAClE,EAGF,IAAK,YAAa,CAChB,IAAM,EAAsC,CAAC,EAM7C,OAJI,EAAQ,WACV,EAAa,SAAW,EAAQ,UAG3B,CACL,MAAM,MAFW,OAAO,KAAK,MAAM,CAAY,GAEpC,IAAK,IAAO,CACrB,GAAI,EAAE,GACN,MAAO,EAAE,MACT,IAAK,EAAE,IACP,OAAQ,EAAE,OACV,SAAU,EAAE,QACd,EAAE,CACJ,CACF,CAEA,IAAK,UAAW,CACd,IAAM,EAAO,EAAQ,OAAS,EAAQ,IAAM,CAAC,EAAQ,GAAG,EAAI,CAAC,aAAa,GACpE,EAAc,CAAC,EACrB,IAAK,IAAI,EAAI,EAAG,EAAI,EAAK,OAAQ,IAAK,CACpC,IAAM,EAA8C,CAClD,IAAK,EAAK,GACV,OAAQ,IAAM,CAChB,EAEI,EAAQ,WACV,EAAc,SAAW,EAAQ,UAEnC,IAAM,EAAS,MAAM,OAAO,KAAK,OAAO,CAAa,EACjD,EAAO,IAAI,EAAY,KAAK,CAAE,MAAO,EAAO,GAAI,IAAK,EAAK,EAAG,CAAC,CACpE,CAIA,OAHI,EAAY,SAAW,EAClB,CAAE,QAAS,GAAM,MAAO,EAAY,EAAE,CAAC,MAAO,IAAK,EAAY,EAAE,CAAC,GAAI,EAExE,CAAE,QAAS,GAAM,KAAM,CAAY,CAC5C,CAEA,IAAK,aAAc,CACjB,IAAM,EAAc,EAAQ,MAC5B,GAAI,CAAC,EAAa,MAAU,MAAM,mBAAmB,EACrD,IAAM,EAAO,MAAM,OAAO,KAAK,OAAO,EAAa,CAAE,OAAQ,EAAK,CAAC,EAInE,OAHI,EAAI,UACN,MAAM,OAAO,QAAQ,OAAO,EAAI,SAAU,CAAE,QAAS,EAAK,CAAC,EAEtD,CAAE,QAAS,GAAM,MAAO,EAAa,IAAK,EAAI,IAAK,MAAO,EAAI,KAAM,CAC7E,CAEA,IAAK,YAAa,CAChB,IAAM,EAAS,EAAQ,SAAW,EAAQ,MAAQ,CAAC,EAAQ,KAAK,EAAI,CAAC,GACrE,GAAI,EAAO,SAAW,EAAG,MAAU,MAAM,sBAAsB,EAK/D,OAJA,MAAM,OAAO,KAAK,OAAO,CAAM,EAC3B,EAAO,SAAW,EACb,CAAE,QAAS,GAAM,MAAO,EAAO,EAAG,EAEpC,CAAE,QAAS,GAAM,OAAQ,CAAO,CACzC,CAEA,IAAK,WAAY,CACf,IAAM,EAAY,EAAQ,SAAW,EAAQ,MAAQ,CAAC,EAAQ,KAAK,EAAI,CAAC,GAClE,GAAU,MAAM,QAAQ,CAAS,EAAI,EAAY,OAAO,CAAS,CAAC,CAAC,MAAM,GAAG,GAC/E,IAAK,GAAO,OAAO,CAAE,CAAC,EACzB,GAAI,EAAO,SAAW,EAAG,MAAU,MAAM,sBAAsB,EAC/D,GAAI,EAAO,KAAM,GAAO,CAAC,OAAO,UAAU,CAAE,GAAK,GAAM,CAAC,EACtD,MAAU,MAAM,kBAAkB,EAGpC,IAAM,EAAW,OAAO,EAAQ,QAAQ,EACxC,GAAI,CAAC,OAAO,UAAU,CAAQ,GAAK,GAAY,EAC7C,MAAU,MAAM,kCAAkC,EAGpD,IAAM,EAAQ,EAAQ,QAAU,OAAoC,GAAxB,OAAO,EAAQ,KAAK,EAChE,GAAI,CAAC,OAAO,UAAU,CAAK,GAAK,EAAQ,GAAI,MAAU,MAAM,mBAAmB,EAE/E,IAAM,EAAiB,CAAE,WAAU,OAAM,EACnC,EAAY,EAAO,SAAW,EAChC,MAAM,OAAO,KAAK,KAAK,EAAO,GAAI,CAAc,EAChD,MAAM,OAAO,KAAK,KAAK,EAAQ,CAAc,EAEjD,MAAO,CACL,QAAS,GACT,MAAO,EACP,oBAAqB,EACrB,QACA,KAAM,MAAM,QAAQ,CAAS,EAAI,EAAY,CAAC,CAAS,CACzD,CACF,CAEA,IAAK,gBAAiB,CACpB,IAAI,EAAc,EAClB,GAAI,CAAC,EAAa,CAChB,IAAM,EAAsC,EAAQ,SAChD,CAAE,OAAQ,GAAM,SAAU,EAAQ,QAAS,EAC3C,CAAE,OAAQ,GAAM,kBAAmB,EAAK,EACtC,CAAC,GAAa,MAAM,OAAO,KAAK,MAAM,CAAY,EACxD,GAAI,GAAa,CAAC,EAAmB,EAAU,GAAG,EAChD,EAAc,EAAU,QAExB,MAAU,MACR,8GACF,CAEJ,CACA,GAAI,CAAC,EAAa,MAAU,MAAM,qBAAqB,EACvD,GAAI,CAAC,EAAQ,KAAM,MAAU,MAAM,kBAAkB,EAErD,OADA,EAAgB,IAAI,EAAQ,KAAM,CAAW,EACtC,CAAE,QAAS,GAAM,KAAM,EAAQ,KAAM,MAAO,CAAY,CACjE,CAEA,IAAK,mBAAoB,CACvB,GAAI,CAAC,EAAQ,KAAM,MAAU,MAAM,kBAAkB,EACrD,IAAM,EAAkB,EAAgB,IAAI,EAAQ,IAAI,EACxD,GAAI,CAAC,EACH,MAAO,CAAE,MAAO,gCAAgC,EAAQ,KAAK,EAAG,EAElE,GAAI,CACF,IAAM,EAAM,MAAM,OAAO,KAAK,IAAI,CAAe,EACjD,MAAO,CAAE,MAAO,EAAiB,IAAK,EAAI,IAAK,MAAO,EAAI,KAAM,CAClE,MAAY,CAEV,OADA,EAAgB,OAAO,EAAQ,IAAI,EAC5B,CAAE,MAAO,QAAQ,EAAQ,KAAK,mBAAoB,CAC3D,CACF,CAEA,IAAK,kBAAmB,CACtB,IAAM,EAA6E,CAAC,EACpF,IAAK,GAAM,CAAC,EAAM,KAAO,EACvB,GAAI,CACF,IAAM,EAAM,MAAM,OAAO,KAAK,IAAI,CAAE,EACpC,EAAU,KAAK,CAAE,OAAM,MAAO,EAAI,IAAK,EAAI,IAAK,MAAO,EAAI,KAAM,CAAC,CACpE,MAAY,CACV,EAAgB,OAAO,CAAI,CAC7B,CAEF,MAAO,CAAE,KAAM,CAAU,CAC3B,CAEA,IAAK,kBACH,GAAI,CAAC,EAAQ,KAAM,MAAU,MAAM,kBAAkB,EAKrD,OAJgB,EAAgB,OAAO,EAAQ,IAC1C,EAGE,CAAE,QAAS,EAAK,EAFd,CAAE,QAAS,GAAO,MAAO,gCAAgC,EAAQ,KAAK,EAAG,EAKpF,IAAK,WAAY,CACf,GAAM,CAAE,sCAAF,IAAE,oBAAqB,wEAC7B,GAAI,CAEF,OAAO,MADc,EAAiB,CAAE,KAAM,UAAW,CAAC,CAE5D,MAAc,CACZ,MAAO,CACL,KAAM,KACN,KAAM,qEACR,CACF,CACF,CAEA,IAAK,qBAAsB,CACzB,GAAM,CAAE,sCAAF,IAAE,oBAAqB,wEAC7B,GAAI,CASF,OARA,MAAM,EAAiB,CACrB,KAAM,cACN,SAAU,EAAQ,SAClB,IAAK,EAAQ,IACb,OAAQ,EAAQ,OAChB,QAAS,EAAQ,QACjB,KAAM,EAAQ,IAChB,CAAC,EACM,CAAE,KAAM,EAAK,CACtB,OAAS,EAAK,CACZ,MAAO,CAAE,MAAO,aAAe,MAAQ,EAAI,QAAU,eAAgB,CACvE,CACF,CAEA,IAAK,iBAAkB,CACrB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAW,EAAQ,SAEzB,GAAI,CAmBF,OAlBA,MAAM,EAAI,sBAAsB,CAAK,EACrC,EAAiB,IAAI,EAAU,CAAK,EAEpC,EAAI,mBAAmB,EAAO,EAAW,GAAU,CACjD,EAAiB,CACf,KAAM,eACN,WACA,MAAO,CACL,KAAM,gBACN,MAAO,EAAM,OAAS,YAAc,QAAU,EAAM,KACpD,KAAM,EAAM,KACZ,UAAW,EAAM,UACjB,IAAK,EAAM,IACX,KAAM,EAAM,IACd,CACF,CAAC,CACH,CAAC,EAEM,CAAE,QAAS,GAAM,UAAW,EAAK,CAC1C,OAAS,EAAK,CAMZ,OALA,EAAiB,CACf,KAAM,eACN,WACA,MAAO,aAAe,MAAQ,EAAI,QAAU,gCAC9C,CAAC,EACM,CAAE,MAAO,aAAe,MAAQ,EAAI,QAAU,gCAAiC,CACxF,CACF,CAEA,IAAK,iBAAkB,CACrB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAW,EAAQ,SAEzB,GAAI,CAmBF,OAlBA,MAAM,EAAI,sBAAsB,CAAK,EACrC,EAAiB,IAAI,EAAU,CAAK,EAEpC,EAAI,mBAAmB,EAAO,EAAW,GAAU,CACjD,EAAiB,CACf,KAAM,eACN,WACA,MAAO,CACL,KAAM,gBACN,OAAQ,EAAM,OACd,IAAK,EAAM,IACX,OAAQ,EAAM,OACd,SAAU,EAAM,SAChB,UAAW,EAAM,SACnB,CACF,CAAC,CACH,CAAC,EAEM,CAAE,QAAS,GAAM,UAAW,EAAK,CAC1C,OAAS,EAAK,CAMZ,OALA,EAAiB,CACf,KAAM,eACN,WACA,MAAO,aAAe,MAAQ,EAAI,QAAU,gCAC9C,CAAC,EACM,CAAE,MAAO,aAAe,MAAQ,EAAI,QAAU,gCAAiC,CACxF,CACF,CAEA,IAAK,cAAe,CAClB,IAAM,EAAW,EAAQ,SACnB,EAAc,EAAiB,IAAI,CAAQ,EAQjD,OANI,IAAgB,SAClB,EAAI,uBAAuB,EAAa,CAAQ,EAChD,EAAI,uBAAuB,EAAa,CAAQ,EAChD,EAAiB,OAAO,CAAQ,GAG3B,CAAE,QAAS,EAAK,CACzB,CAEA,IAAK,cACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,GAAI,CAAC,EAAQ,KAAM,MAAU,MAAM,sBAAsB,EACzD,GAAI,CAOF,OAAO,MANc,OAAO,KAAK,YAAY,EAAO,CAClD,KAAM,cACN,KAAM,EAAQ,KACd,cAAe,EAAQ,eAAiB,GACxC,MAAO,EAAQ,OAAS,EAC1B,EAAG,CAAE,QAAS,EAAiB,EAAO,CAAO,CAAE,CAAC,CAElD,MAAQ,CACN,MAAO,CAAE,MAAO,qDAAsD,CACxE,CAGF,IAAK,mBAAoB,CACvB,IAAM,EAAmB,CAAC,GAAI,EAAQ,QAAU,CAAC,CAAE,EAC7C,EAAO,EAAQ,MAAQ,OAEvB,EAAQ,CADO,OAAQ,OAAQ,MAAO,SAAU,QAAS,OAAQ,SAAU,OAAQ,QAC3E,EAAY,SAAS,EAAQ,KAAK,EAAI,EAAQ,MAAQ,OAMpE,GAJI,EAAO,SAAW,GAAK,GACzB,EAAO,KAAK,CAAK,EAGf,EAAO,SAAW,EAAG,MAAU,MAAM,mBAAmB,EAC5D,IAAM,EAAc,EAAO,SAAW,EAAI,EAAO,GAAM,EAEjD,EAAiB,MAAM,OAAO,UAAU,MAAM,CAAE,MAAO,CAAK,CAAC,EAC/D,EAcJ,OAZI,EAAe,OAAS,GAC1B,EAAU,EAAe,EAAE,CAAC,GAC5B,MAAM,OAAO,KAAK,MAAM,CAAE,OAAQ,EAAa,SAAQ,CAAC,IAExD,EAAU,MAAM,OAAO,KAAK,MAAM,CAAE,OAAQ,CAAY,CAAC,EACzD,MAAM,OAAO,UAAU,OAAO,EAAS,CACrC,MAAO,EACA,QACP,UAAW,EACb,CAAC,GAGI,CAAE,QAAS,GAAM,UAAS,OAAM,QAAO,CAChD,CAEA,IAAK,mBAAoB,CACvB,IAAM,EAAmB,CAAC,GAAI,EAAQ,QAAU,CAAC,CAAE,EAKnD,GAJI,EAAO,SAAW,GAAK,GACzB,EAAO,KAAK,CAAK,EAGf,EAAO,SAAW,EAAG,MAAU,MAAM,mBAAmB,EAC5D,IAAM,EAAgB,EAAO,SAAW,EAAI,EAAO,GAAM,EAGzD,OADA,MAAM,OAAO,KAAK,QAAQ,CAAa,EAChC,CAAE,QAAS,GAAM,UAAW,CAAO,CAC5C,CAEA,IAAK,kBAAmB,CACtB,IAAM,EAAS,MAAM,OAAO,UAAU,MAAM,CAAC,CAAC,EACxC,EAAS,CAAC,EAEhB,IAAK,IAAM,KAAS,EAAQ,CAC1B,IAAM,EAAO,MAAM,OAAO,KAAK,MAAM,CAAE,QAAS,EAAM,EAAG,CAAC,EAC1D,EAAO,KAAK,CACV,GAAI,EAAM,GACV,KAAM,EAAM,OAAS,YACrB,MAAO,EAAM,MACb,UAAW,EAAM,UACjB,KAAM,EAAK,IAAI,IAAM,CAAE,GAAI,EAAE,GAAI,MAAO,EAAE,MAAO,IAAK,EAAE,GAAI,EAAE,CAChE,CAAC,CACH,CAEA,MAAO,CAAE,OAAQ,CAAO,CAC1B,CAEA,IAAK,iBAAkB,CACrB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAW,EAAQ,SACnB,EAAQ,EAAQ,OAAS,EACzB,EAAU,EAAiB,EAAO,CAAO,EAE/C,GAAI,EAAU,EAAG,CACf,GAAM,CAAC,GAAU,MAAM,OAAO,UAAU,cAAc,CACpD,OAAQ,CAAE,QAAO,SAAU,CAAC,CAAO,CAAE,EACrC,MAAO,EAAkB,IAAkB,CACzC,IAAM,EAAW,SAAS,iBAAiB,CAAQ,EAKnD,OAJI,EAAS,SAAW,EAAU,CAAE,MAAO,4BAA6B,EACpE,GAAS,EAAS,OAAe,CAAE,MAAO,SAAS,EAAM,uBAAuB,EAAS,OAAO,WAAY,GAEhH,EAAU,EAAM,CAAiB,MAAM,EAChC,CAAE,QAAS,GAAM,WAAU,QAAO,WAAY,EAAS,MAAO,EACvE,EACA,KAAM,CAAC,EAAU,CAAK,CACxB,CAAC,EACD,OAAO,GAAQ,QAAU,CAAE,MAAO,yBAA0B,CAC9D,CAEA,IAAM,EAAS;qDACgC,KAAK,UAAU,CAAQ,EAAE;;cAEhE,EAAM,kDAAkD,EAAM;;8BAE9C,EAAM;;;;;;;YAUxB,GAAS,MADM,EAAI,eAAe,EAAO,CAAM,GAC/B,QAAQ,MAM9B,OAJI,GAAQ,MAAc,CAAE,MAAO,EAAO,KAAM,EAC3C,GAEL,MAAM,EAAI,MAAM,EAAO,EAAO,EAAG,EAAO,EAAG,OAAQ,EAAG,CAAC,EAChD,CAAE,QAAS,GAAM,WAAU,QAAO,WAAY,EAAO,KAAM,GAH9C,CAAE,MAAO,mCAAoC,CAInE,CAEA,IAAK,cAAe,CAClB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,IAAM,GAAM,MADM,OAAO,KAAK,IAAI,CAAK,GACvB,IAChB,GAAI,CAAC,EAAK,MAAU,MAAM,gBAAgB,EAE1C,MAAO,CAAE,cADa,OAAO,QAAQ,OAAO,CAAE,KAAI,CAAC,CAClC,CACnB,CAEA,IAAK,aAAc,CACjB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,IAAM,GAAM,MADM,OAAO,KAAK,IAAI,CAAK,GACvB,IAChB,GAAI,CAAC,EAAK,MAAU,MAAM,gBAAgB,EAC1C,GAAI,CAAC,EAAQ,KAAM,MAAU,MAAM,sBAAsB,EACzD,IAAM,EAAS,MAAM,OAAO,QAAQ,IAAI,CAAE,MAAK,KAAM,EAAQ,IAAK,CAAC,EAEnE,OADK,EACE,CAAE,QAAO,EADI,CAAE,MAAO,WAAW,EAAQ,KAAK,YAAa,CAEpE,CAEA,IAAK,aAAc,CACjB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,IAAM,GAAM,MADM,OAAO,KAAK,IAAI,CAAK,GACvB,IAChB,GAAI,CAAC,EAAK,MAAU,MAAM,gBAAgB,EAC1C,GAAI,CAAC,EAAQ,KAAM,MAAU,MAAM,sBAAsB,EACzD,GAAI,EAAQ,QAAU,OAAW,MAAU,MAAM,uBAAuB,EAExE,IAAM,EAA2C,CAC/C,MACA,KAAM,EAAQ,KACd,MAAO,EAAQ,KACjB,EAEA,GAAI,EAAQ,QAAS,CACnB,IAAM,EAAiB,IAAI,KAAK,EAAQ,OAAO,CAAC,CAAC,QAAQ,EAAI,IAC7D,GAAI,MAAM,CAAc,EACtB,MAAU,MAAM,4BAA4B,EAAQ,SAAS,EAE/D,EAAc,eAAiB,CACjC,CAGA,MAAO,CAAE,QAAS,GAAM,OAAQ,MADX,OAAO,QAAQ,IAAI,CAAa,CACd,CACzC,CAEA,IAAK,eAAgB,CACnB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,IAAM,GAAM,MADM,OAAO,KAAK,IAAI,CAAK,GACvB,IAChB,GAAI,CAAC,EAAK,MAAU,MAAM,gBAAgB,EAC1C,GAAI,CAAC,EAAQ,KAAM,MAAU,MAAM,sBAAsB,EAGzD,OADA,MAAM,OAAO,QAAQ,OAAO,CAAE,MAAK,KAAM,EAAQ,IAAK,CAAC,EAChD,CAAE,QAAS,GAAM,QAAS,EAAQ,IAAK,CAChD,CAEA,IAAK,mBAAoB,CACvB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,IAAM,GAAM,MADM,OAAO,KAAK,IAAI,CAAK,GACvB,IAChB,GAAI,CAAC,EAAK,MAAU,MAAM,gBAAgB,EAE1C,IAAM,EAAU,MAAM,OAAO,QAAQ,OAAO,CAAE,KAAI,CAAC,EACnD,IAAK,IAAM,KAAU,EACnB,MAAM,OAAO,QAAQ,OAAO,CAAE,MAAK,KAAM,EAAO,IAAK,CAAC,EAExD,MAAO,CAAE,QAAS,GAAM,QAAS,EAAQ,MAAO,CAClD,CAEA,IAAK,aACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,OADA,MAAM,OAAO,KAAK,OAAO,EAAO,CAAE,YAAa,EAAQ,MAAQ,EAAM,CAAC,EAC/D,CAAE,QAAS,EAAK,EAGzB,IAAK,WACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,MAAO,CAAE,WADU,OAAO,KAAK,QAAQ,CAAK,CAC9B,EAGhB,IAAK,WAAY,CACf,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAQ,EAAQ,MACtB,GAAI,EAAQ,KAAQ,EAAQ,EAAG,MAAU,MAAM,uCAAuC,EAEtF,OADA,MAAM,OAAO,KAAK,QAAQ,EAAO,CAAK,EAC/B,CAAE,QAAS,GAAM,KAAM,CAAM,CACtC,CAEA,IAAK,aACH,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAE/C,OADA,MAAM,OAAO,KAAK,QAAQ,EAAO,CAAC,EAC3B,CAAE,QAAS,GAAM,KAAM,CAAI,EAGpC,IAAK,eAAgB,CACnB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAM,MAAM,OAAO,KAAK,IAAI,CAAK,EACjC,EAAkE,CACtE,MAAO,EAAI,OAAS,WACpB,IAAK,EAAI,GACX,EACA,GAAI,EAAQ,OAAQ,CAElB,IAAM,GAAS,MADM,OAAO,UAAU,OAAO,CAAE,MAAO,EAAQ,MAAO,CAAC,GAChD,KAAK,GAAK,CAAC,EAAE,GAAG,EAClC,IACF,EAAY,SAAW,EAAO,GAElC,CACA,IAAM,EAAW,MAAM,OAAO,UAAU,OAAO,CAAW,EAC1D,MAAO,CAAE,QAAS,GAAM,SAAU,CAAE,GAAI,EAAS,GAAI,MAAO,EAAS,MAAO,IAAK,EAAS,GAAI,CAAE,CAClG,CAEA,IAAK,kBAAmB,CACtB,GAAI,CAAC,EAAO,MAAU,MAAM,mBAAmB,EAC/C,IAAM,EAAM,MAAM,OAAO,KAAK,IAAI,CAAK,EACvC,GAAI,CAAC,EAAI,IAAK,MAAU,MAAM,gBAAgB,EAC9C,IAAM,EAAY,MAAM,OAAO,UAAU,OAAO,CAAE,IAAK,EAAI,GAAI,CAAC,EAChE,GAAI,EAAU,SAAW,EAAG,MAAU,MAAM,gCAAgC,EAE5E,OADA,MAAM,OAAO,UAAU,OAAO,EAAU,EAAE,CAAC,EAAE,EACtC,CAAE,QAAS,EAAK,CACzB,CAEA,IAAK,gBAAiB,CACpB,IAAM,EAAQ,OAAO,EAAQ,OAAU,SAAW,EAAQ,MAAQ,GAC9D,EAAiD,CAAC,EAEtD,GAAI,EAAQ,OAAQ,CAElB,IAAM,GAAS,MADM,OAAO,UAAU,OAAO,CAAE,MAAO,EAAQ,MAAO,CAAC,GAChD,KAAK,GAAK,CAAC,EAAE,GAAG,EAClC,IAEF,GAAY,MADW,OAAO,UAAU,YAAY,EAAO,EAAE,GACxC,OAAO,GAAK,EAAE,GAAG,CAAC,CAAC,MAAM,EAAG,CAAK,EAE1D,KAEE,GAAY,MADS,OAAO,UAAU,UAAU,CAAK,EAIvD,MAAO,CACL,UAAW,EAAU,IAAI,IAAM,CAC7B,GAAI,EAAE,GACN,MAAO,EAAE,MACT,IAAK,EAAE,IACP,UAAW,EAAE,SACf,EAAE,CACJ,CACF,CAEA,IAAK,eAAgB,CACnB,IAAM,EAAQ,OAAO,EAAQ,OAAU,SAAW,EAAQ,MAAQ,GAMlE,MAAO,CACL,SAAS,MANS,OAAO,QAAQ,OAAO,CACxC,KAAM,GACN,WAAY,EACZ,UAAW,CACb,CAAC,GAEgB,IAAI,IAAM,CACvB,IAAK,EAAE,IACP,MAAO,EAAE,MACT,cAAe,EAAE,cACjB,WAAY,EAAE,UAChB,EAAE,CACJ,CACF,CAEA,IAAK,iBAAkB,CACrB,IAAM,EAAQ,EAAQ,MAChB,EAAQ,OAAO,EAAQ,OAAU,SAAW,EAAQ,MAAQ,GAMlE,MAAO,CACL,SAAS,MANS,OAAO,QAAQ,OAAO,CACxC,KAAM,EACN,WAAY,EACZ,UAAW,CACb,CAAC,GAEgB,IAAI,IAAM,CACvB,IAAK,EAAE,IACP,MAAO,EAAE,MACT,cAAe,EAAE,cACjB,WAAY,EAAE,UAChB,EAAE,CACJ,CACF,CAEA,IAAK,sBAAuB,CAC1B,IAAM,EAAU,MAAM,OAAO,QAAQ,OAAO,CAAE,OAAQ,cAAe,CAAC,EAChE,EAAgB,MAAM,OAAO,QAAQ,OAAO,CAAE,OAAQ,aAAc,CAAC,EAC3E,MAAO,CAAE,QAAS,CAAC,GAAG,EAAS,GAAG,CAAa,CAAE,CACnD,CAEA,IAAK,kBAAmB,CACtB,IAAM,EAAM,MAAM,OAAO,KAAK,OAAO,CACnC,IAAK,uBACL,OAAQ,EACV,CAAC,EACD,GAAI,CAAC,EAAI,GAAI,MAAU,MAAM,sBAAsB,EAoBnD,OAlBI,MADqB,OAAO,KAAK,IAAI,EAAI,EAAE,GAChC,SAAW,YACxB,MAAM,IAAI,QAAe,GAAY,CACnC,IAAM,GAAY,EAAe,IAAoC,CAC/D,IAAU,EAAI,IAAM,EAAK,SAAW,aACtC,OAAO,KAAK,UAAU,eAAe,CAAQ,EAC7C,EAAQ,EAEZ,EACA,OAAO,KAAK,UAAU,YAAY,CAAQ,EAC1C,eAAiB,CACf,OAAO,KAAK,UAAU,eAAe,CAAQ,EAC7C,EAAQ,CACV,EAAG,GAAK,CACV,CAAC,EAEH,MAAM,EAAI,OAAO,EAAI,EAAE,EAEvB,MAAM,EAAoB,EAAI,GAAI,GAAK,EAChC,CAAE,MAAO,EAAI,EAAG,CACzB,CAEA,IAAK,oBAAqB,CACxB,IAAM,EAAY,EAAQ,MAC1B,GAAI,EAAW,CACb,GAAI,CACF,MAAM,EAAI,OAAO,CAAS,CAC5B,MAAQ,CAAC,CACT,GAAI,CACF,MAAM,OAAO,KAAK,OAAO,CAAS,CACpC,MAAQ,CAAC,CACX,CACA,MAAO,CAAE,QAAS,EAAK,CACzB,CAEA,IAAK,sBAAuB,CAC1B,GAAM,CAAE,SAAQ,UAAW,EAE3B,OAAO,MADc,EAAI,YAAY,EAAQ,MAAO,EAAQ,GAAU,CAAC,CAAC,CAE1E,CAEA,IAAK,mBAEH,OAAO,MADc,EAAI,eAAe,EAAQ,MAAO,EAAQ,UAAU,EAI3E,IAAK,qBAAsB,CACzB,IAAM,EAAM,MAAM,OAAO,KAAK,OAAO,CACnC,IAAK,6BACL,OAAQ,EACV,CAAC,EACD,GAAI,CAAC,EAAI,GAAI,MAAU,MAAM,sBAAsB,EAoBnD,OAlBI,MADqB,OAAO,KAAK,IAAI,EAAI,EAAE,GAChC,SAAW,YACxB,MAAM,IAAI,QAAe,GAAY,CACnC,IAAM,GAAY,EAAe,IAAoC,CAC/D,IAAU,EAAI,IAAM,EAAK,SAAW,aACtC,OAAO,KAAK,UAAU,eAAe,CAAQ,EAC7C,EAAQ,EAEZ,EACA,OAAO,KAAK,UAAU,YAAY,CAAQ,EAC1C,eAAiB,CACf,OAAO,KAAK,UAAU,eAAe,CAAQ,EAC7C,EAAQ,CACV,EAAG,GAAK,CACV,CAAC,EAEH,MAAM,EAAI,OAAO,EAAI,EAAE,EAEvB,MAAM,EAAoB,EAAI,GAAI,GAAK,EAChC,CAAE,MAAO,EAAI,EAAG,CACzB,CAEA,IAAK,uBAAwB,CAC3B,IAAM,EAAY,EAAQ,MAC1B,GAAI,EAAW,CACb,GAAI,CACF,MAAM,EAAI,OAAO,CAAS,CAC5B,MAAQ,CAAC,CACT,GAAI,CACF,MAAM,OAAO,KAAK,OAAO,CAAS,CACpC,MAAQ,CAAC,CACX,CACA,MAAO,CAAE,QAAS,EAAK,CACzB,CAEA,IAAK,yBAA0B,CAC7B,GAAM,CAAE,SAAQ,UAAW,EAE3B,OAAO,MADc,EAAI,YAAY,EAAQ,MAAO,EAAQ,GAAU,CAAC,CAAC,CAE1E,CAEA,IAAK,sBAEH,OAAO,MADc,EAAI,eAAe,EAAQ,MAAO,EAAQ,UAAU,EAI3E,IAAK,sBAAuB,CAE1B,IAAM,EAAU,CAAC,SAAU,eAAgB,QAAS,aAAa,EAC3D,EAAsC,CAAC,EAE7C,IAAK,IAAM,KAAU,EACnB,GAAI,CACF,IAAM,EAAU,MAAM,OAAO,QAAQ,OAAO,CAAE,QAAO,CAAC,EACtD,EAAW,KAAK,GAAG,CAAO,CAC5B,MAAQ,CAAC,CAKX,IAAK,IAAM,IAAO,CADJ,gBAAiB,qBACb,EAChB,GAAI,CACF,IAAM,EAAU,MAAM,OAAO,QAAQ,OAAO,CAAE,KAAI,CAAC,EACnD,EAAW,KAAK,GAAG,CAAO,CAC5B,MAAQ,CAAC,CAIX,IAAM,EAAO,IAAI,IACjB,IAAK,IAAM,KAAU,GAEf,CADa,EAAK,IAAI,EAAO,IAC5B,GAAY,EAAO,QAAQ,SAAS,OAAO,IAC9C,EAAK,IAAI,EAAO,KAAM,CAAM,EAIhC,MAAO,CAAE,QAAS,MAAM,KAAK,EAAK,OAAO,CAAC,CAAE,CAC9C,CAEA,IAAK,eAAgB,CACnB,IAAM,EAAM,MAAM,OAAO,KAAK,OAAO,CACnC,IAAK,uBACL,OAAQ,EACV,CAAC,EACD,GAAI,CAAC,EAAI,GAAI,MAAU,MAAM,sBAAsB,EAoBnD,OAlBI,MADqB,OAAO,KAAK,IAAI,EAAI,EAAE,GAChC,SAAW,YACxB,MAAM,IAAI,QAAe,GAAY,CACnC,IAAM,GAAY,EAAe,IAAoC,CAC/D,IAAU,EAAI,IAAM,EAAK,SAAW,aACtC,OAAO,KAAK,UAAU,eAAe,CAAQ,EAC7C,EAAQ,EAEZ,EACA,OAAO,KAAK,UAAU,YAAY,CAAQ,EAC1C,eAAiB,CACf,OAAO,KAAK,UAAU,eAAe,CAAQ,EAC7C,EAAQ,CACV,EAAG,GAAK,CACV,CAAC,EAEH,MAAM,EAAI,OAAO,EAAI,EAAE,EAEvB,MAAM,EAAoB,EAAI,GAAI,GAAK,EAChC,CAAE,MAAO,EAAI,EAAG,CACzB,CAEA,IAAK,iBAAkB,CACrB,IAAM,EAAY,EAAQ,MAC1B,GAAI,EAAW,CACb,GAAI,CACF,MAAM,EAAI,OAAO,CAAS,CAC5B,MAAQ,CAAC,CACT,GAAI,CACF,MAAM,OAAO,KAAK,OAAO,CAAS,CACpC,MAAQ,CAAC,CACX,CACA,MAAO,CAAE,QAAS,EAAK,CACzB,CAEA,IAAK,mBAAoB,CACvB,GAAM,CAAE,SAAQ,UAAW,EAE3B,OAAO,MADc,EAAI,YAAY,EAAQ,MAAO,EAAQ,GAAU,CAAC,CAAC,CAE1E,CAEA,IAAK,gBAEH,OAAO,MADc,EAAI,eAAe,EAAQ,MAAO,EAAQ,UAAU,EAI3E,IAAK,iBAAkB,CACrB,IAAM,EAAM,MAAM,OAAO,KAAK,OAAO,CACnC,IAAK,gCACL,OAAQ,EACV,CAAC,EACD,GAAI,CAAC,EAAI,GAAI,MAAU,MAAM,sBAAsB,EACnD,MAAO,CAAE,MAAO,EAAI,EAAG,CACzB,CAEA,IAAK,mBAAoB,CACvB,IAAM,EAAc,EAAQ,MAC5B,GAAI,EAAa,CACf,GAAI,CACF,MAAM,EAAI,OAAO,CAAW,CAC9B,MAAQ,CAAC,CACT,GAAI,CACF,MAAM,OAAO,KAAK,OAAO,CAAW,CACtC,MAAQ,CAAC,CACX,CACA,MAAO,CAAE,QAAS,EAAK,CACzB,CAEA,IAAK,wBACL,IAAK,qBAAsB,CACzB,GAAM,CAAE,MAAO,EAAa,aAAc,EACpC,EAAW,EAAQ,OAAS,qBAAuB,SAAW,EAAQ,SAC5E,GAAI,CAAC,GAAe,CAAC,GAAW,OAC9B,MAAU,MAAM,GAAG,EAAQ,KAAK,8BAA8B,EAEhE,GAAI,IAAa,UAAY,IAAa,UACxC,MAAU,MAAM,gCAAgC,GAAU,EAE5D,OAAO,GAAyB,EAAU,EAAa,CAAS,CAClE,CAEA,IAAK,mBAAoB,CACvB,IAAM,EAAW,EAAQ,IACzB,GAAI,CAAC,EAAU,MAAU,MAAM,iBAAiB,EAChD,IAAM,EAAO,MAAM,MAAM,EAAU,CAAE,YAAa,SAAU,CAAC,EAC7D,GAAI,CAAC,EAAK,GAAI,MAAU,MAAM,iBAAiB,EAAK,QAAQ,EAC5D,IAAM,EAAO,MAAM,EAAK,KAAK,EACvB,EAAS,IAAI,WAMnB,MAAO,CAAE,UALiB,IAAI,SAAS,EAAS,IAAW,CACzD,EAAO,WAAe,EAAS,EAAO,OAAkB,MAAM,GAAG,CAAC,CAAC,EAAE,EACrE,EAAO,YAAgB,EAAW,MAAM,mBAAmB,CAAC,EAC5D,EAAO,cAAc,CAAI,CAC3B,CAAC,EACa,KAAM,EAAK,KAAM,KAAM,EAAK,IAAK,CACjD,CAEA,IAAK,mBAAoB,CACvB,IAAM,EAAM,EAAQ,KAAO,+CACrB,EAAM,MAAM,OAAO,KAAK,OAAO,CAAE,MAAK,OAAQ,EAAK,CAAC,EAC1D,GAAI,CAAC,EAAI,GAAI,MAAU,MAAM,sBAAsB,EAmBnD,OAjBI,MADqB,OAAO,KAAK,IAAI,EAAI,EAAE,GAChC,SAAW,YACxB,MAAM,IAAI,QAAe,GAAY,CACnC,IAAM,GAAY,EAAe,IAAoC,CAC/D,IAAU,EAAI,IAAM,EAAK,SAAW,aACtC,OAAO,KAAK,UAAU,eAAe,CAAQ,EAC7C,EAAQ,EAEZ,EACA,OAAO,KAAK,UAAU,YAAY,CAAQ,EAC1C,eAAiB,CACf,OAAO,KAAK,UAAU,eAAe,CAAQ,EAC7C,EAAQ,CACV,EAAG,GAAK,CACV,CAAC,EAEH,MAAM,EAAI,OAAO,EAAI,EAAE,EACvB,MAAM,EAAoB,EAAI,GAAI,GAAK,EAChC,CAAE,MAAO,EAAI,EAAG,CACzB,CAEA,IAAK,qBAAsB,CACzB,IAAM,EAAgB,EAAQ,MAC9B,GAAI,EAAe,CACjB,GAAI,CAAE,MAAM,EAAI,OAAO,CAAa,CAAG,MAAQ,CAAC,CAChD,GAAI,CAAE,MAAM,OAAO,KAAK,OAAO,CAAa,CAAG,MAAQ,CAAC,CAC1D,CACA,MAAO,CAAE,QAAS,EAAK,CACzB,CAEA,IAAK,uBAAwB,CAC3B,GAAM,CAAE,SAAQ,UAAW,EAC3B,OAAO,MAAM,EAAI,YAAY,EAAQ,MAAO,EAAQ,GAAU,CAAC,CAAC,CAClE,CAEA,IAAK,oBACH,OAAO,MAAM,EAAI,eAAe,EAAQ,MAAO,EAAQ,UAAU,EAGnE,IAAK,mBAEH,MAAO,CACL,WAAW,MAFS,OAAO,UAAU,OAAO,EAAQ,cAAgB,CAAC,CAAC,GAEnD,IAAI,IAAM,CAC3B,GAAI,EAAE,GACN,SAAU,EAAE,SACZ,MAAO,EAAE,MACT,MAAO,EAAE,KACX,EAAE,CACJ,EAGF,IAAK,qBAAsB,CAEzB,IAAM,EAAU,CAAC,cAAe,qBAAsB,sBAAuB,gBAAgB,EACvF,EAAsC,CAAC,EAE7C,IAAK,IAAM,KAAU,EACnB,GAAI,CACF,IAAM,EAAU,MAAM,OAAO,QAAQ,OAAO,CAAE,QAAO,CAAC,EACtD,EAAW,KAAK,GAAG,CAAO,CAC5B,MAAQ,CAAC,CAKX,IAAK,IAAM,IAAO,CADJ,4BAA6B,8BAA+B,8BAA+B,wBACvF,EAChB,GAAI,CACF,IAAM,EAAU,MAAM,OAAO,QAAQ,OAAO,CAAE,KAAI,CAAC,EACnD,EAAW,KAAK,GAAG,CAAO,CAC5B,MAAQ,CAAC,CAIX,IAAM,EAAO,IAAI,IACjB,IAAK,IAAM,KAAU,EAAY,CAC/B,IAAM,EAAW,EAAK,IAAI,EAAO,IAAI,GACjC,CAAC,GACA,EAAO,SAAW,eAAiB,EAAO,OAAS,KACnD,CAAC,EAAS,QAAQ,SAAS,YAAY,GAAK,EAAO,QAAQ,SAAS,YAAY,IACnF,EAAK,IAAI,EAAO,KAAM,CAAM,CAEhC,CAEA,MAAO,CAAE,QAAS,MAAM,KAAK,EAAK,OAAO,CAAC,CAAE,CAC9C,CAEA,IAAK,aAAc,CAEjB,IAAM,EAAM,EAAQ,KAAO,+RAErB,EAA2C,CAC/C,QAAS,EAAQ,UAAY,GAC7B,KAAM,SACN,KACF,EAEI,EAAQ,OAAS,EAAQ,SAC3B,EAAc,MAAQ,EAAQ,MAC9B,EAAc,OAAS,EAAQ,QAG7B,EAAQ,YACV,EAAc,UAAY,IAG5B,IAAM,EAAU,MAAM,OAAO,QAAQ,OAAO,CAAa,EAEzD,GAAI,CAAC,EAAO,GAAI,MAAU,MAAM,yBAAyB,EAIzD,IAAM,GAAW,MADE,OAAO,KAAK,MAAM,CAAE,SAAU,EAAO,EAAG,CAAC,GACtC,GAOtB,OAJI,GAAU,IACZ,MAAM,IAAI,QAAQ,GAAK,WAAW,EAAG,GAAG,CAAC,EAGpC,CACL,QAAS,GACT,SAAU,EAAO,GACjB,MAAO,GAAU,GACjB,KAAM,mBAAmB,EAAO,GAAG,uBACrC,CACF,CAEA,IAAK,cAGH,MAAO,CACL,SAAS,MAHW,OAAO,QAAQ,OAAO,CAAE,SAAU,EAAK,CAAC,GAG3C,IAAI,IAAM,CACzB,GAAI,EAAE,GACN,QAAS,EAAE,QACX,KAAM,EAAE,KACR,MAAO,EAAE,MACT,MAAO,EAAE,MACT,OAAQ,EAAE,OACV,SAAU,EAAE,MAAM,QAAU,EAC5B,KAAM,EAAQ,YAAc,EAAE,MAAM,IAAI,IAAM,CAC5C,GAAI,EAAE,GACN,MAAO,EAAE,MACT,IAAK,EAAE,IACP,OAAQ,EAAE,MACZ,EAAE,EAAI,MACR,EAAE,CACJ,EAGF,IAAK,eACH,GAAI,CAAC,EAAQ,SAAU,MAAU,MAAM,sBAAsB,EAG7D,OADA,MAAM,OAAO,QAAQ,OAAO,EAAQ,SAAU,CAAE,QAAS,EAAK,CAAC,EACxD,CAAE,QAAS,GAAM,SAAU,EAAQ,QAAS,EAGrD,IAAK,eACH,GAAI,CAAC,EAAQ,SAAU,MAAU,MAAM,sBAAsB,EAG7D,OADA,MAAM,OAAO,QAAQ,OAAO,EAAQ,QAAQ,EACrC,CAAE,QAAS,GAAM,SAAU,EAAQ,QAAS,EAGrD,IAAK,gBAAiB,CACpB,GAAI,CAAC,EAAQ,SAAU,MAAU,MAAM,sBAAsB,EAE7D,IAAM,EAAwC,CAAC,EAC3C,EAAQ,QAAO,EAAW,MAAQ,EAAQ,OAC1C,EAAQ,SAAQ,EAAW,OAAS,EAAQ,QAC5C,EAAQ,OAAS,SAAW,EAAW,KAAO,EAAQ,MACtD,EAAQ,MAAQ,SAAW,EAAW,IAAM,EAAQ,KACpD,EAAQ,QAAO,EAAW,MAAQ,EAAQ,OAE9C,IAAM,EAAU,MAAM,OAAO,QAAQ,OAAO,EAAQ,SAAU,CAAU,EACxE,MAAO,CACL,QAAS,GACT,SAAU,EAAQ,SAClB,MAAO,EAAO,MACd,OAAQ,EAAO,MACjB,CACF,CAEA,QACE,MAAU,MAAM,yBAAyB,EAAQ,MAAM,CAC3D,CACF,CAEA,OAAO,QAAQ,YAAY,YAAa,GAAY,CAClD,EAAS,+BAAgC,EAAQ,MAAM,CACzD,CAAC,EAED,IAAM,GAAuB,IAAI,IAAI,+7BAgBrC,CAAC,EAED,EAAoB,KAAO,IAAQ,CACjC,IAAI,EAAQ,EAAI,MACV,EAAW,EAAI,SACf,EAAkB,EAAI,MAAM,WAAW,SAAS,EAChD,EAAW,CAAC,GAAqB,IAAI,EAAI,IAAI,EAC/C,EAAiB,GAErB,GAAI,GAAS,CAAC,GAAmB,CAAC,GAAqB,IAAI,EAAI,IAAI,EACjE,GAAI,CACF,MAAM,OAAO,KAAK,IAAI,CAAK,CAC7B,MAAQ,CACN,MAAM,IAAI,EAAoB,WAAY,OAAO,EAAM,mBAAoB,CAAE,OAAM,CAAC,CACtF,MACK,GAAI,CAAC,GAAS,EAAU,CAC7B,GAAI,EAAI,aACN,MAAM,IAAI,EAAoB,kBAAmB,yDAAyD,EAE5G,IAAM,EAAW,MAAM,EAAqB,EAAU,EAAI,EAC1D,EAAQ,EAAS,IAAI,GACrB,EAAiB,EAAS,WAC5B,CAEI,GAAS,EAAI,UAAY,QAAW,MAAM,GAAuB,EAAO,EAAI,OAAO,EACvF,IAAM,EAAS,MAAM,GAAc,CAAE,GAAG,EAAK,OAAM,EAAG,CAAC,CAAiC,EAClF,EAAkB,CAAC,EACrB,GACF,EAAM,KAAK,8BAA8B,EAAS,wDAAwD,EAE5G,IAAI,EACJ,GAAI,EACF,GAAI,CAAE,GAAoB,MAAM,OAAO,KAAK,IAAI,CAAK,GAAG,QAAU,MAAQ,CAAC,CAG7E,MAAO,CACL,GAAG,EACH,eAAgB,EAChB,kBAAmB,EACnB,MAAO,EAAM,OAAS,EAAI,EAAM,KAAK,GAAG,EAAI,MAC9C,CACF,EAAG,EAA0B","names":[],"ignoreList":[],"sources":["../../src/cdp/controller.ts","../../src/utils/debug.ts","../../src/utils/frame-diagnose.ts","../../src/utils/readiness-poll.ts","../../src/native/port-manager.ts","../../src/service-worker/index.ts"],"sourcesContent":["type Debuggee = chrome.debugger.Debuggee;\ntype MouseButton = \"left\" | \"right\" | \"middle\" | \"none\";\n\nclass CDPControllerError extends Error {\n code: string;\n details?: Record<string, unknown>;\n\n constructor(code: string, message: string, details?: Record<string, unknown>) {\n super(message);\n this.name = \"CDPControllerError\";\n this.code = code;\n this.details = details;\n }\n}\n\nexport interface DebuggerCommandError extends Error {\n /** CDP error code (for example -32000) when the browser reported one. */\n cdpCode?: number;\n /** The CDP method that failed. */\n cdpMethod?: string;\n}\n\n/**\n * `chrome.debugger.sendCommand` rejects with the CDP error serialised as\n * JSON in the message (`{\"code\":-32000,\"message\":\"Inspected target navigated\n * or closed\"}`). Surface the message itself and keep the code as a property,\n * so callers and users see \"Inspected target navigated or closed\" instead\n * of a JSON blob. Anything that is not such a JSON object passes through.\n */\nexport function describeDebuggerError(err: unknown, method?: string): Error {\n const raw = err instanceof Error ? err.message : String(err);\n const trimmed = raw.trim();\n if (trimmed.startsWith(\"{\") && trimmed.endsWith(\"}\")) {\n try {\n const parsed = JSON.parse(trimmed) as { code?: unknown; message?: unknown };\n if (parsed && typeof parsed.message === \"string\" && parsed.message.length > 0) {\n const error = new Error(parsed.message, { cause: err }) as DebuggerCommandError;\n if (typeof parsed.code === \"number\") error.cdpCode = parsed.code;\n if (method) error.cdpMethod = method;\n return error;\n }\n } catch {\n // not JSON after all; fall through\n }\n }\n return err instanceof Error ? err : new Error(raw);\n}\n\ninterface ConsoleMessage {\n type: string;\n text: string;\n timestamp: number;\n url?: string;\n line?: number;\n}\n\ninterface NetworkRequest {\n requestId: string;\n url: string;\n method: string;\n status?: number;\n type?: string;\n timestamp: number;\n requestHeaders?: Record<string, string>;\n requestBody?: string;\n responseHeaders?: Record<string, string>;\n responseBody?: string;\n mimeType?: string;\n duration?: number;\n}\n\nexport interface NetworkEntry {\n id: string; // \"r_<timestamp>_<seq>\"\n ts: number; // Request start timestamp (ms)\n duration?: number; // Total time (ms)\n ttfb?: number; // Time to first byte (ms)\n \n // Request\n method: string;\n url: string;\n origin: string; // Extracted from URL\n requestHeaders: Record<string, string>;\n requestBody?: string; // POST/PUT body\n requestBodySize?: number;\n \n // Response \n status?: number;\n statusText?: string;\n mimeType?: string;\n responseHeaders?: Record<string, string>;\n responseBody?: string; // Will be fetched via getResponseBody\n responseBodyEncoding?: \"base64\";\n responseBodySize?: number;\n bodyCapture: { mode: \"none\" | \"text\" | \"all\"; complete: boolean; reason?: string; capturedBytes?: number };\n \n // Metadata\n tabId: number;\n tabUrl?: string; // Page URL that initiated request\n type?: string; // \"xhr\", \"fetch\", \"document\", etc.\n \n // Flags\n flags: string[]; // [\"binary\", \"truncated\", \"protobuf\", \"failed\"]\n \n // Internal tracking\n _requestId: string; // CDP requestId for lazy loading\n _responseReceived: boolean; // Whether response was received\n _loadingFinished: boolean; // Whether loading finished\n}\n\ninterface PendingDialog {\n type: \"alert\" | \"confirm\" | \"prompt\" | \"beforeunload\";\n message: string;\n defaultPrompt?: string;\n timestamp: number;\n}\n\ntype ConsoleEventCallback = (event: ConsoleMessage) => void;\ntype NetworkEventCallback = (event: {\n method: string;\n url: string;\n status?: number;\n duration?: number;\n timestamp: number;\n}) => void;\n\ntype ScreencastFrameCallback = (event: {\n data: string;\n metadata?: Record<string, unknown>;\n sessionId: number;\n}) => void;\n\ntype ScreencastErrorCallback = (error: Error) => void;\n\nconst MODIFIERS = {\n alt: 1,\n ctrl: 2,\n control: 2,\n meta: 4,\n cmd: 4,\n command: 4,\n win: 4,\n windows: 4,\n shift: 8,\n} as const;\n\ninterface KeyDefinition {\n key: string;\n code: string;\n keyCode: number;\n text?: string;\n location?: number;\n}\n\nconst KEY_DEFINITIONS: Record<string, KeyDefinition> = {\n enter: { key: \"Enter\", code: \"Enter\", keyCode: 13, text: \"\\r\" },\n tab: { key: \"Tab\", code: \"Tab\", keyCode: 9 },\n escape: { key: \"Escape\", code: \"Escape\", keyCode: 27 },\n backspace: { key: \"Backspace\", code: \"Backspace\", keyCode: 8 },\n delete: { key: \"Delete\", code: \"Delete\", keyCode: 46 },\n arrowup: { key: \"ArrowUp\", code: \"ArrowUp\", keyCode: 38 },\n arrowdown: { key: \"ArrowDown\", code: \"ArrowDown\", keyCode: 40 },\n arrowleft: { key: \"ArrowLeft\", code: \"ArrowLeft\", keyCode: 37 },\n arrowright: { key: \"ArrowRight\", code: \"ArrowRight\", keyCode: 39 },\n home: { key: \"Home\", code: \"Home\", keyCode: 36 },\n end: { key: \"End\", code: \"End\", keyCode: 35 },\n pageup: { key: \"PageUp\", code: \"PageUp\", keyCode: 33 },\n pagedown: { key: \"PageDown\", code: \"PageDown\", keyCode: 34 },\n space: { key: \" \", code: \"Space\", keyCode: 32, text: \" \" },\n f1: { key: \"F1\", code: \"F1\", keyCode: 112 },\n f2: { key: \"F2\", code: \"F2\", keyCode: 113 },\n f3: { key: \"F3\", code: \"F3\", keyCode: 114 },\n f4: { key: \"F4\", code: \"F4\", keyCode: 115 },\n f5: { key: \"F5\", code: \"F5\", keyCode: 116 },\n f6: { key: \"F6\", code: \"F6\", keyCode: 117 },\n f7: { key: \"F7\", code: \"F7\", keyCode: 118 },\n f8: { key: \"F8\", code: \"F8\", keyCode: 119 },\n f9: { key: \"F9\", code: \"F9\", keyCode: 120 },\n f10: { key: \"F10\", code: \"F10\", keyCode: 121 },\n f11: { key: \"F11\", code: \"F11\", keyCode: 122 },\n f12: { key: \"F12\", code: \"F12\", keyCode: 123 },\n};\n\nexport class CDPController {\n private static readonly SCREENSHOT_TIMEOUT_MS = 5000;\n private targets = new Map<number, Debuggee>();\n private consoleMessages: Map<number, ConsoleMessage[]> = new Map();\n private networkRequests: Map<number, NetworkRequest[]> = new Map();\n private networkEntries: Map<number, Map<string, NetworkEntry>> = new Map(); // tabId -> requestId -> entry\n private consoleCallbacks: Map<number, Map<number, ConsoleEventCallback>> = new Map();\n private networkCallbacks: Map<number, Map<number, NetworkEventCallback>> = new Map();\n private screencastCallbacks: Map<number, Map<string, { onFrame: ScreencastFrameCallback; onError: ScreencastErrorCallback }>> = new Map();\n private networkRequestStartTimes: Map<string, number> = new Map();\n private pendingDialogs: Map<number, PendingDialog> = new Map();\n private detachReasons: Map<number, string> = new Map();\n private networkEntrySeq = 0; // Sequence counter for unique IDs\n private networkBodyBytes: Map<number, number> = new Map();\n private networkCapture: Map<number, { mode: \"none\" | \"text\" | \"all\"; perBodyBytes: number; totalBytes: number }> = new Map();\n private networkEventQueue: Map<number, Promise<void>> = new Map();\n private static debuggerListenerRegistered = false;\n\n // Body fetch settings\n private static readonly DEFAULT_PER_BODY_BYTES = 64 * 1024;\n private static readonly DEFAULT_TOTAL_BODY_BYTES = 2 * 1024 * 1024;\n private static readonly STATIC_ASSET_TYPES = new Set([\n 'image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/svg+xml', 'image/x-icon',\n 'font/woff', 'font/woff2', 'font/ttf', 'font/otf', 'application/font-woff', 'application/font-woff2',\n 'text/css', 'application/javascript', 'text/javascript', 'application/x-javascript',\n ]);\n private static readonly BINARY_TYPES = new Set([\n 'image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/x-icon',\n 'font/woff', 'font/woff2', 'font/ttf', 'font/otf', 'application/font-woff', 'application/font-woff2',\n 'application/octet-stream', 'application/pdf', 'application/zip',\n 'audio/mpeg', 'audio/wav', 'audio/ogg',\n 'video/mp4', 'video/webm', 'video/ogg',\n ]);\n\n async attach(tabId: number): Promise<void> {\n if (this.targets.has(tabId)) return;\n \n const target: Debuggee = { tabId };\n try {\n await chrome.debugger.attach(target, \"1.3\");\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n if (/already attached/i.test(message)) {\n throw new CDPControllerError(\n \"debugger_busy\",\n `Another debugger already controls tab ${tabId}. Close DevTools or the competing debugger and retry.`,\n { tabId },\n );\n }\n if (message.includes(\"Cannot access\") || message.includes(\"Cannot attach\")) {\n throw new CDPControllerError(\n \"restricted_target\",\n \"Cannot control this page. Chrome restricts automation on chrome://, extensions, and web store pages.\",\n { tabId },\n );\n }\n throw new CDPControllerError(\"debugger_attach_failed\", `Failed to attach debugger: ${message}`, { tabId });\n }\n this.targets.set(tabId, target);\n this.detachReasons.delete(tabId);\n\n this.setupEventListener();\n this.consoleMessages.set(tabId, []);\n this.networkRequests.set(tabId, []);\n\n try {\n await this.send(tabId, \"Page.enable\");\n } catch (e) {}\n }\n\n isAttached(tabId: number): boolean {\n return this.targets.has(tabId);\n }\n\n async detach(tabId: number): Promise<{ success: boolean; error?: string }> {\n const target = this.targets.get(tabId);\n let error: string | undefined;\n if (target) {\n try {\n await chrome.debugger.detach(target);\n } catch (e) {\n error = e instanceof Error ? e.message : String(e);\n console.warn(\"[CDPController] Error detaching:\", e);\n }\n this.targets.delete(tabId);\n this.consoleMessages.delete(tabId);\n this.networkRequests.delete(tabId);\n this.networkEntries.delete(tabId);\n this.networkBodyBytes.delete(tabId);\n this.networkCapture.delete(tabId);\n this.consoleCallbacks.delete(tabId);\n this.networkCallbacks.delete(tabId);\n this.notifyScreencastError(tabId, new CDPControllerError(\n \"debugger_detached\",\n `Debugger detached from tab ${tabId}`,\n { tabId },\n ));\n this.screencastCallbacks.delete(tabId);\n this.pendingDialogs.delete(tabId);\n this.clearRequestStartTimes(tabId);\n this.detachReasons.delete(tabId);\n }\n return error ? { success: false, error } : { success: true };\n }\n\n async detachAll(): Promise<void> {\n for (const tabId of this.targets.keys()) {\n await this.detach(tabId);\n }\n }\n\n private setupEventListener(): void {\n if (CDPController.debuggerListenerRegistered) return;\n CDPController.debuggerListenerRegistered = true;\n\n chrome.debugger.onEvent.addListener((source, method, params) => {\n const tabId = source.tabId;\n if (!tabId || !this.targets.has(tabId)) return;\n\n this.enqueueCDPEvent(tabId, method, params);\n });\n\n chrome.debugger.onDetach.addListener((source, reason) => {\n const tabId = source.tabId;\n if (tabId && this.targets.has(tabId)) {\n this.detachReasons.set(tabId, reason || \"unknown\");\n this.targets.delete(tabId);\n this.consoleMessages.delete(tabId);\n this.networkRequests.delete(tabId);\n this.networkEntries.delete(tabId);\n this.networkBodyBytes.delete(tabId);\n this.networkCapture.delete(tabId);\n this.consoleCallbacks.delete(tabId);\n this.networkCallbacks.delete(tabId);\n this.notifyScreencastError(tabId, new CDPControllerError(\n \"debugger_detached\",\n `Debugger detached from tab ${tabId}: ${reason || \"unknown reason\"}`,\n { tabId, reason: reason || \"unknown\" },\n ));\n this.screencastCallbacks.delete(tabId);\n this.pendingDialogs.delete(tabId);\n this.clearRequestStartTimes(tabId);\n }\n });\n }\n\n private requestStartKey(tabId: number, requestId: string): string {\n return `${tabId}:${requestId}`;\n }\n\n private clearRequestStartTimes(tabId: number): void {\n const prefix = `${tabId}:`;\n for (const key of this.networkRequestStartTimes.keys()) {\n if (key.startsWith(prefix)) this.networkRequestStartTimes.delete(key);\n }\n }\n\n private enqueueCDPEvent(tabId: number, method: string, params: any): void {\n const previous = this.networkEventQueue.get(tabId) || Promise.resolve();\n const next = previous\n .catch(() => undefined)\n .then(() => this.handleCDPEvent(tabId, method, params))\n .catch(() => undefined);\n this.networkEventQueue.set(tabId, next);\n next.finally(() => {\n if (this.networkEventQueue.get(tabId) === next) this.networkEventQueue.delete(tabId);\n });\n }\n\n async drainNetworkEvents(tabId: number): Promise<void> {\n await this.networkEventQueue.get(tabId);\n }\n\n private async handleCDPEvent(tabId: number, method: string, params: any): Promise<void> {\n switch (method) {\n case \"Runtime.consoleAPICalled\":\n this.handleRuntimeConsole(tabId, params);\n break;\n case \"Runtime.exceptionThrown\":\n this.handleRuntimeException(tabId, params);\n break;\n case \"Network.requestWillBeSent\":\n this.handleNetworkRequest(tabId, params);\n break;\n case \"Network.responseReceived\":\n this.handleNetworkResponse(tabId, params);\n break;\n case \"Network.loadingFailed\":\n this.handleNetworkFailed(tabId, params);\n break;\n case \"Network.loadingFinished\":\n await this.handleLoadingFinished(tabId, params);\n break;\n case \"Page.javascriptDialogOpening\":\n this.handleDialogOpening(tabId, params);\n break;\n case \"Page.javascriptDialogClosed\":\n this.pendingDialogs.delete(tabId);\n break;\n case \"Page.screencastFrame\":\n await this.handleScreencastFrame(tabId, params);\n break;\n }\n }\n\n private async handleScreencastFrame(tabId: number, params: any): Promise<void> {\n const sessionId = Number(params?.sessionId);\n if (!Number.isInteger(sessionId)) return;\n\n // ACK before forwarding the JPEG. Chrome stops sending frames when these\n // acknowledgements are delayed, so the frame path deliberately does not\n // wait on native messaging or callback work.\n try {\n await this.send(tabId, \"Page.screencastFrameAck\", { sessionId });\n } catch (error) {\n this.notifyScreencastError(tabId, error instanceof Error ? error : new Error(String(error)));\n return;\n }\n\n const callbacks = this.screencastCallbacks.get(tabId);\n if (!callbacks) return;\n const event = {\n data: typeof params?.data === \"string\" ? params.data : \"\",\n metadata: params?.metadata,\n sessionId,\n };\n for (const callback of callbacks.values()) {\n try { callback.onFrame(event); } catch {}\n }\n }\n\n private notifyScreencastError(tabId: number, error: Error): void {\n const callbacks = this.screencastCallbacks.get(tabId);\n if (!callbacks) return;\n for (const callback of callbacks.values()) {\n try { callback.onError(error); } catch {}\n }\n }\n\n private handleRuntimeConsole(tabId: number, params: any): void {\n const messages = this.consoleMessages.get(tabId) || [];\n const args = params.args || [];\n\n const text = args\n .map((a: any) => {\n if (a.value !== undefined) return String(a.value);\n if (a.description) return a.description;\n return \"\";\n })\n .join(\" \");\n\n const callFrame = params.stackTrace?.callFrames?.[0];\n\n const msg: ConsoleMessage = {\n type: params.type || \"log\",\n text,\n timestamp: params.timestamp || Date.now(),\n url: callFrame?.url,\n line: callFrame?.lineNumber,\n };\n\n messages.push(msg);\n if (messages.length > 1000) messages.shift();\n this.consoleMessages.set(tabId, messages);\n\n const callbacks = this.consoleCallbacks.get(tabId);\n if (callbacks) {\n for (const cb of callbacks.values()) {\n cb(msg);\n }\n }\n }\n\n private handleRuntimeException(tabId: number, params: any): void {\n const messages = this.consoleMessages.get(tabId) || [];\n const details = params.exceptionDetails;\n if (!details) return;\n\n const msg: ConsoleMessage = {\n type: \"exception\",\n text: details.exception?.description || details.text || \"Unknown exception\",\n timestamp: details.timestamp || Date.now(),\n url: details.url,\n line: details.lineNumber,\n };\n\n messages.push(msg);\n if (messages.length > 1000) messages.shift();\n this.consoleMessages.set(tabId, messages);\n\n const callbacks = this.consoleCallbacks.get(tabId);\n if (callbacks) {\n for (const cb of callbacks.values()) {\n cb(msg);\n }\n }\n }\n\n private handleNetworkRequest(tabId: number, params: any): void {\n const requests = this.networkRequests.get(tabId) || [];\n const req = params.request;\n if (!req) return;\n\n const timestamp = params.timestamp ? params.timestamp * 1000 : Date.now();\n this.networkRequestStartTimes.set(this.requestStartKey(tabId, params.requestId), timestamp);\n\n // Legacy format for backward compatibility\n const reqHeaders: Record<string, string> = {};\n if (req.headers) {\n for (const [key, value] of Object.entries(req.headers)) {\n reqHeaders[key] = String(value);\n }\n }\n\n requests.push({\n requestId: params.requestId,\n url: req.url,\n method: req.method,\n type: params.type,\n timestamp,\n requestHeaders: reqHeaders,\n requestBody: req.postData,\n });\n\n if (requests.length > 500) requests.shift();\n this.networkRequests.set(tabId, requests);\n\n // Full NetworkEntry format\n if (!this.networkEntries.has(tabId)) {\n this.networkEntries.set(tabId, new Map());\n }\n const entriesMap = this.networkEntries.get(tabId)!;\n \n // Generate unique ID\n const seq = ++this.networkEntrySeq;\n const entryId = `r_${timestamp}_${seq}`;\n\n // Extract headers as Record\n const requestHeaders: Record<string, string> = {};\n if (req.headers) {\n for (const [key, value] of Object.entries(req.headers)) {\n requestHeaders[key] = String(value);\n }\n }\n\n // Extract request body info\n const requestBody = req.postData;\n const requestBodySize = requestBody ? requestBody.length : undefined;\n\n const entry: NetworkEntry = {\n id: entryId,\n ts: timestamp,\n method: req.method,\n url: req.url,\n origin: this.extractOrigin(req.url),\n requestHeaders,\n requestBody,\n requestBodySize,\n tabId,\n tabUrl: params.documentURL,\n type: params.type,\n flags: [],\n bodyCapture: { mode: this.networkCapture.get(tabId)?.mode || \"none\", complete: false, reason: \"pending\" },\n _requestId: params.requestId,\n _responseReceived: false,\n _loadingFinished: false,\n };\n\n // Limit entries per tab\n if (entriesMap.size > 500) {\n const oldestKey = entriesMap.keys().next().value;\n if (oldestKey) entriesMap.delete(oldestKey);\n }\n \n entriesMap.set(params.requestId, entry);\n }\n\n private handleNetworkResponse(tabId: number, params: any): void {\n const requests = this.networkRequests.get(tabId) || [];\n const existing = requests.find((r) => r.requestId === params.requestId);\n if (existing) {\n existing.status = params.response?.status;\n existing.mimeType = params.response?.mimeType;\n\n // Capture response headers\n if (params.response?.headers) {\n const respHeaders: Record<string, string> = {};\n for (const [key, value] of Object.entries(params.response.headers)) {\n respHeaders[key] = String(value);\n }\n existing.responseHeaders = respHeaders;\n }\n\n const callbacks = this.networkCallbacks.get(tabId);\n if (callbacks) {\n const startTime = this.networkRequestStartTimes.get(this.requestStartKey(tabId, params.requestId));\n const now = Date.now();\n const duration = startTime ? Math.round(now - startTime) : undefined;\n // Don't delete start time yet - we need it for loadingFinished\n // this.networkRequestStartTimes.delete(this.requestStartKey(tabId, params.requestId));\n\n for (const cb of callbacks.values()) {\n cb({\n method: existing.method,\n url: existing.url,\n status: existing.status,\n duration,\n timestamp: now,\n });\n }\n }\n }\n\n // Update full NetworkEntry\n const entriesMap = this.networkEntries.get(tabId);\n const entry = entriesMap?.get(params.requestId);\n if (entry && params.response) {\n const response = params.response;\n \n // Calculate TTFB (time to first byte)\n const startTime = this.networkRequestStartTimes.get(this.requestStartKey(tabId, params.requestId));\n const now = params.timestamp ? params.timestamp * 1000 : Date.now();\n if (startTime) {\n entry.ttfb = Math.round(now - startTime);\n }\n \n entry.status = response.status;\n entry.statusText = response.statusText;\n entry.mimeType = response.mimeType;\n \n // Extract response headers\n const responseHeaders: Record<string, string> = {};\n if (response.headers) {\n for (const [key, value] of Object.entries(response.headers)) {\n responseHeaders[key] = String(value);\n }\n }\n entry.responseHeaders = responseHeaders;\n \n // Check if binary type\n if (this.isBinaryType(response.mimeType)) {\n entry.flags.push('binary');\n }\n \n // Check for protobuf\n if (response.mimeType?.includes('protobuf') || \n response.mimeType?.includes('x-protobuf') ||\n response.mimeType?.includes('application/grpc')) {\n entry.flags.push('protobuf');\n }\n \n entry._responseReceived = true;\n }\n }\n\n private handleNetworkFailed(tabId: number, params: any): void {\n const requests = this.networkRequests.get(tabId) || [];\n const existing = requests.find((r) => r.requestId === params.requestId);\n if (existing && !existing.status) {\n existing.status = 0;\n\n const callbacks = this.networkCallbacks.get(tabId);\n if (callbacks) {\n const startTime = this.networkRequestStartTimes.get(this.requestStartKey(tabId, params.requestId));\n const now = Date.now();\n const duration = startTime ? Math.round(now - startTime) : undefined;\n this.networkRequestStartTimes.delete(this.requestStartKey(tabId, params.requestId));\n\n for (const cb of callbacks.values()) {\n cb({\n method: existing.method,\n url: existing.url,\n status: 0,\n duration,\n timestamp: now,\n });\n }\n }\n }\n\n // Update full NetworkEntry\n const entriesMap = this.networkEntries.get(tabId);\n const entry = entriesMap?.get(params.requestId);\n if (entry) {\n const startTime = this.networkRequestStartTimes.get(this.requestStartKey(tabId, params.requestId));\n const now = params.timestamp ? params.timestamp * 1000 : Date.now();\n if (startTime) {\n entry.duration = Math.round(now - startTime);\n }\n this.networkRequestStartTimes.delete(this.requestStartKey(tabId, params.requestId));\n \n entry.status = 0;\n entry.flags.push('failed');\n entry._loadingFinished = true;\n }\n }\n\n private handleDialogOpening(tabId: number, params: any): void {\n this.pendingDialogs.set(tabId, {\n type: params.type,\n message: params.message,\n defaultPrompt: params.defaultPrompt,\n timestamp: Date.now(),\n });\n }\n\n private async handleLoadingFinished(tabId: number, params: any): Promise<void> {\n // Update the simple requests array\n const requests = this.networkRequests.get(tabId) || [];\n const existing = requests.find((r) => r.requestId === params.requestId);\n if (existing) {\n // Calculate duration\n const startTime = this.networkRequestStartTimes.get(this.requestStartKey(tabId, params.requestId));\n const now = params.timestamp ? params.timestamp * 1000 : Date.now();\n if (startTime) {\n existing.duration = Math.round(now - startTime);\n }\n\n }\n\n // Update full NetworkEntry format\n const entriesMap = this.networkEntries.get(tabId);\n const entry = entriesMap?.get(params.requestId);\n if (!entry) return;\n\n // Calculate total duration\n const startTime = this.networkRequestStartTimes.get(this.requestStartKey(tabId, params.requestId));\n const now = params.timestamp ? params.timestamp * 1000 : Date.now();\n if (startTime) {\n entry.duration = Math.round(now - startTime);\n }\n this.networkRequestStartTimes.delete(this.requestStartKey(tabId, params.requestId));\n\n // Set response body size from encoded data length\n entry.responseBodySize = params.encodedDataLength;\n entry._loadingFinished = true;\n const capture = this.networkCapture.get(tabId) || { mode: \"none\" as const, perBodyBytes: 0, totalBytes: 0 };\n const encodedBytes = Math.max(0, Number(params.encodedDataLength) || 0);\n let reason: string | null = null;\n if (capture.mode === \"none\") reason = \"disabled\";\n else if (capture.mode === \"text\" && (this.isStaticAsset(entry.mimeType) || this.isBinaryType(entry.mimeType))) reason = \"content-mode\";\n else if (encodedBytes > capture.perBodyBytes) reason = \"per-body-cap\";\n else if ((this.networkBodyBytes.get(tabId) || 0) + encodedBytes > capture.totalBytes) reason = \"session-cap\";\n if (reason) {\n entry.bodyCapture = { mode: capture.mode, complete: false, reason };\n if (reason.endsWith(\"cap\")) entry.flags.push(\"truncated\");\n return;\n }\n try {\n const result = await this.send(tabId, \"Network.getResponseBody\", { requestId: params.requestId });\n const body = typeof result.body === \"string\" ? result.body : \"\";\n const capturedBytes = result.base64Encoded ? Math.ceil(body.length * 0.75) : new TextEncoder().encode(body).byteLength;\n if (capturedBytes > capture.perBodyBytes || (this.networkBodyBytes.get(tabId) || 0) + capturedBytes > capture.totalBytes) {\n entry.flags.push(\"truncated\");\n entry.bodyCapture = { mode: capture.mode, complete: false, reason: capturedBytes > capture.perBodyBytes ? \"per-body-cap\" : \"session-cap\" };\n return;\n }\n if (result.base64Encoded && capture.mode === \"all\") {\n entry.responseBody = body;\n entry.responseBodyEncoding = \"base64\";\n } else if (result.base64Encoded) {\n try { entry.responseBody = atob(body); } catch { entry.bodyCapture = { mode: capture.mode, complete: false, reason: \"decode-failed\" }; return; }\n } else entry.responseBody = body;\n this.networkBodyBytes.set(tabId, (this.networkBodyBytes.get(tabId) || 0) + capturedBytes);\n entry.bodyCapture = { mode: capture.mode, complete: true, capturedBytes };\n if (existing) existing.responseBody = entry.responseBody;\n } catch {\n entry.bodyCapture = { mode: capture.mode, complete: false, reason: \"unavailable\" };\n }\n }\n\n // Helper: Extract origin from URL\n private extractOrigin(url: string): string {\n try {\n const parsed = new URL(url);\n return parsed.origin;\n } catch {\n return '';\n }\n }\n\n // Helper: Check if MIME type is a static asset (skip body fetch)\n private isStaticAsset(mimeType?: string): boolean {\n if (!mimeType) return false;\n return CDPController.STATIC_ASSET_TYPES.has(mimeType);\n }\n\n // Helper: Check if MIME type is binary\n private isBinaryType(mimeType?: string): boolean {\n if (!mimeType) return false;\n return CDPController.BINARY_TYPES.has(mimeType);\n }\n\n async enableConsoleTracking(tabId: number): Promise<void> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Runtime.enable\");\n } catch (e) {}\n }\n\n async enableNetworkTracking(\n tabId: number,\n options: { bodyMode?: \"none\" | \"text\" | \"all\"; perBodyBytes?: number; totalBytes?: number } = {},\n ): Promise<void> {\n await this.ensureAttached(tabId);\n const mode = options.bodyMode || \"text\";\n const perBodyBytes = options.perBodyBytes ?? CDPController.DEFAULT_PER_BODY_BYTES;\n const totalBytes = options.totalBytes ?? CDPController.DEFAULT_TOTAL_BODY_BYTES;\n if (!Number.isInteger(perBodyBytes) || perBodyBytes < 0 || !Number.isInteger(totalBytes) || totalBytes < 0) {\n throw new Error(\"network body caps must be non-negative integers\");\n }\n this.networkCapture.set(tabId, { mode, perBodyBytes, totalBytes });\n if (!this.networkBodyBytes.has(tabId)) this.networkBodyBytes.set(tabId, 0);\n try {\n await this.send(tabId, \"Network.enable\", { maxPostDataSize: 65536 });\n } catch (e) {}\n }\n\n async disableNetworkTracking(tabId: number): Promise<void> {\n await this.drainNetworkEvents(tabId);\n this.networkCapture.delete(tabId);\n this.networkBodyBytes.delete(tabId);\n if (this.networkCallbacks.get(tabId)?.size) return;\n try {\n await this.send(tabId, \"Network.disable\");\n } catch (e) {}\n }\n\n async handleDialog(tabId: number, accept: boolean, promptText?: string): Promise<{ success: boolean; error?: string }> {\n try {\n await this.send(tabId, \"Page.handleJavaScriptDialog\", {\n accept,\n promptText,\n });\n this.pendingDialogs.delete(tabId);\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n getDialogInfo(tabId: number): PendingDialog | null {\n return this.pendingDialogs.get(tabId) || null;\n }\n\n async emulateNetwork(tabId: number, preset: string): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n const presets: Record<string, { offline: boolean; latency: number; downloadThroughput: number; uploadThroughput: number }> = {\n \"offline\": { offline: true, latency: 0, downloadThroughput: 0, uploadThroughput: 0 },\n \"slow-3g\": { offline: false, latency: 2000, downloadThroughput: 50000, uploadThroughput: 50000 },\n \"fast-3g\": { offline: false, latency: 562.5, downloadThroughput: 180000, uploadThroughput: 84375 },\n \"4g\": { offline: false, latency: 100, downloadThroughput: 4000000, uploadThroughput: 3000000 },\n \"reset\": { offline: false, latency: 0, downloadThroughput: -1, uploadThroughput: -1 },\n };\n const config = presets[preset.toLowerCase().replace(/\\s+/g, \"-\")];\n if (!config) {\n return { success: false, error: `Unknown preset: ${preset}. Available: ${Object.keys(presets).join(\", \")}` };\n }\n try {\n await this.send(tabId, \"Network.enable\");\n await this.send(tabId, \"Network.emulateNetworkConditions\", config);\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateCPU(tabId: number, rate: number): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n if (rate < 1) {\n return { success: false, error: \"CPU throttling rate must be >= 1 (1 = no throttle, 4 = 4x slower)\" };\n }\n try {\n await this.send(tabId, \"Emulation.setCPUThrottlingRate\", { rate });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateGeolocation(tabId: number, latitude: number, longitude: number, accuracy?: number): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Emulation.setGeolocationOverride\", {\n latitude,\n longitude,\n accuracy: accuracy || 100,\n });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async clearGeolocation(tabId: number): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Emulation.clearGeolocationOverride\");\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateDevice(\n tabId: number, \n device: { width: number; height: number; deviceScaleFactor: number; mobile: boolean; touch?: boolean; userAgent?: string }\n ): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n // Set device metrics\n await this.send(tabId, \"Emulation.setDeviceMetricsOverride\", {\n width: device.width,\n height: device.height,\n deviceScaleFactor: device.deviceScaleFactor,\n mobile: device.mobile,\n });\n \n // Set user agent if provided\n if (device.userAgent) {\n await this.send(tabId, \"Emulation.setUserAgentOverride\", {\n userAgent: device.userAgent,\n });\n }\n \n // Enable touch if specified\n if (device.touch) {\n await this.send(tabId, \"Emulation.setTouchEmulationEnabled\", {\n enabled: true,\n maxTouchPoints: 5,\n });\n }\n \n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async clearDeviceEmulation(tabId: number): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Emulation.clearDeviceMetricsOverride\");\n await this.send(tabId, \"Emulation.setUserAgentOverride\", { userAgent: \"\" });\n await this.send(tabId, \"Emulation.setTouchEmulationEnabled\", { enabled: false });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateViewport(\n tabId: number, \n options: { width?: number; height?: number; deviceScaleFactor?: number; mobile?: boolean }\n ): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n // Get current viewport size as defaults\n const viewport = await this.getViewportSize(tabId);\n \n await this.send(tabId, \"Emulation.setDeviceMetricsOverride\", {\n width: options.width || viewport.width,\n height: options.height || viewport.height,\n deviceScaleFactor: options.deviceScaleFactor || 1,\n mobile: options.mobile || false,\n });\n \n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async emulateTouch(tabId: number, enabled: boolean): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Emulation.setTouchEmulationEnabled\", {\n enabled,\n maxTouchPoints: enabled ? 5 : 0,\n });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async startPerformanceTrace(tabId: number, categories?: string[]): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Performance.enable\");\n await this.send(tabId, \"Tracing.start\", {\n categories: categories?.join(\",\") || \"devtools.timeline,v8.execute,disabled-by-default-devtools.timeline\",\n transferMode: \"ReturnAsStream\",\n });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async stopPerformanceTrace(tabId: number): Promise<{ success: boolean; metrics?: any; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Performance.enable\");\n const metricsResult = await this.send(tabId, \"Performance.getMetrics\");\n await this.send(tabId, \"Tracing.end\");\n await this.send(tabId, \"Performance.disable\");\n const metrics: Record<string, number> = {};\n for (const m of metricsResult.metrics || []) {\n metrics[m.name] = m.value;\n }\n return { success: true, metrics };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async getPerformanceMetrics(tabId: number): Promise<{ success: boolean; metrics?: Record<string, number>; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Performance.enable\");\n const result = await this.send(tabId, \"Performance.getMetrics\");\n await this.send(tabId, \"Performance.disable\");\n const metrics: Record<string, number> = {};\n for (const m of result.metrics || []) {\n metrics[m.name] = m.value;\n }\n return { success: true, metrics };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async setFileInputBySelector(tabId: number, selector: string, files: string[]): Promise<{ success: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"DOM.enable\");\n const doc = await this.send(tabId, \"DOM.getDocument\");\n const queryResult = await this.send(tabId, \"DOM.querySelector\", {\n nodeId: doc.root.nodeId,\n selector,\n });\n if (!queryResult.nodeId) {\n return { success: false, error: \"Could not find element by selector\" };\n }\n await this.send(tabId, \"DOM.setFileInputFiles\", {\n nodeId: queryResult.nodeId,\n files,\n });\n return { success: true };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async waitForLoad(tabId: number, timeout: number = 30000): Promise<{ success: boolean; readyState?: string; error?: string }> {\n await this.ensureAttached(tabId);\n const startTime = Date.now();\n try {\n while (Date.now() - startTime < timeout) {\n const result = await this.send(tabId, \"Runtime.evaluate\", {\n expression: \"document.readyState\",\n returnByValue: true,\n });\n const readyState = result.result?.value;\n if (readyState === \"complete\") {\n return { success: true, readyState };\n }\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n return { success: false, error: `Timeout waiting for page load (${timeout}ms)` };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async getFrames(tabId: number): Promise<{ success: boolean; frames?: Array<{ frameId: string; url: string; name: string; parentId?: string }>; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Page.enable\");\n const result = await this.send(tabId, \"Page.getFrameTree\");\n const frames: Array<{ frameId: string; url: string; name: string; parentId?: string }> = [];\n const extractFrames = (frame: any, parentId?: string) => {\n frames.push({\n frameId: frame.frame.id,\n url: frame.frame.url,\n name: frame.frame.name || \"\",\n parentId,\n });\n if (frame.childFrames) {\n for (const child of frame.childFrames) {\n extractFrames(child, frame.frame.id);\n }\n }\n };\n extractFrames(result.frameTree);\n return { success: true, frames };\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n async evaluateInFrame(tabId: number, frameId: string, expression: string): Promise<{ success: boolean; result?: any; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n const contextResult = await this.send(tabId, \"Page.createIsolatedWorld\", {\n frameId,\n worldName: \"surf-isolated\",\n });\n const wrappedExpression = `JSON.stringify((function() { ${expression} })())`;\n const result = await this.send(tabId, \"Runtime.evaluate\", {\n expression: wrappedExpression,\n contextId: contextResult.executionContextId,\n returnByValue: true,\n awaitPromise: true,\n });\n if (result.exceptionDetails) {\n return { success: false, error: result.exceptionDetails.text || result.exceptionDetails.exception?.description || \"Evaluation failed\" };\n }\n try {\n return { success: true, result: JSON.parse(result.result?.value) };\n } catch {\n return { success: true, result: result.result?.value };\n }\n } catch (e) {\n return { success: false, error: e instanceof Error ? e.message : String(e) };\n }\n }\n\n getConsoleMessages(\n tabId: number,\n options?: {\n onlyErrors?: boolean;\n pattern?: string;\n limit?: number;\n }\n ): ConsoleMessage[] {\n let messages = this.consoleMessages.get(tabId) || [];\n\n if (options?.onlyErrors) {\n messages = messages.filter((m) => m.type === \"error\" || m.type === \"exception\");\n }\n if (options?.pattern) {\n try {\n const regex = new RegExp(options.pattern, \"i\");\n messages = messages.filter((m) => regex.test(m.text));\n } catch (e) {\n messages = messages.filter((m) => m.text.includes(options.pattern!));\n }\n }\n if (options?.limit) {\n messages = messages.slice(-options.limit);\n }\n\n return [...messages];\n }\n\n clearConsoleMessages(tabId: number): void {\n this.consoleMessages.set(tabId, []);\n }\n\n getNetworkRequests(\n tabId: number,\n options?: {\n urlPattern?: string;\n limit?: number;\n }\n ): NetworkRequest[] {\n let requests = this.networkRequests.get(tabId) || [];\n\n if (options?.urlPattern) {\n requests = requests.filter((r) => r.url.includes(options.urlPattern!));\n }\n if (options?.limit) {\n requests = requests.slice(-options.limit);\n }\n\n return [...requests];\n }\n\n clearNetworkRequests(tabId: number): void {\n this.networkRequests.set(tabId, []);\n this.networkEntries.set(tabId, new Map());\n this.networkBodyBytes.set(tabId, 0);\n }\n\n /**\n * Get all full network entries for a tab\n */\n getNetworkEntries(\n tabId: number,\n options?: {\n urlPattern?: string;\n limit?: number;\n includeStatic?: boolean;\n }\n ): NetworkEntry[] {\n // First try the full entries map\n const entriesMap = this.networkEntries.get(tabId);\n let entries: NetworkEntry[] = [];\n \n if (entriesMap && entriesMap.size > 0) {\n entries = Array.from(entriesMap.values());\n } else {\n // Fallback to basic networkRequests and convert to NetworkEntry format\n const requests = this.networkRequests.get(tabId) || [];\n entries = requests.map((req, idx) => ({\n id: `r_${req.timestamp}_${idx}`,\n ts: req.timestamp,\n method: req.method,\n url: req.url,\n origin: this.extractOrigin(req.url),\n requestHeaders: {},\n tabId: tabId,\n type: req.type,\n status: req.status,\n flags: [],\n bodyCapture: { mode: \"none\", complete: false, reason: \"legacy\" },\n _requestId: req.requestId,\n _responseReceived: true,\n _loadingFinished: true,\n } as NetworkEntry));\n }\n\n // Filter out static assets by default\n if (!options?.includeStatic) {\n entries = entries.filter(e => !this.isStaticAsset(e.mimeType));\n }\n\n if (options?.urlPattern) {\n entries = entries.filter((e) => e.url.includes(options.urlPattern!));\n }\n\n if (options?.limit) {\n entries = entries.slice(-options.limit);\n }\n\n return entries;\n }\n\n /**\n * Get a single network entry by request ID\n */\n getNetworkEntry(tabId: number, requestId: string): NetworkEntry | null {\n const entriesMap = this.networkEntries.get(tabId);\n return entriesMap?.get(requestId) || null;\n }\n\n /**\n * Fetch response body on demand via CDP\n * Use this for bodies that weren't fetched inline (large or binary)\n */\n async getResponseBody(tabId: number, requestId: string): Promise<{\n success: boolean;\n body?: string;\n base64Encoded?: boolean;\n error?: string;\n }> {\n await this.ensureAttached(tabId);\n \n try {\n const result = await this.send(tabId, \"Network.getResponseBody\", {\n requestId,\n });\n \n return {\n success: true,\n body: result.body,\n base64Encoded: result.base64Encoded,\n };\n } catch (e) {\n return {\n success: false,\n error: e instanceof Error ? e.message : String(e),\n };\n }\n }\n\n subscribeToConsole(tabId: number, streamId: number, callback: ConsoleEventCallback): void {\n if (!this.consoleCallbacks.has(tabId)) {\n this.consoleCallbacks.set(tabId, new Map());\n }\n this.consoleCallbacks.get(tabId)!.set(streamId, callback);\n }\n\n unsubscribeFromConsole(tabId: number, streamId: number): void {\n const callbacks = this.consoleCallbacks.get(tabId);\n if (callbacks) {\n callbacks.delete(streamId);\n if (callbacks.size === 0) {\n this.consoleCallbacks.delete(tabId);\n }\n }\n }\n\n subscribeToNetwork(tabId: number, streamId: number, callback: NetworkEventCallback): void {\n if (!this.networkCallbacks.has(tabId)) {\n this.networkCallbacks.set(tabId, new Map());\n }\n this.networkCallbacks.get(tabId)!.set(streamId, callback);\n }\n\n unsubscribeFromNetwork(tabId: number, streamId: number): void {\n const callbacks = this.networkCallbacks.get(tabId);\n if (callbacks) {\n callbacks.delete(streamId);\n if (callbacks.size === 0) {\n this.networkCallbacks.delete(tabId);\n }\n }\n }\n\n subscribeToScreencast(\n tabId: number,\n recorderId: string,\n onFrame: ScreencastFrameCallback,\n onError: ScreencastErrorCallback = () => {},\n ): void {\n if (!this.screencastCallbacks.has(tabId)) this.screencastCallbacks.set(tabId, new Map());\n this.screencastCallbacks.get(tabId)!.set(recorderId, { onFrame, onError });\n }\n\n unsubscribeFromScreencast(tabId: number, recorderId: string): void {\n const callbacks = this.screencastCallbacks.get(tabId);\n if (!callbacks) return;\n callbacks.delete(recorderId);\n if (callbacks.size === 0) this.screencastCallbacks.delete(tabId);\n }\n\n async startScreencast(\n tabId: number,\n options: { format?: \"jpeg\" | \"png\"; quality?: number; everyNthFrame?: number } = {},\n ): Promise<any> {\n return this.send(tabId, \"Page.startScreencast\", {\n format: options.format || \"jpeg\",\n quality: options.quality ?? 80,\n everyNthFrame: options.everyNthFrame ?? 1,\n });\n }\n\n async stopScreencast(tabId: number): Promise<any> {\n return this.send(tabId, \"Page.stopScreencast\");\n }\n\n /**\n * Parse `expression` in the page without running it. Lets the service\n * worker check syntax although its own CSP forbids `new Function`.\n */\n async compileScript(tabId: number, expression: string): Promise<{ parses: boolean; error?: string }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Runtime.enable\");\n } catch (e) {}\n const result = await this.send(tabId, \"Runtime.compileScript\", {\n expression,\n sourceURL: \"\",\n persistScript: false,\n });\n if (result?.exceptionDetails) {\n return {\n parses: false,\n error: result.exceptionDetails.exception?.description || result.exceptionDetails.text || \"SyntaxError\",\n };\n }\n return { parses: true };\n }\n\n async evaluateScript(tabId: number, expression: string): Promise<{\n result?: { value?: any; type?: string; description?: string };\n exceptionDetails?: { text?: string; exception?: { description?: string } };\n }> {\n await this.ensureAttached(tabId);\n try {\n await this.send(tabId, \"Runtime.enable\");\n } catch (e) {}\n \n return this.send(tabId, \"Runtime.evaluate\", {\n expression,\n returnByValue: true,\n awaitPromise: true,\n timeout: 30000,\n });\n }\n\n private async send(\n tabId: number,\n method: string,\n params?: { [key: string]: unknown },\n ): Promise<any> {\n await this.ensureAttached(tabId);\n const target = this.targets.get(tabId)!;\n try {\n return await chrome.debugger.sendCommand(target, method, params);\n } catch (err) {\n throw describeDebuggerError(err, method);\n }\n }\n\n async sendCommand(\n tabId: number,\n method: string,\n params?: { [key: string]: unknown },\n ): Promise<any> {\n return this.send(tabId, method, params);\n }\n\n private async ensureAttached(tabId: number): Promise<void> {\n const detachReason = this.detachReasons.get(tabId);\n if (detachReason) {\n this.detachReasons.delete(tabId);\n throw new CDPControllerError(\n \"debugger_detached\",\n `Debugger detached from tab ${tabId}: ${detachReason}. Retry after closing any competing debugger.`,\n { tabId, reason: detachReason },\n );\n }\n if (!this.targets.has(tabId)) await this.attach(tabId);\n }\n\n async getViewportSize(tabId: number): Promise<{ width: number; height: number }> {\n const layoutMetrics = await this.send(tabId, \"Page.getLayoutMetrics\");\n const viewport = layoutMetrics.visualViewport || layoutMetrics.layoutViewport;\n return {\n width: Math.round(viewport.clientWidth),\n height: Math.round(viewport.clientHeight),\n };\n }\n\n async captureScreenshot(tabId: number): Promise<{\n base64: string;\n width: number;\n height: number;\n }> {\n return this.withScreenshotDeadline(tabId, (async () => {\n const result: { data: string } = await this.send(tabId, \"Page.captureScreenshot\", {\n format: \"png\",\n captureBeyondViewport: false,\n });\n const { width, height } = await this.getViewportSize(tabId);\n return { base64: result.data, width, height };\n })());\n }\n\n private async withScreenshotDeadline<T>(tabId: number, work: Promise<T>): Promise<T> {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => reject(new CDPControllerError(\n \"screenshot_timeout\",\n `Screenshot capture timed out after ${CDPController.SCREENSHOT_TIMEOUT_MS}ms`,\n { tabId, timeoutMs: CDPController.SCREENSHOT_TIMEOUT_MS },\n )), CDPController.SCREENSHOT_TIMEOUT_MS);\n });\n try {\n return await Promise.race([work, timeout]);\n } finally {\n if (timeoutId !== undefined) clearTimeout(timeoutId);\n }\n }\n\n async captureRegion(tabId: number, x: number, y: number, width: number, height: number): Promise<{\n base64: string;\n width: number;\n height: number;\n }> {\n const result: { data: string } = await this.withScreenshotDeadline(\n tabId,\n this.send(tabId, \"Page.captureScreenshot\", {\n format: \"png\",\n clip: { x, y, width, height, scale: 1 },\n }),\n );\n return { base64: result.data, width, height };\n }\n\n private async dispatchMouseEvent(\n tabId: number,\n type: \"mousePressed\" | \"mouseReleased\" | \"mouseMoved\" | \"mouseWheel\",\n x: number,\n y: number,\n options: {\n button?: MouseButton;\n buttons?: number;\n clickCount?: number;\n modifiers?: number;\n deltaX?: number;\n deltaY?: number;\n } = {}\n ): Promise<void> {\n const params: Record<string, any> = {\n type,\n x: Math.round(x),\n y: Math.round(y),\n modifiers: options.modifiers || 0,\n };\n\n if (type === \"mousePressed\" || type === \"mouseReleased\" || type === \"mouseMoved\") {\n params.button = options.button || \"none\";\n if (type === \"mousePressed\" || type === \"mouseReleased\") {\n params.clickCount = options.clickCount || 1;\n }\n }\n\n if (type !== \"mouseWheel\") {\n params.buttons = options.buttons ?? 0;\n }\n\n if (type === \"mouseWheel\") {\n params.deltaX = options.deltaX || 0;\n params.deltaY = options.deltaY || 0;\n }\n\n await this.send(tabId, \"Input.dispatchMouseEvent\", params);\n }\n\n async click(\n tabId: number,\n x: number,\n y: number,\n button: MouseButton = \"left\",\n clickCount = 1,\n modifiers = 0\n ): Promise<void> {\n const buttonValue = button === \"left\" ? 1 : button === \"right\" ? 2 : button === \"middle\" ? 4 : 0;\n\n await this.dispatchMouseEvent(tabId, \"mouseMoved\", x, y, { button: \"none\", buttons: 0, modifiers });\n await new Promise(resolve => setTimeout(resolve, 100));\n\n for (let i = 1; i <= clickCount; i++) {\n await this.dispatchMouseEvent(tabId, \"mousePressed\", x, y, {\n button,\n buttons: buttonValue,\n clickCount: i,\n modifiers,\n });\n await new Promise(resolve => setTimeout(resolve, 12));\n await this.dispatchMouseEvent(tabId, \"mouseReleased\", x, y, {\n button,\n buttons: 0,\n clickCount: i,\n modifiers,\n });\n if (i < clickCount) {\n await new Promise(resolve => setTimeout(resolve, 100));\n }\n }\n }\n\n async rightClick(tabId: number, x: number, y: number, modifiers = 0): Promise<void> {\n await this.click(tabId, x, y, \"right\", 1, modifiers);\n }\n\n async doubleClick(tabId: number, x: number, y: number, modifiers = 0): Promise<void> {\n await this.click(tabId, x, y, \"left\", 2, modifiers);\n }\n\n async tripleClick(tabId: number, x: number, y: number, modifiers = 0): Promise<void> {\n await this.click(tabId, x, y, \"left\", 3, modifiers);\n }\n\n async hover(tabId: number, x: number, y: number): Promise<void> {\n await this.dispatchMouseEvent(tabId, \"mouseMoved\", x, y, { button: \"none\", buttons: 0 });\n }\n\n async drag(\n tabId: number,\n startX: number,\n startY: number,\n endX: number,\n endY: number,\n modifiers = 0\n ): Promise<void> {\n await this.dispatchMouseEvent(tabId, \"mouseMoved\", startX, startY, { button: \"none\", buttons: 0 });\n await new Promise(resolve => setTimeout(resolve, 50));\n\n await this.dispatchMouseEvent(tabId, \"mousePressed\", startX, startY, {\n button: \"left\",\n buttons: 1,\n clickCount: 1,\n modifiers,\n });\n await new Promise(resolve => setTimeout(resolve, 50));\n\n await this.dispatchMouseEvent(tabId, \"mouseMoved\", endX, endY, { button: \"left\", buttons: 1, modifiers });\n await new Promise(resolve => setTimeout(resolve, 50));\n\n await this.dispatchMouseEvent(tabId, \"mouseReleased\", endX, endY, {\n button: \"left\",\n buttons: 0,\n clickCount: 1,\n modifiers,\n });\n }\n\n async scroll(tabId: number, x: number, y: number, deltaX: number, deltaY: number): Promise<void> {\n await this.dispatchMouseEvent(tabId, \"mouseWheel\", x, y, { deltaX, deltaY });\n }\n\n async type(tabId: number, text: string): Promise<void> {\n for (const char of text) {\n if (char === \"\\n\" || char === \"\\r\") {\n await this.pressKey(tabId, \"Enter\");\n } else {\n const keyDef = this.getKeyDefinition(char);\n if (keyDef) {\n const needsShift = this.requiresShift(char);\n await this.pressKey(tabId, char, needsShift ? MODIFIERS.shift : 0);\n } else {\n await this.send(tabId, \"Input.insertText\", { text: char });\n }\n }\n }\n }\n\n private requiresShift(char: string): boolean {\n return /[A-Z!@#$%^&*()_+{}|:\"<>?~]/.test(char);\n }\n\n private async dispatchKeyEvent(\n tabId: number,\n type: \"keyDown\" | \"keyUp\" | \"rawKeyDown\" | \"char\",\n keyDef: KeyDefinition,\n modifiers = 0\n ): Promise<void> {\n await this.send(tabId, \"Input.dispatchKeyEvent\", {\n type: keyDef.text ? type : (type === \"keyDown\" ? \"rawKeyDown\" : type),\n key: keyDef.key,\n code: keyDef.code,\n windowsVirtualKeyCode: keyDef.keyCode,\n modifiers,\n text: keyDef.text ?? \"\",\n unmodifiedText: keyDef.text ?? \"\",\n location: keyDef.location ?? 0,\n });\n }\n\n async pressKey(tabId: number, key: string, modifiers = 0): Promise<void> {\n const keyDef = this.getKeyDefinition(key);\n if (!keyDef) {\n throw new Error(`Unknown key: ${key}`);\n }\n\n await this.dispatchKeyEvent(tabId, \"keyDown\", keyDef, modifiers);\n await this.dispatchKeyEvent(tabId, \"keyUp\", keyDef, modifiers);\n }\n\n async pressKeyChord(tabId: number, chord: string): Promise<void> {\n const parts = chord.toLowerCase().split(\"+\");\n const modifierKeys: string[] = [];\n let mainKey = \"\";\n\n for (const part of parts) {\n if (part in MODIFIERS) {\n modifierKeys.push(part);\n } else {\n mainKey = part;\n }\n }\n\n let modifiers = 0;\n for (const mod of modifierKeys) {\n modifiers |= MODIFIERS[mod as keyof typeof MODIFIERS] || 0;\n }\n\n if (mainKey) {\n await this.pressKey(tabId, mainKey, modifiers);\n }\n }\n\n private getKeyDefinition(key: string): KeyDefinition | null {\n const lowerKey = key.toLowerCase();\n \n if (KEY_DEFINITIONS[lowerKey]) {\n return KEY_DEFINITIONS[lowerKey];\n }\n\n if (key.length === 1) {\n const code = key.toUpperCase().charCodeAt(0);\n return {\n key,\n code: `Key${key.toUpperCase()}`,\n keyCode: code,\n text: key,\n };\n }\n\n return null;\n }\n\n parseModifiers(modifierString?: string): number {\n if (!modifierString) return 0;\n \n let result = 0;\n const parts = modifierString.toLowerCase().split(\"+\");\n for (const part of parts) {\n const trimmed = part.trim();\n if (trimmed in MODIFIERS) {\n result |= MODIFIERS[trimmed as keyof typeof MODIFIERS];\n }\n }\n return result;\n }\n}\n","let debugMode = false;\nlet initialized = false;\nconst pendingLogs: unknown[][] = [];\n\nchrome.storage.local.get(\"debugMode\").then(({ debugMode: stored }) => {\n debugMode = !!stored;\n initialized = true;\n if (debugMode) {\n for (const args of pendingLogs) {\n console.log(\"[Surf]\", ...args);\n }\n }\n pendingLogs.length = 0;\n});\n\nchrome.storage.onChanged.addListener((changes, areaName) => {\n if (areaName === \"local\" && changes.debugMode) {\n debugMode = !!changes.debugMode.newValue;\n }\n});\n\nexport function debugLog(...args: unknown[]): void {\n if (!initialized) {\n pendingLogs.push(args);\n return;\n }\n if (debugMode) {\n console.log(\"[Surf]\", ...args);\n }\n}\n","/**\n * Frame diagnosis: three inventories of the same page side by side.\n *\n * A page can carry frames that each inventory sees differently:\n *\n * - The DOM lists `<iframe>` elements with their attributes and layout,\n * but a `srcdoc` or script-created frame shows up as `about:blank`.\n * - `chrome.webNavigation.getAllFrames` lists the frames the extension can\n * message, with the numeric ids `frame.switch` uses; a frame the content\n * script did not load in (sandboxed, restricted, still loading) is\n * listed but unreachable.\n * - The CDP frame tree (`Page.getFrameTree`) lists what the renderer knows,\n * with the string ids `frame.js` uses, including out-of-process frames.\n *\n * `buildFrameDiagnosis` correlates the three by URL and explains the\n * mismatches, so an agent can pick the right frame command instead of\n * guessing why a selector never matches.\n */\n\nexport interface FrameRect {\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\nexport interface DomIframeEntry {\n domIndex: number;\n /** Resolved absolute URL (`iframe.src`), empty for srcdoc/blank frames. */\n src: string;\n /** The literal `src` attribute, useful when it is relative. */\n srcAttribute?: string;\n srcdoc: boolean;\n title: string;\n name: string;\n id: string;\n sandbox: string | null;\n allow: string;\n rect: FrameRect;\n /**\n * Path of shadow hosts the iframe sits under (`div#host > x-widget`), or\n * null when it is in the light DOM. `document.querySelectorAll(\"iframe\")`\n * never sees the former.\n */\n shadowHost?: string | null;\n}\n\nexport interface ExtensionFrameEntry {\n frameId: number;\n parentFrameId: number;\n url: string;\n errorOccurred: boolean;\n contentScriptReachable: boolean;\n contentScript?: { href?: string; readyState?: string };\n contentScriptError?: string;\n}\n\nexport interface CdpFrameEntry {\n frameId: string;\n parentId?: string;\n url: string;\n name: string;\n}\n\nexport interface FrameDiagnosisInput {\n mainPage: { href: string; title: string };\n domIframes: DomIframeEntry[];\n extensionFrames: ExtensionFrameEntry[];\n cdpFrames: CdpFrameEntry[];\n cdpFramesAvailable?: boolean;\n}\n\nexport interface DiagnosedDomIframe extends DomIframeEntry {\n origin: string | null;\n crossOrigin: boolean;\n blank: boolean;\n zeroSize: boolean;\n scriptsBlocked: boolean;\n extensionFrameIds: number[];\n cdpFrameIds: string[];\n}\n\nexport interface DiagnosedExtensionFrame extends ExtensionFrameEntry {\n isMain: boolean;\n /** Position accepted by frame.switch --index; null for the main frame. */\n switchIndex: number | null;\n origin: string | null;\n crossOrigin: boolean;\n}\n\nexport interface DiagnosedCdpFrame extends CdpFrameEntry {\n isMain: boolean;\n origin: string | null;\n crossOrigin: boolean;\n extensionFrameIds: number[];\n}\n\nexport interface FrameDiagnosis {\n mainPage: { href: string; title: string; origin: string | null };\n counts: { domIframes: number; extensionFrames: number; cdpFrames: number };\n domIframes: DiagnosedDomIframe[];\n extensionFrames: DiagnosedExtensionFrame[];\n cdpFrames: DiagnosedCdpFrame[];\n warnings: string[];\n}\n\nexport function originOf(url: string): string | null {\n try {\n const parsed = new URL(url);\n return parsed.origin === \"null\" ? null : parsed.origin;\n } catch {\n return null;\n }\n}\n\nexport function isBlankFrameUrl(url: string): boolean {\n return url === \"\" || url === \"about:blank\" || url.startsWith(\"about:blank?\") || url === \"about:srcdoc\";\n}\n\nexport function sandboxBlocksScripts(sandbox: string | null): boolean {\n if (sandbox === null) return false;\n return !sandbox.split(/\\s+/).includes(\"allow-scripts\");\n}\n\nfunction sameUrl(a: string, b: string): boolean {\n if (isBlankFrameUrl(a) && isBlankFrameUrl(b)) return true;\n return a === b;\n}\n\nfunction short(url: string, max = 80): string {\n if (url.length <= max) return url;\n return `${url.slice(0, max - 3)}...`;\n}\n\nfunction frameName(iframe: DomIframeEntry): string {\n return iframe.name || iframe.id || \"\";\n}\n\nexport function buildFrameDiagnosis(input: FrameDiagnosisInput): FrameDiagnosis {\n const mainOrigin = originOf(input.mainPage.href);\n const cdpFramesAvailable = input.cdpFramesAvailable !== false;\n const childExtensionFrames = input.extensionFrames.filter((frame) => frame.parentFrameId !== -1);\n const warnings: string[] = [];\n\n const extensionFrames: DiagnosedExtensionFrame[] = input.extensionFrames.map((frame) => {\n const origin = originOf(frame.url);\n const isMain = frame.parentFrameId === -1;\n return {\n ...frame,\n isMain,\n switchIndex: isMain\n ? null\n : childExtensionFrames.findIndex((candidate) => candidate.frameId === frame.frameId),\n origin,\n crossOrigin: origin !== null && mainOrigin !== null && origin !== mainOrigin,\n };\n });\n\n const cdpFrames: DiagnosedCdpFrame[] = input.cdpFrames.map((frame) => {\n const origin = originOf(frame.url);\n return {\n ...frame,\n isMain: frame.parentId === undefined,\n origin,\n crossOrigin: origin !== null && mainOrigin !== null && origin !== mainOrigin,\n extensionFrameIds: childExtensionFrames\n .filter(\n (candidate) =>\n frame.parentId !== undefined &&\n !isBlankFrameUrl(frame.url) &&\n sameUrl(candidate.url, frame.url),\n )\n .map((candidate) => candidate.frameId),\n };\n });\n\n const domIframes: DiagnosedDomIframe[] = input.domIframes.map((iframe) => {\n const blank = iframe.srcdoc || isBlankFrameUrl(iframe.src);\n const origin = blank ? null : originOf(iframe.src);\n const matchesUrl = (url: string): boolean => !blank && sameUrl(url, iframe.src);\n const name = frameName(iframe);\n // CDP names frames after the iframe's name/id, which is the only handle a\n // srcdoc or about:blank frame has.\n const matchesCdp = (frame: CdpFrameEntry): boolean =>\n frame.parentId !== undefined && (matchesUrl(frame.url) || (name !== \"\" && frame.name === name));\n return {\n ...iframe,\n shadowHost: iframe.shadowHost ?? null,\n origin,\n crossOrigin: origin !== null && mainOrigin !== null && origin !== mainOrigin,\n blank,\n zeroSize: iframe.rect.width <= 0 || iframe.rect.height <= 0,\n scriptsBlocked: sandboxBlocksScripts(iframe.sandbox),\n extensionFrameIds: childExtensionFrames.filter((frame) => matchesUrl(frame.url)).map((frame) => frame.frameId),\n cdpFrameIds: input.cdpFrames.filter(matchesCdp).map((frame) => frame.frameId),\n };\n });\n\n const unmatchedBlank = cdpFramesAvailable\n ? domIframes.filter((iframe) => iframe.blank && iframe.cdpFrameIds.length === 0)\n : [];\n if (unmatchedBlank.length > 0) {\n warnings.push(\n `${unmatchedBlank.length} iframe(s) have no URL (about:blank or srcdoc): DOM indexes ${unmatchedBlank.map((iframe) => iframe.domIndex).join(\", \")}. No CDP frame carries their name or id, so their content cannot be matched; give them a name or id. For frame.switch --index, use extension-inventory indexes, not DOM indexes.`,\n );\n }\n\n for (const iframe of domIframes) {\n if (iframe.scriptsBlocked) {\n warnings.push(`iframe ${iframe.domIndex} (${short(iframe.src) || \"no src\"}) is sandboxed without allow-scripts: no content script or page script runs inside it.`);\n }\n if (iframe.zeroSize) {\n warnings.push(`iframe ${iframe.domIndex} (${short(iframe.src) || \"no src\"}) is rendered at ${iframe.rect.width}x${iframe.rect.height}: hidden, collapsed, or not yet laid out.`);\n }\n if (!iframe.blank && iframe.extensionFrameIds.length === 0) {\n warnings.push(`iframe ${iframe.domIndex} (${short(iframe.src)}) has no matching extension frame: it may still be loading, be blocked, or have navigated elsewhere.`);\n }\n if (iframe.extensionFrameIds.length > 1) {\n warnings.push(`iframe ${iframe.domIndex} (${short(iframe.src)}) matches ${iframe.extensionFrameIds.length} extension frames by URL (${iframe.extensionFrameIds.join(\", \")}); use frame.switch --index to pick one.`);\n }\n if (iframe.cdpFrameIds.length > 1) {\n warnings.push(`iframe ${iframe.domIndex} (${short(iframe.src)}) matches ${iframe.cdpFrameIds.length} CDP frames (${iframe.cdpFrameIds.join(\", \")}); correlation is ambiguous, so frame.js requires an explicit CDP frame id.`);\n }\n if (cdpFramesAvailable && !iframe.blank && iframe.extensionFrameIds.length > 0 && iframe.cdpFrameIds.length === 0) {\n const reachable = iframe.extensionFrameIds.every(\n (id) => input.extensionFrames.find((frame) => frame.frameId === id)?.contentScriptReachable === true,\n );\n if (iframe.crossOrigin) {\n warnings.push(\n `iframe ${iframe.domIndex} (${short(iframe.src)}) is out-of-process: it is missing from this tab's CDP frame tree, so frame.js cannot reach it; ${\n reachable\n ? \"its content script answers, so frame.switch, page.read and click by ref work there.\"\n : \"its content script is unreachable too, so nothing in this tab can drive it.\"\n }`,\n );\n } else {\n warnings.push(\n `iframe ${iframe.domIndex} (${short(iframe.src)}) has an extension frame but no CDP frame: it is still loading, navigated, or runs out of process; retry, or use frame.switch.`,\n );\n }\n }\n }\n\n for (const frame of childExtensionFrames) {\n const domMatches = domIframes.filter((iframe) => iframe.extensionFrameIds.includes(frame.frameId));\n if (domMatches.length > 1) {\n warnings.push(`extension frame ${frame.frameId} (${short(frame.url)}) matches ${domMatches.length} DOM iframes (${domMatches.map((iframe) => iframe.domIndex).join(\", \")}); correlation is ambiguous.`);\n }\n const cdpMatches = cdpFrames.filter((candidate) => candidate.extensionFrameIds.includes(frame.frameId));\n if (cdpMatches.length > 1) {\n warnings.push(`extension frame ${frame.frameId} (${short(frame.url)}) matches ${cdpMatches.length} CDP frames (${cdpMatches.map((candidate) => candidate.frameId).join(\", \")}) by URL; correlation is ambiguous.`);\n }\n }\n\n for (const frame of cdpFrames) {\n if (frame.isMain) continue;\n const domMatches = domIframes.filter((iframe) => iframe.cdpFrameIds.includes(frame.frameId));\n if (domMatches.length > 1) {\n warnings.push(`CDP frame ${frame.frameId} (${short(frame.url)}) matches ${domMatches.length} DOM iframes (${domMatches.map((iframe) => iframe.domIndex).join(\", \")}); correlation is ambiguous.`);\n }\n if (frame.extensionFrameIds.length > 1) {\n warnings.push(`CDP frame ${frame.frameId} (${short(frame.url)}) matches ${frame.extensionFrameIds.length} extension frames by URL (${frame.extensionFrameIds.join(\", \")}); correlation is ambiguous.`);\n }\n }\n\n for (const frame of extensionFrames) {\n if (frame.isMain) continue;\n if (!frame.contentScriptReachable) {\n const reason = frame.contentScriptError ? ` (${frame.contentScriptError})` : \"\";\n warnings.push(`extension frame ${frame.frameId} (${short(frame.url)}) has no reachable content script${reason}: page.read, click by ref and frame.switch will not work inside it; frame.js with its CDP frame id may.`);\n }\n if (frame.errorOccurred) {\n warnings.push(`extension frame ${frame.frameId} (${short(frame.url)}) reported a navigation error.`);\n }\n }\n\n const unseenByExtension = cdpFrames.filter(\n (frame) => !frame.isMain && !isBlankFrameUrl(frame.url) && frame.extensionFrameIds.length === 0,\n );\n for (const frame of unseenByExtension) {\n warnings.push(`CDP frame ${frame.frameId} (${short(frame.url)}) is not reported by chrome.webNavigation: likely out-of-process or detached; only frame.js can reach it.`);\n }\n\n const crossOriginCount = domIframes.filter((iframe) => iframe.crossOrigin).length;\n if (crossOriginCount > 0) {\n warnings.push(`${crossOriginCount} cross-origin iframe(s): selectors from the main page do not reach them; switch with frame.switch first.`);\n }\n\n if (domIframes.length !== childExtensionFrames.length) {\n const nested = childExtensionFrames.filter((frame) => frame.parentFrameId !== 0).length;\n const shadowed = domIframes.filter((iframe) => iframe.shadowHost).length;\n const explained = domIframes.length === childExtensionFrames.length - nested;\n warnings.push(\n `DOM lists ${domIframes.length} iframe(s)${shadowed > 0 ? ` (${shadowed} inside open shadow roots)` : \"\"} but the extension sees ${childExtensionFrames.length} child frame(s)${nested > 0 ? `, ${nested} of them nested below another frame` : \"\"}; ${\n explained\n ? \"the nested frames account for the difference.\"\n : \"the rest live in closed shadow roots, were created after the snapshot, or are detached.\"\n }`,\n );\n }\n\n return {\n mainPage: { ...input.mainPage, origin: mainOrigin },\n counts: {\n domIframes: domIframes.length,\n extensionFrames: extensionFrames.length,\n cdpFrames: cdpFrames.length,\n },\n domIframes,\n extensionFrames,\n cdpFrames,\n warnings,\n };\n}\n\n/** Page-side expression that returns the DOM iframe inventory as a plain object. */\nexport const DOM_IFRAME_INVENTORY_EXPRESSION = `(() => {\n const describe = (el) => el.tagName.toLowerCase() + (el.id ? \"#\" + el.id : \"\") + (el.classList.length ? \".\" + Array.from(el.classList).slice(0, 2).join(\".\") : \"\");\n const found = [];\n // Walk open shadow roots too: querySelectorAll(\"iframe\") on the document\n // misses every frame a custom element renders inside its shadow tree.\n const walk = (root, hostPath) => {\n for (const el of root.querySelectorAll(\"iframe\")) found.push({ el, hostPath });\n for (const host of root.querySelectorAll(\"*\")) {\n if (host.shadowRoot) walk(host.shadowRoot, hostPath ? hostPath + \" > \" + describe(host) : describe(host));\n }\n };\n walk(document, \"\");\n const iframes = found.map(({ el, hostPath }, domIndex) => {\n const rect = el.getBoundingClientRect();\n return {\n domIndex,\n shadowHost: hostPath || null,\n src: el.hasAttribute(\"srcdoc\") ? \"\" : el.src || \"\",\n srcAttribute: el.getAttribute(\"src\") || \"\",\n srcdoc: el.hasAttribute(\"srcdoc\"),\n title: el.title || \"\",\n name: el.getAttribute(\"name\") || \"\",\n id: el.id || \"\",\n sandbox: el.hasAttribute(\"sandbox\") ? el.getAttribute(\"sandbox\") : null,\n allow: el.getAttribute(\"allow\") || \"\",\n rect: { x: rect.x, y: rect.y, width: rect.width, height: rect.height },\n };\n });\n return { href: location.href, title: document.title, iframes };\n})()`;\n","/**\n * Host-side half of page readiness: the state vocabulary, error codes,\n * `--accept` parsing and the bounded poll loop. Bundled into the service\n * worker only; the DOM classifier in `./page-readiness.ts` is content-script\n * only and imports nothing but types from here.\n */\n\nexport type ReadinessState =\n | \"ready\"\n | \"empty\"\n | \"loading\"\n | \"login\"\n | \"challenge\"\n | \"not-found\"\n | \"error\";\n\nexport const NEGATIVE_READINESS_STATES: readonly ReadinessState[] = [\n \"challenge\",\n \"login\",\n \"not-found\",\n \"error\",\n];\n\nexport const SETTLED_READINESS_STATES: readonly ReadinessState[] = [\"ready\", \"empty\"];\n\nexport function readinessErrorCode(state: ReadinessState): string | null {\n switch (state) {\n case \"challenge\":\n return \"page_challenge\";\n case \"login\":\n return \"page_login\";\n case \"not-found\":\n return \"page_not_found\";\n case \"error\":\n return \"page_error\";\n default:\n return null;\n }\n}\n\nexport function isReadinessState(value: unknown): value is ReadinessState {\n return (\n value === \"ready\" ||\n value === \"empty\" ||\n value === \"loading\" ||\n NEGATIVE_READINESS_STATES.includes(value as ReadinessState)\n );\n}\n\nexport function parseAcceptStates(input: unknown): ReadinessState[] {\n const raw: unknown[] = Array.isArray(input)\n ? input\n : typeof input === \"string\"\n ? input.split(\",\")\n : [];\n const states: ReadinessState[] = [];\n for (const entry of raw) {\n const trimmed = typeof entry === \"string\" ? entry.trim() : \"\";\n if (!isReadinessState(trimmed) || !NEGATIVE_READINESS_STATES.includes(trimmed)) {\n throw new Error(\n `Invalid --accept state \"${String(entry)}\". Expected one of: challenge, login, not-found, error`,\n );\n }\n if (!states.includes(trimmed)) states.push(trimmed);\n }\n return states;\n}\n\nexport interface ReadinessProbeResult {\n state: ReadinessState;\n evidence: string[];\n href?: string;\n title?: string;\n readyState?: string;\n tabStatus?: string;\n}\n\nexport interface ReadinessBudget {\n timeoutMs: number;\n intervalMs: number;\n}\n\nexport const DEFAULT_READINESS_TIMEOUT_MS = 20_000;\nexport const MAX_READINESS_TIMEOUT_MS = 120_000;\nexport const DEFAULT_READINESS_INTERVAL_MS = 400;\nexport const MIN_READINESS_INTERVAL_MS = 50;\n\nexport function clampReadinessBudget(input: { timeoutMs?: unknown; intervalMs?: unknown }): ReadinessBudget {\n const timeoutRaw = Number(input.timeoutMs);\n const intervalRaw = Number(input.intervalMs);\n const timeoutMs = Number.isFinite(timeoutRaw) && timeoutRaw > 0\n ? Math.min(timeoutRaw, MAX_READINESS_TIMEOUT_MS)\n : DEFAULT_READINESS_TIMEOUT_MS;\n const intervalBase = Number.isFinite(intervalRaw) && intervalRaw > 0 ? intervalRaw : DEFAULT_READINESS_INTERVAL_MS;\n const intervalMs = Math.min(Math.max(intervalBase, MIN_READINESS_INTERVAL_MS), timeoutMs);\n return { timeoutMs, intervalMs };\n}\n\nexport interface ReadinessPollOptions extends ReadinessBudget {\n probe: () => Promise<ReadinessProbeResult>;\n /** Negative states that end the wait successfully instead of failing it. */\n accept?: readonly ReadinessState[];\n sleep?: (ms: number) => Promise<void>;\n now?: () => number;\n /** Called after every probe; useful for debug lines. */\n onPoll?: (result: ReadinessProbeResult, poll: number, waitedMs: number) => void;\n}\n\nexport type ReadinessPollKind = \"settled\" | \"accepted\" | \"negative\" | \"timeout\";\n\nexport interface ReadinessPollOutcome {\n kind: ReadinessPollKind;\n result: ReadinessProbeResult;\n polls: number;\n waitedMs: number;\n}\n\nconst defaultSleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n/**\n * Probe until the page settles, a negative state appears, or the budget is\n * spent. The loop never spins faster than `intervalMs` and always makes at\n * least one probe.\n */\nexport async function pollReadiness(options: ReadinessPollOptions): Promise<ReadinessPollOutcome> {\n const sleep = options.sleep ?? defaultSleep;\n const now = options.now ?? Date.now;\n const accept = options.accept ?? [];\n const startedAt = now();\n let polls = 0;\n let last: ReadinessProbeResult = { state: \"loading\", evidence: [\"no probe completed\"] };\n\n for (;;) {\n last = await options.probe();\n polls += 1;\n const waitedMs = now() - startedAt;\n options.onPoll?.(last, polls, waitedMs);\n\n if (SETTLED_READINESS_STATES.includes(last.state)) {\n return { kind: \"settled\", result: last, polls, waitedMs };\n }\n if (NEGATIVE_READINESS_STATES.includes(last.state)) {\n return { kind: accept.includes(last.state) ? \"accepted\" : \"negative\", result: last, polls, waitedMs };\n }\n const remaining = options.timeoutMs - (now() - startedAt);\n if (remaining <= 0) {\n return { kind: \"timeout\", result: last, polls, waitedMs: now() - startedAt };\n }\n await sleep(Math.min(options.intervalMs, remaining));\n }\n}\n","import { debugLog } from \"../utils/debug\";\n\nlet nativePort: chrome.runtime.Port | null = null;\nlet messageHandler: ((msg: any) => Promise<any>) | null = null;\nlet reconnectTimeout: ReturnType<typeof setTimeout> | null = null;\nlet pendingNativeRequests = new Map<number, { resolve: (value: any) => void; reject: (err: Error) => void }>();\nlet nativeRequestId = 0;\nlet nativeHostDisconnectHandler: (() => void | Promise<void>) | null = null;\n\nconst INSTANCE_ID_KEY = \"surfBrowserInstanceId\";\nconst EPOCH_KEY = \"surfBrowserEpoch\";\n\nfunction randomId(): string {\n if (globalThis.crypto?.randomUUID) return globalThis.crypto.randomUUID();\n const bytes = new Uint8Array(16);\n globalThis.crypto.getRandomValues(bytes);\n return Array.from(bytes, (value) => value.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\nasync function getBrowserIdentity(): Promise<{ browserInstanceId: string; browserEpoch: string }> {\n const local = await chrome.storage.local.get(INSTANCE_ID_KEY);\n let browserInstanceId = local[INSTANCE_ID_KEY] as string | undefined;\n if (!browserInstanceId) {\n browserInstanceId = randomId();\n await chrome.storage.local.set({ [INSTANCE_ID_KEY]: browserInstanceId });\n }\n\n const session = await chrome.storage.session.get(EPOCH_KEY);\n let browserEpoch = session[EPOCH_KEY] as string | undefined;\n if (!browserEpoch) {\n browserEpoch = randomId();\n await chrome.storage.session.set({ [EPOCH_KEY]: browserEpoch });\n }\n return { browserInstanceId, browserEpoch };\n}\n\nasync function postExtensionHello(port: chrome.runtime.Port): Promise<void> {\n const identity = await getBrowserIdentity();\n if (nativePort !== port) return;\n port.postMessage({\n type: \"EXTENSION_HELLO\",\n protocolVersion: 2,\n extensionVersion: chrome.runtime.getManifest().version,\n capabilities: [\"browser-sessions\", \"strict-targets\", \"keyed-lanes\", \"video-recording\"],\n ...identity,\n });\n}\n\nexport function initNativeMessaging(\n handler: (msg: any) => Promise<any>,\n onDisconnect?: () => void | Promise<void>,\n): void {\n messageHandler = handler;\n nativeHostDisconnectHandler = onDisconnect || null;\n connect();\n}\n\nexport function sendToNativeHost(msg: any): Promise<any> {\n return new Promise((resolve, reject) => {\n if (!nativePort) {\n reject(new Error(\"Native host not connected\"));\n return;\n }\n\n if (msg.type === \"API_REQUEST\") {\n nativePort.postMessage(msg);\n resolve({ sent: true });\n return;\n }\n\n const id = ++nativeRequestId;\n pendingNativeRequests.set(id, { resolve, reject });\n nativePort.postMessage({ ...msg, id });\n\n setTimeout(() => {\n if (pendingNativeRequests.has(id)) {\n pendingNativeRequests.delete(id);\n reject(new Error(\"Native host request timeout\"));\n }\n }, 10000);\n });\n}\n\nexport function postToNativeHost(msg: any): void {\n if (nativePort) nativePort.postMessage(msg);\n}\n\nfunction connect(): void {\n if (reconnectTimeout) {\n clearTimeout(reconnectTimeout);\n reconnectTimeout = null;\n }\n\n try {\n const port = chrome.runtime.connectNative(\"surf.browser.host\");\n nativePort = port;\n debugLog(\"Connecting to native host...\");\n postExtensionHello(port).catch((error) => debugLog(\"Failed to send extension hello:\", error));\n\n port.onMessage.addListener(async (msg) => {\n debugLog(\"Received from native host:\", msg.type || msg.id);\n\n if (msg.type === \"HOST_READY\") {\n debugLog(\"Native host ready\");\n postExtensionHello(port).catch((error) => debugLog(\"Failed to refresh extension hello:\", error));\n return;\n }\n\n if (msg.type?.startsWith(\"API_RESPONSE_\")) {\n chrome.runtime.sendMessage(msg).catch(() => {});\n return;\n }\n\n if (msg.id && pendingNativeRequests.has(msg.id)) {\n const { resolve } = pendingNativeRequests.get(msg.id)!;\n pendingNativeRequests.delete(msg.id);\n resolve(msg);\n return;\n }\n\n if (!messageHandler) return;\n\n try {\n const result = await messageHandler(msg);\n if (nativePort !== port) {\n debugLog(\"Cannot send response - native host disconnected:\", msg.id);\n return;\n }\n port.postMessage({ id: msg.id, ...result });\n } catch (err) {\n if (nativePort !== port) {\n debugLog(\"Cannot send error - native host disconnected:\", msg.id);\n return;\n }\n const error = err as Error & { code?: string; details?: Record<string, unknown> };\n port.postMessage({\n id: msg.id,\n error: error instanceof Error ? error.message : \"Unknown error\",\n errorCode: typeof error?.code === \"string\" ? error.code : undefined,\n errorDetails: error?.details,\n });\n }\n });\n\n port.onDisconnect.addListener(() => {\n const error = chrome.runtime.lastError;\n debugLog(\"Native host disconnected:\", error?.message || \"unknown reason\");\n const wasCurrentPort = nativePort === port;\n if (wasCurrentPort) {\n nativePort = null;\n try {\n Promise.resolve(nativeHostDisconnectHandler?.()).catch((cleanupError) => {\n debugLog(\"Native host disconnect cleanup failed:\", cleanupError);\n });\n } catch (cleanupError) {\n debugLog(\"Native host disconnect cleanup failed:\", cleanupError);\n }\n }\n for (const pending of pendingNativeRequests.values()) {\n pending.reject(new Error(\"Native host disconnected\"));\n }\n pendingNativeRequests.clear();\n\n if (!error?.message?.includes(\"not found\")) {\n reconnectTimeout = setTimeout(connect, 5000);\n }\n });\n } catch (err) {\n debugLog(\"Failed to connect to native host:\", err);\n reconnectTimeout = setTimeout(connect, 10000);\n }\n}\n","import { CDPController } from \"../cdp/controller\";\nimport { debugLog } from \"../utils/debug\";\nimport {\n type CdpFrameEntry,\n DOM_IFRAME_INVENTORY_EXPRESSION,\n type DomIframeEntry,\n type ExtensionFrameEntry,\n buildFrameDiagnosis,\n} from \"../utils/frame-diagnose\";\nimport type { ReadinessExpectations } from \"../utils/page-readiness\";\nimport {\n type ReadinessProbeResult,\n type ReadinessState,\n clampReadinessBudget,\n parseAcceptStates,\n pollReadiness,\n readinessErrorCode,\n} from \"../utils/readiness-poll\";\nimport { initNativeMessaging, postToNativeHost } from \"../native/port-manager\";\n\ndebugLog(\"Service worker loaded\");\n\nconst cdp = new CDPController();\nconst activeStreamTabs = new Map<number, number>();\nlet activeVideoRecorder: { recorderId: string; tabId: number } | null = null;\n\nasync function cleanupActiveVideoRecorder(): Promise<void> {\n const active = activeVideoRecorder;\n if (!active) return;\n\n try {\n await cdp.stopScreencast(active.tabId);\n } catch (error) {\n debugLog(\"Failed to stop video screencast after native host disconnect:\", error);\n } finally {\n cdp.unsubscribeFromScreencast(active.tabId, active.recorderId);\n if (activeVideoRecorder?.recorderId === active.recorderId) activeVideoRecorder = null;\n }\n}\n\nfunction getFrameIdForTab(_tabId: number, message?: { frameId?: unknown }): number {\n const frameId = Number(message?.frameId);\n return Number.isInteger(frameId) && frameId > 0 ? frameId : 0;\n}\n\nasync function validateRequestedFrame(tabId: number, value: unknown): Promise<void> {\n const frameId = Number(value);\n if (!Number.isInteger(frameId) || frameId <= 0) return;\n const frames = await chrome.webNavigation.getAllFrames({ tabId });\n if (frames?.some((frame) => frame.frameId === frameId)) return;\n postToNativeHost({\n type: \"TARGET_EVENT\",\n event: \"frame-reset\",\n tabId,\n frameId,\n reason: \"missing-frame\",\n });\n throw new BrowserCommandError(\n \"frame_context_reset\",\n `Frame context ${frameId} is no longer available in tab ${tabId}`,\n { tabId, frameId, reason: \"missing-frame\", recoveryCommand: \"surf frame.list\" },\n );\n}\n\nfunction isRestrictedTabUrl(url?: string): boolean {\n if (!url) return true;\n return /^(?:about|arc|brave|chrome|chrome-extension|devtools|edge|extension|helium|moz-extension):/i.test(url);\n}\n\nclass BrowserCommandError extends Error {\n code: string;\n details?: Record<string, unknown>;\n\n constructor(code: string, message: string, details?: Record<string, unknown>) {\n super(message);\n this.name = \"BrowserCommandError\";\n this.code = code;\n this.details = details;\n }\n}\n\nasync function inspectTarget(tabId: number): Promise<{\n tabId: number;\n windowId: number;\n url?: string;\n title?: string;\n active: boolean;\n status?: string;\n restricted: boolean;\n groupId: number;\n}> {\n let tab: chrome.tabs.Tab;\n try {\n tab = await chrome.tabs.get(tabId);\n } catch {\n throw new BrowserCommandError(\"tab_gone\", `Tab ${tabId} no longer exists`, { tabId });\n }\n if (!tab.id || tab.windowId === undefined) {\n throw new BrowserCommandError(\"tab_gone\", `Tab ${tabId} no longer has a browser window`, { tabId });\n }\n return {\n tabId: tab.id,\n windowId: tab.windowId,\n url: tab.url,\n title: tab.title,\n active: Boolean(tab.active),\n status: tab.status,\n restricted: isRestrictedTabUrl(tab.url),\n groupId: tab.groupId,\n };\n}\n\nasync function resolveDefaultTarget(windowId?: number, allowCreate = true): Promise<{ tab: chrome.tabs.Tab; autoCreated: boolean }> {\n let tabs: chrome.tabs.Tab[];\n let tab: chrome.tabs.Tab | undefined;\n let autoCreated = false;\n\n if (windowId) {\n tabs = await chrome.tabs.query({ active: true, windowId });\n tab = tabs[0];\n if (!tab || isRestrictedTabUrl(tab.url)) {\n tabs = await chrome.tabs.query({ windowId });\n tab = tabs.find((candidate) => !isRestrictedTabUrl(candidate.url));\n }\n if (!tab?.id && allowCreate) {\n const created = await chrome.tabs.create({\n windowId,\n url: \"data:text/html,<html><head><title>Surf</title></head><body></body></html>\",\n active: true,\n });\n if (!created.id) throw new BrowserCommandError(\"target_create_failed\", `Failed to create tab in window ${windowId}`);\n await sleep(100);\n tab = created;\n autoCreated = true;\n }\n } else {\n tabs = await chrome.tabs.query({ active: true, lastFocusedWindow: true });\n tab = tabs[0];\n if (!tab || isRestrictedTabUrl(tab.url)) {\n tabs = await chrome.tabs.query({ active: true, currentWindow: true });\n tab = tabs[0];\n }\n if (!tab || isRestrictedTabUrl(tab.url)) {\n tabs = await chrome.tabs.query({ active: true });\n tab = tabs.find((candidate) => !isRestrictedTabUrl(candidate.url));\n }\n }\n\n if (!tab?.id) {\n throw new BrowserCommandError(\n \"target_required\",\n \"No active tab found. Use 'surf session.ensure <name> about:blank' or 'surf tab.new <url>'.\",\n );\n }\n return { tab, autoCreated };\n}\n\nasync function labelSessionTab(tabId: number, name: string): Promise<number | undefined> {\n try {\n const groupId = await chrome.tabs.group({ tabIds: tabId });\n await chrome.tabGroups.update(groupId, {\n title: `Surf: ${name}`,\n color: \"blue\",\n collapsed: false,\n });\n return groupId;\n } catch {\n return undefined;\n }\n}\n\nfunction readinessExpectationsFrom(input: unknown): ReadinessExpectations {\n const raw = input && typeof input === \"object\" ? (input as Record<string, unknown>) : {};\n const expect: ReadinessExpectations = {};\n for (const key of [\"selector\", \"text\", \"urlPrefix\", \"emptyText\"] as const) {\n const value = raw[key];\n if (typeof value === \"string\" && value.trim() !== \"\") expect[key] = value;\n }\n return expect;\n}\n\n/**\n * One readiness probe of a tab. A blank tab is `loading` (a navigation is\n * usually pending), other restricted pages are `error`, and an unreachable\n * content script (mid-navigation, or not injected yet) is `loading`, so the\n * poll loop needs no special cases.\n */\nasync function probeTabReadiness(tabId: number, expect: ReadinessExpectations): Promise<ReadinessProbeResult> {\n let tabStatus: string | undefined;\n let tabUrl: string | undefined;\n let pendingUrl: string | undefined;\n try {\n const tab = await chrome.tabs.get(tabId);\n tabStatus = tab.status;\n pendingUrl = tab.pendingUrl;\n tabUrl = pendingUrl || tab.url;\n } catch {}\n if (!tabUrl || tabUrl === \"about:blank\") {\n return { state: \"loading\", evidence: [`tab URL is ${tabUrl || \"empty\"}`], href: tabUrl, tabStatus };\n }\n if (isRestrictedTabUrl(tabUrl)) {\n return { state: \"error\", evidence: [`restricted browser or extension page ${tabUrl}`], href: tabUrl, tabStatus };\n }\n let report;\n try {\n report = await chrome.tabs.sendMessage(tabId, { type: \"PAGE_READINESS\", expect }, { frameId: 0 });\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n return { state: \"loading\", evidence: [`content script unreachable: ${reason}`], href: tabUrl, tabStatus };\n }\n if (report?.state) {\n if (pendingUrl && report.href !== pendingUrl) {\n return {\n state: \"loading\",\n evidence: [`navigation to ${pendingUrl} pending; report is from ${report.href}`],\n href: report.href,\n tabStatus,\n };\n }\n return { ...report, tabStatus };\n }\n if (report?.code === \"invalid_selector\") {\n throw new BrowserCommandError(\"invalid_selector\", String(report.error || \"Invalid CSS selector\"), {\n selector: expect.selector,\n tabId,\n });\n }\n const reason = report?.error ? String(report.error) : \"content script returned no verdict\";\n return { state: \"loading\", evidence: [reason], href: tabUrl, tabStatus };\n}\n\nfunction describeReadiness(result: ReadinessProbeResult): string {\n const where = result.href ? ` at ${result.href}` : \"\";\n const evidence = result.evidence.length > 0 ? ` (${result.evidence.join(\"; \")})` : \"\";\n return `${result.state}${where}${evidence}`;\n}\n\nasync function collectDomIframeInventory(\n tabId: number,\n): Promise<{ href: string; title: string; iframes: DomIframeEntry[] }> {\n const result = await cdp.evaluateScript(tabId, DOM_IFRAME_INVENTORY_EXPRESSION);\n if (result.exceptionDetails) {\n throw new Error(\n result.exceptionDetails.exception?.description ||\n result.exceptionDetails.text ||\n \"Failed to collect the DOM iframe inventory\",\n );\n }\n const value = result.result?.value;\n if (!value || typeof value !== \"object\" || !Array.isArray(value.iframes)) {\n throw new Error(\"Unexpected DOM iframe inventory result shape\");\n }\n return value as { href: string; title: string; iframes: DomIframeEntry[] };\n}\n\n/** webNavigation frames plus a content-script PING per frame. */\nasync function collectExtensionFrames(tabId: number): Promise<ExtensionFrameEntry[]> {\n const frames = (await chrome.webNavigation.getAllFrames({ tabId })) ?? [];\n const entries: ExtensionFrameEntry[] = [];\n for (const frame of frames) {\n const entry: ExtensionFrameEntry = {\n frameId: frame.frameId,\n parentFrameId: frame.parentFrameId,\n url: frame.url,\n errorOccurred: frame.errorOccurred === true,\n contentScriptReachable: false,\n };\n try {\n const ping = await chrome.tabs.sendMessage(tabId, { type: \"PING\" }, { frameId: frame.frameId });\n if (ping?.success) {\n entry.contentScriptReachable = true;\n entry.contentScript = { href: ping.href, readyState: ping.readyState };\n } else {\n entry.contentScriptError = ping?.error ? String(ping.error) : \"no response\";\n }\n } catch (err) {\n entry.contentScriptError = err instanceof Error ? err.message : String(err);\n }\n entries.push(entry);\n }\n return entries;\n}\n\nconst screenshotCache = new Map<string, { base64: string; width: number; height: number }>();\nlet screenshotCounter = 0;\n\nfunction generateScreenshotId(): string {\n return `screenshot_${++screenshotCounter}_${Date.now()}`;\n}\n\nfunction cacheScreenshot(id: string, data: { base64: string; width: number; height: number }): void {\n screenshotCache.set(id, data);\n if (screenshotCache.size > 10) {\n const oldest = screenshotCache.keys().next().value;\n if (oldest) screenshotCache.delete(oldest);\n }\n}\n\nfunction getScreenshot(id: string): { base64: string; width: number; height: number } | null {\n return screenshotCache.get(id) || null;\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nclass ProviderUploadError extends Error {\n code: string;\n\n constructor(code: string, message: string) {\n super(message);\n this.name = \"ProviderUploadError\";\n this.code = code;\n }\n}\n\nfunction uploadError(provider: string, stage: \"selector\" | \"chooser\" | \"processing\", message: string): ProviderUploadError {\n const code = stage === \"selector\"\n ? \"attachment_selector_drift\"\n : stage === \"chooser\" ? \"attachment_chooser_interception\" : \"attachment_processing\";\n const label = stage === \"selector\"\n ? \"UI selector drift\"\n : stage === \"chooser\" ? \"chooser interception\" : \"processing\";\n return new ProviderUploadError(code, `${provider} attachment ${label}: ${message}`);\n}\n\nconst providerUploadStrategies = {\n gemini: {\n openerSelector: 'button[aria-label=\"Upload & tools\"], button[aria-label=\"Open upload file menu\"]',\n closeSelector: 'button[aria-label=\"Close upload file menu\"]',\n uploadItemSelector: '[data-test-id=\"local-images-files-uploader-button\"], [data-testid=\"local-images-files-uploader-button\"], button[aria-label^=\"Upload files\"]',\n },\n chatgpt: {\n directInputSelector: 'form input[type=\"file\"]:not([accept*=\"image\"]), input[type=\"file\"]:not([accept*=\"image\"]), input[type=\"file\"]',\n openerSelector: 'button[data-testid=\"composer-plus-btn\"], button[aria-label=\"Add files and more\"]',\n },\n};\n\nasync function setFileInputFilesBySelector(\n tabId: number,\n filePaths: string[],\n selector: string,\n): Promise<boolean> {\n let result: any;\n try {\n result = await cdp.sendCommand(tabId, \"Runtime.evaluate\", {\n expression: `(() => {\n const input = document.querySelector(${JSON.stringify(selector)});\n if (!input || input.tagName !== 'INPUT' || input.type !== 'file') return null;\n return input;\n })()`,\n userGesture: true,\n });\n } catch (error) {\n throw uploadError(\"ChatGPT\", \"selector\", error instanceof Error ? error.message : String(error));\n }\n if (result?.exceptionDetails) {\n throw uploadError(\"ChatGPT\", \"selector\", \"file input selector evaluation failed\");\n }\n const objectId = result?.result?.objectId;\n if (!objectId) return false;\n try {\n await cdp.sendCommand(tabId, \"DOM.setFileInputFiles\", { files: filePaths, objectId });\n } catch (error) {\n throw uploadError(\"ChatGPT\", \"processing\", error instanceof Error ? error.message : String(error));\n }\n return true;\n}\n\nasync function uploadFilesWithChooser(\n tabId: number,\n filePaths: string[],\n provider: \"gemini\" | \"chatgpt\",\n): Promise<void> {\n try {\n await cdp.sendCommand(tabId, \"Page.setInterceptFileChooserDialog\", { enabled: true });\n } catch (error) {\n throw uploadError(provider, \"chooser\", error instanceof Error ? error.message : String(error));\n }\n\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n let handler: ((source: chrome.debugger.Debuggee, method: string, params: any) => void) | null = null;\n const cleanup = () => {\n if (timeoutId) { clearTimeout(timeoutId); timeoutId = null; }\n if (handler) { chrome.debugger.onEvent.removeListener(handler); handler = null; }\n };\n\n const attemptFileChooser = (attemptNum: number, timeoutMs: number): Promise<void> => {\n return new Promise<void>((resolve, reject) => {\n timeoutId = setTimeout(() => {\n cleanup();\n reject(new Error(`${provider} file chooser did not open within ${timeoutMs / 1000}s (attempt ${attemptNum})`));\n }, timeoutMs);\n handler = (source: chrome.debugger.Debuggee, method: string, params: any) => {\n if (source.tabId === tabId && method === \"Page.fileChooserOpened\") {\n cleanup();\n if (!params?.backendNodeId) {\n reject(uploadError(provider, \"chooser\", \"file chooser did not provide a backend node\"));\n return;\n }\n cdp.sendCommand(tabId, \"DOM.setFileInputFiles\", {\n files: filePaths,\n backendNodeId: params.backendNodeId,\n }).then(() => resolve()).catch((error) => reject(uploadError(\n provider,\n \"processing\",\n error instanceof Error ? error.message : String(error),\n )));\n }\n };\n chrome.debugger.onEvent.addListener(handler);\n });\n };\n\n const clickUploadSequence = async () => {\n if (provider === \"gemini\") {\n await cdp.sendCommand(tabId, \"Runtime.evaluate\", {\n expression: `document.querySelector(${JSON.stringify(providerUploadStrategies.gemini.closeSelector)})?.click()`,\n userGesture: true,\n });\n await sleep(300);\n await cdp.sendCommand(tabId, \"Runtime.evaluate\", {\n expression: `document.querySelector(${JSON.stringify(providerUploadStrategies.gemini.openerSelector)})?.click()`,\n userGesture: true,\n });\n await sleep(500);\n await cdp.sendCommand(tabId, \"Runtime.evaluate\", {\n expression: `document.querySelector(${JSON.stringify(providerUploadStrategies.gemini.uploadItemSelector)})?.click()`,\n userGesture: true,\n });\n return;\n }\n\n let result: any;\n try {\n result = await cdp.sendCommand(tabId, \"Runtime.evaluate\", {\n expression: `(() => { const button = document.querySelector(${JSON.stringify(providerUploadStrategies.chatgpt.openerSelector)}); if (!button) return false; button.click(); return true; })()`,\n userGesture: true,\n });\n } catch (error) {\n throw uploadError(\"ChatGPT\", \"selector\", error instanceof Error ? error.message : String(error));\n }\n if (result?.exceptionDetails) {\n throw uploadError(\"ChatGPT\", \"selector\", \"Add files selector evaluation failed\");\n }\n if (result?.result?.value === false || result?.result?.value === null) {\n throw uploadError(\"ChatGPT\", \"selector\", \"Add files control was not found\");\n }\n };\n\n const maxAttempts = 3;\n const timeouts = [10000, 15000, 20000];\n let lastError: Error | null = null;\n\n try {\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const fileSetPromise = attemptFileChooser(attempt, timeouts[attempt - 1]);\n await clickUploadSequence();\n await fileSetPromise;\n return;\n } catch (err) {\n lastError = err as Error;\n cleanup();\n const errorCode = (lastError as Error & { code?: string })?.code;\n if (errorCode && errorCode !== \"attachment_chooser_interception\") throw lastError;\n if (attempt < maxAttempts) await sleep(1000);\n }\n }\n throw lastError || uploadError(provider, \"chooser\", \"file chooser did not open\");\n } finally {\n cleanup();\n try { await cdp.sendCommand(tabId, \"Page.setInterceptFileChooserDialog\", { enabled: false }); } catch {}\n }\n}\n\nasync function uploadFilesToProviderTab(\n provider: \"gemini\" | \"chatgpt\",\n tabId: number,\n filePaths: string[],\n): Promise<{ success: true }> {\n try {\n await cdp.attach(tabId);\n await cdp.sendCommand(tabId, \"DOM.enable\", {});\n } catch (error) {\n throw uploadError(provider === \"chatgpt\" ? \"ChatGPT\" : \"Gemini\", \"selector\", error instanceof Error ? error.message : String(error));\n }\n\n if (provider === \"chatgpt\") {\n const directUpload = await setFileInputFilesBySelector(\n tabId,\n filePaths,\n providerUploadStrategies.chatgpt.directInputSelector,\n );\n if (directUpload) return { success: true };\n }\n\n await uploadFilesWithChooser(tabId, filePaths, provider);\n return { success: true };\n}\n\nconst ELEMENT_COLORS: Record<string, string> = {\n button: '#FF6B6B',\n input: '#4ECDC4',\n select: '#45B7D1',\n a: '#96CEB4',\n textarea: '#FF8C42',\n default: '#DDA0DD',\n};\n\nasync function annotateScreenshot(\n screenshot: { base64: string; width: number; height: number },\n elements: Array<{ ref: string; tag: string; bounds: { x: number; y: number; width: number; height: number } }>,\n scale: { scaleX: number; scaleY: number }\n): Promise<{ base64: string; width: number; height: number }> {\n const blob = base64ToBlob(screenshot.base64);\n const bitmap = await createImageBitmap(blob);\n\n const canvas = new OffscreenCanvas(bitmap.width, bitmap.height);\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) throw new Error(\"Failed to get canvas context\");\n\n ctx.drawImage(bitmap, 0, 0);\n bitmap.close();\n\n const scaleFactor = Math.min(scale.scaleX, scale.scaleY);\n\n for (const element of elements) {\n const color = ELEMENT_COLORS[element.tag] || ELEMENT_COLORS.default;\n\n const x = Math.round(element.bounds.x * scaleFactor);\n const y = Math.round(element.bounds.y * scaleFactor);\n const w = Math.round(element.bounds.width * scaleFactor);\n const h = Math.round(element.bounds.height * scaleFactor);\n\n if (w < 1 || h < 1) continue;\n\n ctx.strokeStyle = color;\n ctx.lineWidth = 2;\n ctx.setLineDash([4, 4]);\n ctx.strokeRect(x, y, w, h);\n ctx.setLineDash([]);\n\n const labelText = element.ref;\n const fontSize = Math.max(10, Math.min(16, Math.round(canvas.width * 0.01)));\n ctx.font = `bold ${fontSize}px sans-serif`;\n const textWidth = ctx.measureText(labelText).width;\n const padding = 4;\n const labelWidth = textWidth + padding * 2;\n const labelHeight = fontSize + padding * 2;\n\n let labelX = x + Math.floor((w - labelWidth) / 2);\n let labelY = y + 2;\n if (w < 60 || h < 30) {\n labelY = y - labelHeight - 2 < 0 ? y + h + 2 : y - labelHeight - 2;\n }\n\n labelX = Math.max(0, Math.min(canvas.width - labelWidth, labelX));\n labelY = Math.max(0, Math.min(canvas.height - labelHeight, labelY));\n\n ctx.fillStyle = color;\n ctx.fillRect(labelX, labelY, labelWidth, labelHeight);\n ctx.strokeStyle = \"white\";\n ctx.lineWidth = 1;\n ctx.strokeRect(labelX, labelY, labelWidth, labelHeight);\n\n ctx.fillStyle = \"white\";\n ctx.textBaseline = \"top\";\n ctx.fillText(labelText, labelX + padding, labelY + padding);\n }\n\n const resultBlob = await canvas.convertToBlob({ type: \"image/png\" });\n const base64 = await blobToBase64(resultBlob);\n\n return { base64, width: canvas.width, height: canvas.height };\n}\n\nfunction blobToBase64(blob: Blob): Promise<string> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = () => {\n const dataUrl = reader.result as string;\n const base64 = dataUrl.split(\",\")[1];\n resolve(base64);\n };\n reader.onerror = () => reject(new Error(\"Failed to convert blob to base64\"));\n reader.readAsDataURL(blob);\n });\n}\n\nfunction base64ToBlob(base64: string, mimeType = \"image/png\"): Blob {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return new Blob([bytes], { type: mimeType });\n}\n\nfunction codeWithExpressionReturn(code: string): string {\n return `return (\\n${code}\\n);`;\n}\n\n/**\n * Whether the wrapped statement body parses. The MV3 extension CSP\n * (`script-src 'self'`) makes `new Function` throw an EvalError inside the\n * service worker; in that case ask the page's parser through CDP instead,\n * which compiles without running anything.\n */\nasync function statementBodyParses(tabId: number, body: string): Promise<boolean> {\n try {\n new Function(body);\n return true;\n } catch (err) {\n if (err instanceof SyntaxError) return false;\n }\n const compiled = await cdp.compileScript(tabId, `(async () => { 'use strict'; ${body} })()`);\n return compiled.parses;\n}\n\nasync function captureFullPage(tabId: number, maxHeight: number): Promise<{ base64: string; width: number; height: number }> {\n const dimensionsResult = await cdp.evaluateScript(tabId, `(() => ({\n viewportHeight: window.innerHeight,\n totalHeight: Math.min(document.documentElement.scrollHeight, ${maxHeight}),\n width: window.innerWidth,\n devicePixelRatio: window.devicePixelRatio || 1,\n originalScrollY: window.scrollY,\n }))()`);\n\n const dimensions = dimensionsResult.result?.value;\n if (!dimensions) throw new Error(\"Failed to get page dimensions\");\n\n const { viewportHeight, totalHeight, width, devicePixelRatio, originalScrollY } = dimensions;\n const chunks: ImageBitmap[] = [];\n let currentY = 0;\n\n while (currentY < totalHeight) {\n await cdp.evaluateScript(tabId, `window.scrollTo(0, ${currentY})`);\n await new Promise(r => setTimeout(r, 300));\n\n const chunk = await cdp.captureScreenshot(tabId);\n const chunkBlob = base64ToBlob(chunk.base64);\n chunks.push(await createImageBitmap(chunkBlob));\n\n currentY += viewportHeight;\n }\n\n await cdp.evaluateScript(tabId, `window.scrollTo(0, ${originalScrollY})`);\n\n const canvasWidth = Math.round(width * devicePixelRatio);\n const canvasHeight = Math.round(totalHeight * devicePixelRatio);\n const canvas = new OffscreenCanvas(canvasWidth, canvasHeight);\n const ctx = canvas.getContext(\"2d\");\n if (!ctx) throw new Error(\"Failed to get canvas context\");\n\n let y = 0;\n const chunkHeight = Math.round(viewportHeight * devicePixelRatio);\n for (let i = 0; i < chunks.length; i++) {\n const chunk = chunks[i];\n const remainingHeight = canvasHeight - y;\n const drawHeight = Math.min(chunkHeight, remainingHeight);\n ctx.drawImage(chunk, 0, 0, chunk.width, drawHeight, 0, y, chunk.width, drawHeight);\n y += drawHeight;\n chunk.close();\n }\n\n const resultBlob = await canvas.convertToBlob({ type: \"image/png\" });\n const base64 = await blobToBase64(resultBlob);\n\n return { base64, width: canvasWidth, height: canvasHeight };\n}\n\nconst navigationResolvers = new Map<number, () => void>();\nconst tabNameRegistry = new Map<string, number>();\n\nchrome.webNavigation.onCompleted.addListener((details) => {\n if (details.frameId === 0) {\n // Clear frame context on main frame navigation (iframes may have changed)\n chrome.tabs.get(details.tabId)\n .then((tab) => postToNativeHost({\n type: \"TARGET_EVENT\",\n event: \"navigation\",\n tabId: details.tabId,\n url: details.url,\n title: tab.title,\n }))\n .catch(() => postToNativeHost({ type: \"TARGET_EVENT\", event: \"navigation\", tabId: details.tabId, url: details.url }));\n const resolver = navigationResolvers.get(details.tabId);\n if (resolver) {\n resolver();\n navigationResolvers.delete(details.tabId);\n }\n }\n});\n\nchrome.webNavigation.onErrorOccurred.addListener((details) => {\n if (details.frameId === 0) {\n const resolver = navigationResolvers.get(details.tabId);\n if (resolver) {\n resolver();\n navigationResolvers.delete(details.tabId);\n }\n }\n});\n\n\n\nchrome.tabs.onRemoved.addListener((tabId) => {\n postToNativeHost({ type: \"TARGET_EVENT\", event: \"tab-removed\", tabId });\n cdp.detach(tabId);\n for (const [name, id] of tabNameRegistry) {\n if (id === tabId) {\n tabNameRegistry.delete(name);\n }\n }\n for (const [streamId, streamTabId] of activeStreamTabs) {\n if (streamTabId === tabId) {\n activeStreamTabs.delete(streamId);\n }\n }\n if (activeVideoRecorder?.tabId === tabId) activeVideoRecorder = null;\n});\n\nchrome.windows.onRemoved.addListener((windowId) => {\n postToNativeHost({ type: \"TARGET_EVENT\", event: \"window-removed\", windowId });\n});\n\n/**\n * Wait for JavaScript runtime to be ready in a newly created/attached tab.\n * This is needed because document.readyState === 'complete' doesn't mean\n * React/Vue/etc frameworks have finished hydrating.\n */\nasync function waitForRuntimeReady(tabId: number, timeoutMs = 10000): Promise<void> {\n const deadline = Date.now() + timeoutMs;\n\n // Poll until we can successfully evaluate JS\n while (Date.now() < deadline) {\n try {\n const result = await cdp.evaluateScript(tabId, \"document.readyState\");\n if (result?.result?.value === \"complete\") {\n // Extra delay for framework hydration (React, Vue, etc.)\n await sleep(1500);\n return;\n }\n } catch {\n // CDP not ready yet, continue polling\n }\n await sleep(200);\n }\n\n // Timeout but proceed anyway - the page might still work\n console.warn(`waitForRuntimeReady timed out for tab ${tabId}`);\n}\n\n// Helper for locate.* commands with actions\nasync function performLocateAction(\n tabId: number,\n ref: string,\n action: string,\n value: string | undefined,\n cdp: CDPController,\n frameId: number = 0\n): Promise<any> {\n switch (action) {\n case \"click\": {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"CLICK_ELEMENT\",\n ref,\n button: \"left\",\n }, { frameId });\n return result.error ? result : { success: true, action: \"click\", ref };\n }\n case \"fill\": {\n if (!value) return { error: \"fill action requires --value\" };\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"FORM_INPUT\",\n ref,\n value,\n }, { frameId });\n return result.error ? result : { success: true, action: \"fill\", ref, value };\n }\n case \"hover\": {\n const coords = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_COORDINATES\",\n ref,\n }, { frameId });\n if (coords.error) return coords;\n await cdp.hover(tabId, coords.x, coords.y);\n return { success: true, action: \"hover\", ref };\n }\n case \"text\": {\n const textResult = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_TEXT\",\n ref,\n }, { frameId });\n return textResult;\n }\n default:\n return { error: `Unknown action: ${action}. Use click|fill|hover|text` };\n }\n}\n\nchrome.runtime.onMessage.addListener((message, sender, sendResponse) => {\n handleMessage(message, sender)\n .then(sendResponse)\n .catch((err) => sendResponse({ error: err.message }));\n return true;\n});\n\nexport async function handleMessage(\n message: any,\n sender: chrome.runtime.MessageSender\n): Promise<any> {\n const tabId = message.tabId;\n\n switch (message.type) {\n case \"GET_CURRENT_TAB_ID\": {\n const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });\n return { tabId: tab?.id };\n }\n\n case \"TARGET_INSPECT\": {\n const targetTabId = Number(message.tabId);\n if (!Number.isInteger(targetTabId) || targetTabId <= 0) {\n throw new BrowserCommandError(\"target_required\", \"TARGET_INSPECT requires a valid tabId\");\n }\n return inspectTarget(targetTabId);\n }\n\n case \"TARGET_RESOLVE\": {\n const requestedWindowId = message.windowId === undefined ? undefined : Number(message.windowId);\n if (requestedWindowId !== undefined && (!Number.isInteger(requestedWindowId) || requestedWindowId <= 0)) {\n throw new BrowserCommandError(\"target_invalid\", \"windowId must be a positive integer\");\n }\n const { tab, autoCreated } = await resolveDefaultTarget(requestedWindowId, message.allowCreate !== false);\n const inspected = await inspectTarget(tab.id!);\n return { ...inspected, autoCreated };\n }\n\n case \"SESSION_CREATE_TARGET\": {\n const name = String(message.name || \"\");\n const url = typeof message.url === \"string\" && message.url ? message.url : \"about:blank\";\n const mode = message.mode === \"tab\" ? \"tab\" : \"window\";\n const focused = message.focused === true;\n let createdTab: chrome.tabs.Tab | undefined;\n let createdWindowId: number | undefined;\n\n if (mode === \"tab\") {\n const createOptions: chrome.tabs.CreateProperties = { url, active: focused };\n if (message.windowId !== undefined) {\n const targetWindowId = Number(message.windowId);\n if (!Number.isInteger(targetWindowId) || targetWindowId <= 0) {\n throw new BrowserCommandError(\"target_invalid\", \"--window-id must be a positive integer\");\n }\n createOptions.windowId = targetWindowId;\n }\n createdTab = await chrome.tabs.create(createOptions);\n createdWindowId = createdTab.windowId;\n } else {\n const createdWindow = await chrome.windows.create({\n url,\n focused,\n type: \"normal\",\n });\n if (!createdWindow) {\n throw new BrowserCommandError(\"target_create_failed\", `Failed to create target for session ${name}`);\n }\n createdWindowId = createdWindow.id;\n createdTab = createdWindow.tabs?.[0];\n if (!createdTab && createdWindowId !== undefined) {\n const tabs = await chrome.tabs.query({ windowId: createdWindowId });\n createdTab = tabs[0];\n }\n }\n\n if (!createdTab?.id || createdWindowId === undefined) {\n throw new BrowserCommandError(\"target_create_failed\", `Failed to create target for session ${name}`);\n }\n const groupId = await labelSessionTab(createdTab.id, name);\n const inspected = await inspectTarget(createdTab.id);\n return { ...inspected, mode, groupId };\n }\n\n case \"SESSION_CLOSE_TARGET\": {\n const targetTabId = Number(message.tabId);\n if (!Number.isInteger(targetTabId) || targetTabId <= 0) {\n throw new BrowserCommandError(\"target_required\", \"SESSION_CLOSE_TARGET requires a valid tabId\");\n }\n try {\n await chrome.tabs.remove(targetTabId);\n } catch {\n return { success: true, tabId: targetTabId, alreadyGone: true };\n }\n return { success: true, tabId: targetTabId };\n }\n\n case \"EXECUTE_SCREENSHOT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n\n try {\n let result: { base64: string; width: number; height: number };\n let scaleInfo = { scaleX: 1, scaleY: 1 };\n let usedFallback = false;\n\n if (message.fullpage) {\n result = await captureFullPage(tabId, message.maxHeight || 4000);\n try {\n const viewport = await cdp.getViewportSize(tabId);\n const dpr = result.width / viewport.width;\n scaleInfo = { scaleX: dpr, scaleY: dpr };\n } catch {}\n } else {\n try {\n const rawResult = await cdp.captureScreenshot(tabId);\n result = rawResult;\n try {\n const viewport = await cdp.getViewportSize(tabId);\n scaleInfo = {\n scaleX: rawResult.width / viewport.width,\n scaleY: rawResult.height / viewport.height,\n };\n } catch {}\n } catch (cdpError) {\n const tab = await chrome.tabs.get(tabId);\n if (!tab.windowId) throw cdpError;\n if (message.strictTarget) {\n const [activeTab] = await chrome.tabs.query({ active: true, windowId: tab.windowId });\n if (activeTab?.id !== tabId) {\n throw new BrowserCommandError(\n \"screenshot_target_not_visible\",\n `Cannot use screenshot fallback because tab ${tabId} is not visible in window ${tab.windowId}`,\n { tabId, windowId: tab.windowId, activeTabId: activeTab?.id },\n );\n }\n }\n const dataUrl = await chrome.tabs.captureVisibleTab(tab.windowId, { format: \"png\" });\n const base64 = dataUrl.replace(/^data:image\\/png;base64,/, \"\");\n const binaryString = atob(base64);\n const bytes = new Uint8Array(binaryString.length);\n for (let i = 0; i < binaryString.length; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n const blob = new Blob([bytes], { type: \"image/png\" });\n const bitmap = await createImageBitmap(blob);\n result = { base64, width: bitmap.width, height: bitmap.height };\n bitmap.close();\n usedFallback = true;\n }\n }\n\n if (message.annotate && !usedFallback) {\n try {\n const treeResult = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_BOUNDS_FOR_ANNOTATION\",\n }, { frameId: 0 });\n\n if (treeResult?.elements && treeResult.elements.length > 0) {\n result = await annotateScreenshot(result, treeResult.elements, scaleInfo);\n }\n } catch {}\n }\n\n const screenshotId = generateScreenshotId();\n cacheScreenshot(screenshotId, result);\n return { ...result, screenshotId };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n }\n }\n\n case \"EXECUTE_CLICK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.click(tabId, message.x, message.y, \"left\", 1, mods);\n return { success: true };\n }\n\n case \"EXECUTE_RIGHT_CLICK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.rightClick(tabId, message.x, message.y, mods);\n return { success: true };\n }\n\n case \"EXECUTE_DOUBLE_CLICK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.doubleClick(tabId, message.x, message.y, mods);\n return { success: true };\n }\n\n case \"EXECUTE_TRIPLE_CLICK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.tripleClick(tabId, message.x, message.y, mods);\n return { success: true };\n }\n\n case \"EXECUTE_DRAG\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const mods = message.modifiers ? cdp.parseModifiers(message.modifiers) : 0;\n await cdp.drag(tabId, message.startX, message.startY, message.endX, message.endY, mods);\n return { success: true };\n }\n\n case \"EXECUTE_HOVER\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await cdp.hover(tabId, message.x, message.y);\n return { success: true };\n }\n\n case \"EXECUTE_TYPE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.text === undefined || message.text === null) throw new Error(\"No text provided\");\n await cdp.type(tabId, message.text);\n return { success: true };\n }\n\n case \"TYPE_SUBMIT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n await cdp.type(tabId, message.text);\n await cdp.pressKey(tabId, message.submitKey || \"Enter\");\n return { success: true };\n }\n\n case \"CLICK_TYPE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n const clickTypeFrameId = getFrameIdForTab(tabId, message);\n let clicked = false;\n if (message.ref) {\n try {\n const result = await chrome.tabs.sendMessage(tabId, { type: \"CLICK_ELEMENT\", ref: message.ref, button: \"left\" }, { frameId: clickTypeFrameId });\n if (!result.error) clicked = true;\n } catch {}\n }\n if (!clicked && message.coordinate) {\n await cdp.click(tabId, message.coordinate[0], message.coordinate[1], \"left\", 1, 0);\n clicked = true;\n }\n if (!clicked) {\n const result = await cdp.evaluateScript(tabId, `(() => {\n const el = document.querySelector('textarea, input[type=\"text\"], input[type=\"search\"], input:not([type]), [contenteditable=\"true\"]');\n if (!el) return null;\n const r = el.getBoundingClientRect();\n return { x: r.left + r.width/2, y: r.top + r.height/2 };\n })()`);\n if (result.result?.value) {\n await cdp.click(tabId, result.result.value.x, result.result.value.y, \"left\", 1, 0);\n clicked = true;\n }\n }\n if (!clicked) return { error: \"Could not find input element\" };\n await cdp.type(tabId, message.text);\n return { success: true };\n }\n\n case \"CLICK_TYPE_SUBMIT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n const clickTypeSubmitFrameId = getFrameIdForTab(tabId, message);\n let clicked = false;\n if (message.ref) {\n try {\n const result = await chrome.tabs.sendMessage(tabId, { type: \"CLICK_ELEMENT\", ref: message.ref, button: \"left\" }, { frameId: clickTypeSubmitFrameId });\n if (!result.error) clicked = true;\n } catch {}\n }\n if (!clicked && message.coordinate) {\n await cdp.click(tabId, message.coordinate[0], message.coordinate[1], \"left\", 1, 0);\n clicked = true;\n }\n if (!clicked) {\n const result = await cdp.evaluateScript(tabId, `(() => {\n const el = document.querySelector('textarea, input[type=\"text\"], input[type=\"search\"], input:not([type]), [contenteditable=\"true\"]');\n if (!el) return null;\n const r = el.getBoundingClientRect();\n return { x: r.left + r.width/2, y: r.top + r.height/2 };\n })()`);\n if (result.result?.value) {\n await cdp.click(tabId, result.result.value.x, result.result.value.y, \"left\", 1, 0);\n clicked = true;\n }\n }\n if (!clicked) return { error: \"Could not find input element\" };\n await cdp.type(tabId, message.text);\n await cdp.pressKey(tabId, message.submitKey || \"Enter\");\n return { success: true };\n }\n\n case \"FIND_AND_TYPE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n const findResult = await cdp.evaluateScript(tabId, `(() => {\n const selectors = [\n 'textarea:not([readonly]):not([disabled])',\n 'input[type=\"text\"]:not([readonly]):not([disabled])',\n 'input[type=\"search\"]:not([readonly]):not([disabled])',\n 'input:not([type]):not([readonly]):not([disabled])',\n '[contenteditable=\"true\"]',\n '[role=\"textbox\"]'\n ];\n for (const sel of selectors) {\n const el = document.querySelector(sel);\n if (el) {\n const r = el.getBoundingClientRect();\n if (r.width > 0 && r.height > 0) {\n el.focus();\n return { x: r.left + r.width/2, y: r.top + r.height/2, found: true };\n }\n }\n }\n return { found: false };\n })()`);\n const coords = findResult.result?.value;\n if (!coords?.found) return { error: \"No input field found on page\" };\n await cdp.click(tabId, coords.x, coords.y, \"left\", 1, 0);\n await cdp.type(tabId, message.text);\n if (message.submit) {\n await cdp.pressKey(tabId, message.submitKey || \"Enter\");\n }\n return { success: true, coordinates: { x: coords.x, y: coords.y } };\n }\n\n case \"AUTOCOMPLETE_SELECT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"No text provided\");\n const autocompleteFrameId = getFrameIdForTab(tabId, message);\n let clicked = false;\n if (message.ref) {\n try {\n const result = await chrome.tabs.sendMessage(tabId, { type: \"CLICK_ELEMENT\", ref: message.ref, button: \"left\" }, { frameId: autocompleteFrameId });\n if (!result.error) clicked = true;\n } catch {}\n }\n if (!clicked && message.coordinate) {\n await cdp.click(tabId, message.coordinate[0], message.coordinate[1], \"left\", 1, 0);\n clicked = true;\n }\n if (!clicked) return { error: \"ref or coordinate required\" };\n await new Promise(r => setTimeout(r, 100));\n await cdp.type(tabId, message.text);\n const waitMs = message.waitMs || 500;\n await new Promise(r => setTimeout(r, waitMs));\n if (message.index && message.index > 0) {\n for (let i = 0; i < message.index; i++) {\n await cdp.pressKey(tabId, \"ArrowDown\");\n await new Promise(r => setTimeout(r, 50));\n }\n }\n await cdp.pressKey(tabId, \"Enter\");\n return { success: true };\n }\n\n case \"SET_INPUT_VALUE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.value === undefined) throw new Error(\"No value provided\");\n const selector = message.selector;\n const ref = message.ref;\n if (!selector && !ref) throw new Error(\"selector or ref required\");\n\n const script = ref\n ? `(() => {\n const el = document.querySelector('[data-pi-ref=\"${ref}\"]') ||\n [...document.querySelectorAll('*')].find(e => e.getAttribute?.('data-ref') === '${ref}');\n if (!el) return { error: 'Element not found' };\n el.focus();\n const isContentEditable = el.isContentEditable || el.getAttribute('contenteditable') === 'true';\n const target = isContentEditable ? (el.querySelector('p') || el) : el;\n if (isContentEditable) {\n target.textContent = ${JSON.stringify(message.value)};\n } else {\n el.value = ${JSON.stringify(message.value)};\n }\n el.dispatchEvent(new Event('input', { bubbles: true }));\n el.dispatchEvent(new Event('change', { bubbles: true }));\n return { success: true, contentEditable: isContentEditable };\n })()`\n : `(() => {\n const el = document.querySelector(${JSON.stringify(selector)});\n if (!el) return { error: 'Element not found: ' + ${JSON.stringify(selector)} };\n el.focus();\n const isContentEditable = el.isContentEditable || el.getAttribute('contenteditable') === 'true';\n const target = isContentEditable ? (el.querySelector('p') || el) : el;\n if (isContentEditable) {\n target.textContent = ${JSON.stringify(message.value)};\n } else {\n el.value = ${JSON.stringify(message.value)};\n }\n el.dispatchEvent(new Event('input', { bubbles: true }));\n el.dispatchEvent(new Event('change', { bubbles: true }));\n return { success: true, contentEditable: isContentEditable };\n })()`;\n\n const result = await cdp.evaluateScript(tabId, script);\n return result.result?.value || { error: \"Script failed\" };\n }\n\n case \"SMART_TYPE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const { selector, text, clear = true, submit = false } = message;\n if (!selector) throw new Error(\"selector required\");\n if (text === undefined) throw new Error(\"text required\");\n\n try {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"SMART_TYPE\",\n selector,\n text,\n clear,\n submit,\n }, { frameId: getFrameIdForTab(tabId, message) });\n } catch (err) {\n throw new Error(`Could not type into selector: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n case \"CLOSE_DIALOGS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const maxAttempts = message.maxAttempts || 3;\n for (let i = 0; i < maxAttempts; i++) {\n await cdp.pressKey(tabId, \"Escape\");\n await new Promise(r => setTimeout(r, 100));\n }\n return { success: true };\n }\n\n case \"PAGE_STATE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const stateScript = `(() => {\n const hasModal = !!(\n document.querySelector('[role=\"dialog\"]') ||\n document.querySelector('[role=\"alertdialog\"]') ||\n document.querySelector('.modal:not([hidden])') ||\n document.querySelector('[aria-modal=\"true\"]') ||\n document.querySelector('.MuiModal-root') ||\n document.querySelector('.MuiDialog-root')\n );\n const hasDropdown = !!(\n document.querySelector('[role=\"listbox\"]') ||\n document.querySelector('[role=\"menu\"]:not([hidden])') ||\n document.querySelector('.dropdown-menu.show') ||\n document.querySelector('[aria-expanded=\"true\"]')\n );\n const hasDatePicker = !!(\n document.querySelector('[role=\"grid\"][aria-label*=\"calendar\" i]') ||\n document.querySelector('.react-datepicker') ||\n document.querySelector('.flatpickr-calendar.open') ||\n document.querySelector('[class*=\"DatePicker\"]')\n );\n const focusedEl = document.activeElement;\n const focusedTag = focusedEl?.tagName?.toLowerCase();\n const focusedType = focusedEl?.getAttribute?.('type');\n return {\n hasModal,\n hasDropdown,\n hasDatePicker,\n hasOverlay: hasModal || hasDropdown || hasDatePicker,\n focusedElement: focusedTag ? { tag: focusedTag, type: focusedType } : null,\n url: location.href,\n title: document.title\n };\n })()`;\n const stateResult = await cdp.evaluateScript(tabId, stateScript);\n return stateResult.result?.value || { error: \"Failed to get page state\" };\n }\n\n case \"SEMANTIC_LOCAL_COMPARE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n return await chrome.tabs.sendMessage(tabId, {\n type: \"SEMANTIC_LOCAL_COMPARE\",\n ref: message.ref,\n predicate: message.predicate,\n expectedIdentity: message.expectedIdentity,\n }, { frameId: getFrameIdForTab(tabId, message) });\n }\n\n case \"SEMANTIC_SCROLL_SCOPE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n return await chrome.tabs.sendMessage(tabId, {\n type: \"SEMANTIC_SCROLL_SCOPE\",\n action: message.action,\n scopeToken: message.scopeToken,\n expectedIdentity: message.expectedIdentity,\n }, { frameId: getFrameIdForTab(tabId, message) });\n }\n\n case \"EXECUTE_SCROLL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const deltaX = message.deltaX || 0;\n const deltaY = message.deltaY || 0;\n if (message.expectedIdentity) {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"SEMANTIC_SCROLL\",\n deltaX,\n deltaY,\n expectedIdentity: message.expectedIdentity,\n }, { frameId: getFrameIdForTab(tabId, message) });\n }\n\n const scrollScript = (dx: number, dy: number) => {\n const before = { x: window.scrollX, y: window.scrollY };\n window.scrollBy(dx, dy);\n const after = { x: window.scrollX, y: window.scrollY };\n return {\n scrollX: after.x,\n scrollY: after.y,\n pageHeight: document.documentElement.scrollHeight,\n viewportHeight: window.innerHeight,\n scrolled: before.x !== after.x || before.y !== after.y\n };\n };\n\n try {\n const result = await cdp.evaluateScript(tabId,\n `(${scrollScript.toString()})(${deltaX}, ${deltaY})`\n );\n return result.result?.value || { error: \"Script failed\" };\n } catch {\n try {\n const results = await chrome.scripting.executeScript({\n target: { tabId },\n func: scrollScript,\n args: [deltaX, deltaY],\n });\n return results[0]?.result || { error: \"Script failed\" };\n } catch {\n return { error: \"Cannot scroll on this page (restricted)\" };\n }\n }\n }\n\n case \"EXECUTE_KEY\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const key = message.key;\n if (!key) throw new Error(\"No key provided\");\n if (key.includes(\"+\")) {\n await cdp.pressKeyChord(tabId, key);\n } else {\n await cdp.pressKey(tabId, key);\n }\n return { success: true };\n }\n\n case \"EXECUTE_NAVIGATE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.url) throw new Error(\"No url provided\");\n if (message.expectedIdentity) {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"SEMANTIC_NAVIGATE\",\n url: message.url,\n expectedIdentity: message.expectedIdentity,\n }, { frameId: getFrameIdForTab(tabId, message) });\n }\n\n const navigationPromise = new Promise<void>((resolve) => {\n navigationResolvers.set(tabId, resolve);\n setTimeout(() => {\n if (navigationResolvers.has(tabId)) {\n navigationResolvers.delete(tabId);\n resolve();\n }\n }, 30000);\n });\n\n await chrome.tabs.update(tabId, { url: message.url });\n await navigationPromise;\n\n await new Promise(resolve => setTimeout(resolve, 500));\n\n return { success: true };\n }\n\n case \"GET_VIEWPORT_SIZE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n return await cdp.getViewportSize(tabId);\n }\n\n case \"READ_PAGE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const readFrameId = getFrameIdForTab(tabId, message);\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n\n let result;\n try {\n result = await chrome.tabs.sendMessage(tabId, {\n type: \"GENERATE_ACCESSIBILITY_TREE\",\n options: message.options || {},\n }, { frameId: readFrameId });\n } catch (err) {\n return {\n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n }\n\n // Include visible text content if requested\n if (message.options?.includeText) {\n try {\n const textResult = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_PAGE_TEXT\",\n options: {\n compact: message.options?.compact === true,\n maxBytes: message.options?.maxBytes,\n },\n }, { frameId: readFrameId });\n if (textResult?.text) {\n result.text = textResult.text;\n }\n } catch (err) {\n // Ignore text extraction errors\n }\n }\n\n if (message.options?.includeScreenshot) {\n try {\n const screenshot = await cdp.captureScreenshot(tabId);\n return { ...result, screenshot };\n } catch (err) {\n return {\n ...result,\n screenshotError: err instanceof Error ? err.message : \"Failed to capture screenshot\",\n };\n }\n }\n if (result?.semanticObservation?.identity) {\n result.semanticObservation.identity.tabId = tabId;\n result.semanticObservation.identity.frameId = readFrameId;\n }\n return result;\n }\n\n case \"GET_ELEMENT_COORDINATES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_COORDINATES\",\n ref: message.ref,\n }, { frameId: getFrameIdForTab(tabId, message) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"FORM_INPUT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"FORM_INPUT\",\n ref: message.ref,\n value: message.value,\n }, { frameId: getFrameIdForTab(tabId, message) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"EVAL_IN_PAGE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.code) throw new Error(\"No code provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"EVAL_IN_PAGE\",\n code: message.code,\n }, { frameId: getFrameIdForTab(tabId, message) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"SCROLL_TO_ELEMENT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"SCROLL_TO_ELEMENT\",\n ref: message.ref,\n }, { frameId: getFrameIdForTab(tabId, message) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"SCROLL_TO_POSITION\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const position = message.position;\n if (position === undefined) throw new Error(\"position required (\\\"top\\\", \\\"bottom\\\", or number)\");\n const selector = message.selector;\n if (message.expectedIdentity) {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"SEMANTIC_SCROLL\",\n position,\n expectedIdentity: message.expectedIdentity,\n }, { frameId: getFrameIdForTab(tabId, message) });\n }\n\n try {\n return await chrome.tabs.sendMessage(tabId, {\n type: \"SCROLL_TO_POSITION\",\n position,\n selector,\n }, { frameId: getFrameIdForTab(tabId, message) });\n } catch {}\n\n const scrollScript = (pos: string | number, sel: string | null) => {\n const findScrollable = (): Element => {\n const candidates = [...document.querySelectorAll(\"*\")].filter(el =>\n el.scrollHeight > el.clientHeight && el.clientHeight > 200\n ).sort((a,b) => b.scrollHeight - a.scrollHeight);\n return candidates[0] || document.documentElement;\n };\n\n const container = sel ? document.querySelector(sel) || findScrollable() : findScrollable();\n if (!container) return { error: \"No scrollable container found\" };\n\n if (pos === \"bottom\") {\n container.scrollTop = container.scrollHeight;\n } else if (pos === \"top\") {\n container.scrollTop = 0;\n } else if (typeof pos === \"number\") {\n container.scrollTop = pos;\n }\n\n return {\n scrollTop: container.scrollTop,\n scrollHeight: container.scrollHeight,\n clientHeight: container.clientHeight,\n atBottom: container.scrollTop + container.clientHeight >= container.scrollHeight - 10,\n atTop: container.scrollTop < 10\n };\n };\n\n try {\n const script = `(${scrollScript.toString()})(${JSON.stringify(position)}, ${JSON.stringify(selector)})`;\n const result = await cdp.evaluateScript(tabId, script);\n return result.result?.value || { error: \"Script failed\" };\n } catch {\n try {\n const results = await chrome.scripting.executeScript({\n target: { tabId },\n func: scrollScript,\n args: [position, selector],\n });\n return results[0]?.result || { error: \"Script failed\" };\n } catch {\n return { error: \"Cannot scroll on this page (restricted)\" };\n }\n }\n }\n\n case \"GET_SCROLL_INFO\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const selector = message.selector;\n\n const scrollInfoScript = (sel: string | null) => {\n const findScrollable = (): Element => {\n const candidates = [...document.querySelectorAll(\"*\")].filter(el =>\n el.scrollHeight > el.clientHeight && el.clientHeight > 200\n ).sort((a,b) => b.scrollHeight - a.scrollHeight);\n return candidates[0] || document.documentElement;\n };\n\n const container = sel ? document.querySelector(sel) || findScrollable() : findScrollable();\n if (!container) return { error: \"No scrollable container found\" };\n\n const maxScroll = container.scrollHeight - container.clientHeight;\n return {\n scrollTop: container.scrollTop,\n scrollHeight: container.scrollHeight,\n clientHeight: container.clientHeight,\n atBottom: container.scrollTop + container.clientHeight >= container.scrollHeight - 10,\n atTop: container.scrollTop < 10,\n scrollPercentage: maxScroll > 0 ? Math.round((container.scrollTop / maxScroll) * 100) : 100\n };\n };\n\n try {\n const script = `(${scrollInfoScript.toString()})(${JSON.stringify(selector)})`;\n const result = await cdp.evaluateScript(tabId, script);\n return result.result?.value || { error: \"Script failed\" };\n } catch {\n try {\n const results = await chrome.scripting.executeScript({\n target: { tabId },\n func: scrollInfoScript,\n args: [selector],\n });\n return results[0]?.result || { error: \"Script failed\" };\n } catch {\n return { error: \"Cannot get scroll info on this page (restricted)\" };\n }\n }\n }\n\n case \"GET_PAGE_TEXT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, { type: \"GET_PAGE_TEXT\" }, { frameId: getFrameIdForTab(tabId, message) });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"GET_PAGE_HTML\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const results = await chrome.scripting.executeScript({\n target: { tabId, frameIds: [getFrameIdForTab(tabId, message)] },\n func: (selector?: unknown, stripScripts?: boolean) => {\n if (selector !== undefined && (typeof selector !== \"string\" || selector.length === 0)) {\n throw new Error(\"selector must be a non-empty string\");\n }\n const root = selector === undefined ? document.documentElement : document.querySelector(selector);\n if (!root) throw new Error(`No element matches selector \"${selector}\"`);\n const exportRoot = stripScripts ? root.cloneNode(true) as Element : root;\n if (stripScripts) {\n if (exportRoot.matches(\"script\")) return \"\";\n exportRoot.querySelectorAll(\"script\").forEach((script) => script.remove());\n }\n const doctype = selector === undefined && document.doctype ? `<!doctype ${document.doctype.name}>\\n` : \"\";\n return doctype + exportRoot.outerHTML;\n },\n args: [message.selector, message.stripScripts],\n });\n const html = results[0]?.result;\n if (typeof html !== \"string\") throw new Error(\"Page HTML extraction returned an invalid result\");\n return { html };\n }\n\n case \"LOCATE_ROLE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.role) throw new Error(\"role required\");\n const locateFrameId = getFrameIdForTab(tabId, message);\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"LOCATE_ROLE\",\n role: message.role,\n name: message.name,\n all: message.all,\n }, { frameId: locateFrameId });\n\n if (result.error) return result;\n\n // Perform action if specified\n if (message.action && result.ref) {\n return await performLocateAction(tabId, result.ref, message.action, message.value, cdp, locateFrameId);\n }\n\n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"LOCATE_TEXT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.text) throw new Error(\"text required\");\n const textFrameId = getFrameIdForTab(tabId, message);\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"LOCATE_TEXT\",\n text: message.text,\n exact: message.exact,\n }, { frameId: textFrameId });\n\n if (result.error) return result;\n\n // Perform action if specified\n if (message.action && result.ref) {\n return await performLocateAction(tabId, result.ref, message.action, message.value, cdp, textFrameId);\n }\n\n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"LOCATE_LABEL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.label) throw new Error(\"label required\");\n const labelFrameId = getFrameIdForTab(tabId, message);\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"LOCATE_LABEL\",\n label: message.label,\n }, { frameId: labelFrameId });\n\n if (result.error) return result;\n\n // Perform action if specified\n if (message.action && result.ref) {\n return await performLocateAction(tabId, result.ref, message.action, message.value, cdp, labelFrameId);\n }\n\n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"GET_ELEMENT_STYLES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.selector) throw new Error(\"selector required\");\n const stylesFrameId = getFrameIdForTab(tabId, message);\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_STYLES\",\n selector: message.selector,\n }, { frameId: stylesFrameId });\n\n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"SELECT_OPTION\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.selector) throw new Error(\"selector required\");\n if (!message.values) throw new Error(\"values required\");\n const selectFrameId = getFrameIdForTab(tabId, message);\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"SELECT_OPTION\",\n selector: message.selector,\n values: message.values,\n by: message.by || \"value\",\n }, { frameId: selectFrameId });\n\n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"SHOW_AGENT_INDICATORS\":\n case \"HIDE_AGENT_INDICATORS\":\n case \"SHOW_STATIC_INDICATOR\":\n case \"HIDE_STATIC_INDICATOR\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n return await chrome.tabs.sendMessage(tabId, { type: message.type }, { frameId: 0 });\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"STOP_AGENT\": {\n const fromTabId = message.fromTabId;\n let targetTabId: number | undefined;\n\n if (fromTabId === \"CURRENT_TAB\" && sender.tab?.id) {\n targetTabId = sender.tab.id;\n } else if (typeof fromTabId === \"number\") {\n targetTabId = fromTabId;\n }\n\n if (targetTabId) {\n chrome.runtime.sendMessage({ type: \"STOP_AGENT\", targetTabId });\n }\n return { success: true };\n }\n\n case \"DISMISS_STATIC_INDICATOR\": {\n return { success: true };\n }\n\n case \"STATIC_INDICATOR_HEARTBEAT\": {\n return { success: true };\n }\n\n case \"CLICK_REF\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"CLICK_ELEMENT\",\n ref: message.ref,\n button: message.button || \"left\",\n expectedIdentity: message.expectedIdentity,\n }, { frameId: getFrameIdForTab(tabId, message) });\n if (result.error) return { error: result.error, code: result.code };\n return { success: true };\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"HOVER_REF\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n try {\n const coords = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_ELEMENT_COORDINATES\",\n ref: message.ref,\n }, { frameId: getFrameIdForTab(tabId, message) });\n if (coords.error) return { error: coords.error };\n await cdp.hover(tabId, coords.x, coords.y);\n return { success: true };\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"PING\": {\n return { success: true, status: \"connected\" };\n }\n\n case \"HEALTH_CHECK_URL\": {\n if (!message.url) throw new Error(\"No url provided\");\n const timeout = message.timeout || 30000;\n const expect = message.expect || 200;\n const startTime = Date.now();\n const pollInterval = 500;\n\n let lastError: string | null = null;\n while (Date.now() - startTime < timeout) {\n try {\n const response = await fetch(message.url, { method: \"GET\" });\n await response.text();\n if (response.status === expect) {\n return { success: true, status: response.status, time: Date.now() - startTime };\n }\n lastError = `Got status ${response.status}`;\n } catch (e) {\n lastError = e instanceof Error ? e.message : String(e);\n }\n await new Promise((r) => setTimeout(r, pollInterval));\n }\n return {\n error: `Timeout waiting for ${message.url} to return ${expect}`,\n lastError,\n time: Date.now() - startTime\n };\n }\n\n case \"SMOKE_TEST\": {\n const urls: string[] = message.urls || [];\n const captureScreenshots: boolean = message.savePath !== undefined;\n const failFast: boolean = message.failFast || false;\n\n if (urls.length === 0) {\n return { error: \"No URLs provided for smoke test\" };\n }\n\n const results: Array<{\n url: string;\n status: \"pass\" | \"fail\";\n time: number;\n errors: string[];\n screenshotBase64?: string;\n hostname?: string;\n }> = [];\n\n let pass = 0;\n let fail = 0;\n\n for (const url of urls) {\n const startTime = Date.now();\n const errors: string[] = [];\n let screenshotBase64: string | undefined;\n let hostname: string | undefined;\n let testTabId: number | undefined;\n\n try {\n hostname = new URL(url).hostname.replace(/[^a-zA-Z0-9.-]/g, \"_\");\n const testTab = await chrome.tabs.create({ url, active: false });\n if (!testTab.id) throw new Error(\"Failed to create tab\");\n testTabId = testTab.id;\n\n try {\n await cdp.enableConsoleTracking(testTabId);\n } catch (e) {}\n\n await new Promise<void>((resolve) => {\n const onComplete = (details: chrome.webNavigation.WebNavigationFramedCallbackDetails) => {\n if (details.tabId === testTabId && details.frameId === 0) {\n chrome.webNavigation.onCompleted.removeListener(onComplete);\n chrome.webNavigation.onErrorOccurred.removeListener(onError);\n resolve();\n }\n };\n const onError = (details: chrome.webNavigation.WebNavigationFramedErrorCallbackDetails) => {\n if (details.tabId === testTabId && details.frameId === 0) {\n chrome.webNavigation.onCompleted.removeListener(onComplete);\n chrome.webNavigation.onErrorOccurred.removeListener(onError);\n errors.push(`Navigation error: ${details.error}`);\n resolve();\n }\n };\n chrome.webNavigation.onCompleted.addListener(onComplete);\n chrome.webNavigation.onErrorOccurred.addListener(onError);\n setTimeout(() => {\n chrome.webNavigation.onCompleted.removeListener(onComplete);\n chrome.webNavigation.onErrorOccurred.removeListener(onError);\n errors.push(\"Navigation timeout (30s)\");\n resolve();\n }, 30000);\n });\n\n await new Promise(r => setTimeout(r, 2000));\n\n const consoleMessages = cdp.getConsoleMessages(testTabId, { onlyErrors: true, limit: 50 });\n for (const msg of consoleMessages) {\n errors.push(`[${msg.type}] ${msg.text}`);\n }\n\n if (captureScreenshots) {\n try {\n const screenshot = await cdp.captureScreenshot(testTabId);\n screenshotBase64 = screenshot.base64;\n } catch (e) {}\n }\n } catch (e) {\n errors.push(e instanceof Error ? e.message : String(e));\n } finally {\n if (testTabId) {\n try { await chrome.tabs.remove(testTabId); } catch {}\n }\n }\n\n const elapsed = Date.now() - startTime;\n const status = errors.length === 0 ? \"pass\" : \"fail\";\n if (status === \"pass\") pass++;\n else fail++;\n\n results.push({\n url,\n status,\n time: elapsed,\n errors,\n ...(screenshotBase64 && { screenshotBase64, hostname }),\n });\n\n if (failFast && status === \"fail\") {\n break;\n }\n }\n\n return {\n results,\n summary: { pass, fail, total: results.length },\n savePath: message.savePath,\n };\n }\n\n case \"WAIT_FOR_ELEMENT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.selector) throw new Error(\"No selector provided\");\n const waitFrameId = getFrameIdForTab(tabId, message);\n\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"WAIT_FOR_ELEMENT\",\n selector: message.selector,\n state: message.state || \"visible\",\n timeout: message.timeout || 20000,\n }, { frameId: waitFrameId });\n return result;\n } catch (err) {\n return {\n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n }\n }\n\n case \"WAIT_FOR_URL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.pattern) throw new Error(\"No URL pattern provided\");\n\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"WAIT_FOR_URL\",\n pattern: message.pattern,\n timeout: message.timeout || 20000,\n }, { frameId: 0 });\n return result;\n } catch (err) {\n return {\n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n }\n }\n\n case \"WAIT_FOR_NETWORK_IDLE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"WAIT_FOR_NETWORK_IDLE\",\n timeout: message.timeout || 10000,\n }, { frameId: 0 });\n return result;\n } catch (err) {\n return {\n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n }\n }\n\n case \"PAGE_READINESS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n return await probeTabReadiness(tabId, readinessExpectationsFrom(message.expect));\n }\n\n case \"WAIT_FOR_READY\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const expect = readinessExpectationsFrom(message.expect);\n const budget = clampReadinessBudget({ timeoutMs: message.timeout, intervalMs: message.interval });\n const accept: ReadinessState[] = parseAcceptStates(message.accept);\n const outcome = await pollReadiness({\n ...budget,\n accept,\n probe: () => probeTabReadiness(tabId, expect),\n });\n const summary = {\n state: outcome.result.state,\n evidence: outcome.result.evidence,\n href: outcome.result.href,\n title: outcome.result.title,\n readyState: outcome.result.readyState,\n tabStatus: outcome.result.tabStatus,\n polls: outcome.polls,\n waited: outcome.waitedMs,\n timeout: budget.timeoutMs,\n interval: budget.intervalMs,\n };\n if (outcome.kind === \"settled\" || outcome.kind === \"accepted\") {\n // No `success` key on purpose: formatToolContent renders any\n // {success, readyState} result as a fixed \"Page loaded\" line.\n return { accepted: outcome.kind === \"accepted\", ...summary };\n }\n if (outcome.kind === \"timeout\") {\n throw new BrowserCommandError(\n \"page_timeout\",\n `Page did not become ready within ${budget.timeoutMs}ms; last state ${describeReadiness(outcome.result)}`,\n { ...summary, tabId },\n );\n }\n throw new BrowserCommandError(\n readinessErrorCode(outcome.result.state) ?? \"page_not_ready\",\n `Page is not ready: ${describeReadiness(outcome.result)}`,\n { ...summary, tabId },\n );\n }\n\n case \"WAIT_FOR_DOM_STABLE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"HIDE_FOR_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n await new Promise(resolve => setTimeout(resolve, 50));\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"WAIT_FOR_DOM_STABLE\",\n stable: message.stable || 100,\n timeout: message.timeout || 5000,\n }, { frameId: 0 });\n return result;\n } catch (err) {\n return {\n error: \"Content script not loaded. Try refreshing the page.\",\n pageContent: \"\",\n viewport: { width: 0, height: 0 }\n };\n } finally {\n try {\n await chrome.tabs.sendMessage(tabId, { type: \"SHOW_AFTER_TOOL_USE\" }, { frameId: 0 });\n } catch (e) {}\n }\n }\n\n case \"DIALOG_ACCEPT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.handleDialog(tabId, true, message.text);\n return result;\n }\n\n case \"DIALOG_DISMISS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.handleDialog(tabId, false);\n return result;\n }\n\n case \"DIALOG_INFO\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const dialog = cdp.getDialogInfo(tabId);\n if (!dialog) {\n return { hasDialog: false };\n }\n return {\n hasDialog: true,\n type: dialog.type,\n message: dialog.message,\n defaultPrompt: dialog.defaultPrompt,\n };\n }\n\n case \"EMULATE_NETWORK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.preset) throw new Error(\"No preset provided\");\n const result = await cdp.emulateNetwork(tabId, message.preset);\n if (!result.success) throw new Error(result.error);\n return { success: true, preset: message.preset };\n }\n\n case \"EMULATE_CPU\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.rate === undefined) throw new Error(\"No rate provided\");\n const result = await cdp.emulateCPU(tabId, message.rate);\n if (!result.success) throw new Error(result.error);\n return { success: true, rate: message.rate };\n }\n\n case \"EMULATE_GEO\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.clear) {\n const result = await cdp.clearGeolocation(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, cleared: true };\n }\n if (message.latitude === undefined || message.longitude === undefined) {\n throw new Error(\"Latitude and longitude required\");\n }\n const result = await cdp.emulateGeolocation(tabId, message.latitude, message.longitude, message.accuracy);\n if (!result.success) throw new Error(result.error);\n return { success: true, latitude: message.latitude, longitude: message.longitude };\n }\n\n case \"EMULATE_DEVICE_LIST\": {\n // Return list of available devices - handled in CLI\n const devices = [\n \"iPhone 12\", \"iPhone 13\", \"iPhone 14\", \"iPhone 14 Pro\", \"iPhone 14 Pro Max\", \"iPhone SE\",\n \"iPad\", \"iPad Pro\", \"iPad Mini\",\n \"Pixel 5\", \"Pixel 6\", \"Pixel 7\", \"Pixel 7 Pro\",\n \"Galaxy S21\", \"Galaxy S22\", \"Galaxy S23\", \"Galaxy Tab S7\",\n \"Nest Hub\", \"Nest Hub Max\"\n ];\n return { devices };\n }\n\n case \"EMULATE_DEVICE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const deviceName = message.device;\n\n // Handle reset\n if (deviceName.toLowerCase() === \"reset\") {\n const result = await cdp.clearDeviceEmulation(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, message: \"Device emulation reset\" };\n }\n\n // Device presets (synced with device-presets.cjs)\n const presets: Record<string, { width: number; height: number; deviceScaleFactor: number; mobile: boolean; touch: boolean; userAgent: string }> = {\n // Apple devices\n \"iPhone 12\": { width: 390, height: 844, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone 13\": { width: 390, height: 844, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone 14\": { width: 390, height: 844, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone 14 Pro\": { width: 393, height: 852, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone 14 Pro Max\": { width: 430, height: 932, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1\" },\n \"iPhone SE\": { width: 375, height: 667, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1\" },\n \"iPad\": { width: 768, height: 1024, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1\" },\n \"iPad Pro\": { width: 1024, height: 1366, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1\" },\n \"iPad Mini\": { width: 768, height: 1024, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (iPad; CPU OS 14_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1\" },\n // Google devices\n \"Pixel 5\": { width: 393, height: 851, deviceScaleFactor: 2.75, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36\" },\n \"Pixel 6\": { width: 412, height: 915, deviceScaleFactor: 2.625, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 12; Pixel 6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Mobile Safari/537.36\" },\n \"Pixel 7\": { width: 412, height: 915, deviceScaleFactor: 2.625, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 13; Pixel 7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36\" },\n \"Pixel 7 Pro\": { width: 412, height: 892, deviceScaleFactor: 3.5, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 13; Pixel 7 Pro) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Mobile Safari/537.36\" },\n // Samsung devices\n \"Galaxy S21\": { width: 360, height: 800, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 11; SM-G991B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.210 Mobile Safari/537.36\" },\n \"Galaxy S22\": { width: 360, height: 780, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 12; SM-S901B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Mobile Safari/537.36\" },\n \"Galaxy S23\": { width: 360, height: 780, deviceScaleFactor: 3, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 13; SM-S911B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Mobile Safari/537.36\" },\n \"Galaxy Tab S7\": { width: 800, height: 1280, deviceScaleFactor: 2, mobile: true, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android 10; SM-T870) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Safari/537.36\" },\n // Other\n \"Nest Hub\": { width: 1024, height: 600, deviceScaleFactor: 2, mobile: false, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666\" },\n \"Nest Hub Max\": { width: 1280, height: 800, deviceScaleFactor: 2, mobile: false, touch: true, userAgent: \"Mozilla/5.0 (Linux; Android) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.109 Safari/537.36 CrKey/1.54.248666\" },\n };\n\n // Find matching device (case-insensitive partial match, prefer longest match)\n type DevicePreset = { width: number; height: number; deviceScaleFactor: number; mobile: boolean; touch: boolean; userAgent: string };\n const aliases: Record<string, string> = {\n iphone: \"iPhone 14\",\n iphone14: \"iPhone 14\",\n iphone13: \"iPhone 13\",\n iphone12: \"iPhone 12\",\n iphonese: \"iPhone SE\",\n pixel: \"Pixel 7\",\n pixel7: \"Pixel 7\",\n pixel6: \"Pixel 6\",\n galaxy: \"Galaxy S23\",\n galaxys23: \"Galaxy S23\",\n ipad: \"iPad\",\n ipadpro: \"iPad Pro\",\n };\n let device: DevicePreset | undefined = presets[deviceName];\n if (!device) {\n const lowerName = deviceName.toLowerCase();\n device = presets[aliases[lowerName.replace(/\\s+/g, \"\")]];\n }\n if (!device) {\n const lowerName = deviceName.toLowerCase();\n let bestMatch: { name: string; preset: DevicePreset } | null = null;\n\n for (const [name, preset] of Object.entries(presets)) {\n const presetLower = name.toLowerCase();\n const presetNoSpaces = presetLower.replace(/\\s+/g, \"\");\n\n // Check if it's a match\n if (presetLower.includes(lowerName) || lowerName.includes(presetNoSpaces)) {\n // Prefer longer matches (more specific devices)\n if (!bestMatch || name.length > bestMatch.name.length) {\n bestMatch = { name, preset };\n }\n }\n }\n\n if (bestMatch) {\n device = bestMatch.preset;\n }\n }\n\n if (!device) {\n throw new Error(`Unknown device: ${deviceName}. Use --list to see available devices.`);\n }\n\n const result = await cdp.emulateDevice(tabId, device);\n if (!result.success) throw new Error(result.error);\n return { success: true, device: deviceName };\n }\n\n case \"EMULATE_VIEWPORT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.width && !message.height) {\n throw new Error(\"--width or --height required\");\n }\n const result = await cdp.emulateViewport(tabId, {\n width: message.width,\n height: message.height,\n deviceScaleFactor: message.deviceScaleFactor,\n mobile: message.mobile,\n });\n if (!result.success) throw new Error(result.error);\n return { success: true, width: message.width, height: message.height };\n }\n\n case \"EMULATE_TOUCH\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.emulateTouch(tabId, message.enabled);\n if (!result.success) throw new Error(result.error);\n return { success: true, enabled: message.enabled };\n }\n\n case \"FORM_FILL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.data) throw new Error(\"No data provided\");\n const response = await chrome.tabs.sendMessage(tabId, {\n type: \"FORM_FILL\",\n data: message.data,\n expectedIdentity: message.expectedIdentity,\n }, { frameId: getFrameIdForTab(tabId, message) });\n return response;\n }\n\n case \"PERF_START\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.startPerformanceTrace(tabId, message.categories);\n if (!result.success) throw new Error(result.error);\n return { success: true, message: \"Performance tracing started\" };\n }\n\n case \"PERF_STOP\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.stopPerformanceTrace(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, metrics: result.metrics };\n }\n\n case \"PERF_METRICS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.getPerformanceMetrics(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, metrics: result.metrics };\n }\n\n case \"UPLOAD_FILE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.ref) throw new Error(\"No ref provided\");\n if (!message.files || !message.files.length) throw new Error(\"No files provided\");\n const selectorResult = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_FILE_INPUT_SELECTOR\",\n ref: message.ref,\n }, { frameId: getFrameIdForTab(tabId, message) });\n if (selectorResult.error) throw new Error(selectorResult.error);\n const setResult = await cdp.setFileInputBySelector(tabId, selectorResult.selector, message.files);\n if (!setResult.success) throw new Error(setResult.error);\n return { success: true, filesSet: message.files.length };\n }\n\n case \"WAIT_FOR_LOAD\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.waitForLoad(tabId, message.timeout || 30000);\n if (!result.success) throw new Error(result.error);\n return { success: true, readyState: result.readyState };\n }\n\n case \"GET_FRAMES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const result = await cdp.getFrames(tabId);\n if (!result.success) throw new Error(result.error);\n return { success: true, frames: result.frames };\n }\n\n case \"FRAME_DIAGNOSE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const extensionFrames = await collectExtensionFrames(tabId);\n const mainExtensionFrame = extensionFrames.find((frame) => frame.parentFrameId === -1);\n let dom = { href: mainExtensionFrame?.url ?? \"\", title: \"\", iframes: [] as DomIframeEntry[] };\n let cdpFrames: CdpFrameEntry[] = [];\n let cdpFramesAvailable = true;\n const inventoryWarnings: string[] = [];\n const ownedAttachment = !cdp.isAttached(tabId);\n try {\n if (ownedAttachment) {\n try {\n await cdp.attach(tabId);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n inventoryWarnings.push(`CDP inventories unavailable: ${message}`);\n cdpFramesAvailable = false;\n }\n }\n if (cdp.isAttached(tabId)) {\n try {\n dom = await collectDomIframeInventory(tabId);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n inventoryWarnings.push(`DOM iframe inventory unavailable: ${message}`);\n }\n try {\n const cdpResult = await cdp.getFrames(tabId);\n if (cdpResult.success) {\n cdpFrames = cdpResult.frames ?? [];\n } else {\n inventoryWarnings.push(`CDP frame tree unavailable: ${cdpResult.error}`);\n cdpFramesAvailable = false;\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n inventoryWarnings.push(`CDP frame tree unavailable: ${message}`);\n cdpFramesAvailable = false;\n }\n }\n } finally {\n if (ownedAttachment && cdp.isAttached(tabId)) {\n const detachResult = await cdp.detach(tabId);\n if (!detachResult.success) {\n inventoryWarnings.push(`CDP detach failed: ${detachResult.error}`);\n }\n }\n }\n const diagnosis = buildFrameDiagnosis({\n mainPage: { href: dom.href, title: dom.title },\n domIframes: dom.iframes,\n extensionFrames,\n cdpFrames,\n cdpFramesAvailable,\n });\n diagnosis.warnings.unshift(...inventoryWarnings);\n // No `success` key on purpose: formatToolContent renders {success, frames}\n // as the bare frame list.\n return diagnosis;\n }\n\n case \"FRAME_SWITCH\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const { selector, name, index } = message;\n\n if (!selector && !name && index === undefined) {\n throw new Error(\"--selector, --name, or --index required\");\n }\n\n // Get all frames using Chrome's webNavigation API (gives us correct frameIds for messaging)\n const chromeFrames = await chrome.webNavigation.getAllFrames({ tabId });\n if (!chromeFrames || chromeFrames.length === 0) {\n throw new Error(\"No frames found in tab\");\n }\n\n // Filter to child frames only (frameId !== 0)\n const childFrames = chromeFrames.filter(f => f.frameId !== 0);\n\n if (childFrames.length === 0) {\n throw new Error(\"No iframes found on this page\");\n }\n\n let targetFrame: chrome.webNavigation.GetAllFrameResultDetails | null = null;\n if (index !== undefined) {\n if (index < 0 || index >= childFrames.length) {\n throw new Error(`Frame index ${index} out of range. Found ${childFrames.length} frame(s).`);\n }\n targetFrame = childFrames[index];\n } else if (name) {\n // Try to find frame by name using content script in each frame\n for (const frame of childFrames) {\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_FRAME_NAME\",\n }, { frameId: frame.frameId });\n if (result?.name === name) {\n targetFrame = frame;\n break;\n }\n } catch {\n // Frame may not have content script loaded\n }\n }\n if (!targetFrame) {\n throw new Error(`Frame with name \"${name}\" not found`);\n }\n } else if (selector) {\n // Find frame by selector - ask main frame for iframe element's info\n try {\n const selectorResult = await chrome.tabs.sendMessage(tabId, {\n type: \"GET_FRAME_BY_SELECTOR\",\n selector,\n }, { frameId: 0 });\n\n if (selectorResult?.error) throw new Error(selectorResult.error);\n\n // Match by URL since that's what we can reliably get\n if (selectorResult?.url) {\n targetFrame = childFrames.find(f => f.url === selectorResult.url) || null;\n }\n\n // If no URL match and only one child frame, use it\n if (!targetFrame && childFrames.length === 1) {\n targetFrame = childFrames[0];\n }\n } catch (e) {\n throw new Error(`Could not find frame with selector \"${selector}\"`);\n }\n }\n\n if (!targetFrame) {\n throw new Error(\"Frame not found\");\n }\n\n return {\n success: true,\n frameId: targetFrame.frameId,\n url: targetFrame.url,\n };\n }\n\n case \"FRAME_MAIN\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n\n // Clear frame context - go back to main frame (frameId 0)\n\n return { success: true, message: \"Returned to main frame\" };\n }\n\n case \"EVALUATE_IN_FRAME\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.frameId) throw new Error(\"No frameId provided\");\n if (!message.code) throw new Error(\"No code provided\");\n const result = await cdp.evaluateInFrame(tabId, message.frameId, message.code);\n if (!result.success) throw new Error(result.error);\n return { value: result.result };\n }\n\n case \"EXECUTE_JAVASCRIPT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.code) throw new Error(\"No code provided\");\n\n try {\n const piHelpersCode = `if(!window.piHelpers){const piHelpers={wait(ms){return new Promise(r=>setTimeout(r,ms))},setValue(el,v,events=['input','change']){let p=Object.getPrototypeOf(el),s=null;while(p&&p!==Object.prototype){const d=Object.getOwnPropertyDescriptor(p,'value');if(d&&d.set){s=d.set;break}p=Object.getPrototypeOf(p)}if(s)s.call(el,v);else el.value=v;for(const n of events)el.dispatchEvent(new Event(n,{bubbles:n!=='blur'}));return el},async waitForSelector(sel,opts={}){const{state='visible',timeout=20000}=opts;const isVis=el=>el&&getComputedStyle(el).display!=='none'&&getComputedStyle(el).visibility!=='hidden'&&getComputedStyle(el).opacity!=='0'&&el.offsetWidth>0&&el.offsetHeight>0;const chk=()=>{const el=document.querySelector(sel);switch(state){case'attached':return el;case'detached':return el?null:document.body;case'hidden':return(!el||!isVis(el))?(el||document.body):null;default:return isVis(el)?el:null}};return new Promise((res,rej)=>{const r=chk();if(r){res(state==='detached'||state==='hidden'?null:r);return}const obs=new MutationObserver(()=>{const r=chk();if(r){obs.disconnect();clearTimeout(tid);res(state==='detached'||state==='hidden'?null:r)}});const tid=setTimeout(()=>{obs.disconnect();rej(new Error('Timeout'))},timeout);obs.observe(document.documentElement,{childList:true,subtree:true,attributes:true,attributeFilter:['style','class','hidden']})})},async waitForText(text,opts={}){const{selector,timeout=20000}=opts;const chk=()=>{const root=selector?document.querySelector(selector):document.body;if(!root)return null;const w=document.createTreeWalker(root,NodeFilter.SHOW_TEXT);while(w.nextNode())if(w.currentNode.textContent?.includes(text))return w.currentNode.parentElement;return null};return new Promise((res,rej)=>{const r=chk();if(r){res(r);return}const obs=new MutationObserver(()=>{const r=chk();if(r){obs.disconnect();clearTimeout(tid);res(r)}});const tid=setTimeout(()=>{obs.disconnect();rej(new Error('Timeout'))},timeout);obs.observe(document.documentElement,{childList:true,subtree:true,characterData:true})})},async waitForHidden(sel,t=20000){await piHelpers.waitForSelector(sel,{state:'hidden',timeout:t})},getByRole(role,opts={}){const{name}=opts;const roles={button:['button','input[type=button]','input[type=submit]','input[type=reset]'],link:['a[href]'],textbox:['input:not([type])','input[type=text]','input[type=email]','input[type=password]','textarea'],checkbox:['input[type=checkbox]'],radio:['input[type=radio]'],combobox:['select'],heading:['h1','h2','h3','h4','h5','h6']};const cands=[...document.querySelectorAll('[role='+role+']')];if(roles[role])roles[role].forEach(s=>cands.push(...document.querySelectorAll(s+':not([role])')));if(!name)return cands[0]||null;const n=name.toLowerCase().trim();for(const el of cands){const l=el.getAttribute('aria-label')?.toLowerCase().trim();const t=el.textContent?.toLowerCase().trim();if(l===n||t===n||l?.includes(n)||t?.includes(n))return el}return null}};window.__piHelpers=piHelpers;window.piHelpers=piHelpers}`;\n await cdp.evaluateScript(tabId, piHelpersCode);\n\n const body = codeWithExpressionReturn(message.code);\n const expression = `(async () => { 'use strict'; ${body} })()`;\n\n let result = await cdp.evaluateScript(tabId, expression);\n\n // Statement scripts (declarations, loops, explicit `return`) cannot be\n // wrapped as an expression; retry them in statement mode when the\n // expression form failed to parse.\n if (result.exceptionDetails && !(await statementBodyParses(tabId, body))) {\n result = await cdp.evaluateScript(tabId, `(async () => { 'use strict'; ${message.code} })()`);\n }\n\n if (result.exceptionDetails) {\n const err = result.exceptionDetails.exception?.description ||\n result.exceptionDetails.text ||\n \"Script execution failed\";\n return { error: err };\n }\n\n const value = result.result?.value;\n const output = value === undefined ? \"undefined\" : JSON.stringify(value, null, 2);\n return { output: output?.substring(0, 50000) || \"undefined\" };\n } catch (err) {\n const msg = err instanceof Error ? err.message : \"Script execution failed\";\n if (msg.includes(\"Cannot access\") || msg.includes(\"Cannot attach\")) {\n return { error: \"Cannot execute JavaScript on this page (restricted URL)\" };\n }\n return { error: msg };\n }\n }\n\n case \"ANIMATE_AUDIT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.selector || typeof message.selector !== \"string\") throw new Error(\"selector required\");\n\n if (typeof message.durationMs === \"boolean\") throw new Error(\"duration must be a number\");\n if (typeof message.fps === \"boolean\") throw new Error(\"fps must be a number\");\n const durationMs = message.durationMs !== undefined ? Number(message.durationMs) : 2000;\n const fps = message.fps !== undefined ? Number(message.fps) : 10;\n if (!Number.isFinite(durationMs) || durationMs < 100 || durationMs > 10000) {\n throw new Error(\"duration must be between 100 and 10000 ms\");\n }\n if (!Number.isFinite(fps) || fps < 1 || fps > 30) {\n throw new Error(\"fps must be between 1 and 30\");\n }\n\n try {\n const expression = `(async () => {\n const selector = ${JSON.stringify(message.selector)};\n const durationMs = ${Math.round(durationMs)};\n const fps = ${Math.round(fps)};\n const intervalMs = Math.max(1, Math.round(1000 / fps));\n const maxElements = 25;\n const maxSamples = Math.min(Math.floor(durationMs / intervalMs) + 1, 301);\n const startedAt = Date.now();\n const start = performance.now();\n const samples = [];\n const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));\n const sample = () => {\n const now = performance.now();\n const elements = Array.from(document.querySelectorAll(selector)).slice(0, maxElements).map((el, index) => {\n const rect = el.getBoundingClientRect();\n const style = getComputedStyle(el);\n const text = (el.textContent || \"\").replace(/\\\\s+/g, \" \").trim().slice(0, 120);\n return {\n selector,\n index,\n rect: {\n x: Math.round(rect.x * 100) / 100,\n y: Math.round(rect.y * 100) / 100,\n width: Math.round(rect.width * 100) / 100,\n height: Math.round(rect.height * 100) / 100,\n top: Math.round(rect.top * 100) / 100,\n right: Math.round(rect.right * 100) / 100,\n bottom: Math.round(rect.bottom * 100) / 100,\n left: Math.round(rect.left * 100) / 100,\n },\n opacity: style.opacity,\n transform: style.transform,\n visibility: style.visibility,\n display: style.display,\n text,\n };\n });\n samples.push({ t: Math.round((now - start) * 100) / 100, timestamp: Date.now(), elements });\n };\n\n for (let i = 0; i < maxSamples; i++) {\n sample();\n const elapsed = performance.now() - start;\n if (elapsed >= durationMs || i === maxSamples - 1) break;\n await wait(Math.max(0, Math.min(intervalMs, durationMs - elapsed)));\n }\n\n return {\n selector,\n durationMs,\n fps,\n intervalMs,\n maxElementsPerSample: maxElements,\n startedAt,\n endedAt: Date.now(),\n sampleCount: samples.length,\n samples,\n };\n })()`;\n\n const result = await cdp.evaluateScript(tabId, expression);\n if (result.exceptionDetails) {\n const err = result.exceptionDetails.exception?.description ||\n result.exceptionDetails.text ||\n \"Animation audit failed\";\n return { error: err };\n }\n return result.result?.value ?? { error: \"Animation audit returned no data\" };\n } catch (err) {\n const msg = err instanceof Error ? err.message : \"Animation audit failed\";\n if (msg.includes(\"Cannot access\") || msg.includes(\"Cannot attach\")) {\n return { error: \"Cannot execute animation audit on this page (restricted URL)\" };\n }\n return { error: msg };\n }\n }\n\n case \"PERF_AUDIT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (typeof message.durationMs === \"boolean\") throw new Error(\"duration must be a number\");\n if (message.trigger !== undefined && typeof message.trigger !== \"string\") {\n throw new Error(\"trigger must be action:target\");\n }\n const durationMs = message.durationMs !== undefined ? Number(message.durationMs) : 3000;\n if (!Number.isFinite(durationMs) || durationMs < 100 || durationMs > 10000) {\n throw new Error(\"duration must be between 100 and 10000 ms\");\n }\n\n try {\n const expression = `(async () => {\n const durationMs = ${Math.round(durationMs)};\n const trigger = ${JSON.stringify(message.trigger || null)};\n const startedAt = Date.now();\n const startedAtPerformance = performance.now();\n const supportedEntryTypes = typeof PerformanceObserver !== \"undefined\" && Array.isArray(PerformanceObserver.supportedEntryTypes) ? PerformanceObserver.supportedEntryTypes : [];\n const requestedTypes = [\"layout-shift\", \"long-animation-frame\", \"event\", \"longtask\", \"paint\"];\n const observedEntryTypes = [];\n const entries = {\n layoutShifts: [],\n longAnimationFrames: [],\n events: [],\n longTasks: [],\n paints: [],\n };\n const round = (value) => Math.round(value * 100) / 100;\n const auditEndsAtPerformance = startedAtPerformance + durationMs;\n const inAuditWindow = (entry) => entry.startTime >= startedAtPerformance && entry.startTime <= auditEndsAtPerformance;\n const nodeSummary = (node) => {\n if (!node || node.nodeType !== Node.ELEMENT_NODE) return null;\n const el = node;\n return {\n tag: el.tagName?.toLowerCase(),\n id: el.id || undefined,\n className: typeof el.className === \"string\" ? el.className.slice(0, 120) : undefined,\n };\n };\n const rectSummary = (rect) => rect ? {\n x: round(rect.x),\n y: round(rect.y),\n width: round(rect.width),\n height: round(rect.height),\n top: round(rect.top),\n right: round(rect.right),\n bottom: round(rect.bottom),\n left: round(rect.left),\n } : null;\n const pushEntry = (entry) => {\n if (!inAuditWindow(entry)) return;\n if (entry.entryType === \"layout-shift\") {\n entries.layoutShifts.push({\n name: entry.name,\n startTime: round(entry.startTime),\n duration: round(entry.duration || 0),\n value: round(entry.value || 0),\n hadRecentInput: Boolean(entry.hadRecentInput),\n sources: Array.from(entry.sources || []).slice(0, 10).map((source) => ({\n node: nodeSummary(source.node),\n previousRect: rectSummary(source.previousRect),\n currentRect: rectSummary(source.currentRect),\n })),\n });\n return;\n }\n if (entry.entryType === \"long-animation-frame\") {\n entries.longAnimationFrames.push({\n name: entry.name,\n startTime: round(entry.startTime),\n duration: round(entry.duration || 0),\n renderStart: round(entry.renderStart || 0),\n styleAndLayoutStart: round(entry.styleAndLayoutStart || 0),\n blockingDuration: round(entry.blockingDuration || 0),\n firstUIEventTimestamp: round(entry.firstUIEventTimestamp || 0),\n scripts: Array.from(entry.scripts || []).slice(0, 10).map((script) => ({\n name: script.name,\n sourceURL: script.sourceURL,\n sourceFunctionName: script.sourceFunctionName,\n duration: round(script.duration || 0),\n invoker: script.invoker,\n invokerType: script.invokerType,\n })),\n });\n return;\n }\n if (entry.entryType === \"event\") {\n entries.events.push({\n name: entry.name,\n startTime: round(entry.startTime),\n duration: round(entry.duration || 0),\n processingStart: round(entry.processingStart || 0),\n processingEnd: round(entry.processingEnd || 0),\n interactionId: entry.interactionId || 0,\n cancelable: Boolean(entry.cancelable),\n });\n return;\n }\n if (entry.entryType === \"longtask\") {\n entries.longTasks.push({\n name: entry.name,\n startTime: round(entry.startTime),\n duration: round(entry.duration || 0),\n });\n return;\n }\n if (entry.entryType === \"paint\") {\n entries.paints.push({\n name: entry.name,\n startTime: round(entry.startTime),\n duration: round(entry.duration || 0),\n });\n }\n };\n const observers = [];\n for (const type of requestedTypes) {\n if (!supportedEntryTypes.includes(type)) continue;\n try {\n const observer = new PerformanceObserver((list) => {\n for (const entry of list.getEntries()) pushEntry(entry);\n });\n const options = type === \"event\"\n ? { type, buffered: true, durationThreshold: 16 }\n : { type, buffered: true };\n observer.observe(options);\n observers.push(observer);\n observedEntryTypes.push(type);\n } catch {}\n }\n const fireTrigger = () => {\n if (!trigger) return null;\n const separator = trigger.indexOf(\":\");\n if (separator === -1) throw new Error(\"trigger must be action:target\");\n const action = trigger.slice(0, separator).trim();\n const target = trigger.slice(separator + 1).trim();\n if (!action || !target) throw new Error(\"trigger must be action:target\");\n if (action === \"click\") {\n const el = document.querySelector(target);\n if (!el) return { action, selector: target, fired: false };\n el.click();\n return { action, selector: target, fired: true };\n }\n if (action === \"scroll\") {\n if ([\"up\", \"down\", \"left\", \"right\"].includes(target)) {\n const deltas = { up: [0, -500], down: [0, 500], left: [-500, 0], right: [500, 0] };\n const [left, top] = deltas[target];\n window.scrollBy({ left, top, behavior: \"instant\" });\n return { action, target, fired: true };\n }\n if (target === \"top\" || target === \"bottom\") {\n window.scrollTo({ top: target === \"top\" ? 0 : document.documentElement.scrollHeight, behavior: \"instant\" });\n return { action, target, fired: true };\n }\n const el = document.querySelector(target);\n if (!el) return { action, selector: target, fired: false };\n el.scrollTop = el.scrollHeight;\n el.dispatchEvent(new Event(\"scroll\", { bubbles: true }));\n return { action, selector: target, fired: true };\n }\n throw new Error(\"trigger action must be click or scroll\");\n };\n const triggerResult = fireTrigger();\n await new Promise((resolve) => setTimeout(resolve, durationMs));\n for (const observer of observers) observer.disconnect();\n const cls = entries.layoutShifts\n .filter((entry) => !entry.hadRecentInput)\n .reduce((sum, entry) => sum + entry.value, 0);\n const maxDuration = (items) => items.reduce((max, entry) => Math.max(max, entry.duration || 0), 0);\n const longTaskTotalDuration = entries.longTasks.reduce((sum, entry) => sum + (entry.duration || 0), 0);\n\n return {\n durationMs,\n startedAt,\n endedAt: Date.now(),\n elapsedMs: round(performance.now() - startedAtPerformance),\n supportedEntryTypes,\n observedEntryTypes,\n trigger: triggerResult,\n summary: {\n cumulativeLayoutShift: round(cls),\n maxEventDuration: round(maxDuration(entries.events)),\n maxLongAnimationFrame: round(maxDuration(entries.longAnimationFrames)),\n longTaskTotalDuration: round(longTaskTotalDuration),\n counts: {\n layoutShifts: entries.layoutShifts.length,\n longAnimationFrames: entries.longAnimationFrames.length,\n events: entries.events.length,\n longTasks: entries.longTasks.length,\n paints: entries.paints.length,\n },\n },\n entries,\n };\n })()`;\n\n const result = await cdp.evaluateScript(tabId, expression);\n if (result.exceptionDetails) {\n const err = result.exceptionDetails.exception?.description ||\n result.exceptionDetails.text ||\n \"Performance audit failed\";\n return { error: err };\n }\n return result.result?.value ?? { error: \"Performance audit returned no data\" };\n } catch (err) {\n const msg = err instanceof Error ? err.message : \"Performance audit failed\";\n if (msg.includes(\"Cannot access\") || msg.includes(\"Cannot attach\")) {\n return { error: \"Cannot execute performance audit on this page (restricted URL)\" };\n }\n return { error: msg };\n }\n }\n\n case \"READ_CONSOLE_MESSAGES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n\n try {\n await cdp.enableConsoleTracking(tabId);\n } catch (e) {}\n\n const messages = cdp.getConsoleMessages(tabId, {\n onlyErrors: message.onlyErrors,\n pattern: message.pattern,\n limit: message.limit || 100,\n });\n\n if (message.clear) {\n cdp.clearConsoleMessages(tabId);\n }\n\n return { messages };\n }\n\n case \"CLEAR_CONSOLE_MESSAGES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n cdp.clearConsoleMessages(tabId);\n return { success: true };\n }\n\n case \"START_NETWORK_CAPTURE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n cdp.clearNetworkRequests(tabId);\n await cdp.enableNetworkTracking(tabId, {\n bodyMode: message.bodyMode || \"text\",\n perBodyBytes: message.perBodyBytes,\n totalBytes: message.totalBodyBytes,\n });\n return { success: true };\n }\n\n case \"STOP_NETWORK_CAPTURE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await cdp.disableNetworkTracking(tabId);\n return { success: true };\n }\n\n case \"VIDEO_START\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const recorderId = String(message.recorderId || \"\");\n if (!recorderId) throw new Error(\"VIDEO_START requires recorderId\");\n if (activeVideoRecorder) throw new Error(\"A video recording is already active\");\n const fps = Number(message.fps);\n if (!Number.isFinite(fps) || fps <= 0 || fps > 60) throw new Error(\"fps must be a number between 1 and 60\");\n\n const onError = (error: Error) => {\n // Keep the active recorder until native fail-closed cleanup sends\n // VIDEO_STOP, so Page.stopScreencast can still reach Chrome.\n postToNativeHost({\n type: \"VIDEO_ERROR\",\n recorderId,\n tabId,\n errorCode: (error as Error & { code?: string }).code || \"video_screencast_failed\",\n error: error.message,\n });\n };\n cdp.subscribeToScreencast(tabId, recorderId, (event) => {\n postToNativeHost({\n type: \"VIDEO_FRAME\",\n recorderId,\n tabId,\n data: event.data,\n metadata: event.metadata,\n sessionId: event.sessionId,\n receivedAt: Date.now(),\n });\n }, onError);\n activeVideoRecorder = { recorderId, tabId };\n try {\n await cdp.startScreencast(tabId, {\n format: \"jpeg\",\n quality: Number.isFinite(Number(message.quality)) ? Number(message.quality) : 80,\n everyNthFrame: Number.isFinite(Number(message.everyNthFrame)) ? Number(message.everyNthFrame) : 1,\n });\n if (activeVideoRecorder?.recorderId !== recorderId) throw new Error(\"Video screencast stopped while starting\");\n return { success: true, recording: true, recorderId, tabId, fps };\n } catch (error) {\n if (activeVideoRecorder?.recorderId === recorderId) activeVideoRecorder = null;\n cdp.unsubscribeFromScreencast(tabId, recorderId);\n throw error;\n }\n }\n\n case \"VIDEO_STOP\": {\n const recorderId = message.recorderId ? String(message.recorderId) : undefined;\n let active = activeVideoRecorder;\n if (recorderId && active?.recorderId !== recorderId) active = null;\n if (!recorderId && active?.tabId !== tabId) active = null;\n if (!active) return { success: true, stopped: false };\n let stopError: unknown;\n try {\n await cdp.stopScreencast(active.tabId);\n } catch (error) {\n stopError = error;\n } finally {\n if (activeVideoRecorder?.recorderId === active.recorderId) activeVideoRecorder = null;\n cdp.unsubscribeFromScreencast(active.tabId, active.recorderId);\n }\n if (stopError) throw stopError;\n return { success: true, stopped: true, recorderId: active.recorderId, tabId: active.tabId };\n }\n\n case \"GET_PLAYBOOK_RECORD_CONTEXT\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n let origin: string | undefined;\n try {\n if (tab.url) {\n const parsed = new URL(tab.url);\n if (parsed.protocol === \"http:\" || parsed.protocol === \"https:\") origin = parsed.origin;\n }\n } catch {}\n return { success: true, origin, url: tab.url };\n }\n\n case \"START_PLAYBOOK_WATCH\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await chrome.tabs.sendMessage(tabId, { type: \"PLAYBOOK_WATCH_START\", includeInputValues: message.includeInputValues === true }, { frameId: 0 });\n return { success: true };\n }\n\n case \"STOP_PLAYBOOK_WATCH\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await chrome.tabs.sendMessage(tabId, { type: \"PLAYBOOK_WATCH_STOP\" }, { frameId: 0 }).catch(() => {});\n return { success: true };\n }\n\n case \"PLAYBOOK_WATCH_EVENT\": {\n postToNativeHost({ ...message, tabId: sender.tab?.id, type: \"PLAYBOOK_WATCH_EVENT\" });\n return { success: true };\n }\n\n case \"READ_NETWORK_REQUESTS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n\n try {\n if (message.bodyMode !== undefined || message.perBodyBytes !== undefined || message.totalBodyBytes !== undefined) {\n await cdp.enableNetworkTracking(tabId, { bodyMode: message.bodyMode, perBodyBytes: message.perBodyBytes, totalBytes: message.totalBodyBytes });\n } else await cdp.enableNetworkTracking(tabId);\n } catch (e) {}\n await cdp.drainNetworkEvents(tabId);\n\n // If full flag is passed, use getNetworkEntries for rich data\n if (message.full) {\n let entries = cdp.getNetworkEntries(tabId, {\n urlPattern: message.urlPattern,\n });\n\n // Apply filters\n if (message.method) {\n entries = entries.filter(e => e.method === message.method);\n }\n if (message.status) {\n entries = entries.filter(e => e.status === message.status);\n }\n if (message.contentType) {\n entries = entries.filter(e => e.type === message.contentType);\n }\n\n if (message.clear) {\n cdp.clearNetworkRequests(tabId);\n }\n\n // Return entries sliced to limit\n const limit = message.limit || 100;\n return {\n entries: entries.slice(0, limit),\n format: message.format,\n verbose: message.verbose\n };\n }\n\n let requests = cdp.getNetworkRequests(tabId, {\n urlPattern: message.urlPattern,\n limit: message.limit || 100,\n });\n\n // Apply filters\n if (message.method) {\n requests = requests.filter(r => r.method === message.method);\n }\n if (message.status) {\n requests = requests.filter(r => r.status === message.status);\n }\n if (message.contentType) {\n requests = requests.filter(r => r.type === message.contentType);\n }\n\n if (message.clear) {\n cdp.clearNetworkRequests(tabId);\n }\n\n return {\n requests,\n format: message.format,\n verbose: message.verbose\n };\n }\n\n case \"EXPORT_NETWORK_REQUESTS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.har && message.jsonl) throw new Error(\"network export cannot combine HAR and JSONL\");\n try {\n if (message.bodyMode !== undefined || message.perBodyBytes !== undefined || message.totalBodyBytes !== undefined) {\n await cdp.enableNetworkTracking(tabId, { bodyMode: message.bodyMode, perBodyBytes: message.perBodyBytes, totalBytes: message.totalBodyBytes });\n } else await cdp.enableNetworkTracking(tabId);\n } catch (e) {}\n await cdp.drainNetworkEvents(tabId);\n const entries = cdp.getNetworkEntries(tabId, {});\n const serializedSize = new TextEncoder().encode(JSON.stringify(entries)).byteLength;\n if (serializedSize > 16 * 1024 * 1024) {\n throw new Error(\"network export source exceeds the 16 MiB native-message limit\");\n }\n return { entries, har: Boolean(message.har), jsonl: Boolean(message.jsonl) };\n }\n\n case \"CLEAR_NETWORK_REQUESTS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n cdp.clearNetworkRequests(tabId);\n return { success: true };\n }\n\n case \"GET_NETWORK_ENTRIES\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n\n try {\n await cdp.enableNetworkTracking(tabId);\n } catch (e) {}\n await cdp.drainNetworkEvents(tabId);\n\n let entries = cdp.getNetworkEntries(tabId, {\n urlPattern: message.urlPattern,\n includeStatic: !message.excludeStatic,\n });\n\n // Apply additional filters\n if (message.origin) {\n entries = entries.filter(e => e.origin === message.origin);\n }\n if (message.method) {\n entries = entries.filter(e => e.method === message.method);\n }\n if (message.status) {\n entries = entries.filter(e => e.status === message.status);\n }\n if (message.type) {\n entries = entries.filter(e => e.type === message.type);\n }\n if (message.since) {\n entries = entries.filter(e => e.ts >= message.since);\n }\n if (message.hasBody !== undefined) {\n entries = entries.filter(e => message.hasBody ? (e.responseBodySize && e.responseBodySize > 0) : !e.responseBodySize);\n }\n if (message.last) {\n entries = entries.slice(-message.last);\n }\n\n if (message.clear) {\n cdp.clearNetworkRequests(tabId);\n }\n\n return { entries };\n }\n\n case \"GET_NETWORK_ENTRY\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.requestId) throw new Error(\"No requestId provided\");\n await cdp.drainNetworkEvents(tabId);\n\n // First try direct lookup by CDP requestId\n let entry = cdp.getNetworkEntry(tabId, message.requestId);\n\n // If not found, try lookup by entry.id (r_xxx format)\n if (!entry) {\n const entries = cdp.getNetworkEntries(tabId, {});\n entry = entries.find(e => e.id === message.requestId) || null;\n }\n\n // Also try lookup by _requestId for entries that use the generated id\n if (!entry) {\n const entries = cdp.getNetworkEntries(tabId, {});\n entry = entries.find(e => e._requestId === message.requestId) || null;\n }\n\n if (!entry) {\n return { error: `Entry not found: ${message.requestId}` };\n }\n return { entry };\n }\n\n case \"GET_RESPONSE_BODY\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.requestId) throw new Error(\"No requestId provided\");\n await cdp.drainNetworkEvents(tabId);\n\n // If requestId looks like entry.id format (r_xxx), look up the CDP requestId\n let cdpRequestId = message.requestId;\n if (message.requestId.startsWith('r_')) {\n const entries = cdp.getNetworkEntries(tabId, {});\n const entry = entries.find(e => e.id === message.requestId);\n if (entry) {\n cdpRequestId = entry._requestId;\n }\n }\n\n const result = await cdp.getResponseBody(tabId, cdpRequestId);\n return result;\n }\n\n case \"GET_NETWORK_ORIGINS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await cdp.drainNetworkEvents(tabId);\n\n const entries = cdp.getNetworkEntries(tabId, {});\n const origins: Record<string, { count: number; lastSeen: number; size: number }> = {};\n\n for (const entry of entries) {\n if (!origins[entry.origin]) {\n origins[entry.origin] = { count: 0, lastSeen: 0, size: 0 };\n }\n origins[entry.origin].count++;\n origins[entry.origin].lastSeen = Math.max(origins[entry.origin].lastSeen, entry.ts);\n origins[entry.origin].size += (entry.responseBodySize || 0);\n }\n\n return { origins };\n }\n\n case \"GET_NETWORK_STATS\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await cdp.drainNetworkEvents(tabId);\n\n const entries = cdp.getNetworkEntries(tabId, {});\n const origins: Record<string, number> = {};\n const byMethod: Record<string, number> = {};\n const byStatus: Record<string, number> = {};\n let totalSize = 0;\n let oldestEntry = Infinity;\n let newestEntry = 0;\n\n for (const entry of entries) {\n // Count by origin\n if (!origins[entry.origin]) {\n origins[entry.origin] = 0;\n }\n origins[entry.origin]++;\n\n // Count by method\n const method = entry.method || 'GET';\n byMethod[method] = (byMethod[method] || 0) + 1;\n\n // Count by status\n if (entry.status) {\n const statusGroup = `${Math.floor(entry.status / 100)}xx`;\n byStatus[statusGroup] = (byStatus[statusGroup] || 0) + 1;\n }\n\n // Sum size\n totalSize += (entry.responseBodySize || 0);\n\n // Track time range\n if (entry.ts < oldestEntry) oldestEntry = entry.ts;\n if (entry.ts > newestEntry) newestEntry = entry.ts;\n }\n\n return {\n stats: {\n totalRequests: entries.length,\n totalSize,\n uniqueOrigins: Object.keys(origins).length,\n startTime: oldestEntry === Infinity ? null : oldestEntry,\n duration: (newestEntry && oldestEntry !== Infinity) ? newestEntry - oldestEntry : 0,\n byMethod,\n byStatus,\n }\n };\n }\n\n case \"RESIZE_WINDOW\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (message.width === undefined && message.height === undefined) {\n throw new Error(\"width or height required\");\n }\n\n const tab = await chrome.tabs.get(tabId);\n if (!tab.windowId) throw new Error(\"Tab has no window\");\n\n const currentWindow =\n message.width === undefined || message.height === undefined\n ? await chrome.windows.get(tab.windowId)\n : null;\n const width = message.width === undefined ? currentWindow?.width : message.width;\n const height = message.height === undefined ? currentWindow?.height : message.height;\n if (width === undefined || height === undefined) {\n throw new Error(\"current window size unavailable\");\n }\n\n await chrome.windows.update(tab.windowId, {\n width: Math.floor(width),\n height: Math.floor(height),\n });\n\n return { success: true, width, height };\n }\n\n case \"TABS_CREATE\": {\n const activeTab = tabId ? await chrome.tabs.get(tabId) : null;\n\n const newTab = await chrome.tabs.create({\n url: message.url || \"about:blank\",\n active: false,\n });\n\n if (!newTab.id) throw new Error(\"Failed to create tab\");\n\n if (activeTab?.groupId && activeTab.groupId !== chrome.tabGroups.TAB_GROUP_ID_NONE) {\n await chrome.tabs.group({ tabIds: newTab.id, groupId: activeTab.groupId });\n }\n\n return {\n success: true,\n tabId: newTab.id,\n url: newTab.url || message.url || \"about:blank\"\n };\n }\n\n case \"UPLOAD_IMAGE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.screenshotId) throw new Error(\"screenshotId required\");\n if (!message.ref && !message.coordinate) throw new Error(\"ref or coordinate required\");\n\n const screenshot = getScreenshot(message.screenshotId);\n if (!screenshot) throw new Error(`Screenshot not found: ${message.screenshotId}`);\n\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"UPLOAD_IMAGE\",\n base64: screenshot.base64,\n ref: message.ref,\n coordinate: message.coordinate,\n filename: message.filename || \"screenshot.png\",\n }, { frameId: getFrameIdForTab(tabId, message) });\n\n return result;\n } catch (err) {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"GET_TABS\": {\n const tabs = await chrome.tabs.query({});\n return {\n tabs: tabs.map((t) => ({ id: t.id, title: t.title, url: t.url })),\n };\n }\n\n case \"LIST_TABS\": {\n const queryOptions: chrome.tabs.QueryInfo = {};\n // Support filtering by window\n if (message.windowId) {\n queryOptions.windowId = message.windowId;\n }\n const tabs = await chrome.tabs.query(queryOptions);\n return {\n tabs: tabs.map((t) => ({\n id: t.id,\n title: t.title,\n url: t.url,\n active: t.active,\n windowId: t.windowId,\n })),\n };\n }\n\n case \"NEW_TAB\": {\n const urls = message.urls || (message.url ? [message.url] : [\"about:blank\"]);\n const createdTabs = [];\n for (let i = 0; i < urls.length; i++) {\n const createOptions: chrome.tabs.CreateProperties = {\n url: urls[i],\n active: i === 0,\n };\n // Support creating tab in specific window\n if (message.windowId) {\n createOptions.windowId = message.windowId;\n }\n const newTab = await chrome.tabs.create(createOptions);\n if (newTab.id) createdTabs.push({ tabId: newTab.id, url: urls[i] });\n }\n if (createdTabs.length === 1) {\n return { success: true, tabId: createdTabs[0].tabId, url: createdTabs[0].url };\n }\n return { success: true, tabs: createdTabs };\n }\n\n case \"SWITCH_TAB\": {\n const targetTabId = message.tabId;\n if (!targetTabId) throw new Error(\"No tabId provided\");\n const tab = (await chrome.tabs.update(targetTabId, { active: true })) as chrome.tabs.Tab;\n if (tab.windowId) {\n await chrome.windows.update(tab.windowId, { focused: true });\n }\n return { success: true, tabId: targetTabId, url: tab.url, title: tab.title };\n }\n\n case \"CLOSE_TAB\": {\n const tabIds = message.tabIds || (message.tabId ? [message.tabId] : []);\n if (tabIds.length === 0) throw new Error(\"No tabId(s) provided\");\n await chrome.tabs.remove(tabIds);\n if (tabIds.length === 1) {\n return { success: true, tabId: tabIds[0] };\n }\n return { success: true, closed: tabIds };\n }\n\n case \"TAB_MOVE\": {\n const rawTabIds = message.tabIds || (message.tabId ? [message.tabId] : []);\n const tabIds = (Array.isArray(rawTabIds) ? rawTabIds : String(rawTabIds).split(\",\"))\n .map((id) => Number(id));\n if (tabIds.length === 0) throw new Error(\"No tabId(s) provided\");\n if (tabIds.some((id) => !Number.isInteger(id) || id <= 0)) {\n throw new Error(\"Invalid tabId(s)\");\n }\n\n const windowId = Number(message.windowId);\n if (!Number.isInteger(windowId) || windowId <= 0) {\n throw new Error(\"No destination windowId provided\");\n }\n\n const index = message.index !== undefined ? Number(message.index) : -1;\n if (!Number.isInteger(index) || index < -1) throw new Error(\"Invalid tab index\");\n\n const moveProperties = { windowId, index };\n const movedTabs = tabIds.length === 1\n ? await chrome.tabs.move(tabIds[0], moveProperties)\n : await chrome.tabs.move(tabIds, moveProperties);\n\n return {\n success: true,\n moved: tabIds,\n destinationWindowId: windowId,\n index,\n tabs: Array.isArray(movedTabs) ? movedTabs : [movedTabs],\n };\n }\n\n case \"TABS_REGISTER\": {\n let targetTabId = tabId;\n if (!targetTabId) {\n const queryOptions: chrome.tabs.QueryInfo = message.windowId\n ? { active: true, windowId: message.windowId }\n : { active: true, lastFocusedWindow: true };\n const [activeTab] = await chrome.tabs.query(queryOptions);\n if (activeTab && !isRestrictedTabUrl(activeTab.url)) {\n targetTabId = activeTab.id;\n } else {\n throw new Error(\n \"Cannot register a restricted browser or extension page. Focus a regular web page, or pass an explicit tabId.\"\n );\n }\n }\n if (!targetTabId) throw new Error(\"No active tab found\");\n if (!message.name) throw new Error(\"No name provided\");\n tabNameRegistry.set(message.name, targetTabId);\n return { success: true, name: message.name, tabId: targetTabId };\n }\n\n case \"TABS_GET_BY_NAME\": {\n if (!message.name) throw new Error(\"No name provided\");\n const registeredTabId = tabNameRegistry.get(message.name);\n if (!registeredTabId) {\n return { error: `No tab registered with name \"${message.name}\"` };\n }\n try {\n const tab = await chrome.tabs.get(registeredTabId);\n return { tabId: registeredTabId, url: tab.url, title: tab.title };\n } catch (e) {\n tabNameRegistry.delete(message.name);\n return { error: `Tab \"${message.name}\" no longer exists` };\n }\n }\n\n case \"TABS_LIST_NAMED\": {\n const namedTabs: { name: string; tabId: number; url?: string; title?: string }[] = [];\n for (const [name, id] of tabNameRegistry) {\n try {\n const tab = await chrome.tabs.get(id);\n namedTabs.push({ name, tabId: id, url: tab.url, title: tab.title });\n } catch (e) {\n tabNameRegistry.delete(name);\n }\n }\n return { tabs: namedTabs };\n }\n\n case \"TABS_UNREGISTER\": {\n if (!message.name) throw new Error(\"No name provided\");\n const deleted = tabNameRegistry.delete(message.name);\n if (!deleted) {\n return { success: false, error: `No tab registered with name \"${message.name}\"` };\n }\n return { success: true };\n }\n\n case \"GET_AUTH\": {\n const { sendToNativeHost } = await import(\"../native/port-manager\");\n try {\n const result = await sendToNativeHost({ type: \"GET_AUTH\" });\n return result;\n } catch (err) {\n return {\n auth: null,\n hint: \"Native host not connected. Make sure surf native host is installed.\"\n };\n }\n }\n\n case \"NATIVE_API_REQUEST\": {\n const { sendToNativeHost } = await import(\"../native/port-manager\");\n try {\n await sendToNativeHost({\n type: \"API_REQUEST\",\n streamId: message.streamId,\n url: message.url,\n method: message.method,\n headers: message.headers,\n body: message.body,\n });\n return { sent: true };\n } catch (err) {\n return { error: err instanceof Error ? err.message : \"Unknown error\" };\n }\n }\n\n case \"STREAM_CONSOLE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const streamId = message.streamId;\n\n try {\n await cdp.enableConsoleTracking(tabId);\n activeStreamTabs.set(streamId, tabId);\n\n cdp.subscribeToConsole(tabId, streamId, (event) => {\n postToNativeHost({\n type: \"STREAM_EVENT\",\n streamId,\n event: {\n type: \"console_event\",\n level: event.type === \"exception\" ? \"error\" : event.type,\n text: event.text,\n timestamp: event.timestamp,\n url: event.url,\n line: event.line,\n },\n });\n });\n\n return { success: true, streaming: true };\n } catch (err) {\n postToNativeHost({\n type: \"STREAM_ERROR\",\n streamId,\n error: err instanceof Error ? err.message : \"Failed to start console stream\",\n });\n return { error: err instanceof Error ? err.message : \"Failed to start console stream\" };\n }\n }\n\n case \"STREAM_NETWORK\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const streamId = message.streamId;\n\n try {\n await cdp.enableNetworkTracking(tabId);\n activeStreamTabs.set(streamId, tabId);\n\n cdp.subscribeToNetwork(tabId, streamId, (event) => {\n postToNativeHost({\n type: \"STREAM_EVENT\",\n streamId,\n event: {\n type: \"network_event\",\n method: event.method,\n url: event.url,\n status: event.status,\n duration: event.duration,\n timestamp: event.timestamp,\n },\n });\n });\n\n return { success: true, streaming: true };\n } catch (err) {\n postToNativeHost({\n type: \"STREAM_ERROR\",\n streamId,\n error: err instanceof Error ? err.message : \"Failed to start network stream\",\n });\n return { error: err instanceof Error ? err.message : \"Failed to start network stream\" };\n }\n }\n\n case \"STREAM_STOP\": {\n const streamId = message.streamId;\n const streamTabId = activeStreamTabs.get(streamId);\n\n if (streamTabId !== undefined) {\n cdp.unsubscribeFromConsole(streamTabId, streamId);\n cdp.unsubscribeFromNetwork(streamTabId, streamId);\n activeStreamTabs.delete(streamId);\n }\n\n return { success: true };\n }\n\n case \"SEARCH_PAGE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n if (!message.term) throw new Error(\"Search term required\");\n try {\n const result = await chrome.tabs.sendMessage(tabId, {\n type: \"SEARCH_PAGE\",\n term: message.term,\n caseSensitive: message.caseSensitive || false,\n limit: message.limit || 10,\n }, { frameId: getFrameIdForTab(tabId, message) });\n return result;\n } catch {\n return { error: \"Content script not loaded. Try refreshing the page.\" };\n }\n }\n\n case \"TAB_GROUP_CREATE\": {\n const tabIds: number[] = [...(message.tabIds || [])];\n const name = message.name || \"Surf\";\n const validColors = [\"grey\", \"blue\", \"red\", \"yellow\", \"green\", \"pink\", \"purple\", \"cyan\", \"orange\"];\n const color = validColors.includes(message.color) ? message.color : \"blue\";\n\n if (tabIds.length === 0 && tabId) {\n tabIds.push(tabId);\n }\n\n if (tabIds.length === 0) throw new Error(\"No tabs specified\");\n const groupTabIds = tabIds.length === 1 ? tabIds[0] : (tabIds as [number, ...number[]]);\n\n const existingGroups = await chrome.tabGroups.query({ title: name });\n let groupId: number;\n\n if (existingGroups.length > 0) {\n groupId = existingGroups[0].id;\n await chrome.tabs.group({ tabIds: groupTabIds, groupId });\n } else {\n groupId = await chrome.tabs.group({ tabIds: groupTabIds });\n await chrome.tabGroups.update(groupId, {\n title: name,\n color: color as `${chrome.tabGroups.Color}`,\n collapsed: false,\n });\n }\n\n return { success: true, groupId, name, tabIds };\n }\n\n case \"TAB_GROUP_REMOVE\": {\n const tabIds: number[] = [...(message.tabIds || [])];\n if (tabIds.length === 0 && tabId) {\n tabIds.push(tabId);\n }\n\n if (tabIds.length === 0) throw new Error(\"No tabs specified\");\n const ungroupTabIds = tabIds.length === 1 ? tabIds[0] : (tabIds as [number, ...number[]]);\n\n await chrome.tabs.ungroup(ungroupTabIds);\n return { success: true, ungrouped: tabIds };\n }\n\n case \"TAB_GROUPS_LIST\": {\n const groups = await chrome.tabGroups.query({});\n const result = [];\n\n for (const group of groups) {\n const tabs = await chrome.tabs.query({ groupId: group.id });\n result.push({\n id: group.id,\n name: group.title || \"(unnamed)\",\n color: group.color,\n collapsed: group.collapsed,\n tabs: tabs.map(t => ({ id: t.id, title: t.title, url: t.url })),\n });\n }\n\n return { groups: result };\n }\n\n case \"CLICK_SELECTOR\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const selector = message.selector;\n const index = message.index || 0;\n const frameId = getFrameIdForTab(tabId, message);\n\n if (frameId > 0) {\n const [result] = await chrome.scripting.executeScript({\n target: { tabId, frameIds: [frameId] },\n func: (selector: string, index: number) => {\n const elements = document.querySelectorAll(selector);\n if (elements.length === 0) return { error: \"No elements match selector\" };\n if (index >= elements.length) return { error: `Index ${index} out of range (found ${elements.length} elements)` };\n\n (elements[index] as HTMLElement).click();\n return { success: true, selector, index, matchCount: elements.length };\n },\n args: [selector, index],\n });\n return result?.result || { error: \"Failed to click element\" };\n }\n\n const script = `(() => {\n const elements = document.querySelectorAll(${JSON.stringify(selector)});\n if (elements.length === 0) return { error: \"No elements match selector\" };\n if (${index} >= elements.length) return { error: \"Index \" + ${index} + \" out of range (found \" + elements.length + \" elements)\" };\n\n const el = elements[${index}];\n const rect = el.getBoundingClientRect();\n return {\n x: rect.left + rect.width / 2,\n y: rect.top + rect.height / 2,\n count: elements.length\n };\n })()`;\n\n const result = await cdp.evaluateScript(tabId, script);\n const coords = result.result?.value;\n\n if (coords?.error) return { error: coords.error };\n if (!coords) return { error: \"Failed to get element coordinates\" };\n\n await cdp.click(tabId, coords.x, coords.y, \"left\", 1, 0);\n return { success: true, selector, index, matchCount: coords.count };\n }\n\n case \"COOKIE_LIST\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n const cookies = await chrome.cookies.getAll({ url });\n return { cookies };\n }\n\n case \"COOKIE_GET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n if (!message.name) throw new Error(\"Cookie name required\");\n const cookie = await chrome.cookies.get({ url, name: message.name });\n if (!cookie) return { error: `Cookie \"${message.name}\" not found` };\n return { cookie };\n }\n\n case \"COOKIE_SET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n if (!message.name) throw new Error(\"Cookie name required\");\n if (message.value === undefined) throw new Error(\"Cookie value required\");\n\n const cookieDetails: chrome.cookies.SetDetails = {\n url,\n name: message.name,\n value: message.value,\n };\n\n if (message.expires) {\n const expirationDate = new Date(message.expires).getTime() / 1000;\n if (isNaN(expirationDate)) {\n throw new Error(`Invalid expiration date: ${message.expires}`);\n }\n cookieDetails.expirationDate = expirationDate;\n }\n\n const result = await chrome.cookies.set(cookieDetails);\n return { success: true, cookie: result };\n }\n\n case \"COOKIE_CLEAR\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n if (!message.name) throw new Error(\"Cookie name required\");\n\n await chrome.cookies.remove({ url, name: message.name });\n return { success: true, cleared: message.name };\n }\n\n case \"COOKIE_CLEAR_ALL\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const url = tab.url;\n if (!url) throw new Error(\"Tab has no URL\");\n\n const cookies = await chrome.cookies.getAll({ url });\n for (const cookie of cookies) {\n await chrome.cookies.remove({ url, name: cookie.name });\n }\n return { success: true, cleared: cookies.length };\n }\n\n case \"TAB_RELOAD\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await chrome.tabs.reload(tabId, { bypassCache: message.hard || false });\n return { success: true };\n }\n\n case \"ZOOM_GET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const zoom = await chrome.tabs.getZoom(tabId);\n return { zoom };\n }\n\n case \"ZOOM_SET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const level = message.level;\n if (level < 0.25 || level > 5) throw new Error(\"Zoom level must be between 0.25 and 5\");\n await chrome.tabs.setZoom(tabId, level);\n return { success: true, zoom: level };\n }\n\n case \"ZOOM_RESET\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n await chrome.tabs.setZoom(tabId, 0);\n return { success: true, zoom: 1.0 };\n }\n\n case \"BOOKMARK_ADD\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n const createProps: { title: string; url?: string; parentId?: string } = {\n title: tab.title || \"Untitled\",\n url: tab.url,\n };\n if (message.folder) {\n const search = await chrome.bookmarks.search({ title: message.folder });\n const folder = search.find(b => !b.url);\n if (folder) {\n createProps.parentId = folder.id;\n }\n }\n const bookmark = await chrome.bookmarks.create(createProps);\n return { success: true, bookmark: { id: bookmark.id, title: bookmark.title, url: bookmark.url } };\n }\n\n case \"BOOKMARK_REMOVE\": {\n if (!tabId) throw new Error(\"No tabId provided\");\n const tab = await chrome.tabs.get(tabId);\n if (!tab.url) throw new Error(\"Tab has no URL\");\n const bookmarks = await chrome.bookmarks.search({ url: tab.url });\n if (bookmarks.length === 0) throw new Error(\"No bookmark found for this URL\");\n await chrome.bookmarks.remove(bookmarks[0].id);\n return { success: true };\n }\n\n case \"BOOKMARK_LIST\": {\n const limit = typeof message.limit === 'number' ? message.limit : 50;\n let bookmarks: chrome.bookmarks.BookmarkTreeNode[] = [];\n\n if (message.folder) {\n const search = await chrome.bookmarks.search({ title: message.folder });\n const folder = search.find(b => !b.url);\n if (folder) {\n const children = await chrome.bookmarks.getChildren(folder.id);\n bookmarks = children.filter(b => b.url).slice(0, limit);\n }\n } else {\n const recent = await chrome.bookmarks.getRecent(limit);\n bookmarks = recent;\n }\n\n return {\n bookmarks: bookmarks.map(b => ({\n id: b.id,\n title: b.title,\n url: b.url,\n dateAdded: b.dateAdded\n }))\n };\n }\n\n case \"HISTORY_LIST\": {\n const limit = typeof message.limit === 'number' ? message.limit : 20;\n const items = await chrome.history.search({\n text: \"\",\n maxResults: limit,\n startTime: 0\n });\n return {\n history: items.map(h => ({\n url: h.url,\n title: h.title,\n lastVisitTime: h.lastVisitTime,\n visitCount: h.visitCount\n }))\n };\n }\n\n case \"HISTORY_SEARCH\": {\n const query = message.query;\n const limit = typeof message.limit === 'number' ? message.limit : 20;\n const items = await chrome.history.search({\n text: query,\n maxResults: limit,\n startTime: 0\n });\n return {\n history: items.map(h => ({\n url: h.url,\n title: h.title,\n lastVisitTime: h.lastVisitTime,\n visitCount: h.visitCount\n }))\n };\n }\n\n case \"GET_CHATGPT_COOKIES\": {\n const cookies = await chrome.cookies.getAll({ domain: \".chatgpt.com\" });\n const openaiCookies = await chrome.cookies.getAll({ domain: \".openai.com\" });\n return { cookies: [...cookies, ...openaiCookies] };\n }\n\n case \"CHATGPT_NEW_TAB\": {\n const tab = await chrome.tabs.create({\n url: \"https://chatgpt.com/\",\n active: true,\n });\n if (!tab.id) throw new Error(\"Failed to create tab\");\n const currentTab = await chrome.tabs.get(tab.id);\n if (currentTab.status !== \"complete\") {\n await new Promise<void>((resolve) => {\n const listener = (tabId: number, info: chrome.tabs.OnUpdatedInfo) => {\n if (tabId === tab.id && info.status === \"complete\") {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }\n };\n chrome.tabs.onUpdated.addListener(listener);\n setTimeout(() => {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }, 30000);\n });\n }\n await cdp.attach(tab.id);\n // Wait for JS runtime to be ready after CDP attach\n await waitForRuntimeReady(tab.id, 10000);\n return { tabId: tab.id };\n }\n\n case \"CHATGPT_CLOSE_TAB\": {\n const chatTabId = message.tabId;\n if (chatTabId) {\n try {\n await cdp.detach(chatTabId);\n } catch {}\n try {\n await chrome.tabs.remove(chatTabId);\n } catch {}\n }\n return { success: true };\n }\n\n case \"CHATGPT_CDP_COMMAND\": {\n const { method, params } = message;\n const result = await cdp.sendCommand(message.tabId, method, params || {});\n return result;\n }\n\n case \"CHATGPT_EVALUATE\": {\n const result = await cdp.evaluateScript(message.tabId, message.expression);\n return result;\n }\n\n case \"PERPLEXITY_NEW_TAB\": {\n const tab = await chrome.tabs.create({\n url: \"https://www.perplexity.ai/\",\n active: true,\n });\n if (!tab.id) throw new Error(\"Failed to create tab\");\n const currentTab = await chrome.tabs.get(tab.id);\n if (currentTab.status !== \"complete\") {\n await new Promise<void>((resolve) => {\n const listener = (tabId: number, info: chrome.tabs.OnUpdatedInfo) => {\n if (tabId === tab.id && info.status === \"complete\") {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }\n };\n chrome.tabs.onUpdated.addListener(listener);\n setTimeout(() => {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }, 30000);\n });\n }\n await cdp.attach(tab.id);\n // Wait for JS runtime to be ready after CDP attach\n await waitForRuntimeReady(tab.id, 10000);\n return { tabId: tab.id };\n }\n\n case \"PERPLEXITY_CLOSE_TAB\": {\n const pplxTabId = message.tabId;\n if (pplxTabId) {\n try {\n await cdp.detach(pplxTabId);\n } catch {}\n try {\n await chrome.tabs.remove(pplxTabId);\n } catch {}\n }\n return { success: true };\n }\n\n case \"PERPLEXITY_CDP_COMMAND\": {\n const { method, params } = message;\n const result = await cdp.sendCommand(message.tabId, method, params || {});\n return result;\n }\n\n case \"PERPLEXITY_EVALUATE\": {\n const result = await cdp.evaluateScript(message.tabId, message.expression);\n return result;\n }\n\n case \"GET_TWITTER_COOKIES\": {\n // Grok requires X.com cookies for authentication\n const domains = [\".x.com\", \".twitter.com\", \"x.com\", \"twitter.com\"];\n const allCookies: chrome.cookies.Cookie[] = [];\n\n for (const domain of domains) {\n try {\n const cookies = await chrome.cookies.getAll({ domain });\n allCookies.push(...cookies);\n } catch {}\n }\n\n // Also try by URL\n const urls = [\"https://x.com\", \"https://twitter.com\"];\n for (const url of urls) {\n try {\n const cookies = await chrome.cookies.getAll({ url });\n allCookies.push(...cookies);\n } catch {}\n }\n\n // Dedupe by name\n const seen = new Map<string, chrome.cookies.Cookie>();\n for (const cookie of allCookies) {\n const existing = seen.get(cookie.name);\n if (!existing || cookie.domain?.includes(\"x.com\")) {\n seen.set(cookie.name, cookie);\n }\n }\n\n return { cookies: Array.from(seen.values()) };\n }\n\n case \"GROK_NEW_TAB\": {\n const tab = await chrome.tabs.create({\n url: \"https://x.com/i/grok\",\n active: true,\n });\n if (!tab.id) throw new Error(\"Failed to create tab\");\n const currentTab = await chrome.tabs.get(tab.id);\n if (currentTab.status !== \"complete\") {\n await new Promise<void>((resolve) => {\n const listener = (tabId: number, info: chrome.tabs.OnUpdatedInfo) => {\n if (tabId === tab.id && info.status === \"complete\") {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }\n };\n chrome.tabs.onUpdated.addListener(listener);\n setTimeout(() => {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }, 30000);\n });\n }\n await cdp.attach(tab.id);\n // Wait for JS runtime to be ready after CDP attach\n await waitForRuntimeReady(tab.id, 10000);\n return { tabId: tab.id };\n }\n\n case \"GROK_CLOSE_TAB\": {\n const grokTabId = message.tabId;\n if (grokTabId) {\n try {\n await cdp.detach(grokTabId);\n } catch {}\n try {\n await chrome.tabs.remove(grokTabId);\n } catch {}\n }\n return { success: true };\n }\n\n case \"GROK_CDP_COMMAND\": {\n const { method, params } = message;\n const result = await cdp.sendCommand(message.tabId, method, params || {});\n return result;\n }\n\n case \"GROK_EVALUATE\": {\n const result = await cdp.evaluateScript(message.tabId, message.expression);\n return result;\n }\n\n case \"GEMINI_NEW_TAB\": {\n const tab = await chrome.tabs.create({\n url: \"https://gemini.google.com/app\",\n active: true,\n });\n if (!tab.id) throw new Error(\"Failed to create tab\");\n return { tabId: tab.id };\n }\n\n case \"GEMINI_CLOSE_TAB\": {\n const geminiTabId = message.tabId;\n if (geminiTabId) {\n try {\n await cdp.detach(geminiTabId);\n } catch {}\n try {\n await chrome.tabs.remove(geminiTabId);\n } catch {}\n }\n return { success: true };\n }\n\n case \"AI_UPLOAD_FILE_TO_TAB\":\n case \"UPLOAD_FILE_TO_TAB\": {\n const { tabId: uploadTabId, filePaths } = message;\n const provider = message.type === \"UPLOAD_FILE_TO_TAB\" ? \"gemini\" : message.provider;\n if (!uploadTabId || !filePaths?.length) {\n throw new Error(`${message.type} requires tabId and filePaths`);\n }\n if (provider !== \"gemini\" && provider !== \"chatgpt\") {\n throw new Error(`Unsupported upload provider: ${provider}`);\n }\n return uploadFilesToProviderTab(provider, uploadTabId, filePaths);\n }\n\n case \"GEMINI_FETCH_URL\": {\n const imageUrl = message.url;\n if (!imageUrl) throw new Error(\"No URL provided\");\n const resp = await fetch(imageUrl, { credentials: \"include\" });\n if (!resp.ok) throw new Error(`Fetch failed: ${resp.status}`);\n const blob = await resp.blob();\n const reader = new FileReader();\n const b64: string = await new Promise((resolve, reject) => {\n reader.onload = () => resolve((reader.result as string).split(\",\")[1]);\n reader.onerror = () => reject(new Error(\"FileReader failed\"));\n reader.readAsDataURL(blob);\n });\n return { b64, size: blob.size, type: blob.type };\n }\n\n case \"AISTUDIO_NEW_TAB\": {\n const url = message.url || \"https://aistudio.google.com/prompts/new_chat\";\n const tab = await chrome.tabs.create({ url, active: true });\n if (!tab.id) throw new Error(\"Failed to create tab\");\n const currentTab = await chrome.tabs.get(tab.id);\n if (currentTab.status !== \"complete\") {\n await new Promise<void>((resolve) => {\n const listener = (tabId: number, info: chrome.tabs.OnUpdatedInfo) => {\n if (tabId === tab.id && info.status === \"complete\") {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }\n };\n chrome.tabs.onUpdated.addListener(listener);\n setTimeout(() => {\n chrome.tabs.onUpdated.removeListener(listener);\n resolve();\n }, 30000);\n });\n }\n await cdp.attach(tab.id);\n await waitForRuntimeReady(tab.id, 10000);\n return { tabId: tab.id };\n }\n\n case \"AISTUDIO_CLOSE_TAB\": {\n const aiStudioTabId = message.tabId;\n if (aiStudioTabId) {\n try { await cdp.detach(aiStudioTabId); } catch {}\n try { await chrome.tabs.remove(aiStudioTabId); } catch {}\n }\n return { success: true };\n }\n\n case \"AISTUDIO_CDP_COMMAND\": {\n const { method, params } = message;\n return await cdp.sendCommand(message.tabId, method, params || {});\n }\n\n case \"AISTUDIO_EVALUATE\": {\n return await cdp.evaluateScript(message.tabId, message.expression);\n }\n\n case \"DOWNLOADS_SEARCH\": {\n const results = await chrome.downloads.search(message.searchParams || {});\n return {\n downloads: results.map(d => ({\n id: d.id,\n filename: d.filename,\n state: d.state,\n error: d.error,\n }))\n };\n }\n\n case \"GET_GOOGLE_COOKIES\": {\n // Gemini requires cookies from multiple Google domains\n const domains = [\".google.com\", \".gemini.google.com\", \"accounts.google.com\", \"www.google.com\"];\n const allCookies: chrome.cookies.Cookie[] = [];\n\n for (const domain of domains) {\n try {\n const cookies = await chrome.cookies.getAll({ domain });\n allCookies.push(...cookies);\n } catch {}\n }\n\n // Also try by URL for better coverage\n const urls = [\"https://gemini.google.com\", \"https://aistudio.google.com\", \"https://accounts.google.com\", \"https://www.google.com\"];\n for (const url of urls) {\n try {\n const cookies = await chrome.cookies.getAll({ url });\n allCookies.push(...cookies);\n } catch {}\n }\n\n // Dedupe by name, preferring google.com domain with root path\n const seen = new Map<string, chrome.cookies.Cookie>();\n for (const cookie of allCookies) {\n const existing = seen.get(cookie.name);\n if (!existing ||\n (cookie.domain === \".google.com\" && cookie.path === \"/\") ||\n (!existing.domain?.includes(\"google.com\") && cookie.domain?.includes(\"google.com\"))) {\n seen.set(cookie.name, cookie);\n }\n }\n\n return { cookies: Array.from(seen.values()) };\n }\n\n case \"WINDOW_NEW\": {\n // Default to a usable blank page if no URL provided\n const url = message.url || 'data:text/html,<html><head><title>Surf Agent</title></head><body style=\"font-family:system-ui;display:flex;align-items:center;justify-content:center;height:100vh;margin:0;color:%23666\"><div style=\"text-align:center\"><h2>Agent Window</h2><p>Ready for automation</p></div></body></html>';\n\n const createOptions: chrome.windows.CreateData = {\n focused: message.focused !== false,\n type: \"normal\",\n url,\n };\n\n if (message.width && message.height) {\n createOptions.width = message.width;\n createOptions.height = message.height;\n }\n\n if (message.incognito) {\n createOptions.incognito = true;\n }\n\n const window = (await chrome.windows.create(createOptions)) as chrome.windows.Window;\n\n if (!window.id) throw new Error(\"Failed to create window\");\n\n // Get the tab that was created with the window\n const tabs = await chrome.tabs.query({ windowId: window.id });\n const firstTab = tabs[0];\n\n // Wait for tab to be ready\n if (firstTab?.id) {\n await new Promise(r => setTimeout(r, 150));\n }\n\n return {\n success: true,\n windowId: window.id,\n tabId: firstTab?.id,\n hint: `Use --window-id ${window.id} to target this window`,\n };\n }\n\n case \"WINDOW_LIST\": {\n const windows = await chrome.windows.getAll({ populate: true });\n\n return {\n windows: windows.map(w => ({\n id: w.id,\n focused: w.focused,\n type: w.type,\n state: w.state,\n width: w.width,\n height: w.height,\n tabCount: w.tabs?.length || 0,\n tabs: message.includeTabs ? w.tabs?.map(t => ({\n id: t.id,\n title: t.title,\n url: t.url,\n active: t.active,\n })) : undefined,\n }))\n };\n }\n\n case \"WINDOW_FOCUS\": {\n if (!message.windowId) throw new Error(\"No windowId provided\");\n\n await chrome.windows.update(message.windowId, { focused: true });\n return { success: true, windowId: message.windowId };\n }\n\n case \"WINDOW_CLOSE\": {\n if (!message.windowId) throw new Error(\"No windowId provided\");\n\n await chrome.windows.remove(message.windowId);\n return { success: true, windowId: message.windowId };\n }\n\n case \"WINDOW_RESIZE\": {\n if (!message.windowId) throw new Error(\"No windowId provided\");\n\n const updateInfo: chrome.windows.UpdateInfo = {};\n if (message.width) updateInfo.width = message.width;\n if (message.height) updateInfo.height = message.height;\n if (message.left !== undefined) updateInfo.left = message.left;\n if (message.top !== undefined) updateInfo.top = message.top;\n if (message.state) updateInfo.state = message.state as `${chrome.windows.WindowState}`;\n\n const window = (await chrome.windows.update(message.windowId, updateInfo)) as chrome.windows.Window;\n return {\n success: true,\n windowId: message.windowId,\n width: window.width,\n height: window.height,\n };\n }\n\n default:\n throw new Error(`Unknown message type: ${message.type}`);\n }\n}\n\nchrome.runtime.onInstalled.addListener((details) => {\n debugLog(\"Extension installed/updated:\", details.reason);\n});\n\nconst COMMANDS_WITHOUT_TAB = new Set([\n \"LIST_TABS\", \"NEW_TAB\", \"TABS_NEW\", \"CLOSE_TAB\", \"CLOSE_TABS\", \"TAB_MOVE\", \"SWITCH_TAB\", \"TABS_SWITCH\",\n \"TABS_REGISTER\", \"TABS_UNREGISTER\", \"TABS_LIST_NAMED\", \"TABS_GET_BY_NAME\",\n \"CREATE_TAB_GROUP\", \"UNGROUP_TABS\", \"LIST_TAB_GROUPS\", \"GET_HISTORY\", \"SEARCH_HISTORY\",\n \"GET_COOKIES\", \"SET_COOKIE\", \"DELETE_COOKIES\", \"GET_BOOKMARKS\", \"ADD_BOOKMARK\",\n \"DELETE_BOOKMARK\", \"DIALOG_DISMISS\", \"DIALOG_ACCEPT\", \"DIALOG_INFO\",\n \"CHATGPT_NEW_TAB\", \"CHATGPT_CLOSE_TAB\", \"CHATGPT_EVALUATE\", \"CHATGPT_CDP_COMMAND\",\n \"GET_CHATGPT_COOKIES\", \"GET_GOOGLE_COOKIES\", \"GET_TWITTER_COOKIES\",\n \"PERPLEXITY_NEW_TAB\", \"PERPLEXITY_CLOSE_TAB\", \"PERPLEXITY_EVALUATE\", \"PERPLEXITY_CDP_COMMAND\",\n \"GROK_NEW_TAB\", \"GROK_CLOSE_TAB\", \"GROK_EVALUATE\", \"GROK_CDP_COMMAND\",\n \"GEMINI_NEW_TAB\", \"GEMINI_CLOSE_TAB\", \"GEMINI_FETCH_URL\", \"AI_UPLOAD_FILE_TO_TAB\", \"UPLOAD_FILE_TO_TAB\",\n \"AISTUDIO_NEW_TAB\", \"AISTUDIO_CLOSE_TAB\", \"AISTUDIO_EVALUATE\", \"AISTUDIO_CDP_COMMAND\",\n \"DOWNLOADS_SEARCH\",\n \"WINDOW_NEW\", \"WINDOW_LIST\", \"WINDOW_FOCUS\", \"WINDOW_CLOSE\", \"WINDOW_RESIZE\",\n \"TARGET_INSPECT\", \"TARGET_RESOLVE\", \"SESSION_CREATE_TARGET\", \"SESSION_CLOSE_TARGET\",\n \"EMULATE_DEVICE_LIST\"\n]);\n\ninitNativeMessaging(async (msg) => {\n let tabId = msg.tabId;\n const windowId = msg.windowId;\n const isDialogCommand = msg.type?.startsWith(\"DIALOG_\");\n const needsTab = !COMMANDS_WITHOUT_TAB.has(msg.type);\n let autoCreatedTab = false;\n\n if (tabId && !isDialogCommand && !COMMANDS_WITHOUT_TAB.has(msg.type)) {\n try {\n await chrome.tabs.get(tabId);\n } catch {\n throw new BrowserCommandError(\"tab_gone\", `Tab ${tabId} no longer exists`, { tabId });\n }\n } else if (!tabId && needsTab) {\n if (msg.strictTarget) {\n throw new BrowserCommandError(\"target_required\", \"Strict browser command requires an explicit tab binding\");\n }\n const resolved = await resolveDefaultTarget(windowId, true);\n tabId = resolved.tab.id;\n autoCreatedTab = resolved.autoCreated;\n }\n\n if (tabId && msg.frameId !== undefined) await validateRequestedFrame(tabId, msg.frameId);\n const result = await handleMessage({ ...msg, tabId }, {} as chrome.runtime.MessageSender);\n const hints: string[] = [];\n if (autoCreatedTab) {\n hints.push(`Auto-created tab in window ${windowId} (no usable tabs existed). Navigate to your target URL.`);\n }\n let resolvedWindowId: number | undefined;\n if (tabId) {\n try { resolvedWindowId = (await chrome.tabs.get(tabId)).windowId; } catch {}\n }\n\n return {\n ...result,\n _resolvedTabId: tabId,\n _resolvedWindowId: resolvedWindowId,\n _hint: hints.length > 0 ? hints.join(\" \") : undefined,\n };\n}, cleanupActiveVideoRecorder);\n"],"file":"index.js"}