@vostride/agent-qa-web 0.1.21 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2725 -772
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +139 -20
- package/dist/index.d.ts +139 -20
- package/dist/index.js +2731 -766
- package/dist/index.js.map +1 -1
- package/package.json +6 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapter.ts","../src/dom-extractor.ts","../src/observer.ts","../src/element-resolver.ts","../src/action-validator.ts","../src/smart-wait.ts","../src/scroll-helper.ts","../src/browser-install-error.ts","../src/farm-adapter.ts","../src/accessibility.ts"],"sourcesContent":["import type { Browser, BrowserContext, Page } from 'playwright-core'\nimport type { PlatformAdapter, PlatformConfig, ScreenState, Action, ActionResult, ObserveOptions, ConsoleLogEntry, NetworkLogEntry } from '@vostride/agent-qa-core'\nimport { convertKeysForPlatform, isMacPlatform, warnIfOutOfBounds } from '@vostride/agent-qa-core'\nimport { observePage } from './observer.js'\nimport { ElementResolver } from './element-resolver.js'\nimport { validateAction } from './action-validator.js'\nimport { waitForPageReady } from './smart-wait.js'\nimport { scrollWithRef } from './scroll-helper.js'\nimport type { RefMap } from './types.js'\nimport { formatMissingBrowserError, isPlaywrightMissingBrowserError } from './browser-install-error.js'\n\ninterface PageLogBuffers {\n consoleLogs: ConsoleLogEntry[]\n networkLogs: NetworkLogEntry[]\n consoleDrainIndex: number\n networkDrainIndex: number\n pendingRequests: Map<string, { url: string; method: string; headers: Record<string, string>; startTime: number; postData?: string }>\n}\n\nfunction clickDelayOption(clickDelay?: number): { delay?: number } {\n return clickDelay !== undefined && clickDelay > 0 ? { delay: clickDelay } : {}\n}\n\nexport class WebPlatformAdapter implements PlatformAdapter {\n readonly platform = 'web' as const\n\n private browser: Browser | null = null\n private context: BrowserContext | null = null\n private page: Page | null = null\n private lastRefs: RefMap = {}\n private pageLogBuffers = new Map<Page, PageLogBuffers>()\n private logCaptureConfig: { console: boolean; network: boolean } = { console: true, network: true }\n private disconnected = false\n private intentionalClose = false\n\n async setup(config: PlatformConfig): Promise<void> {\n const { chromium, firefox, webkit } = await import('playwright-core')\n const launchers = { chromium, firefox, webkit } as const\n const browserName = config.browser?.name ?? 'chromium'\n const launcher = launchers[browserName]\n\n try {\n this.browser = await launcher.launch({\n headless: config.browser?.headless ?? true,\n ...(browserName === 'chromium' ? { args: ['--disable-blink-features=AutomationControlled'] } : {}),\n })\n } catch (error) {\n if (isPlaywrightMissingBrowserError(error)) {\n throw new Error(formatMissingBrowserError(browserName))\n }\n throw error\n }\n\n this.disconnected = false\n this.intentionalClose = false\n this.browser.on('disconnected', () => {\n if (!this.intentionalClose) {\n this.disconnected = true\n }\n })\n\n const contextOptions: Record<string, unknown> = {\n viewport: config.browser?.viewport ?? { width: 1280, height: 720 },\n }\n if (config.recording?.enabled) {\n contextOptions.recordVideo = {\n dir: config.recording.videoDir,\n size: config.recording.videoSize ?? config.browser?.viewport ?? { width: 1280, height: 720 },\n }\n }\n if (config.authState?.storageStatePath) {\n contextOptions.storageState = config.authState.storageStatePath\n }\n this.context = await this.browser.newContext(contextOptions)\n\n // Clipboard write permission — chromium only (firefox/webkit reject this permission per Pitfall 3)\n if (browserName === 'chromium') {\n await this.context.grantPermissions(['clipboard-write'])\n }\n\n this.logCaptureConfig = { console: config.logCapture?.console !== false, network: config.logCapture?.network !== false }\n\n // Hide automation signals so bot-protected sites don't redirect\n await this.context.addInitScript(() => {\n Object.defineProperty(navigator, 'webdriver', { get: () => false })\n })\n\n this.page = await this.context.newPage()\n this.attachLogListeners(this.page)\n }\n\n async cleanup(): Promise<void> {\n this.intentionalClose = true\n if (this.browser) {\n await this.browser.close()\n }\n this.browser = null\n this.context = null\n this.page = null\n this.lastRefs = {}\n this.pageLogBuffers.clear()\n this.disconnected = false\n this.intentionalClose = false\n }\n\n get isBrowserDisconnected(): boolean {\n return this.disconnected\n }\n\n async observe(options?: ObserveOptions): Promise<ScreenState> {\n if (!this.page) {\n throw new Error('WebPlatformAdapter not initialized — call setup() first')\n }\n\n await waitForPageReady(this.page)\n const state = await observePage(this.page, {\n extractDom: options?.extractDom,\n })\n this.lastRefs = (state.metadata.refMap as RefMap) ?? {}\n return state\n }\n\n async execute(action: Action): Promise<ActionResult> {\n if (!this.page) {\n throw new Error('WebPlatformAdapter not initialized — call setup() first')\n }\n\n try {\n return await this.executeAction(action)\n } catch (err) {\n let screenshot: Buffer | undefined\n let boundingBox: { x: number; y: number; width: number; height: number } | undefined\n try {\n screenshot = await this.page.screenshot({ scale: 'css' })\n } catch {\n // ignore screenshot failure\n }\n try {\n if ('ref' in action && typeof (action as any).ref === 'string') {\n const resolver = new ElementResolver(this.page, this.lastRefs)\n const box = await resolver.getBoundingBox((action as any).ref)\n if (box) boundingBox = box\n }\n } catch {\n // ignore bounding box failure\n }\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n screenshot,\n boundingBox,\n }\n }\n }\n\n async screenshot(): Promise<Buffer | undefined> {\n try {\n if (this.page) {\n return await this.page.screenshot({ scale: 'css' })\n }\n return undefined\n } catch {\n return undefined\n }\n }\n\n getPage(): Page | null {\n return this.page\n }\n\n async getVideoPath(): Promise<string | null> {\n try {\n const video = this.page?.video()\n if (!video) return null\n return await video.path()\n } catch {\n return null\n }\n }\n\n drainConsoleLogs(level?: string): ConsoleLogEntry[] {\n const all: ConsoleLogEntry[] = []\n for (const buffers of this.pageLogBuffers.values()) {\n const newLogs = buffers.consoleLogs.slice(buffers.consoleDrainIndex)\n buffers.consoleDrainIndex = buffers.consoleLogs.length\n all.push(...newLogs)\n }\n if (!level) return all\n return all.filter(e => e.level === level)\n }\n\n drainNetworkLogs(urlPattern?: string): NetworkLogEntry[] {\n const all: NetworkLogEntry[] = []\n for (const buffers of this.pageLogBuffers.values()) {\n const newLogs = buffers.networkLogs.slice(buffers.networkDrainIndex)\n buffers.networkDrainIndex = buffers.networkLogs.length\n all.push(...newLogs)\n }\n if (!urlPattern) return all\n return all.filter(e => e.url.includes(urlPattern))\n }\n\n private attachLogListeners(page: Page): void {\n const buffers: PageLogBuffers = {\n consoleLogs: [],\n networkLogs: [],\n consoleDrainIndex: 0,\n networkDrainIndex: 0,\n pendingRequests: new Map(),\n }\n this.pageLogBuffers.set(page, buffers)\n\n if (this.logCaptureConfig.console) {\n page.on('console', (msg) => {\n buffers.consoleLogs.push({\n level: msg.type(),\n text: msg.text(),\n location: msg.location(),\n timestamp: Date.now(),\n })\n if (buffers.consoleLogs.length > 1000) {\n buffers.consoleLogs = buffers.consoleLogs.slice(-500)\n }\n })\n }\n\n if (this.logCaptureConfig.network) {\n page.on('request', (request) => {\n buffers.pendingRequests.set(request.url() + request.method(), {\n url: request.url(),\n method: request.method(),\n headers: request.headers(),\n startTime: Date.now(),\n postData: request.postData() ?? undefined,\n })\n })\n\n page.on('response', async (response) => {\n const key = response.url() + response.request().method()\n const pending = buffers.pendingRequests.get(key)\n buffers.pendingRequests.delete(key)\n\n let body: string | undefined\n try {\n const buf = await response.body()\n const ct = response.headers()['content-type'] ?? ''\n if (ct.includes('image/') && !ct.includes('svg')) {\n body = buf.length > 32768 ? undefined : `data:${ct.split(';')[0]};base64,${buf.toString('base64')}`\n } else {\n const text = buf.toString('utf-8')\n body = text.length > 32768 ? text.slice(0, 32768) + '...[truncated]' : text\n }\n } catch {\n body = undefined\n }\n\n buffers.networkLogs.push({\n url: response.url(),\n method: response.request().method(),\n status: response.status(),\n requestHeaders: pending?.headers ?? response.request().headers(),\n responseHeaders: response.headers(),\n body,\n requestBody: pending?.postData,\n startTime: pending?.startTime ?? Date.now(),\n endTime: Date.now(),\n timing: response.request().timing(),\n })\n if (buffers.networkLogs.length > 500) {\n buffers.networkLogs = buffers.networkLogs.slice(-250)\n }\n })\n }\n }\n\n private async resolveTabTargetAsync(tab: { index?: number; title?: string; url?: string }): Promise<Page | undefined> {\n const pages = this.context!.pages()\n if (tab.index !== undefined) {\n return (tab.index >= 0 && tab.index < pages.length) ? pages[tab.index] : undefined\n }\n if (tab.title) {\n for (const p of pages) {\n const t = await p.title()\n if (t.includes(tab.title)) return p\n }\n return undefined\n }\n if (tab.url) {\n return pages.find(p => p.url().includes(tab.url!))\n }\n return undefined\n }\n\n private async executeAction(action: Action): Promise<ActionResult> {\n const page = this.page!\n const resolver = new ElementResolver(page, this.lastRefs)\n\n // Validate action-element compatibility for ref-targeting actions\n if ('ref' in action && typeof (action as any).ref === 'string') {\n const refData = this.lastRefs[(action as any).ref]\n const role = refData?.role\n const validation = validateAction(action, role)\n if (!validation.valid) {\n return { success: false, error: validation.error }\n }\n }\n\n switch (action.type) {\n case 'click': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n const coordinates = box ? { x: box.x + box.width / 2, y: box.y + box.height / 2 } : undefined\n await locator.click({\n ...clickDelayOption(action.clickDelay),\n })\n return { success: true, coordinates, boundingBox: box ?? undefined }\n }\n\n case 'fill': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.fill(action.value)\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'select': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.selectOption(action.value)\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'navigate': {\n await page.goto(action.url, { waitUntil: 'domcontentloaded' })\n await waitForPageReady(page)\n return { success: true }\n }\n\n case 'scroll': {\n const deltaX = action.scrollType === 'horizontal' ? action.value : 0\n const deltaY = action.scrollType === 'vertical' ? action.value : 0\n let coordinates: { x: number; y: number } | undefined\n let boundingBox: { x: number; y: number; width: number; height: number } | undefined\n let scrollData: { scrolled: boolean; scrolledContainer: string } | undefined\n\n if (action.ref) {\n const refData = this.lastRefs[action.ref]\n if (refData) {\n const scrollAxis = action.scrollType === 'horizontal' ? 'horizontal' : 'vertical'\n const result = await scrollWithRef(page, refData, deltaX, deltaY, scrollAxis)\n if (result.bounds) {\n coordinates = { x: result.bounds.x + result.bounds.width / 2, y: result.bounds.y + result.bounds.height / 2 }\n boundingBox = result.bounds\n }\n scrollData = { scrolled: result.scrolled, scrolledContainer: result.scrolledContainer }\n } else {\n await page.mouse.wheel(deltaX, deltaY)\n }\n } else {\n await page.mouse.wheel(deltaX, deltaY)\n }\n\n await page.evaluate(`new Promise(resolve => {\n const t = setTimeout(() => resolve('timeout'), 500);\n requestAnimationFrame(() => requestAnimationFrame(() => {\n clearTimeout(t);\n resolve('raf');\n }));\n })`)\n\n return { success: true, coordinates, boundingBox, data: scrollData }\n }\n\n case 'waitFor': {\n // Wait for condition: try as text content first, then fall back to selector.\n // The LLM generates natural language conditions (\"loading spinner disappears\")\n // which aren't CSS selectors — use page.waitForFunction for text matching.\n const timeout = action.timeout ?? 5000\n try {\n // Runs in browser context — checks if the condition text appears on page\n await page.waitForFunction(\n `document.body && document.body.innerText.includes(${JSON.stringify(action.condition)})`,\n { timeout },\n )\n } catch {\n // Fall back to waitForSelector for CSS-selector-shaped conditions\n try {\n await page.waitForSelector(action.condition, { timeout })\n } catch {\n // Best-effort — return success so the agent loop can re-observe\n }\n }\n return { success: true }\n }\n\n case 'delay': {\n await page.waitForTimeout(action.ms)\n return { success: true }\n }\n\n case 'waitForUrl': {\n try {\n // Explicit 30s timeout overrides Playwright's infinite default (Pitfall 2)\n await page.waitForURL(action.pattern, { timeout: 30_000 })\n return { success: true }\n } catch (err) {\n return {\n success: false,\n error: `URL pattern \"${action.pattern}\" did not match within 30s. Hint: use \"**\" wildcards for substring matching (e.g., \"**/dashboard**\"). ${err instanceof Error ? err.message : String(err)}`,\n }\n }\n }\n\n case 'keypress': {\n const effectiveKeys = convertKeysForPlatform(action.keys, {\n enabled: action.convertPlatformKeys !== false,\n isMac: isMacPlatform(),\n })\n for (const key of effectiveKeys) {\n await page.keyboard.press(key)\n }\n return { success: true }\n }\n\n case 'hover': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.hover()\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'paste': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.focus()\n await page.evaluate(`(() => {\n const el = document.activeElement;\n if (!el) return;\n const dt = new DataTransfer();\n dt.setData('text/plain', ${JSON.stringify(action.value)});\n el.dispatchEvent(new ClipboardEvent('paste', {\n clipboardData: dt,\n bubbles: true,\n cancelable: true,\n }));\n })()`)\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'fileUpload': {\n // Paths are pre-resolved to absolute by runner loop.ts (see Plan 01 Task 2)\n const { existsSync } = await import('node:fs')\n for (const filePath of action.files) {\n if (!existsSync(filePath)) {\n return { success: false, error: `File not found: ${filePath}` }\n }\n }\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.setInputFiles(action.files)\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'copy': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n const text = (await locator.textContent()) ?? ''\n await page.evaluate(`navigator.clipboard.writeText(${JSON.stringify(text)})`)\n return { success: true, boundingBox: box ?? undefined, data: { copied: text } }\n }\n\n case 'keyDown': {\n await page.keyboard.down(action.key)\n return { success: true }\n }\n\n case 'keyUp': {\n await page.keyboard.up(action.key)\n return { success: true }\n }\n\n case 'refresh': {\n await page.reload({ waitUntil: 'domcontentloaded' })\n await waitForPageReady(page)\n return { success: true }\n }\n\n case 'navigateHistory': {\n if (action.direction === 'back') {\n await page.goBack({ waitUntil: 'domcontentloaded' })\n } else {\n await page.goForward({ waitUntil: 'domcontentloaded' })\n }\n await waitForPageReady(page)\n return { success: true }\n }\n\n case 'readConsoleLogs': {\n let entries: ConsoleLogEntry[]\n if (action.tab) {\n const targetPage = await this.resolveTabTargetAsync(action.tab)\n if (!targetPage) {\n return { success: false, error: `No tab found matching ${JSON.stringify(action.tab)}` }\n }\n const buffers = this.pageLogBuffers.get(targetPage)\n entries = buffers ? [...buffers.consoleLogs] : []\n } else {\n entries = []\n for (const buffers of this.pageLogBuffers.values()) {\n entries.push(...buffers.consoleLogs)\n }\n }\n if (action.level) {\n entries = entries.filter(e => e.level === action.level)\n }\n return { success: true, data: entries }\n }\n\n case 'readNetworkLogs': {\n let entries: NetworkLogEntry[]\n if (action.tab) {\n const targetPage = await this.resolveTabTargetAsync(action.tab)\n if (!targetPage) {\n return { success: false, error: `No tab found matching ${JSON.stringify(action.tab)}` }\n }\n const buffers = this.pageLogBuffers.get(targetPage)\n entries = buffers ? [...buffers.networkLogs] : []\n } else {\n entries = []\n for (const buffers of this.pageLogBuffers.values()) {\n entries.push(...buffers.networkLogs)\n }\n }\n if (action.urlPattern) {\n entries = entries.filter(e => e.url.includes(action.urlPattern!))\n }\n return { success: true, data: entries }\n }\n\n case 'readCookies': {\n const cookies = await this.context!.cookies()\n if (action.name) {\n const cookie = cookies.find(c => c.name === action.name) ?? null\n return { success: true, data: cookie }\n }\n return { success: true, data: cookies }\n }\n\n case 'setCookies': {\n const cookiesWithDefaults = action.cookies.map(c => ({\n ...c,\n url: !c.domain ? page.url() : undefined,\n }))\n await this.context!.addCookies(cookiesWithDefaults)\n return { success: true }\n }\n\n case 'readLocalStorage': {\n const pageUrl = page.url()\n if (pageUrl === 'about:blank') {\n return { success: true, data: action.key ? null : {} }\n }\n if (action.key) {\n const value = await page.evaluate(\n (k: string) => localStorage.getItem(k), action.key\n )\n return { success: true, data: value }\n }\n const all = await page.evaluate(\n () => Object.fromEntries(\n Object.keys(localStorage).map(k => [k, localStorage.getItem(k)])\n )\n )\n return { success: true, data: all }\n }\n\n case 'setLocalStorage': {\n await page.evaluate((entries: Array<{ key: string; value: string }>) => {\n for (const { key, value } of entries) {\n localStorage.setItem(key, value)\n }\n }, action.entries)\n return { success: true }\n }\n\n case 'assert': {\n return { success: true }\n }\n\n case 'clearText': {\n const loc = resolver.resolve(action.ref)\n const clearBox = await resolver.getBoundingBox(action.ref)\n await loc.clear()\n return { success: true, boundingBox: clearBox ?? undefined }\n }\n\n case 'drag': {\n const fromLoc = resolver.resolve(action.fromRef)\n const toLoc = resolver.resolve(action.toRef)\n await fromLoc.dragTo(toLoc)\n return { success: true }\n }\n\n case 'doubleTap': {\n const dblLoc = resolver.resolve(action.ref)\n const dblBox = await resolver.getBoundingBox(action.ref)\n await dblLoc.dblclick()\n return { success: true, boundingBox: dblBox ?? undefined }\n }\n\n case 'doubleClick': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n const coordinates = box\n ? action.relativePosition\n ? { x: box.x + action.relativePosition.x, y: box.y + action.relativePosition.y }\n : { x: box.x + box.width / 2, y: box.y + box.height / 2 }\n : undefined\n await locator.dblclick({\n ...(action.relativePosition && { position: action.relativePosition }),\n ...clickDelayOption(action.clickDelay),\n })\n return { success: true, coordinates, boundingBox: box ?? undefined }\n }\n\n case 'rightClick': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n const coordinates = box\n ? action.relativePosition\n ? { x: box.x + action.relativePosition.x, y: box.y + action.relativePosition.y }\n : { x: box.x + box.width / 2, y: box.y + box.height / 2 }\n : undefined\n await locator.click({\n button: 'right',\n ...(action.relativePosition && { position: action.relativePosition }),\n ...clickDelayOption(action.clickDelay),\n })\n return { success: true, coordinates, boundingBox: box ?? undefined }\n }\n\n case 'openLink': {\n await page.goto(action.url, { waitUntil: 'domcontentloaded' })\n await waitForPageReady(page)\n return { success: true }\n }\n\n case 'newTab': {\n const newPage = await this.context!.newPage()\n this.attachLogListeners(newPage)\n await newPage.goto(action.url, { waitUntil: 'domcontentloaded' })\n await waitForPageReady(newPage)\n this.page = newPage\n return { success: true }\n }\n\n case 'switchTab': {\n const pages = this.context!.pages()\n\n let target: Page | undefined\n\n if (action.index !== undefined) {\n if (action.index < 0 || action.index >= pages.length) {\n return { success: false, error: `Tab index ${action.index} out of range (${pages.length} tabs open)` }\n }\n target = pages[action.index]\n } else if (action.title) {\n for (const p of pages) {\n const t = await p.title()\n if (t.includes(action.title)) { target = p; break }\n }\n } else if (action.url) {\n target = pages.find(p => p.url().includes(action.url!))\n } else {\n return { success: false, error: 'switchTab requires at least one of: index, title, or url' }\n }\n\n if (!target) {\n return { success: false, error: `No tab found matching ${JSON.stringify({ index: action.index, title: action.title, url: action.url })}` }\n }\n\n this.page = target\n return { success: true }\n }\n\n // Mobile-only actions — graceful unsupported messages\n case 'tap':\n case 'swipe':\n case 'longpress':\n case 'pinch':\n case 'multiTap': {\n return { success: false, error: `${action.type} is a mobile-only gesture` }\n }\n\n case 'tapCoordinate': {\n const vp = page.viewportSize()\n if (vp) {\n warnIfOutOfBounds({ x: action.x, y: action.y }, { width: vp.width, height: vp.height }, 'tapCoordinate')\n }\n await page.mouse.click(action.x, action.y)\n return { success: true, coordinates: { x: action.x, y: action.y } }\n }\n\n case 'executeScript': {\n return { success: false, error: 'executeScript is a mobile-only action' }\n }\n\n case 'hideKeyboard':\n case 'launchApp':\n case 'stopApp':\n case 'setOrientation': {\n return { success: true }\n }\n\n default: {\n return { success: false, error: `Unknown action type: ${(action as any).type}` }\n }\n }\n }\n}\n","import type { Page } from 'playwright-core'\n\nconst SKIP_TAGS = new Set([\n 'SCRIPT', 'STYLE', 'SVG', 'NOSCRIPT', 'LINK', 'META',\n 'TEMPLATE', 'IFRAME',\n])\n\n// Browser-context functions use (globalThis as any) to access document\n// because the Node tsconfig has no DOM lib — these functions serialize and run in browser\nexport function extractDomTree(opts: { maxDepth: number; maxTextLen: number }): string {\n const { maxDepth, maxTextLen } = opts\n const doc = (globalThis as any).document\n const win = (globalThis as any).window\n const lines: string[] = []\n\n function isHidden(el: any): boolean {\n if (!el.offsetParent && el.tagName !== 'BODY' && el.tagName !== 'HTML') {\n const style = win.getComputedStyle(el)\n if (style.display === 'none' || style.visibility === 'hidden') return true\n }\n return false\n }\n\n function walk(node: any, depth: number, indent: string): void {\n if (depth > maxDepth) {\n lines.push(indent + '[... deeper content truncated]')\n return\n }\n\n for (let child = node.firstChild; child; child = child.nextSibling) {\n if (child.nodeType === 3) {\n const text = child.textContent.trim()\n if (text) {\n const truncated = text.length > maxTextLen\n ? text.slice(0, maxTextLen) + '...'\n : text\n lines.push(indent + truncated)\n }\n continue\n }\n\n if (child.nodeType !== 1) continue\n\n const tag = child.tagName\n if (SKIP_TAGS.has(tag)) continue\n if (isHidden(child)) continue\n\n const isCustom = tag.toLowerCase().includes('-')\n const annotation = child.getAttribute('aria-label')\n || child.getAttribute('role')\n || ''\n\n let label = tag.toLowerCase()\n if (isCustom) {\n if (!child.shadowRoot && !child.firstChild) {\n label += ' (custom element, closed shadow root)'\n } else {\n label += ' (custom element)'\n }\n }\n if (annotation) label += ` [${annotation}]`\n\n lines.push(indent + label)\n\n if (child.shadowRoot) {\n lines.push(indent + ' #shadow-root')\n walk(child.shadowRoot, depth + 1, indent + ' ')\n }\n\n walk(child, depth + 1, indent + ' ')\n }\n }\n\n walk(doc.body, 0, '')\n return lines.join('\\n')\n}\n\nexport interface ExtractDomOptions {\n maxDepth?: number\n maxTextLen?: number\n}\n\nexport async function extractDom(\n page: Page,\n opts?: ExtractDomOptions,\n): Promise<string | undefined> {\n const maxDepth = opts?.maxDepth ?? 20\n const maxTextLen = opts?.maxTextLen ?? 200\n\n try {\n return await page.evaluate(extractDomTree, { maxDepth, maxTextLen })\n } catch {\n return undefined\n }\n}\n","import type { Page } from 'playwright-core'\nimport type { ScreenState, ElementInfo } from '@vostride/agent-qa-core'\nimport type { RefMap } from './types.js'\nimport { extractDom } from './dom-extractor.js'\n\nconst INTERACTIVE_ROLES = new Set([\n 'button', 'link', 'textbox', 'checkbox', 'radio', 'combobox', 'listbox',\n 'menuitem', 'menuitemradio', 'menuitemcheckbox', 'option',\n 'searchbox', 'slider', 'spinbutton', 'switch', 'tab', 'treeitem',\n // WAI-ARIA 1.2 standalone widget roles\n 'gridcell', 'scrollbar', 'separator',\n // WAI-ARIA 1.2 composite widget roles (interactive containers)\n 'grid', 'menu', 'menubar', 'tree', 'treegrid',\n])\n\nconst CONTENT_ROLES = new Set([\n 'heading', 'cell', 'listitem', 'article', 'region', 'navigation',\n 'progressbar', 'tabpanel',\n])\n\nconst LINE_PATTERN = /^(\\s*-\\s*)(\\w+)(?:\\s+\"([^\"]*)\")?(.*)$/\n// Playwright wraps ARIA entries in single quotes when element names contain\n// colons or other characters that are ambiguous in its snapshot format.\n// e.g. - 'button \"Spoken Language: Any\"'\nconst QUOTED_LINE_PATTERN = /^(\\s*-\\s*)'(\\w+)(?:\\s+\"([^\"]*)\")?(.*)'\\s*$/\n\nexport function parseAriaSnapshot(ariaTree: string): { tree: string; elements: ElementInfo[]; refs: RefMap } {\n const lines = ariaTree.split('\\n')\n const elements: ElementInfo[] = []\n const refs: RefMap = {}\n const resultLines: string[] = []\n let refCounter = 0\n\n // Track role+name occurrences for disambiguation\n const roleNameCounts = new Map<string, number>()\n const refToKey = new Map<string, string>()\n\n for (const line of lines) {\n const match = line.match(LINE_PATTERN) || line.match(QUOTED_LINE_PATTERN)\n if (!match) {\n resultLines.push(line)\n continue\n }\n\n const [, prefix, role, name, suffix] = match\n const roleLower = role.toLowerCase()\n const shouldGetRef = INTERACTIVE_ROLES.has(roleLower) || CONTENT_ROLES.has(roleLower)\n\n if (!shouldGetRef) {\n resultLines.push(line)\n continue\n }\n\n refCounter++\n const ref = `e${refCounter}`\n const key = `${roleLower}:${name ?? ''}`\n\n const currentCount = roleNameCounts.get(key) ?? 0\n roleNameCounts.set(key, currentCount + 1)\n refToKey.set(ref, key)\n\n refs[ref] = { role: roleLower, name, nth: currentCount }\n\n // Parse attributes from suffix like [level=1], [checked], [disabled]\n const attributes: Record<string, string> = {}\n const attrMatches = suffix?.matchAll(/\\[(\\w+)(?:=([^\\]]*))?\\]/g)\n if (attrMatches) {\n for (const am of attrMatches) {\n attributes[am[1]] = am[2] ?? 'true'\n }\n }\n\n elements.push({ ref, role: roleLower, name: name ?? '', attributes })\n\n let enhanced = `${prefix}${role}`\n if (name) enhanced += ` \"${name}\"`\n enhanced += ` [ref=${ref}]`\n if (suffix?.trim()) enhanced += suffix\n resultLines.push(enhanced)\n }\n\n // Post-process: remove nth from refs that don't have duplicates\n for (const [ref, data] of Object.entries(refs)) {\n const key = refToKey.get(ref)!\n if ((roleNameCounts.get(key) ?? 0) <= 1) {\n delete refs[ref].nth\n }\n }\n\n return { tree: resultLines.join('\\n'), elements, refs }\n}\n\n// Browser-context functions use (globalThis as any) to access document\n// because the Node tsconfig has no DOM lib — these functions serialize and run in browser\nfunction hideAgentQaElements() {\n const doc = (globalThis as any).document\n doc.querySelectorAll('[data-agent-qa-internal]').forEach((el: any) => {\n el.style.display = 'none'\n el.setAttribute('aria-hidden', 'true')\n })\n}\n\nfunction restoreAgentQaElements() {\n const doc = (globalThis as any).document\n doc.querySelectorAll('[data-agent-qa-internal]').forEach((el: any) => {\n el.style.display = ''\n el.removeAttribute('aria-hidden')\n })\n}\n\nexport async function observePage(\n page: Page,\n options?: { filterSelector?: string; extractDom?: boolean },\n): Promise<ScreenState> {\n const viewport = page.viewportSize()\n const locator = options?.filterSelector\n ? page.locator(options.filterSelector)\n : page.locator(':root')\n\n // Hide framework-injected elements from ARIA snapshot\n await page.evaluate(hideAgentQaElements)\n\n let ariaTree: string\n try {\n ariaTree = await locator.ariaSnapshot()\n } finally {\n // Restore framework-injected elements (always, even if snapshot fails)\n await page.evaluate(restoreAgentQaElements)\n }\n\n if (!ariaTree) {\n return {\n tree: '(empty)',\n elements: [],\n url: page.url(),\n timestamp: Date.now(),\n metadata: {\n coordSpace: 'viewport' as const,\n viewportWidth: viewport?.width ?? 0,\n viewportHeight: viewport?.height ?? 0,\n refMap: {},\n },\n }\n }\n\n const { tree, elements, refs } = parseAriaSnapshot(ariaTree)\n\n // Bulk bounding box enrichment — single page.evaluate collects all rects in one DOM call.\n // Previous approach used N sequential getByRole().boundingBox({timeout:500}) calls which\n // all timed out on complex external pages (100+ elements), reporting \"0 visible elements\".\n try {\n const refEntries = Object.entries(refs)\n if (refEntries.length > 0) {\n const refArgs: Array<[string, string, string | undefined, number | undefined]> = refEntries.map(\n ([ref, data]) => [ref, data.role, data.name, data.nth]\n )\n\n type BBoxResult = Array<[string, { x: number; y: number; width: number; height: number } | null]>\n const result = await Promise.race([\n page.evaluate((args: Array<[string, string, string | undefined, number | undefined]>) => {\n const doc = (globalThis as any).document\n const IMPLICIT_ROLES: Record<string, string> = {\n button: 'button', a: 'link', input: 'textbox', select: 'combobox',\n textarea: 'textbox', h1: 'heading', h2: 'heading', h3: 'heading',\n h4: 'heading', h5: 'heading', h6: 'heading', nav: 'navigation',\n main: 'main', aside: 'complementary', footer: 'contentinfo',\n header: 'banner', form: 'form', table: 'table', img: 'img',\n ul: 'list', ol: 'list', li: 'listitem', dialog: 'dialog',\n details: 'group', summary: 'button', progress: 'progressbar',\n meter: 'meter', output: 'status', article: 'article',\n section: 'region', fieldset: 'group', legend: 'legend',\n }\n const INPUT_TYPE_ROLES: Record<string, string> = {\n checkbox: 'checkbox', radio: 'radio', range: 'slider',\n number: 'spinbutton', search: 'searchbox', email: 'textbox',\n tel: 'textbox', url: 'textbox', password: 'textbox',\n }\n\n function getAccessibleName(el: any): string {\n const label = el.getAttribute('aria-label')\n if (label) return label.trim()\n const labelledBy = el.getAttribute('aria-labelledby')\n if (labelledBy) {\n const parts = labelledBy.split(/\\s+/).map((id: string) => {\n const ref = doc.getElementById(id)\n return ref ? (ref.textContent || '').trim() : ''\n }).filter(Boolean)\n if (parts.length) return parts.join(' ')\n }\n const title = el.getAttribute('title')\n if (title) return title.trim()\n const alt = el.getAttribute('alt')\n if (alt) return alt.trim()\n return (el.textContent || '').trim()\n }\n\n function matchesName(elName: string, targetName: string): boolean {\n return elName.toLowerCase().includes(targetName.toLowerCase())\n }\n\n function getImplicitRole(el: any): string | null {\n const tag = el.tagName.toLowerCase()\n if (tag === 'input') {\n const type = (el.getAttribute('type') || 'text').toLowerCase()\n return INPUT_TYPE_ROLES[type] || 'textbox'\n }\n if (tag === 'a' && el.hasAttribute('href')) return 'link'\n return IMPLICIT_ROLES[tag] || null\n }\n\n const results: Array<[string, { x: number; y: number; width: number; height: number } | null]> = []\n for (const [ref, role, name, nth] of args) {\n const candidates: any[] = []\n doc.querySelectorAll(`[role=\"${role}\"]`).forEach((el: any) => candidates.push(el))\n doc.querySelectorAll('*').forEach((el: any) => {\n if (el.getAttribute('role')) return\n if (getImplicitRole(el) === role) candidates.push(el)\n })\n let matched = candidates\n if (name) {\n matched = candidates.filter((el: any) => matchesName(getAccessibleName(el), name))\n }\n const target = matched[nth ?? 0]\n if (target) {\n const rect = target.getBoundingClientRect()\n results.push([ref, {\n x: Math.round(rect.x), y: Math.round(rect.y),\n width: Math.round(rect.width), height: Math.round(rect.height),\n }])\n } else {\n results.push([ref, null])\n }\n }\n return results\n }, refArgs),\n new Promise<null>(resolve => setTimeout(() => resolve(null), 3000)),\n ]) as BBoxResult | null\n\n if (result) {\n for (const [ref, box] of result) {\n if (box) refs[ref].bounds = box\n }\n }\n }\n } catch {\n // Bounding box enrichment is best-effort — never block observation\n }\n\n let domContext: string | undefined\n if (options?.extractDom) {\n try {\n domContext = await extractDom(page)\n } catch {\n // DOM extraction is best-effort\n }\n }\n\n return {\n tree,\n elements,\n url: page.url(),\n timestamp: Date.now(),\n metadata: {\n coordSpace: 'viewport' as const,\n viewportWidth: viewport?.width ?? 0,\n viewportHeight: viewport?.height ?? 0,\n refMap: refs,\n ...(domContext ? { domContext } : {}),\n },\n }\n}\n","import type { Page, Locator } from 'playwright-core'\nimport type { Action } from '@vostride/agent-qa-core'\nimport type { RefMap } from './types.js'\n\nconst ACTIONS_WITHOUT_REF = new Set(['navigate', 'waitFor', 'delay', 'waitForUrl', 'assert'])\n\nexport class ElementResolver {\n constructor(\n private page: Page,\n private refs: RefMap,\n ) {}\n\n resolve(ref: string): Locator {\n const data = this.refs[ref]\n if (!data) {\n throw new Error(`Unknown ref \"${ref}\". Available refs: ${Object.keys(this.refs).join(', ') || 'none'}`)\n }\n\n let locator: Locator\n if (data.name) {\n locator = this.page.getByRole(data.role as any, { name: data.name, exact: true })\n } else {\n locator = this.page.getByRole(data.role as any)\n }\n\n if (data.nth !== undefined) {\n locator = locator.nth(data.nth)\n }\n\n return locator\n }\n\n resolveAction(action: Action): Locator | null {\n if (ACTIONS_WITHOUT_REF.has(action.type)) {\n return null\n }\n\n if ('ref' in action && typeof action.ref === 'string') {\n return this.resolve(action.ref)\n }\n\n return null\n }\n\n async getBoundingBox(ref: string): Promise<{ x: number; y: number; width: number; height: number } | null> {\n try {\n const locator = this.resolve(ref)\n return await locator.boundingBox()\n } catch {\n return null\n }\n }\n}\n","import type { Action } from '@vostride/agent-qa-core'\n\nexport type ValidationResult =\n | { valid: true }\n | { valid: false; error: string; suggestion?: string }\n\nexport class ActionValidationError extends Error {\n readonly suggestion?: string\n\n constructor(message: string, suggestion?: string) {\n super(message)\n this.name = 'ActionValidationError'\n this.suggestion = suggestion\n }\n}\n\nconst FILL_ROLES = new Set(['textbox', 'searchbox', 'spinbutton', 'combobox'])\nconst SELECT_ROLES = new Set(['listbox', 'combobox'])\n\n// Actions that don't target elements — always valid\nconst NO_REF_ACTIONS = new Set(['scroll', 'navigate', 'waitFor', 'delay', 'waitForUrl', 'assert', 'pinch', 'multiTap', 'keyDown', 'keyUp', 'refresh', 'navigateHistory', 'readConsoleLogs', 'readNetworkLogs', 'readCookies', 'setCookies', 'readLocalStorage', 'setLocalStorage', 'executeScript'])\n\n// Actions valid for any role\nconst ANY_ROLE_ACTIONS = new Set(['click', 'hover', 'keypress', 'paste', 'doubleClick', 'rightClick'])\n\nexport function validateAction(action: Action, elementRole: string | undefined): ValidationResult {\n // Actions that don't require an element ref are always valid\n if (NO_REF_ACTIONS.has(action.type)) {\n return { valid: true }\n }\n\n // Actions valid for any role\n if (ANY_ROLE_ACTIONS.has(action.type)) {\n return { valid: true }\n }\n\n // Unknown or missing role — allow with permissive pass (LLM might know better)\n if (!elementRole) {\n return { valid: true }\n }\n\n const role = elementRole.toLowerCase()\n\n if (action.type === 'fill') {\n if (FILL_ROLES.has(role)) {\n return { valid: true }\n }\n if (SELECT_ROLES.has(role)) {\n return {\n valid: false,\n error: `Cannot fill() on a '${role}' element — fill is for text inputs. Try 'select' to choose an option.`,\n suggestion: 'select',\n }\n }\n return {\n valid: false,\n error: `Element ${(action as any).ref} is not fillable (role: ${role}). Use a textbox or input element instead.`,\n suggestion: 'click',\n }\n }\n\n if (action.type === 'clearText') {\n if (FILL_ROLES.has(role)) {\n return { valid: true }\n }\n return {\n valid: false,\n error: `Element ${(action as any).ref} is not fillable (role: ${role}). clearText only works on text inputs. Use a textbox or input element instead.`,\n suggestion: 'click',\n }\n }\n\n if (action.type === 'select') {\n if (SELECT_ROLES.has(role)) {\n return { valid: true }\n }\n if (FILL_ROLES.has(role)) {\n return {\n valid: false,\n error: `Cannot select() on a '${role}' element — select is for lists. Try 'fill' to type a value instead.`,\n suggestion: 'fill',\n }\n }\n return {\n valid: false,\n error: `Cannot select() on a '${role}' element — select is for list/combo elements.`,\n suggestion: 'click',\n }\n }\n\n // Unknown action type — allow (forward-compatible)\n return { valid: true }\n}\n","import type { Page } from 'playwright-core'\n\nexport interface SmartWaitOptions {\n timeout?: number\n}\n\nconst LOADING_SELECTORS = [\n '[aria-busy=\"true\"]',\n '[aria-label*=\"loading\" i]',\n '.loading', '.spinner', '.skeleton',\n '[data-loading]', '[data-testid=\"loading\"]',\n 'progress:not([value])',\n]\n\nexport async function waitForPageReady(page: Page, options?: SmartWaitOptions): Promise<void> {\n const timeout = options?.timeout ?? 10000\n\n await Promise.race([\n runReadinessChecks(page),\n new Promise<void>(resolve => setTimeout(resolve, timeout)),\n ])\n}\n\n// Browser-context functions use (globalThis as any) to access document\n// because the Node tsconfig has no DOM lib — these functions serialize and run in browser\nfunction checkLoadingIndicators(selectors: string[]): boolean {\n const doc = (globalThis as any).document\n return selectors.some((sel: string) => doc.querySelector(sel) !== null)\n}\n\nfunction checkLoadingGone(selectors: string[]): boolean {\n const doc = (globalThis as any).document\n return !selectors.some((sel: string) => doc.querySelector(sel))\n}\n\nfunction checkAnimationsRunning(): boolean {\n const doc = (globalThis as any).document\n return doc.getAnimations().filter((a: any) => a.playState === 'running').length > 0\n}\n\nfunction checkAnimationsSettled(): boolean {\n const doc = (globalThis as any).document\n return doc.getAnimations().filter((a: any) => a.playState === 'running').length === 0\n}\n\nasync function runReadinessChecks(page: Page): Promise<void> {\n // 1. Document ready\n try {\n await page.waitForLoadState('domcontentloaded', { timeout: 5000 })\n } catch {\n // Already loaded or timed out — continue\n }\n\n // 2. Network settle (best effort)\n try {\n await page.waitForLoadState('networkidle', { timeout: 5000 })\n } catch {\n // SPA with websockets or long-polling — proceed anyway\n }\n\n // 3. Loading indicators gone\n try {\n const hasIndicators = await page.evaluate(checkLoadingIndicators, LOADING_SELECTORS)\n\n if (hasIndicators) {\n try {\n await page.waitForFunction(checkLoadingGone, LOADING_SELECTORS, { timeout: 3000 })\n } catch {\n // Indicators didn't clear in 3s — proceed anyway\n }\n }\n } catch {\n // page.evaluate failed (navigation in progress, context destroyed) — continue\n }\n\n // 4. Animations settled\n try {\n const hasRunning = await page.evaluate(checkAnimationsRunning)\n\n if (hasRunning) {\n try {\n await page.waitForFunction(checkAnimationsSettled, undefined, { timeout: 2000 })\n } catch {\n // Animations didn't settle in 2s — proceed anyway\n }\n }\n } catch {\n // page.evaluate failed — continue\n }\n}\n","import type { Page } from 'playwright-core'\n\ninterface ScrollRefData {\n role: string\n name?: string\n nth?: number\n}\n\ninterface ScrollResult {\n bounds: { x: number; y: number; width: number; height: number } | null\n scrolledContainer: 'element' | 'ancestor' | 'documentElement' | 'notFound'\n scrolled: boolean\n}\n\nexport async function scrollWithRef(\n page: Page,\n refData: ScrollRefData,\n deltaX: number,\n deltaY: number,\n scrollAxis: 'horizontal' | 'vertical',\n): Promise<ScrollResult> {\n return page.evaluate(\n (args: [string, string | undefined, number, number, number, string]) => {\n const [role, name, nth, dx, dy, axis] = args\n const doc = (globalThis as any).document\n const win = (globalThis as any).window\n\n const IMPLICIT_ROLES: Record<string, string> = {\n button: 'button', a: 'link', input: 'textbox', select: 'combobox',\n textarea: 'textbox', h1: 'heading', h2: 'heading', h3: 'heading',\n h4: 'heading', h5: 'heading', h6: 'heading', nav: 'navigation',\n main: 'main', aside: 'complementary', footer: 'contentinfo',\n header: 'banner', form: 'form', table: 'table', img: 'img',\n ul: 'list', ol: 'list', li: 'listitem', dialog: 'dialog',\n details: 'group', summary: 'button', progress: 'progressbar',\n meter: 'meter', output: 'status', article: 'article',\n section: 'region', fieldset: 'group', legend: 'legend',\n }\n const INPUT_TYPE_ROLES: Record<string, string> = {\n checkbox: 'checkbox', radio: 'radio', range: 'slider',\n number: 'spinbutton', search: 'searchbox', email: 'textbox',\n tel: 'textbox', url: 'textbox', password: 'textbox',\n }\n\n function getAccessibleName(el: any): string {\n const label = el.getAttribute('aria-label')\n if (label) return label.trim()\n const labelledBy = el.getAttribute('aria-labelledby')\n if (labelledBy) {\n const parts = labelledBy.split(/\\s+/).map((id: string) => {\n const ref = doc.getElementById(id)\n return ref ? (ref.textContent || '').trim() : ''\n }).filter(Boolean)\n if (parts.length) return parts.join(' ')\n }\n const title = el.getAttribute('title')\n if (title) return title.trim()\n const alt = el.getAttribute('alt')\n if (alt) return alt.trim()\n return (el.textContent || '').trim()\n }\n\n function getImplicitRole(el: any): string | null {\n const tag = el.tagName.toLowerCase()\n if (tag === 'input') {\n const type = (el.getAttribute('type') || 'text').toLowerCase()\n return INPUT_TYPE_ROLES[type] || 'textbox'\n }\n if (tag === 'a' && el.hasAttribute('href')) return 'link'\n return IMPLICIT_ROLES[tag] || null\n }\n\n const candidates: any[] = []\n doc.querySelectorAll(`[role=\"${role}\"]`).forEach((el: any) => candidates.push(el))\n doc.querySelectorAll('*').forEach((el: any) => {\n if (el.getAttribute('role')) return\n if (getImplicitRole(el) === role) candidates.push(el)\n })\n\n let matched = candidates\n if (name) {\n matched = candidates.filter((el: any) =>\n getAccessibleName(el).toLowerCase().includes(name.toLowerCase())\n )\n }\n\n const target = matched[nth]\n if (!target) {\n win.scrollBy(dx, dy)\n return { bounds: null, scrolledContainer: 'notFound' as const, scrolled: true }\n }\n\n // Check target element itself for scrollability\n const targetStyle = win.getComputedStyle(target)\n const targetOverflow = axis === 'horizontal' ? targetStyle.overflowX : targetStyle.overflowY\n const targetScrollable = targetOverflow === 'auto' || targetOverflow === 'scroll' || targetOverflow === 'hidden'\n const targetHasContent = axis === 'horizontal'\n ? target.scrollWidth > target.clientWidth\n : target.scrollHeight > target.clientHeight\n if (targetScrollable && targetHasContent) {\n const prop = axis === 'horizontal' ? 'scrollLeft' : 'scrollTop'\n const before = target[prop]\n target.scrollBy(dx, dy)\n const after = target[prop]\n const rect = target.getBoundingClientRect()\n return {\n bounds: { x: Math.round(rect.x), y: Math.round(rect.y), width: Math.round(rect.width), height: Math.round(rect.height) },\n scrolledContainer: 'element' as const,\n scrolled: before !== after,\n }\n }\n\n // Walk ancestors\n let parent = target.parentElement\n while (parent && parent !== doc.documentElement) {\n const style = win.getComputedStyle(parent)\n const overflow = axis === 'horizontal' ? style.overflowX : style.overflowY\n const isScrollable = overflow === 'auto' || overflow === 'scroll' || overflow === 'hidden'\n const hasContent = axis === 'horizontal'\n ? parent.scrollWidth > parent.clientWidth\n : parent.scrollHeight > parent.clientHeight\n if (isScrollable && hasContent) {\n const prop = axis === 'horizontal' ? 'scrollLeft' : 'scrollTop'\n const before = parent[prop]\n parent.scrollBy(dx, dy)\n const after = parent[prop]\n const rect = target.getBoundingClientRect()\n return {\n bounds: { x: Math.round(rect.x), y: Math.round(rect.y), width: Math.round(rect.width), height: Math.round(rect.height) },\n scrolledContainer: 'ancestor' as const,\n scrolled: before !== after,\n }\n }\n parent = parent.parentElement\n }\n\n const prop = axis === 'horizontal' ? 'scrollLeft' : 'scrollTop'\n const before = doc.documentElement[prop]\n doc.documentElement.scrollBy(dx, dy)\n const after = doc.documentElement[prop]\n const rect = target.getBoundingClientRect()\n return {\n bounds: { x: Math.round(rect.x), y: Math.round(rect.y), width: Math.round(rect.width), height: Math.round(rect.height) },\n scrolledContainer: 'documentElement' as const,\n scrolled: before !== after,\n }\n },\n [refData.role, refData.name, refData.nth ?? 0, deltaX, deltaY, scrollAxis] as [string, string | undefined, number, number, number, string],\n )\n}\n","type BrowserName = 'chromium' | 'firefox' | 'webkit'\n\nfunction displayBrowserName(browserName: BrowserName): string {\n if (browserName === 'chromium') return 'Chromium'\n if (browserName === 'firefox') return 'Firefox'\n return 'WebKit'\n}\n\nexport function isPlaywrightMissingBrowserError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error)\n const lower = message.toLowerCase()\n return lower.includes(\"executable doesn't exist\")\n && lower.includes('playwright')\n && lower.includes('install')\n}\n\nexport function formatMissingBrowserError(browserName: BrowserName): string {\n return [\n `agent-qa browser support is not installed for ${displayBrowserName(browserName)}.`,\n '',\n 'Install the browser managed by agent-qa, then rerun the test:',\n ` agent-qa install-browsers --${browserName}`,\n '',\n 'This can happen after upgrading agent-qa or Playwright because browser binaries live outside the package install.',\n ].join('\\n')\n}\n","import type { Browser, BrowserContext, Page } from 'playwright-core'\nimport type { PlatformAdapter, PlatformConfig, ScreenState, Action, ActionResult, ObserveOptions, ConsoleLogEntry, NetworkLogEntry } from '@vostride/agent-qa-core'\nimport { getProvider, registerAllProviders } from '@vostride/agent-qa-core'\nimport { convertKeysForPlatform, isMacPlatform } from '@vostride/agent-qa-core'\nimport type { FarmWebConfig } from '@vostride/agent-qa-core'\nimport { observePage } from './observer.js'\nimport { ElementResolver } from './element-resolver.js'\nimport { validateAction } from './action-validator.js'\nimport { waitForPageReady } from './smart-wait.js'\nimport { scrollWithRef } from './scroll-helper.js'\nimport type { RefMap } from './types.js'\n\ninterface PageLogBuffers {\n consoleLogs: ConsoleLogEntry[]\n networkLogs: NetworkLogEntry[]\n consoleDrainIndex: number\n networkDrainIndex: number\n pendingRequests: Map<string, { url: string; method: string; headers: Record<string, string>; startTime: number; postData?: string }>\n}\n\nfunction clickDelayOption(clickDelay?: number): { delay?: number } {\n return clickDelay !== undefined && clickDelay > 0 ? { delay: clickDelay } : {}\n}\n\nexport class FarmWebAdapter implements PlatformAdapter {\n readonly platform = 'web' as const\n\n private browser: Browser | null = null\n private context: BrowserContext | null = null\n private page: Page | null = null\n private lastRefs: RefMap = {}\n private sessionUrl: string | undefined\n private sessionId: string | undefined\n private testFailed = false\n private exitHandler: (() => void) | null = null\n private credentials: { username: string; accessKey: string } | null = null\n private pageLogBuffers = new Map<Page, PageLogBuffers>()\n private logCaptureConfig: { console: boolean; network: boolean } = { console: true, network: true }\n\n async setup(config: PlatformConfig): Promise<void> {\n if (!config.farmSession) {\n throw new Error('FarmWebAdapter requires config.farmSession to be set')\n }\n\n registerAllProviders()\n const provider = getProvider('browserstack')\n if (!provider) {\n throw new Error('Unknown farm provider: browserstack')\n }\n\n this.credentials = provider.resolveCredentials(config.farmSession.capabilities as any)\n if (!config.browser?.name) {\n throw new Error('FarmWebAdapter requires config.browser.name to be set')\n }\n const credentials = this.credentials\n\n const farmWebConfig: FarmWebConfig = {\n browser: config.browser,\n credentials,\n testName: (config.farmSession.capabilities as any)?.testName,\n }\n\n const { wsEndpoint } = await provider.resolveWebEndpoint(farmWebConfig)\n\n const { chromium } = await import('playwright-core')\n this.browser = await chromium.connect({ wsEndpoint })\n\n const contextOptions: Record<string, unknown> = {\n viewport: config.browser?.viewport ?? { width: 1280, height: 720 },\n }\n if (config.recording?.enabled) {\n contextOptions.recordVideo = {\n dir: config.recording.videoDir,\n size: config.recording.videoSize ?? config.browser?.viewport ?? { width: 1280, height: 720 },\n }\n }\n if (config.authState?.storageStatePath) {\n contextOptions.storageState = config.authState.storageStatePath\n }\n this.context = await this.browser.newContext(contextOptions)\n\n // Clipboard write permission — farm-adapter always uses chromium (see chromium.connect above)\n await this.context.grantPermissions(['clipboard-write'])\n\n this.page = await this.context.newPage()\n\n try {\n const cdpSession = await this.page.context().newCDPSession(this.page)\n const result = await cdpSession.send('Browser.getVersion') as Record<string, string>\n await cdpSession.detach()\n // BrowserStack includes session info in the debugger URL or we extract from the WSS endpoint\n // Use REST API to get session details\n const auth = Buffer.from(`${credentials.username}:${credentials.accessKey}`).toString('base64')\n const resp = await fetch('https://api.browserstack.com/automate/builds.json?limit=1&status=running', {\n headers: { Authorization: `Basic ${auth}` },\n })\n if (resp.ok) {\n const builds = await resp.json() as Array<{ automation_build: { hashed_id: string; name: string } }>\n if (builds.length > 0) {\n const buildId = builds[0].automation_build.hashed_id\n const sessResp = await fetch(`https://api.browserstack.com/automate/builds/${buildId}/sessions.json?limit=1`, {\n headers: { Authorization: `Basic ${auth}` },\n })\n if (sessResp.ok) {\n const sessions = await sessResp.json() as Array<{ automation_session: { hashed_id: string; browser_url: string } }>\n if (sessions.length > 0) {\n this.sessionId = sessions[0].automation_session.hashed_id\n this.sessionUrl = sessions[0].automation_session.browser_url\n }\n }\n }\n }\n } catch {\n // Session details extraction is best-effort\n }\n\n this.exitHandler = () => {\n try {\n this.browser?.close()\n } catch {\n // Best-effort cleanup on exit\n }\n }\n process.on('exit', this.exitHandler)\n\n this.logCaptureConfig = { console: config.logCapture?.console !== false, network: config.logCapture?.network !== false }\n this.attachLogListeners(this.page)\n }\n\n async cleanup(): Promise<void> {\n if (this.browser) {\n await this.browser.close()\n }\n\n // Set session status via REST API after browser is closed\n if (this.sessionId && this.credentials) {\n try {\n const status = this.testFailed ? 'failed' : 'passed'\n const reason = this.testFailed ? 'Test failed' : 'Test passed'\n const auth = Buffer.from(`${this.credentials.username}:${this.credentials.accessKey}`).toString('base64')\n await fetch(`https://api.browserstack.com/automate/sessions/${this.sessionId}.json`, {\n method: 'PUT',\n headers: { Authorization: `Basic ${auth}`, 'Content-Type': 'application/json' },\n body: JSON.stringify({ status, reason }),\n })\n } catch {\n // Status reporting is best-effort\n }\n }\n\n if (this.exitHandler) {\n process.removeListener('exit', this.exitHandler)\n this.exitHandler = null\n }\n\n this.browser = null\n this.context = null\n this.page = null\n this.lastRefs = {}\n this.pageLogBuffers.clear()\n }\n\n async observe(options?: ObserveOptions): Promise<ScreenState> {\n if (!this.page) {\n throw new Error('FarmWebAdapter not initialized — call setup() first')\n }\n\n await waitForPageReady(this.page)\n const state = await observePage(this.page, {\n extractDom: options?.extractDom,\n })\n this.lastRefs = (state.metadata.refMap as RefMap) ?? {}\n return state\n }\n\n async execute(action: Action): Promise<ActionResult> {\n if (!this.page) {\n throw new Error('FarmWebAdapter not initialized — call setup() first')\n }\n\n try {\n return await this.executeAction(action)\n } catch (err) {\n let screenshot: Buffer | undefined\n let boundingBox: { x: number; y: number; width: number; height: number } | undefined\n try {\n screenshot = await this.page.screenshot()\n } catch {\n // ignore screenshot failure\n }\n try {\n if ('ref' in action && typeof (action as any).ref === 'string') {\n const resolver = new ElementResolver(this.page, this.lastRefs)\n const box = await resolver.getBoundingBox((action as any).ref)\n if (box) boundingBox = box\n }\n } catch {\n // ignore bounding box failure\n }\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n screenshot,\n boundingBox,\n }\n }\n }\n\n async screenshot(): Promise<Buffer | undefined> {\n try {\n if (this.page) {\n return await this.page.screenshot()\n }\n return undefined\n } catch {\n return undefined\n }\n }\n\n getPage(): Page | null {\n return this.page\n }\n\n async getVideoPath(): Promise<string | null> {\n try {\n const video = this.page?.video()\n if (!video) return null\n return await video.path()\n } catch {\n return null\n }\n }\n\n markFailed(): void {\n this.testFailed = true\n }\n\n getSessionUrl(): string | undefined {\n return this.sessionUrl\n }\n\n getSessionId(): string | undefined {\n return this.sessionId\n }\n\n drainConsoleLogs(level?: string): ConsoleLogEntry[] {\n const all: ConsoleLogEntry[] = []\n for (const buffers of this.pageLogBuffers.values()) {\n const newLogs = buffers.consoleLogs.slice(buffers.consoleDrainIndex)\n buffers.consoleDrainIndex = buffers.consoleLogs.length\n all.push(...newLogs)\n }\n if (!level) return all\n return all.filter(e => e.level === level)\n }\n\n drainNetworkLogs(urlPattern?: string): NetworkLogEntry[] {\n const all: NetworkLogEntry[] = []\n for (const buffers of this.pageLogBuffers.values()) {\n const newLogs = buffers.networkLogs.slice(buffers.networkDrainIndex)\n buffers.networkDrainIndex = buffers.networkLogs.length\n all.push(...newLogs)\n }\n if (!urlPattern) return all\n return all.filter(e => e.url.includes(urlPattern))\n }\n\n private attachLogListeners(page: Page): void {\n const buffers: PageLogBuffers = {\n consoleLogs: [],\n networkLogs: [],\n consoleDrainIndex: 0,\n networkDrainIndex: 0,\n pendingRequests: new Map(),\n }\n this.pageLogBuffers.set(page, buffers)\n\n if (this.logCaptureConfig.console) {\n page.on('console', (msg) => {\n buffers.consoleLogs.push({\n level: msg.type(),\n text: msg.text(),\n location: msg.location(),\n timestamp: Date.now(),\n })\n if (buffers.consoleLogs.length > 1000) {\n buffers.consoleLogs = buffers.consoleLogs.slice(-500)\n }\n })\n }\n\n if (this.logCaptureConfig.network) {\n page.on('request', (request) => {\n buffers.pendingRequests.set(request.url() + request.method(), {\n url: request.url(),\n method: request.method(),\n headers: request.headers(),\n startTime: Date.now(),\n postData: request.postData() ?? undefined,\n })\n })\n\n page.on('response', async (response) => {\n const key = response.url() + response.request().method()\n const pending = buffers.pendingRequests.get(key)\n buffers.pendingRequests.delete(key)\n\n let body: string | undefined\n try {\n const buf = await response.body()\n const ct = response.headers()['content-type'] ?? ''\n if (ct.includes('image/') && !ct.includes('svg')) {\n body = buf.length > 32768 ? undefined : `data:${ct.split(';')[0]};base64,${buf.toString('base64')}`\n } else {\n const text = buf.toString('utf-8')\n body = text.length > 32768 ? text.slice(0, 32768) + '...[truncated]' : text\n }\n } catch {\n body = undefined\n }\n\n buffers.networkLogs.push({\n url: response.url(),\n method: response.request().method(),\n status: response.status(),\n requestHeaders: pending?.headers ?? response.request().headers(),\n responseHeaders: response.headers(),\n body,\n requestBody: pending?.postData,\n startTime: pending?.startTime ?? Date.now(),\n endTime: Date.now(),\n timing: response.request().timing(),\n })\n if (buffers.networkLogs.length > 500) {\n buffers.networkLogs = buffers.networkLogs.slice(-250)\n }\n })\n }\n }\n\n private async resolveTabTargetAsync(tab: { index?: number; title?: string; url?: string }): Promise<Page | undefined> {\n const pages = this.context!.pages()\n if (tab.index !== undefined) {\n return (tab.index >= 0 && tab.index < pages.length) ? pages[tab.index] : undefined\n }\n if (tab.title) {\n for (const p of pages) {\n const t = await p.title()\n if (t.includes(tab.title)) return p\n }\n return undefined\n }\n if (tab.url) {\n return pages.find(p => p.url().includes(tab.url!))\n }\n return undefined\n }\n\n private async executeAction(action: Action): Promise<ActionResult> {\n const page = this.page!\n const resolver = new ElementResolver(page, this.lastRefs)\n\n if ('ref' in action && typeof (action as any).ref === 'string') {\n const refData = this.lastRefs[(action as any).ref]\n const role = refData?.role\n const validation = validateAction(action, role)\n if (!validation.valid) {\n return { success: false, error: validation.error }\n }\n }\n\n switch (action.type) {\n case 'click': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n const coordinates = box ? { x: box.x + box.width / 2, y: box.y + box.height / 2 } : undefined\n await locator.click({\n ...clickDelayOption(action.clickDelay),\n })\n return { success: true, coordinates, boundingBox: box ?? undefined }\n }\n\n case 'fill': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.fill(action.value)\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'select': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.selectOption(action.value)\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'navigate': {\n await page.goto(action.url, { waitUntil: 'domcontentloaded' })\n await waitForPageReady(page)\n return { success: true }\n }\n\n case 'scroll': {\n const deltaX = action.scrollType === 'horizontal' ? action.value : 0\n const deltaY = action.scrollType === 'vertical' ? action.value : 0\n let coordinates: { x: number; y: number } | undefined\n let boundingBox: { x: number; y: number; width: number; height: number } | undefined\n let scrollData: { scrolled: boolean; scrolledContainer: string } | undefined\n\n if (action.ref) {\n const refData = this.lastRefs[action.ref]\n if (refData) {\n const scrollAxis = action.scrollType === 'horizontal' ? 'horizontal' : 'vertical'\n const result = await scrollWithRef(page, refData, deltaX, deltaY, scrollAxis)\n if (result.bounds) {\n coordinates = { x: result.bounds.x + result.bounds.width / 2, y: result.bounds.y + result.bounds.height / 2 }\n boundingBox = result.bounds\n }\n scrollData = { scrolled: result.scrolled, scrolledContainer: result.scrolledContainer }\n } else {\n await page.mouse.wheel(deltaX, deltaY)\n }\n } else {\n await page.mouse.wheel(deltaX, deltaY)\n }\n\n await page.evaluate(`new Promise(resolve => {\n const t = setTimeout(() => resolve('timeout'), 500);\n requestAnimationFrame(() => requestAnimationFrame(() => {\n clearTimeout(t);\n resolve('raf');\n }));\n })`)\n\n return { success: true, coordinates, boundingBox, data: scrollData }\n }\n\n case 'waitFor': {\n const timeout = action.timeout ?? 5000\n try {\n await page.waitForFunction(\n `document.body && document.body.innerText.includes(${JSON.stringify(action.condition)})`,\n { timeout },\n )\n } catch {\n try {\n await page.waitForSelector(action.condition, { timeout })\n } catch {\n // Best-effort\n }\n }\n return { success: true }\n }\n\n case 'delay': {\n await page.waitForTimeout(action.ms)\n return { success: true }\n }\n\n case 'waitForUrl': {\n try {\n // Explicit 30s timeout overrides Playwright's infinite default (Pitfall 2)\n await page.waitForURL(action.pattern, { timeout: 30_000 })\n return { success: true }\n } catch (err) {\n return {\n success: false,\n error: `URL pattern \"${action.pattern}\" did not match within 30s. Hint: use \"**\" wildcards for substring matching (e.g., \"**/dashboard**\"). ${err instanceof Error ? err.message : String(err)}`,\n }\n }\n }\n\n case 'keypress': {\n const effectiveKeys = convertKeysForPlatform(action.keys, {\n enabled: action.convertPlatformKeys !== false,\n isMac: isMacPlatform(),\n })\n for (const key of effectiveKeys) {\n await page.keyboard.press(key)\n }\n return { success: true }\n }\n\n case 'hover': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.hover()\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'paste': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.focus()\n await page.evaluate(`(() => {\n const el = document.activeElement;\n if (!el) return;\n const dt = new DataTransfer();\n dt.setData('text/plain', ${JSON.stringify(action.value)});\n el.dispatchEvent(new ClipboardEvent('paste', {\n clipboardData: dt,\n bubbles: true,\n cancelable: true,\n }));\n })()`)\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'fileUpload': {\n // Paths are pre-resolved to absolute by runner loop.ts (see Plan 01 Task 2)\n const { existsSync } = await import('node:fs')\n for (const filePath of action.files) {\n if (!existsSync(filePath)) {\n return { success: false, error: `File not found: ${filePath}` }\n }\n }\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.setInputFiles(action.files)\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'copy': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n const text = (await locator.textContent()) ?? ''\n await page.evaluate(`navigator.clipboard.writeText(${JSON.stringify(text)})`)\n return { success: true, boundingBox: box ?? undefined, data: { copied: text } }\n }\n\n case 'keyDown': {\n await page.keyboard.down(action.key)\n return { success: true }\n }\n\n case 'keyUp': {\n await page.keyboard.up(action.key)\n return { success: true }\n }\n\n case 'refresh': {\n await page.reload({ waitUntil: 'domcontentloaded' })\n await waitForPageReady(page)\n return { success: true }\n }\n\n case 'navigateHistory': {\n if (action.direction === 'back') {\n await page.goBack({ waitUntil: 'domcontentloaded' })\n } else {\n await page.goForward({ waitUntil: 'domcontentloaded' })\n }\n await waitForPageReady(page)\n return { success: true }\n }\n\n case 'readConsoleLogs': {\n let entries: ConsoleLogEntry[]\n if (action.tab) {\n const targetPage = await this.resolveTabTargetAsync(action.tab)\n if (!targetPage) {\n return { success: false, error: `No tab found matching ${JSON.stringify(action.tab)}` }\n }\n const buffers = this.pageLogBuffers.get(targetPage)\n entries = buffers ? [...buffers.consoleLogs] : []\n } else {\n entries = []\n for (const buffers of this.pageLogBuffers.values()) {\n entries.push(...buffers.consoleLogs)\n }\n }\n if (action.level) {\n entries = entries.filter(e => e.level === action.level)\n }\n return { success: true, data: entries }\n }\n\n case 'readNetworkLogs': {\n let entries: NetworkLogEntry[]\n if (action.tab) {\n const targetPage = await this.resolveTabTargetAsync(action.tab)\n if (!targetPage) {\n return { success: false, error: `No tab found matching ${JSON.stringify(action.tab)}` }\n }\n const buffers = this.pageLogBuffers.get(targetPage)\n entries = buffers ? [...buffers.networkLogs] : []\n } else {\n entries = []\n for (const buffers of this.pageLogBuffers.values()) {\n entries.push(...buffers.networkLogs)\n }\n }\n if (action.urlPattern) {\n entries = entries.filter(e => e.url.includes(action.urlPattern!))\n }\n return { success: true, data: entries }\n }\n\n case 'readCookies': {\n const cookies = await this.context!.cookies()\n if (action.name) {\n const cookie = cookies.find(c => c.name === action.name) ?? null\n return { success: true, data: cookie }\n }\n return { success: true, data: cookies }\n }\n\n case 'setCookies': {\n const cookiesWithDefaults = action.cookies.map(c => ({\n ...c,\n url: !c.domain ? page.url() : undefined,\n }))\n await this.context!.addCookies(cookiesWithDefaults)\n return { success: true }\n }\n\n case 'readLocalStorage': {\n const pageUrl = page.url()\n if (pageUrl === 'about:blank') {\n return { success: true, data: action.key ? null : {} }\n }\n if (action.key) {\n const value = await page.evaluate(\n (k: string) => localStorage.getItem(k), action.key\n )\n return { success: true, data: value }\n }\n const all = await page.evaluate(\n () => Object.fromEntries(\n Object.keys(localStorage).map(k => [k, localStorage.getItem(k)])\n )\n )\n return { success: true, data: all }\n }\n\n case 'setLocalStorage': {\n await page.evaluate((entries: Array<{ key: string; value: string }>) => {\n for (const { key, value } of entries) {\n localStorage.setItem(key, value)\n }\n }, action.entries)\n return { success: true }\n }\n\n case 'assert': {\n return { success: true }\n }\n\n case 'clearText': {\n const loc = resolver.resolve(action.ref)\n const clearBox = await resolver.getBoundingBox(action.ref)\n await loc.clear()\n return { success: true, boundingBox: clearBox ?? undefined }\n }\n\n case 'drag': {\n const fromLoc = resolver.resolve(action.fromRef)\n const toLoc = resolver.resolve(action.toRef)\n await fromLoc.dragTo(toLoc)\n return { success: true }\n }\n\n case 'doubleTap': {\n const dblLoc = resolver.resolve(action.ref)\n const dblBox = await resolver.getBoundingBox(action.ref)\n await dblLoc.dblclick()\n return { success: true, boundingBox: dblBox ?? undefined }\n }\n\n case 'doubleClick': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n const coordinates = box\n ? action.relativePosition\n ? { x: box.x + action.relativePosition.x, y: box.y + action.relativePosition.y }\n : { x: box.x + box.width / 2, y: box.y + box.height / 2 }\n : undefined\n await locator.dblclick({\n ...(action.relativePosition && { position: action.relativePosition }),\n ...clickDelayOption(action.clickDelay),\n })\n return { success: true, coordinates, boundingBox: box ?? undefined }\n }\n\n case 'rightClick': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n const coordinates = box\n ? action.relativePosition\n ? { x: box.x + action.relativePosition.x, y: box.y + action.relativePosition.y }\n : { x: box.x + box.width / 2, y: box.y + box.height / 2 }\n : undefined\n await locator.click({\n button: 'right',\n ...(action.relativePosition && { position: action.relativePosition }),\n ...clickDelayOption(action.clickDelay),\n })\n return { success: true, coordinates, boundingBox: box ?? undefined }\n }\n\n case 'openLink': {\n await page.goto(action.url, { waitUntil: 'domcontentloaded' })\n await waitForPageReady(page)\n return { success: true }\n }\n\n case 'newTab': {\n const newPage = await this.context!.newPage()\n this.attachLogListeners(newPage)\n await newPage.goto(action.url, { waitUntil: 'domcontentloaded' })\n await waitForPageReady(newPage)\n this.page = newPage\n return { success: true }\n }\n\n case 'switchTab': {\n const pages = this.context!.pages()\n\n let target: Page | undefined\n\n if (action.index !== undefined) {\n if (action.index < 0 || action.index >= pages.length) {\n return { success: false, error: `Tab index ${action.index} out of range (${pages.length} tabs open)` }\n }\n target = pages[action.index]\n } else if (action.title) {\n for (const p of pages) {\n const t = await p.title()\n if (t.includes(action.title)) { target = p; break }\n }\n } else if (action.url) {\n target = pages.find(p => p.url().includes(action.url!))\n } else {\n return { success: false, error: 'switchTab requires at least one of: index, title, or url' }\n }\n\n if (!target) {\n return { success: false, error: `No tab found matching ${JSON.stringify({ index: action.index, title: action.title, url: action.url })}` }\n }\n\n this.page = target\n return { success: true }\n }\n\n case 'tap':\n case 'swipe':\n case 'longpress':\n case 'pinch':\n case 'multiTap': {\n return { success: false, error: `${action.type} is a mobile-only gesture` }\n }\n\n case 'tapCoordinate': {\n await page.mouse.click(action.x, action.y)\n return { success: true, coordinates: { x: action.x, y: action.y } }\n }\n\n case 'hideKeyboard':\n case 'launchApp':\n case 'stopApp':\n case 'setOrientation': {\n return { success: true }\n }\n\n default: {\n return { success: false, error: `Unknown action type: ${(action as any).type}` }\n }\n }\n }\n}\n","import { AxeBuilder } from '@axe-core/playwright'\nimport type { Page } from 'playwright-core'\nimport type { AccessibilityViolation } from '@vostride/agent-qa-core'\n\nexport interface AccessibilityOptions {\n standard?: 'wcag2a' | 'wcag2aa' | 'wcag2aaa'\n disableRules?: string[]\n exclude?: string[]\n}\n\nexport async function runAccessibilityCheck(\n page: Page,\n options?: AccessibilityOptions,\n): Promise<AccessibilityViolation[]> {\n let builder = new AxeBuilder({ page })\n\n if (options?.standard) {\n const tagMap: Record<string, string[]> = {\n 'wcag2a': ['wcag2a'],\n 'wcag2aa': ['wcag2a', 'wcag2aa'],\n 'wcag2aaa': ['wcag2a', 'wcag2aa', 'wcag2aaa'],\n }\n builder = builder.withTags(tagMap[options.standard] ?? ['wcag2a', 'wcag2aa'])\n }\n\n if (options?.disableRules?.length) {\n builder = builder.disableRules(options.disableRules)\n }\n\n if (options?.exclude?.length) {\n for (const selector of options.exclude) {\n builder = builder.exclude(selector)\n }\n }\n\n const results = await builder.analyze()\n\n return results.violations.map(v => ({\n ruleId: v.id,\n impact: v.impact as AccessibilityViolation['impact'],\n description: v.description,\n help: v.help,\n helpUrl: v.helpUrl,\n nodes: v.nodes.slice(0, 10).map(n => ({\n html: n.html,\n target: n.target as string[],\n })),\n }))\n}\n"],"mappings":"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","names":["prop","before","after","rect","convertKeysForPlatform","isMacPlatform","clickDelayOption","convertKeysForPlatform","isMacPlatform"]}
|
|
1
|
+
{"version":3,"sources":["../src/adapter.ts","../src/observer.ts","../src/dom-extractor.ts","../src/element-resolver.ts","../src/binding.ts","../src/action-validator.ts","../src/smart-wait.ts","../src/compound-web.ts","../src/scroll-helper.ts","../src/browser-install-error.ts","../src/recording.ts","../src/operation-capture.ts","../src/farm-adapter.ts","../src/accessibility.ts"],"sourcesContent":["import type { Browser, BrowserContext, CDPSession, Dialog, Page } from 'playwright-core'\nimport type {\n ActionsFor,\n ActionResult,\n ConsoleLogEntry,\n ExecuteOptions,\n LiveStreamCapability,\n NetworkLogEntry,\n ObserveOptions,\n OperationCaptureSupport,\n PlatformAdapter,\n PlatformConfig,\n RecordingCapability,\n} from '@vostride/agent-qa-runner'\nimport type { LiveFrame } from '@vostride/agent-qa-schema'\nimport {\n assertNever,\n buildScreenState,\n createSnapshotLiveStream,\n LIVE_KEEPALIVE_QUIET_MS,\n} from '@vostride/agent-qa-runner'\nimport type { ScreenState } from '@vostride/agent-qa-schema'\nimport { convertKeysForPlatform, isMacPlatform } from '@vostride/agent-qa-runner'\nimport { parseAriaSnapshot, enrichWebNodes, captureWebScroll } from './observer.js'\nimport { extractDom } from './dom-extractor.js'\nimport { ElementResolver, buildRefMap } from './element-resolver.js'\nimport {\n bindingRefusal,\n captureEpoch,\n checkBinding,\n checkDocument,\n disposeEpoch,\n laneRefs,\n snapshotRoot,\n} from './binding.js'\nimport type { ObservationEpoch, SnapshotRootOptions } from './binding.js'\nimport { validateAction } from './action-validator.js'\nimport { waitForPageReady } from './smart-wait.js'\nimport { runWebFillCompound, runWebScrollCompound, webOpenAppError } from './compound-web.js'\nimport type { RefMap } from './types.js'\nimport { formatMissingBrowserError, isPlaywrightMissingBrowserError } from './browser-install-error.js'\nimport { createScreencastRecording, type ScreencastRecording } from './recording.js'\nimport { isHeadlessLaunch, OperationCapture } from './operation-capture.js'\nimport type { CapturedOperations } from './operation-capture.js'\n\ninterface PageLogBuffers {\n consoleLogs: ConsoleLogEntry[]\n networkLogs: NetworkLogEntry[]\n consoleDrainIndex: number\n networkDrainIndex: number\n pendingRequests: Map<string, { url: string; method: string; headers: Record<string, string>; startTime: number; postData?: string }>\n}\n\n// 2026-10-08 (436-24): a frame or navigation that never answers must not hold observe, the\n// screenshot or a Chromium click (CR-05). The ai-mode snapshot waits for each child frame and the\n// screenshot for document.fonts.ready, which a hung iframe keeps pending; both are bounded here. A\n// Chromium click no longer waits for the navigation it starts to commit: the capture's start\n// window owns that wait and ends it at NAVIGATION_WINDOW_CAP_MS.\n// 2026-10-08 (436-27): the short snapshot bound applies to the first attempt only. Playwright\n// absorbs a child frame's timeout, so a TimeoutError means the main frame itself was slow: the\n// snapshot is taken once more with OBSERVE_SNAPSHOT_RETRY_TIMEOUT_MS (CR-09). The acting page is\n// passed to the capture, whose own main-frame navigation waits up to half the time left (WR-21).\n/** The longest observe's first ai-mode snapshot waits; a child frame that has not answered by then is left empty. */\nexport const OBSERVE_SNAPSHOT_TIMEOUT_MS = 5_000\n/** The bound a main-frame snapshot gets after it outlasts the short one: Playwright's default, the pre-436-24 bound. */\nexport const OBSERVE_SNAPSHOT_RETRY_TIMEOUT_MS = 30_000\nconst OBSERVE_SNAPSHOT: SnapshotRootOptions = {\n timeoutMs: OBSERVE_SNAPSHOT_TIMEOUT_MS,\n retryTimeoutMs: OBSERVE_SNAPSHOT_RETRY_TIMEOUT_MS,\n}\n/** The longest screenshot() waits before it gives up and returns undefined. */\nexport const SCREENSHOT_TIMEOUT_MS = 5_000\n\n// 436 D-22: the adapter carries the capture on metadata.download and metadata.clipboard; the loop\n// masks it, moves it onto the sub-action's operationEvidence and removes both keys from the\n// recorded result (D-16).\nfunction withOperationMetadata(result: ActionResult, captured: CapturedOperations | undefined): ActionResult {\n const download = captured?.downloads?.length ? captured.downloads : undefined\n const clipboard = captured?.clipboard?.length ? captured.clipboard : undefined\n if (!download && !clipboard) return result\n return {\n ...result,\n metadata: { ...result.metadata, ...(download ? { download } : {}), ...(clipboard ? { clipboard } : {}) },\n }\n}\n\nfunction clickDelayOption(clickDelay?: number): { delay?: number } {\n return clickDelay !== undefined && clickDelay > 0 ? { delay: clickDelay } : {}\n}\n\n// The Plan 10 dispatch seam injects the persisted raw Playwright storage-state blob onto a\n// `storageState`/restore action before it reaches the adapter (the schema restore shape carries\n// only `{op,name}`; the adapter never reads it off disk — D-14). Reading that seam field lives in\n// this `unknown`-typed helper so no cast leaks into the execute switch (no-shims law).\nfunction readSeamStorageState(action: unknown): Parameters<BrowserContext['setStorageState']>[0] {\n return (action as { state: Parameters<BrowserContext['setStorageState']>[0] }).state\n}\n\n/**\n * The `Page.startScreencast` parameters this adapter ships (403 discretion D-06).\n *\n * WHAT MAKES THE STREAM CHANGE-DRIVEN is the ack, not a parameter: CDP emits a frame when the\n * compositor produces one and then stalls until `Page.screencastFrameAck` arrives, so a moving page\n * streams at the viewer's pace and a page that is not moving produces no screencast frames at all.\n * `live-stream.screencast.test.ts` measures both halves on a real Chromium: an animating page yields\n * hundreds of frames in 3 s WITH acks and 3 without.\n *\n * A STATIC PAGE STILL PRODUCES A FRAME EVERY 2 S (428 D-15). After `LIVE_KEEPALIVE_QUIET_MS` without\n * a screencast frame the capability takes a fresh `Page.captureScreenshot` on the same CDP session\n * and emits it, so the viewer's freshness dot stays green on a page that is simply still. It is a\n * new capture stamped when it resolves, never the last frame re-sent: a wedged renderer produces\n * nothing and the dot ages to amber, which is the truth. STATIC-PAGE-KEEPALIVE bounds the cadence\n * both ways (2-4 frames in 6 s, gaps of at least 1.8 s), so a 1 s poller still fails it.\n *\n * `maxFramesInFlight` IS NOT A CDP PARAMETER and was removed after being measured to do nothing:\n * with and without it, an unacked stream delivered the same 3 frames per 3 s. Chromium tolerates\n * the unknown key silently, which is how a comment claiming \"exactly one in flight\" survived — the\n * bound is Chromium's own, and the ack is what releases it.\n */\nexport const SCREENCAST_PARAMS = {\n format: 'jpeg',\n quality: 60,\n maxWidth: 1280,\n maxHeight: 720,\n everyNthFrame: 1,\n} as const\n\n/**\n * How many un-acked CDP ack tokens the producer will remember.\n *\n * Chromium keeps only a couple of frames in flight, so this is generous by two orders of magnitude;\n * it exists so a viewer that stops acking cannot grow the map without bound. An evicted token is\n * ACKED on its way out rather than dropped, because a token nobody acks is a producer that stalls\n * forever — the failure this whole ack path exists to avoid.\n */\nconst SCREENCAST_ACK_WINDOW = 64\n\n/**\n * How long after a keepalive frame one screencast frame is treated as that capture's echo.\n *\n * `Page.captureScreenshot` makes the compositor paint once, and the screencast delivers that paint\n * as a frame within a millisecond of the capture (measured: same-millisecond stamps on every\n * keepalive of a static page). It is the same picture the keepalive just emitted, so it is acked at\n * once and not emitted; a page that really starts moving is only one frame later.\n */\nconst KEEPALIVE_ECHO_WINDOW_MS = 250\n\n/**\n * How often a screencast that fell back to snapshots tries to come back (428 WR-08). A withdrawal is\n * not always permanent, and without a way back one bad moment labels the rest of the run a\n * snapshot preview.\n */\nexport const SCREENCAST_RECOVERY_MS = 10_000\n\n/** Decode a CDP base64 frame payload to bytes without a `Buffer` round-trip in the hot path. */\nfunction decodeBase64(data: string): Uint8Array {\n const binary = atob(data)\n const bytes = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i)\n return bytes\n}\n\nexport interface WebPlatformAdapterOptions {\n // 2026-10-17 (444-22, D-46; 2026-10-18 444-25, D-60): only a host with its own SIGINT, SIGTERM\n // and SIGHUP path (agent-qa run) sets this.\n readonly hostOwnsSignals?: true\n}\n\nexport class WebPlatformAdapter implements PlatformAdapter<'web'> {\n readonly platform = 'web' as const\n\n constructor(private readonly options: WebPlatformAdapterOptions = {}) {}\n\n private browser: Browser | null = null\n private context: BrowserContext | null = null\n private page: Page | null = null\n // The native binding of the last observation and its document (438 D-06). Neither crosses the\n // port (observe returns only the ScreenState).\n private lastRefs: RefMap = {}\n private epoch: ObservationEpoch | undefined\n private pageLogBuffers = new Map<Page, PageLogBuffers>()\n private logCaptureConfig: { console: boolean; network: boolean } = { console: true, network: true }\n private disconnected = false\n private intentionalClose = false\n // Persistent route interception + one-shot dialog arms live until an explicit unroute or\n // test teardown (D-12/D-18); cleanup() drains both so nothing bleeds across tests (Pitfall 7).\n private armedRoutes = new Set<string>()\n private pendingDialogArm: ((dialog: Dialog) => void) | null = null\n // 403 D-05: the live screencast's CDP session, owned here and never handed out.\n private browserName: 'chromium' | 'firefox' | 'webkit' = 'chromium'\n private screencast: CDPSession | null = null\n private screencastCapability: LiveStreamCapability | null = null\n private recordingCapability: ScreencastRecording | undefined\n private recordingPageRevision = 0\n private recordingConfig: PlatformConfig['recording']\n // 403-02: the PRODUCT's frame identity, and the CDP ack token it maps to. See `liveStream`.\n private screencastFrameSeq = 0\n private screencastAckTokens = new Map<number, number>()\n // 428 D-15: the running screencast's consumer, its quiet-page keepalive, and the size a keepalive\n // frame reports (the last screencast frame's device size).\n private screencastOnFrame: ((frame: LiveFrame) => void) | null = null\n private keepaliveTimer: ReturnType<typeof setTimeout> | null = null\n private lastScreencastSize: { width: number; height: number } | null = null\n private keepaliveEchoDeadline: number | null = null\n private screencastChain: Promise<void> = Promise.resolve()\n // 428 D-12: the labelled snapshot preview standing in for a screencast withdrawn mid-stream.\n private withdrawnSnapshot: LiveStreamCapability | null = null\n private screencastRecoveryTimer: ReturnType<typeof setTimeout> | null = null\n // 436 D-19, D-21: download and app-clipboard capture, Chromium only; armed around each execute().\n private operationCapture: OperationCapture | null = null\n // 436 D-23: Firefox and WebKit run no capture and name themselves as the reason.\n operationCaptureSupport: OperationCaptureSupport | undefined\n\n async setup(config: PlatformConfig): Promise<void> {\n this.recordingConfig = config.recording\n const { chromium, firefox, webkit } = await import('playwright-core')\n const launchers = { chromium, firefox, webkit } as const\n const browserName = config.browser?.name ?? 'chromium'\n this.browserName = browserName\n const launcher = launchers[browserName]\n const headless = config.browser?.headless ?? true\n\n try {\n this.browser = await launcher.launch({\n headless,\n ...(browserName === 'chromium' ? { args: ['--disable-blink-features=AutomationControlled'] } : {}),\n ...(this.options.hostOwnsSignals === true\n ? { handleSIGINT: false, handleSIGTERM: false, handleSIGHUP: false }\n : {}),\n })\n } catch (error) {\n if (isPlaywrightMissingBrowserError(error)) {\n throw new Error(formatMissingBrowserError(browserName))\n }\n throw error\n }\n\n this.disconnected = false\n this.intentionalClose = false\n this.browser.on('disconnected', () => {\n if (!this.intentionalClose) {\n this.disconnected = true\n }\n })\n\n const contextOptions: Record<string, unknown> = {\n viewport: config.browser?.viewport ?? { width: 1280, height: 720 },\n }\n if (config.authState?.storageStatePath) {\n contextOptions.storageState = config.authState.storageStatePath\n }\n this.context = await this.browser.newContext(contextOptions)\n\n // Clipboard write permission — chromium only (firefox/webkit reject this permission per Pitfall 3)\n if (browserName === 'chromium') {\n await this.context.grantPermissions(['clipboard-write'])\n }\n\n this.logCaptureConfig = { console: config.logCapture?.console !== false, network: config.logCapture?.network !== false }\n\n // Hide automation signals so bot-protected sites don't redirect\n await this.context.addInitScript(() => {\n Object.defineProperty(navigator, 'webdriver', { get: () => false })\n })\n\n this.page = await this.context.newPage()\n this.attachLogListeners(this.page)\n\n if (browserName === 'chromium') {\n // 2026-10-08 (436-15): the step deadline reaches the capture per action through execute().\n // 2026-10-08 (436-21): owner ruling on D-21, a headed or undetermined launch never reads.\n this.operationCapture = new OperationCapture({ headless: isHeadlessLaunch({ headless }, process.env) })\n await this.operationCapture.attach(this.context)\n this.operationCaptureSupport = { download: true, clipboard: true }\n } else {\n this.operationCaptureSupport = { download: false, clipboard: false, reason: browserName }\n }\n }\n\n /**\n * 403 D-05/LIVE-01: the Chromium screencast producer, or ABSENT when this adapter cannot stream.\n *\n * Absence means \"no continuous stream\", not \"no preview\": since 428-05 the composition's\n * `liveStreamFor` wraps this adapter's `screenshot()` in the labelled 1 s snapshot producer, both\n * as the fallback behind a screencast that fails to start and as the whole preview on a\n * non-Chromium target. The two gates here (Chromium only, and a page to stream) stay exactly as\n * they are, so the absence stays honest.\n *\n * SCOPE (428 D-18, closes WIN #273): the screencast shows the page the test is acting on. Both\n * page-switch sites (`tab new`, `tab switch`) go through `setActivePage`, which re-binds the\n * running screencast to the new page INSIDE this same capability object: no stop, no re-register,\n * no stream end, so a subscriber only sees the picture change. Start, stop and re-bind run on one\n * serialised chain. A popup or a closing tab never changes `this.page` in this adapter, so the\n * preview already shows the acting page in those cases.\n */\n get liveStream(): LiveStreamCapability | undefined {\n if (this.browserName !== 'chromium') return undefined\n if (!this.page || !this.context) return undefined\n if (this.screencastCapability) return this.screencastCapability\n const capability: LiveStreamCapability = {\n kind: 'cdp-screencast',\n start: (onFrame: (frame: LiveFrame) => void): Promise<void> =>\n this.onScreencastChain(async () => {\n if (this.screencastOnFrame !== null) return\n const page = this.page\n const context = this.context\n if (!page || !context) return\n const cdp = await context.newCDPSession(page)\n this.screencast = cdp\n this.screencastOnFrame = onFrame\n this.screencastAckTokens.clear()\n this.attachScreencast(cdp, onFrame)\n try {\n await cdp.send('Page.startScreencast', { ...SCREENCAST_PARAMS })\n } catch (error) {\n // A start that fails leaves nothing started, so the hub's fallback owns the handle.\n this.screencast = null\n this.screencastOnFrame = null\n try { await cdp.detach() } catch { /* best-effort */ }\n throw error\n }\n if (this.screencast === cdp) this.armKeepalive(cdp)\n }),\n ack: async (frameId: number): Promise<void> => {\n const cdp = this.screencast\n if (!cdp) return\n const sessionId = this.screencastAckTokens.get(frameId)\n this.screencastAckTokens.delete(frameId)\n // An ack for a frame this producer never minted (a stale viewer, a re-started stream, a\n // keepalive, a frame from before a re-bind) is dropped rather than forwarded: acking an\n // arbitrary token is worse than acking nothing.\n if (sessionId === undefined) return\n try {\n await cdp.send('Page.screencastFrameAck', { sessionId })\n } catch {\n // Acking after stop (or after the page navigated away) is expected, never an error.\n }\n },\n stop: (): Promise<void> =>\n this.onScreencastChain(async () => {\n this.screencastOnFrame = null\n await this.stopWithdrawnSnapshot()\n await this.detachScreencast()\n }),\n }\n this.screencastCapability = capability\n return capability\n }\n\n /** Run `step` after every earlier start, stop and re-bind has settled (428 D-18). */\n private onScreencastChain(step: () => Promise<void>): Promise<void> {\n const run = this.screencastChain.then(step)\n this.screencastChain = run.catch(() => undefined)\n return run\n }\n\n /** Stop and detach the current CDP session, best-effort, and forget its tokens and keepalive. */\n private async detachScreencast(): Promise<void> {\n const cdp = this.screencast\n this.screencast = null\n this.clearKeepalive()\n this.keepaliveEchoDeadline = null\n this.screencastAckTokens.clear()\n if (!cdp) return\n try { await cdp.send('Page.stopScreencast') } catch { /* best-effort */ }\n try { await cdp.detach() } catch { /* best-effort */ }\n }\n\n /** Wire `cdp`'s screencast frames to `onFrame`; shared by `start` and `rebindScreencast`. */\n private attachScreencast(cdp: CDPSession, onFrame: (frame: LiveFrame) => void): void {\n cdp.on('Page.screencastFrame', (event) => {\n // A session being replaced by a re-bind may still deliver a frame of the old page.\n if (this.screencast !== cdp) return\n const metadata = event.metadata\n this.lastScreencastSize = { width: metadata.deviceWidth, height: metadata.deviceHeight }\n this.armKeepalive(cdp)\n const echoDeadline = this.keepaliveEchoDeadline\n this.keepaliveEchoDeadline = null\n if (echoDeadline !== null && Date.now() <= echoDeadline) {\n void cdp.send('Page.screencastFrameAck', { sessionId: event.sessionId }).catch(() => undefined)\n return\n }\n // `LiveFrame.id` IS NOT `event.sessionId`, AND CONFLATING THEM WAS A BUG (403-02).\n //\n // `sessionId` is CDP's ack TOKEN. Measured on Chromium 1.59.1 it is `1` for every frame\n // of a stream — 281 frames, one distinct value. `LiveFrame.id` is the PRODUCT's frame\n // identity: the hub keys its per-frame ack quorum on it, the wire protocol pairs a\n // `frame` header with an `ack` by it, and the embed page correlates its pending header\n // with the binary that follows by it. A constant id makes the hub's second\n // `awaiting.set(id, …)` overwrite the first — orphaning its bound timer and dropping the\n // outstanding set, so one frame is acked twice and another never at all.\n //\n // So the adapter mints a monotonic id and remembers which CDP token it stands for. The\n // sequence continues across re-binds, so ids stay monotonic for every subscriber.\n const id = ++this.screencastFrameSeq\n this.screencastAckTokens.set(id, event.sessionId)\n // Bound the map. An evicted token is acked on its way out: an un-acked token is a\n // producer stalled forever, which is worse than a frame nobody watched.\n while (this.screencastAckTokens.size > SCREENCAST_ACK_WINDOW) {\n const oldest = this.screencastAckTokens.keys().next()\n if (oldest.done === true) break\n const token = this.screencastAckTokens.get(oldest.value)\n this.screencastAckTokens.delete(oldest.value)\n if (token !== undefined) {\n void cdp.send('Page.screencastFrameAck', { sessionId: token }).catch(() => undefined)\n }\n }\n onFrame({\n id,\n bytes: decodeBase64(event.data),\n metadata: {\n width: metadata.deviceWidth,\n height: metadata.deviceHeight,\n // CDP's `TimeSinceEpoch` is SECONDS; every other layer reads epoch ms (428 D-15).\n ...(metadata.timestamp === undefined\n ? {}\n : { timestamp: Math.round(metadata.timestamp * 1000) }),\n scrollOffsetX: metadata.scrollOffsetX,\n scrollOffsetY: metadata.scrollOffsetY,\n },\n })\n })\n }\n\n /**\n * The one place the page the test acts on changes (428 D-18). Recording keeps following its\n * starting page through the revision counter (424 reconciliation 25(d)); the live screencast,\n * when running, re-binds to the new page on the serialised chain.\n */\n private setActivePage(page: Page): void {\n this.page = page\n this.recordingPageRevision++\n if (this.screencastOnFrame !== null) {\n void this.onScreencastChain(() => this.rebindScreencast())\n }\n }\n\n /**\n * Move the running screencast onto `this.page` without its subscribers noticing: the old session\n * is stopped and detached, a new one is started with the stored `onFrame`, and the id sequence\n * continues. Ids still pending in the hub settle through its ack bound and are dropped here as\n * unknown. Best-effort throughout; it never throws into a step.\n */\n private async rebindScreencast(options: { focus?: boolean } = {}): Promise<void> {\n const onFrame = this.screencastOnFrame\n const page = this.page\n const context = this.context\n if (onFrame === null || !page || !context) return\n await this.detachScreencast()\n this.lastScreencastSize = null\n // A headed browser may not paint a background tab (RESEARCH P15, assumption A4). A recovery\n // attempt keeps the page where it is, so it never takes focus on a person's desktop.\n if (options.focus !== false) {\n try { await page.bringToFront() } catch { /* best-effort */ }\n }\n let cdp: CDPSession\n try {\n cdp = await context.newCDPSession(page)\n } catch {\n this.handleScreencastWithdrawn(null)\n return\n }\n this.screencast = cdp\n this.attachScreencast(cdp, onFrame)\n try {\n await cdp.send('Page.startScreencast', { ...SCREENCAST_PARAMS })\n } catch {\n this.handleScreencastWithdrawn(cdp)\n return\n }\n if (this.screencast !== cdp) return\n this.armKeepalive(cdp)\n await this.stopWithdrawnSnapshot()\n }\n\n /**\n * 428 D-12's second half: the screencast was withdrawn while the browser is still up (its CDP\n * session detached or unusable), which only this capability can see. Detected when a keepalive\n * capture or a re-bind's start rejects on the active session; the capability then serves the\n * labelled 1 s snapshot preview of the current page through the same `onFrame`, until `stop()`,\n * `cleanup()` or a successful re-bind. The declared kind stays `cdp-screencast`; the frames carry\n * `kind: 'snapshot'`, which is what labels the preview. Runs on the serialised chain.\n */\n private handleScreencastWithdrawn(cdp: CDPSession | null): void {\n void this.onScreencastChain(async () => {\n if (this.screencast !== cdp) return\n const onFrame = this.screencastOnFrame\n if (onFrame === null || this.withdrawnSnapshot !== null || !this.browserIsLive()) return\n await this.detachScreencast()\n const snapshot = createSnapshotLiveStream({ capture: () => this.screenshot() })\n this.withdrawnSnapshot = snapshot\n // Re-minted into the capability's own id sequence, so ids stay monotonic for every viewer.\n await snapshot.start((frame) => {\n if (this.withdrawnSnapshot !== snapshot) return\n onFrame({ ...frame, id: ++this.screencastFrameSeq })\n })\n this.armScreencastRecovery()\n })\n }\n\n /** While the snapshot fallback runs, try the screencast again every SCREENCAST_RECOVERY_MS (428 WR-08). */\n private armScreencastRecovery(): void {\n this.clearScreencastRecovery()\n const timer = setTimeout(() => {\n this.screencastRecoveryTimer = null\n void this.onScreencastChain(async () => {\n if (this.withdrawnSnapshot === null || this.screencastOnFrame === null || !this.browserIsLive()) return\n await this.rebindScreencast({ focus: false })\n if (this.withdrawnSnapshot !== null) this.armScreencastRecovery()\n })\n }, SCREENCAST_RECOVERY_MS)\n timer.unref?.()\n this.screencastRecoveryTimer = timer\n }\n\n private clearScreencastRecovery(): void {\n if (this.screencastRecoveryTimer !== null) clearTimeout(this.screencastRecoveryTimer)\n this.screencastRecoveryTimer = null\n }\n\n private browserIsLive(): boolean {\n return !this.intentionalClose && !this.disconnected && this.browser?.isConnected() === true\n }\n\n private async stopWithdrawnSnapshot(): Promise<void> {\n this.clearScreencastRecovery()\n const snapshot = this.withdrawnSnapshot\n this.withdrawnSnapshot = null\n try { await snapshot?.stop() } catch { /* best-effort */ }\n }\n\n private clearKeepalive(): void {\n if (this.keepaliveTimer !== null) clearTimeout(this.keepaliveTimer)\n this.keepaliveTimer = null\n }\n\n /** (Re-)arm the quiet-page keepalive for `cdp`; every screencast frame pushes it back. */\n private armKeepalive(cdp: CDPSession): void {\n this.clearKeepalive()\n const timer = setTimeout(() => { void this.fireKeepalive(cdp) }, LIVE_KEEPALIVE_QUIET_MS)\n timer.unref?.()\n this.keepaliveTimer = timer\n }\n\n /**\n * 428 D-15: a fresh capture on the same CDP session, emitted as a frame with no ack token (the ack\n * path drops ids it never minted a token for). A capture that rejects emits nothing. While the\n * capability is started under a live browser, a session that then fails a trivial probe too is a\n * withdrawn screencast (D-12, see `handleScreencastWithdrawn`); one that still answers only had a\n * bad moment, such as a cross-process navigation, and re-arms (428 WR-08). One that never settles\n * emits nothing and arms nothing, which is the honest amber.\n */\n private async fireKeepalive(cdp: CDPSession): Promise<void> {\n this.keepaliveTimer = null\n if (this.screencast !== cdp) return\n const framesBefore = this.screencastFrameSeq\n let data: string\n try {\n const result = await cdp.send('Page.captureScreenshot', { format: 'jpeg', quality: 60 })\n data = result.data\n } catch {\n if (this.screencast !== cdp) return\n const withdrawn = this.screencastOnFrame !== null && this.browserIsLive() && !(await this.sessionAnswers(cdp))\n if (this.screencast !== cdp) return\n if (withdrawn) this.handleScreencastWithdrawn(cdp)\n else this.armKeepalive(cdp)\n return\n }\n if (this.screencast !== cdp) return\n const onFrame = this.screencastOnFrame\n if (onFrame === null) return\n // A screencast frame that landed while the capture was in flight is already a fresh frame.\n if (this.screencastFrameSeq !== framesBefore) return\n const size = this.lastScreencastSize ?? this.page?.viewportSize() ?? { width: 0, height: 0 }\n onFrame({\n id: ++this.screencastFrameSeq,\n bytes: decodeBase64(data),\n metadata: { width: size.width, height: size.height, timestamp: Date.now() },\n })\n this.keepaliveEchoDeadline = Date.now() + KEEPALIVE_ECHO_WINDOW_MS\n this.armKeepalive(cdp)\n }\n\n /** Whether `cdp` still answers a command that cannot fail on a usable session. */\n private async sessionAnswers(cdp: CDPSession): Promise<boolean> {\n try {\n await cdp.send('Runtime.evaluate', { expression: '1' })\n return true\n } catch {\n return false\n }\n }\n\n get recording(): RecordingCapability | undefined {\n if (!this.page || !this.context || !this.recordingConfig) return undefined\n return this.recordingCapability ??= createScreencastRecording(\n () => this.page,\n this.recordingConfig,\n () => this.recordingPageRevision,\n )\n }\n\n async cleanup(): Promise<void> {\n this.intentionalClose = true\n try { await this.recordingCapability?.stop() } catch { /* best-effort */ }\n this.recordingCapability = undefined\n this.recordingConfig = undefined\n // 403: stop the screencast before the browser goes away so the CDP session is detached cleanly.\n // Clearing the consumer first makes any re-bind still queued on the chain a no-op.\n this.screencastOnFrame = null\n await this.stopWithdrawnSnapshot()\n try { await this.screencastCapability?.stop() } catch { /* best-effort */ }\n this.screencastCapability = null\n // 2026-10-08 (436-14): close the clipboard read-back probe context before the browser goes.\n try { await this.operationCapture?.dispose() } catch { /* best-effort */ }\n // Pitfall 7: clear persistent route interception, network emulation, and any pending\n // dialog arm BEFORE closing the browser so state never bleeds into the next test.\n if (this.context) {\n try { await this.context.unrouteAll({ behavior: 'ignoreErrors' }) } catch { /* best-effort */ }\n try { await this.context.setOffline(false) } catch { /* best-effort */ }\n }\n if (this.page && this.pendingDialogArm) {\n try { this.page.off('dialog', this.pendingDialogArm) } catch { /* best-effort */ }\n }\n this.armedRoutes.clear()\n this.pendingDialogArm = null\n await disposeEpoch(this.epoch)\n this.epoch = undefined\n if (this.browser) {\n await this.browser.close()\n }\n this.browser = null\n this.context = null\n this.page = null\n this.operationCapture = null\n this.operationCaptureSupport = undefined\n this.lastRefs = {}\n this.pageLogBuffers.clear()\n this.disconnected = false\n this.intentionalClose = false\n this.screencast = null\n this.screencastOnFrame = null\n this.clearKeepalive()\n this.lastScreencastSize = null\n this.screencastAckTokens.clear()\n this.screencastChain = Promise.resolve()\n }\n\n get isBrowserDisconnected(): boolean {\n return this.disconnected\n }\n\n async observe(options?: ObserveOptions): Promise<ScreenState> {\n if (!this.page) {\n throw new Error('WebPlatformAdapter not initialized — call setup() first')\n }\n const page = this.page\n\n await waitForPageReady(page)\n\n // The epoch is taken before the snapshot, so a document replaced at any point after it is\n // refused as stale-observation at dispatch (D-09).\n const epoch = await captureEpoch(page)\n try {\n const state = await this.observeDocument(page, options)\n await disposeEpoch(this.epoch)\n this.epoch = epoch\n return state\n } catch (error) {\n await disposeEpoch(epoch)\n throw error\n }\n }\n\n private async observeDocument(\n page: Page,\n options: ObserveOptions | undefined,\n ): Promise<ScreenState> {\n // ai-mode snapshot: Playwright annotates each element with a native [ref=eN] handle\n // (adapter-PRIVATE) that aria-ref locators resolve against — the enrichment ground\n // truth and the dispatch handle (D-06).\n const ariaTree = await snapshotRoot(page, OBSERVE_SNAPSHOT)\n\n // parse -> enrich -> scroll: the interim-node walker (352-03), exact per-element\n // enrichment via aria-ref locators, and exact window scroll/viewport capture.\n const { nodes, nativeRefs } = parseAriaSnapshot(ariaTree)\n if (nodes.length > 0) {\n await enrichWebNodes(page, nodes, nativeRefs)\n }\n const { viewport, scroll } = await captureWebScroll(page)\n\n // domContext is web-only (D-04), captured only when the loop asks for it.\n let domContext: string | undefined\n if (options?.extractDom) {\n try {\n domContext = await extractDom(page)\n } catch {\n // DOM extraction is best-effort — never block observation.\n }\n }\n\n // The shared runner builder mints refs, normalizes names, and assembles the schema\n // v2 ScreenState. The binding stays adapter-private; only the state crosses the port.\n const { state, binding } = buildScreenState({\n platform: 'web',\n nodes,\n viewport,\n scroll,\n coordSpace: 'viewport',\n timestamp: Date.now(),\n url: page.url(),\n ...(domContext !== undefined ? { domContext } : {}),\n })\n\n this.lastRefs = buildRefMap(binding, nodes, nativeRefs, state.elements)\n return state\n }\n\n async execute(action: ActionsFor<'web'>, options?: ExecuteOptions): Promise<ActionResult> {\n if (!this.page) {\n throw new Error('WebPlatformAdapter not initialized — call setup() first')\n }\n\n const capture = this.operationCapture\n await capture?.arm(action, options, this.page)\n const result = await this.executeWithErrorResult(action)\n // The download-start grace and the clipboard read-back follow the action (436-10, 436-11); the\n // recorded interval is the action's.\n this.recordingCapability?.endAction()\n let captured: CapturedOperations | undefined\n try {\n captured = await capture?.collect()\n } catch {\n captured = undefined\n }\n return withOperationMetadata(result, captured)\n }\n\n private async executeWithErrorResult(action: ActionsFor<'web'>): Promise<ActionResult> {\n if (!this.page) {\n throw new Error('WebPlatformAdapter not initialized — call setup() first')\n }\n try {\n return await this.executeAction(action)\n } catch (err) {\n let screenshot: Buffer | undefined\n let boundingBox: { x: number; y: number; width: number; height: number } | undefined\n try {\n screenshot = await this.page.screenshot({ scale: 'css' })\n } catch {\n // ignore screenshot failure\n }\n try {\n if ('ref' in action && typeof (action as any).ref === 'string') {\n const resolver = new ElementResolver(this.page, this.lastRefs)\n const box = await resolver.getBoundingBox((action as any).ref)\n if (box) boundingBox = box\n }\n } catch {\n // ignore bounding box failure\n }\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n screenshot,\n boundingBox,\n }\n }\n }\n\n async screenshot(): Promise<Buffer | undefined> {\n try {\n if (this.page) {\n return await this.page.screenshot({ scale: 'css', timeout: SCREENSHOT_TIMEOUT_MS })\n }\n return undefined\n } catch {\n return undefined\n }\n }\n\n getPage(): Page | null {\n return this.page\n }\n\n drainConsoleLogs(level?: string): ConsoleLogEntry[] {\n const all: ConsoleLogEntry[] = []\n for (const buffers of this.pageLogBuffers.values()) {\n const newLogs = buffers.consoleLogs.slice(buffers.consoleDrainIndex)\n buffers.consoleDrainIndex = buffers.consoleLogs.length\n all.push(...newLogs)\n }\n if (!level) return all\n return all.filter(e => e.level === level)\n }\n\n drainNetworkLogs(urlPattern?: string): NetworkLogEntry[] {\n const all: NetworkLogEntry[] = []\n for (const buffers of this.pageLogBuffers.values()) {\n const newLogs = buffers.networkLogs.slice(buffers.networkDrainIndex)\n buffers.networkDrainIndex = buffers.networkLogs.length\n all.push(...newLogs)\n }\n if (!urlPattern) return all\n return all.filter(e => e.url.includes(urlPattern))\n }\n\n /** 439 D-04: a completed download's bytes held in memory, by its sha256. */\n readDownloadBytes(sha256: string): Uint8Array | undefined {\n return this.operationCapture?.readDownloadBytes(sha256)\n }\n\n peekNetworkLogs(urlPattern?: string): NetworkLogEntry[] {\n const all: NetworkLogEntry[] = []\n for (const buffers of this.pageLogBuffers.values()) {\n all.push(...buffers.networkLogs.slice(buffers.networkDrainIndex))\n }\n if (!urlPattern) return all\n return all.filter(e => e.url.includes(urlPattern))\n }\n\n private attachLogListeners(page: Page): void {\n const buffers: PageLogBuffers = {\n consoleLogs: [],\n networkLogs: [],\n consoleDrainIndex: 0,\n networkDrainIndex: 0,\n pendingRequests: new Map(),\n }\n this.pageLogBuffers.set(page, buffers)\n\n if (this.logCaptureConfig.console) {\n page.on('console', (msg) => {\n buffers.consoleLogs.push({\n level: msg.type(),\n text: msg.text(),\n location: msg.location(),\n timestamp: Date.now(),\n })\n if (buffers.consoleLogs.length > 1000) {\n buffers.consoleLogs = buffers.consoleLogs.slice(-500)\n }\n })\n }\n\n if (this.logCaptureConfig.network) {\n page.on('request', (request) => {\n buffers.pendingRequests.set(request.url() + request.method(), {\n url: request.url(),\n method: request.method(),\n headers: request.headers(),\n startTime: Date.now(),\n postData: request.postData() ?? undefined,\n })\n })\n\n page.on('response', async (response) => {\n const key = response.url() + response.request().method()\n const pending = buffers.pendingRequests.get(key)\n buffers.pendingRequests.delete(key)\n\n let body: string | undefined\n try {\n const buf = await response.body()\n const ct = response.headers()['content-type'] ?? ''\n if (ct.includes('image/') && !ct.includes('svg')) {\n body = buf.length > 32768 ? undefined : `data:${ct.split(';')[0]};base64,${buf.toString('base64')}`\n } else {\n const text = buf.toString('utf-8')\n body = text.length > 32768 ? text.slice(0, 32768) + '...[truncated]' : text\n }\n } catch {\n body = undefined\n }\n\n buffers.networkLogs.push({\n url: response.url(),\n method: response.request().method(),\n status: response.status(),\n requestHeaders: pending?.headers ?? response.request().headers(),\n responseHeaders: response.headers(),\n body,\n requestBody: pending?.postData,\n startTime: pending?.startTime ?? Date.now(),\n endTime: Date.now(),\n timing: response.request().timing(),\n })\n if (buffers.networkLogs.length > 500) {\n buffers.networkLogs = buffers.networkLogs.slice(-250)\n }\n })\n }\n }\n\n private async resolveTabTargetAsync(tab: { index?: number; title?: string; url?: string }): Promise<Page | undefined> {\n const pages = this.context!.pages()\n if (tab.index !== undefined) {\n return (tab.index >= 0 && tab.index < pages.length) ? pages[tab.index] : undefined\n }\n if (tab.title) {\n for (const p of pages) {\n const t = await p.title()\n if (t.includes(tab.title)) return p\n }\n return undefined\n }\n if (tab.url) {\n return pages.find(p => p.url().includes(tab.url!))\n }\n return undefined\n }\n\n private async executeAction(action: ActionsFor<'web'>): Promise<ActionResult> {\n const page = this.page!\n const resolver = new ElementResolver(page, this.lastRefs)\n\n // 438 D-07, D-09: the element each lane names must still be the one observed; anything else is\n // a typed refusal with no page interaction. A ref absent from the map keeps the Unknown ref\n // path.\n for (const ref of laneRefs(action)) {\n const entry = this.lastRefs[ref]\n if (entry === undefined) continue\n // A scroll's ref names its container, not an input target: only its document is checked,\n // and a lost or child-frame container reads unknown in the compound (436 D-25).\n const check = action.type === 'scroll'\n ? await checkDocument(page, this.epoch)\n : await checkBinding(page, this.epoch, entry, OBSERVE_SNAPSHOT)\n if (check.outcome !== 'ok') return bindingRefusal(check.outcome, ref)\n }\n\n // Validate action-element compatibility for ref-targeting actions\n if ('ref' in action && typeof (action as any).ref === 'string') {\n const refData = this.lastRefs[(action as any).ref]\n const role = refData?.role\n const validation = validateAction(action, role)\n if (!validation.valid) {\n return { success: false, error: validation.error }\n }\n }\n\n switch (action.type) {\n case 'click': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n const coordinates = box ? { x: box.x + box.width / 2, y: box.y + box.height / 2 } : undefined\n await locator.click({\n ...clickDelayOption(action.clickDelay),\n ...(this.operationCapture ? { noWaitAfter: true } : {}),\n })\n return { success: true, coordinates, boundingBox: box ?? undefined }\n }\n\n case 'fill': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n return runWebFillCompound(locator, box ?? undefined, action)\n }\n\n case 'openApp': {\n return webOpenAppError()\n }\n\n case 'select': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.selectOption(action.value)\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'navigate': {\n // Fold re-key: the schema `to` discriminant drives url/history/reload on the proven\n // legacy bodies (goto / goBack|goForward / reload).\n switch (action.to) {\n case 'url':\n await page.goto(action.url, { waitUntil: 'domcontentloaded' })\n break\n case 'back':\n await page.goBack({ waitUntil: 'domcontentloaded' })\n break\n case 'forward':\n await page.goForward({ waitUntil: 'domcontentloaded' })\n break\n case 'reload':\n await page.reload({ waitUntil: 'domcontentloaded' })\n break\n }\n await waitForPageReady(page)\n return { success: true }\n }\n\n case 'scroll': {\n return runWebScrollCompound(page, this.lastRefs, action)\n }\n\n case 'waitFor': {\n const timeout = action.timeoutMs\n try {\n switch (action.on) {\n case 'text':\n await page.getByText(action.text).first().waitFor({ state: 'visible', timeout })\n break\n case 'gone':\n await page.getByText(action.text).first().waitFor({ state: 'hidden', timeout })\n break\n case 'selector':\n await page.waitForSelector(action.selector, { timeout })\n break\n }\n } catch {\n const what = action.on === 'selector' ? `selector \"${action.selector}\"` : `text \"${action.text}\"`\n const how = action.on === 'gone' ? 'was still present after' : 'did not appear within'\n return { success: false, error: `waitFor: ${what} ${how} ${timeout}ms.` }\n }\n return { success: true }\n }\n\n case 'delay': {\n await page.waitForTimeout(action.ms)\n return { success: true }\n }\n\n case 'waitForUrl': {\n try {\n // Explicit 30s timeout overrides Playwright's infinite default (Pitfall 2)\n await page.waitForURL(action.pattern, { timeout: 30_000 })\n return { success: true }\n } catch (err) {\n return {\n success: false,\n error: `URL pattern \"${action.pattern}\" did not match within 30s. Hint: use \"**\" wildcards for substring matching (e.g., \"**/dashboard**\"). ${err instanceof Error ? err.message : String(err)}`,\n }\n }\n }\n\n case 'keypress': {\n // Fold re-key of keyDown/keyUp: the schema `mode` selects press / down / up on the\n // platform-normalized keys.\n const effectiveKeys = convertKeysForPlatform(action.keys, {\n enabled: action.convertPlatformKeys !== false,\n isMac: isMacPlatform(),\n })\n for (const key of effectiveKeys) {\n if (action.mode === 'down') {\n await page.keyboard.down(key)\n } else if (action.mode === 'up') {\n await page.keyboard.up(key)\n } else {\n await page.keyboard.press(key)\n }\n }\n return { success: true }\n }\n\n case 'hover': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.hover()\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'paste': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.focus()\n await page.evaluate(`(() => {\n const el = document.activeElement;\n if (!el) return;\n const dt = new DataTransfer();\n dt.setData('text/plain', ${JSON.stringify(action.value)});\n el.dispatchEvent(new ClipboardEvent('paste', {\n clipboardData: dt,\n bubbles: true,\n cancelable: true,\n }));\n })()`)\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'fileUpload': {\n // Paths are pre-resolved to absolute by runner loop.ts (see Plan 01 Task 2)\n const { existsSync } = await import('node:fs')\n for (const filePath of action.files) {\n if (!existsSync(filePath)) {\n return { success: false, error: `File not found: ${filePath}` }\n }\n }\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.setInputFiles(action.files)\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'copy': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n const text = (await locator.textContent()) ?? ''\n await page.evaluate(`navigator.clipboard.writeText(${JSON.stringify(text)})`)\n return { success: true, boundingBox: box ?? undefined, data: { copied: text } }\n }\n\n case 'tab': {\n // Fold re-key of newTab/switchTab: `action` discriminant selects open-new vs switch.\n if (action.action === 'new') {\n const newPage = await this.context!.newPage()\n this.attachLogListeners(newPage)\n await newPage.goto(action.url, { waitUntil: 'domcontentloaded' })\n await waitForPageReady(newPage)\n this.setActivePage(newPage)\n return { success: true }\n }\n const pages = this.context!.pages()\n let target: Page | undefined\n if (action.index !== undefined) {\n if (action.index < 0 || action.index >= pages.length) {\n return { success: false, error: `Tab index ${action.index} out of range (${pages.length} tabs open)` }\n }\n target = pages[action.index]\n } else if (action.title !== undefined) {\n for (const p of pages) {\n const t = await p.title()\n if (t.includes(action.title)) { target = p; break }\n }\n } else if (action.url !== undefined) {\n target = pages.find(p => p.url().includes(action.url!))\n }\n if (!target) {\n return { success: false, error: `No tab found matching ${JSON.stringify({ index: action.index, title: action.title, url: action.url })}` }\n }\n this.setActivePage(target)\n return { success: true }\n }\n\n case 'inspect': {\n // Fold re-key of the four read* verbs; output rides ActionResult.data through the\n // existing guardActionData/guardBlob compaction path (no new compaction).\n switch (action.what) {\n case 'console': {\n let entries: ConsoleLogEntry[]\n if (action.tab) {\n const targetPage = await this.resolveTabTargetAsync(action.tab)\n if (!targetPage) {\n return { success: false, error: `No tab found matching ${JSON.stringify(action.tab)}` }\n }\n const buffers = this.pageLogBuffers.get(targetPage)\n entries = buffers ? [...buffers.consoleLogs] : []\n } else {\n entries = []\n for (const buffers of this.pageLogBuffers.values()) {\n entries.push(...buffers.consoleLogs)\n }\n }\n if (action.level) {\n entries = entries.filter(e => e.level === action.level)\n }\n return { success: true, data: entries }\n }\n case 'network': {\n let entries: NetworkLogEntry[]\n if (action.tab) {\n const targetPage = await this.resolveTabTargetAsync(action.tab)\n if (!targetPage) {\n return { success: false, error: `No tab found matching ${JSON.stringify(action.tab)}` }\n }\n const buffers = this.pageLogBuffers.get(targetPage)\n entries = buffers ? [...buffers.networkLogs] : []\n } else {\n entries = []\n for (const buffers of this.pageLogBuffers.values()) {\n entries.push(...buffers.networkLogs)\n }\n }\n if (action.urlPattern) {\n entries = entries.filter(e => e.url.includes(action.urlPattern!))\n }\n return { success: true, data: entries }\n }\n case 'cookies': {\n const cookies = await this.context!.cookies()\n if (action.name) {\n const cookie = cookies.find(c => c.name === action.name) ?? null\n return { success: true, data: cookie }\n }\n return { success: true, data: cookies }\n }\n case 'localStorage': {\n const pageUrl = page.url()\n if (pageUrl === 'about:blank') {\n return { success: true, data: action.key ? null : {} }\n }\n if (action.key) {\n const value = await page.evaluate(\n (k: string) => localStorage.getItem(k), action.key\n )\n return { success: true, data: value }\n }\n const all = await page.evaluate(\n () => Object.fromEntries(\n Object.keys(localStorage).map(k => [k, localStorage.getItem(k)])\n )\n )\n return { success: true, data: all }\n }\n }\n return { success: true }\n }\n\n case 'setCookies': {\n const cookiesWithDefaults = action.cookies.map(c => ({\n ...c,\n url: !c.domain ? page.url() : undefined,\n }))\n await this.context!.addCookies(cookiesWithDefaults)\n return { success: true }\n }\n\n case 'setLocalStorage': {\n await page.evaluate((entries: Array<{ key: string; value: string }>) => {\n for (const { key, value } of entries) {\n localStorage.setItem(key, value)\n }\n }, action.entries)\n return { success: true }\n }\n\n case 'focus': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.focus()\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'assertValue': {\n // D-10: the adapter RESOLVES the requested source to a raw value on ActionResult.data;\n // the runner-side comparator applies the op and judges. The adapter never compares.\n let value: unknown\n if ('expr' in action) {\n value = await page.evaluate(action.expr)\n } else {\n switch (action.source) {\n case 'url':\n value = page.url()\n break\n case 'storage':\n value = page.url() === 'about:blank'\n ? {}\n : await page.evaluate(\n () => Object.fromEntries(\n Object.keys(localStorage).map(k => [k, localStorage.getItem(k)])\n )\n )\n break\n case 'network':\n value = this.peekNetworkLogs()\n break\n case 'expr-result':\n value = undefined\n break\n }\n }\n return { success: true, data: value }\n }\n\n case 'clearText': {\n const loc = resolver.resolve(action.ref)\n const clearBox = await resolver.getBoundingBox(action.ref)\n await loc.clear()\n return { success: true, boundingBox: clearBox ?? undefined }\n }\n\n case 'doubleClick': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n const coordinates = box\n ? action.relativePosition\n ? { x: box.x + action.relativePosition.x, y: box.y + action.relativePosition.y }\n : { x: box.x + box.width / 2, y: box.y + box.height / 2 }\n : undefined\n await locator.dblclick({\n ...(action.relativePosition && { position: action.relativePosition }),\n ...clickDelayOption(action.clickDelay),\n })\n return { success: true, coordinates, boundingBox: box ?? undefined }\n }\n\n case 'rightClick': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n const coordinates = box\n ? action.relativePosition\n ? { x: box.x + action.relativePosition.x, y: box.y + action.relativePosition.y }\n : { x: box.x + box.width / 2, y: box.y + box.height / 2 }\n : undefined\n await locator.click({\n button: 'right',\n ...(action.relativePosition && { position: action.relativePosition }),\n ...clickDelayOption(action.clickDelay),\n })\n return { success: true, coordinates, boundingBox: box ?? undefined }\n }\n\n case 'route': {\n // D-18: persistent interception until an explicit unroute or teardown. Planner-authored\n // status/headers/body fulfil the matched request (a mocked response body crosses into\n // page context — declared destructive in the risk metadata, Plan 09).\n await this.context!.route(action.urlPattern, async (route) => {\n await route.fulfill({\n status: 200,\n ...(action.contentType !== undefined ? { contentType: action.contentType } : {}),\n ...(action.headers !== undefined ? { headers: action.headers } : {}),\n ...(action.body !== undefined ? { body: action.body } : {}),\n })\n })\n this.armedRoutes.add(action.urlPattern)\n return { success: true }\n }\n\n case 'unroute': {\n if (action.urlPattern !== undefined) {\n await this.context!.unroute(action.urlPattern)\n this.armedRoutes.delete(action.urlPattern)\n } else {\n await this.context!.unrouteAll({ behavior: 'ignoreErrors' })\n this.armedRoutes.clear()\n }\n return { success: true }\n }\n\n case 'networkState': {\n if (action.mode === 'offline') {\n await this.context!.setOffline(true)\n return { success: true }\n }\n // throttle: Chromium-only via CDP; non-Chromium contexts reject newCDPSession (D-18).\n try {\n const cdp = await this.context!.newCDPSession(page)\n await cdp.send('Network.emulateNetworkConditions', {\n offline: false,\n latency: action.latencyMs,\n downloadThroughput: (action.downloadKbps * 1000) / 8,\n uploadThroughput: (action.uploadKbps * 1000) / 8,\n })\n return { success: true }\n } catch (err) {\n return {\n success: false,\n error: `Network throttling is only available on Chromium (via CDP); this context does not support it. ${err instanceof Error ? err.message : String(err)}`,\n }\n }\n }\n\n case 'storageState': {\n // D-14: the adapter only PRODUCES/CONSUMES the raw blob. On save it returns the state +\n // name (the Plan 10 seam strips + persists it — never fs here); on restore it applies the\n // seam-injected blob via setStorageState (present in pinned 1.59.1 — never hand-rolled).\n if (action.op === 'save') {\n const state = await this.context!.storageState()\n return { success: true, data: { name: action.name, state } }\n }\n await this.context!.setStorageState(readSeamStorageState(action))\n return { success: true }\n }\n\n case 'handleDialog': {\n // D-12: one-shot arm for the NEXT dialog; a re-arm REPLACES the pending arm (never stacks).\n if (this.pendingDialogArm) {\n page.off('dialog', this.pendingDialogArm)\n this.pendingDialogArm = null\n }\n const accept = action.accept\n const promptText = action.promptText\n const handler = (dialog: Dialog): void => {\n this.pendingDialogArm = null\n if (accept) {\n void dialog.accept(promptText)\n } else {\n void dialog.dismiss()\n }\n }\n this.pendingDialogArm = handler\n page.once('dialog', handler)\n return { success: true }\n }\n\n case 'executeScript': {\n return { success: false, error: 'executeScript is a mobile-only action' }\n }\n\n // Runner-minted / author-channel verbs (D-01/D-15/D-16): reportValue, uniqueValue, assertAI,\n // extractAI, and setVariable are intercepted at the dispatch seam and never reach the adapter.\n // A grouped §7.1 defensive case surfaces a dispatch-routing error if one arrives here;\n // assertNever remains the backstop for a genuinely unknown schema verb.\n case 'reportValue':\n case 'uniqueValue':\n case 'assertAI':\n case 'extractAI':\n case 'setVariable':\n return {\n success: false,\n error: `Action \"${action.type}\" is handled by the runner dispatch seam and must not reach the web adapter (runner-minted/author-channel verb). This indicates a dispatch routing error.`,\n }\n\n default:\n return assertNever(action)\n }\n }\n}\n","import type { Page } from 'playwright-core'\nimport type { ScreenState, ElementState, ElementLabels } from '@vostride/agent-qa-schema'\nimport { buildScreenState, type InterimNode } from '@vostride/agent-qa-runner'\nimport { extractDom } from './dom-extractor.js'\n\nconst INTERACTIVE_ROLES = new Set([\n 'button', 'link', 'textbox', 'checkbox', 'radio', 'combobox', 'listbox',\n 'menuitem', 'menuitemradio', 'menuitemcheckbox', 'option',\n 'searchbox', 'slider', 'spinbutton', 'switch', 'tab', 'treeitem',\n // WAI-ARIA 1.2 standalone widget roles\n 'gridcell', 'scrollbar', 'separator',\n // WAI-ARIA 1.2 composite widget roles (interactive containers)\n 'grid', 'menu', 'menubar', 'tree', 'treegrid',\n])\n\n// 439 D-16: 'dialog' and 'alertdialog' are kept so an open dialog is on the screen the judge reads.\nconst CONTENT_ROLES = new Set([\n 'heading', 'cell', 'listitem', 'article', 'region', 'navigation',\n 'progressbar', 'tabpanel', 'row', 'dialog', 'alertdialog',\n])\n\nconst LIMIT_KEYS = ['valuenow', 'valuemin', 'valuemax'] as const\n\nconst LINE_PATTERN = /^(\\s*-\\s*)(\\w+)(?:\\s+\"([^\"]*)\")?(.*)$/\n// Playwright wraps ARIA entries in single quotes when element names contain\n// colons or other characters that are ambiguous in its snapshot format.\n// e.g. - 'button \"Spoken Language: Any\"'\nconst QUOTED_LINE_PATTERN = /^(\\s*-\\s*)'(\\w+)(?:\\s+\"([^\"]*)\")?(.*)'\\s*$/\n// Playwright's ai-mode snapshot annotates each element with a native reference,\n// e.g. `- button \"Login\" [ref=e5]`. These refs are adapter-PRIVATE handles for\n// aria-ref locators; they are NEVER copied into the node identity (D-03).\nconst REF_ANNOTATION = /\\[ref=([A-Za-z0-9_-]+)\\]/\nconst BRACKET_ATTR = /\\[(\\w+)(?:=([^\\]]*))?\\]/g\n// The inline text after a line's bracket annotations: `- paragraph [ref=e7]: 7 Elm Street`.\nconst INLINE_TEXT = /^(?:\\s*\\[[^\\]]*\\])*\\s*:\\s*(.*)$/\n\nfunction inlineText(suffix: string | undefined): string | undefined {\n const raw = suffix?.match(INLINE_TEXT)?.[1]?.trim()\n if (!raw) return undefined\n if (raw.length >= 2 && raw.startsWith('\"') && raw.endsWith('\"')) {\n try {\n const parsed: unknown = JSON.parse(raw)\n if (typeof parsed === 'string') return parsed\n } catch {\n return raw.slice(1, -1)\n }\n }\n return raw\n}\n\nfunction appendText(node: InterimNode, text: string | undefined): void {\n const tidy = text?.replace(/\\s+/g, ' ').trim()\n if (!tidy) return\n node.text = node.text === undefined ? tidy : `${node.text} ${tidy}`\n}\n\n/**\n * Parse a Playwright ARIA snapshot into platform-neutral runner interim nodes.\n *\n * Emits nodes in document order with role/name/attributes and a `parentIndex`\n * derived from indentation depth: the nearest kept entry among the line's true\n * ancestors; a dropped line still bounds its subtree (438 gap round, CR-02). A line\n * whose role is not kept never becomes a node: its quoted name and inline text fold\n * into the nearest kept entry among the line's true ancestors (438 D-02, the row\n * text), and a kept content line's own inline text becomes its `text`. Playwright\n * ai-mode `[ref=eN]` annotations are captured into an index-aligned `nativeRefs`\n * array (adapter-private native handles) and are never written into the node. Accepts both ai-mode (annotated) and default-mode\n * (unannotated) snapshot text.\n *\n * No ref minting and no tree rendering happen here — the shared runner builder\n * owns both (D-01/D-02/D-03).\n */\nexport function parseAriaSnapshot(ariaTree: string): {\n nodes: InterimNode[]\n nativeRefs: (string | undefined)[]\n} {\n const lines = ariaTree.split('\\n')\n const nodes: InterimNode[] = []\n const nativeRefs: (string | undefined)[] = []\n // Every matched line's depth; `index` (into the FILTERED nodes array) only on kept lines.\n const ancestors: Array<{ depth: number; index?: number }> = []\n\n for (const line of lines) {\n const match = line.match(LINE_PATTERN) || line.match(QUOTED_LINE_PATTERN)\n if (!match) continue\n\n const [, , role, name, suffix] = match\n const roleLower = role.toLowerCase()\n\n // Indentation depth: Playwright indents snapshot children by 2 spaces per level.\n const leadingSpaces = line.length - line.trimStart().length\n const depth = Math.floor(leadingSpaces / 2)\n\n while (ancestors.length > 0 && ancestors[ancestors.length - 1].depth >= depth) {\n ancestors.pop()\n }\n let keptAncestor: number | undefined\n for (let k = ancestors.length - 1; k >= 0; k--) {\n if (ancestors[k].index !== undefined) {\n keptAncestor = ancestors[k].index\n break\n }\n }\n\n if (!INTERACTIVE_ROLES.has(roleLower) && !CONTENT_ROLES.has(roleLower)) {\n if (keptAncestor !== undefined) {\n appendText(nodes[keptAncestor], name)\n appendText(nodes[keptAncestor], inlineText(suffix))\n }\n ancestors.push({ depth })\n continue\n }\n\n const parentIndex = keptAncestor\n\n // Capture the adapter-private native ref (ai-mode) — never copied into the node.\n const refMatch = suffix?.match(REF_ANNOTATION)\n const nativeRef = refMatch ? refMatch[1] : undefined\n\n // Remaining bracket annotations become the raw attribute bag (ref excluded).\n const attributes: Record<string, string> = {}\n if (suffix) {\n for (const am of suffix.matchAll(BRACKET_ATTR)) {\n if (am[1] === 'ref') continue\n attributes[am[1]] = am[2] ?? 'true'\n }\n }\n\n const node: InterimNode = { role: roleLower }\n if (name) node.name = name\n if (parentIndex !== undefined) node.parentIndex = parentIndex\n if (Object.keys(attributes).length > 0) node.attributes = attributes\n // Only signals actually present in the snapshot text populate state; the\n // builder derives all defaults. A [disabled] annotation is the only state\n // signal the default snapshot text carries.\n if ('disabled' in attributes) node.state = { enabled: false }\n // A control's inline text is its value (a password field's included), never static text.\n if (CONTENT_ROLES.has(roleLower)) appendText(node, inlineText(suffix))\n\n const index = nodes.length\n nodes.push(node)\n nativeRefs.push(nativeRef)\n ancestors.push({ depth, index })\n }\n\n return { nodes, nativeRefs }\n}\n\n// Browser-context functions use (globalThis as any) to access document\n// because the Node tsconfig has no DOM lib — these functions serialize and run in browser\nfunction hideAgentQaElements() {\n const doc = (globalThis as any).document\n doc.querySelectorAll('[data-agent-qa-internal]').forEach((el: any) => {\n el.style.display = 'none'\n el.setAttribute('aria-hidden', 'true')\n })\n}\n\nfunction restoreAgentQaElements() {\n const doc = (globalThis as any).document\n doc.querySelectorAll('[data-agent-qa-internal]').forEach((el: any) => {\n el.style.display = ''\n el.removeAttribute('aria-hidden')\n })\n}\n\n/**\n * Capture exact web scroll state (Pitfall #2 / D-10). Web scroll is precise:\n * real `window.scrollX/Y` offsets and `document.documentElement.scrollWidth/Height`\n * content size — never hardcoded zeros. Best-effort: on failure it degrades to the\n * Playwright viewport size and zero scroll rather than throwing.\n */\nexport async function captureWebScroll(page: Page): Promise<{\n viewport: { width: number; height: number }\n scroll: { offsetX: number; offsetY: number; contentWidth: number; contentHeight: number }\n}> {\n const fallbackViewport = page.viewportSize() ?? { width: 0, height: 0 }\n try {\n const raw = await page.evaluate(() => {\n const w = globalThis as any\n const docEl = w.document.documentElement\n return {\n width: w.innerWidth,\n height: w.innerHeight,\n offsetX: w.scrollX,\n offsetY: w.scrollY,\n contentWidth: docEl.scrollWidth,\n contentHeight: docEl.scrollHeight,\n }\n })\n if (raw && typeof raw === 'object') {\n return {\n viewport: {\n width: numberOr(raw.width, fallbackViewport.width),\n height: numberOr(raw.height, fallbackViewport.height),\n },\n scroll: {\n offsetX: numberOr(raw.offsetX, 0),\n offsetY: numberOr(raw.offsetY, 0),\n contentWidth: numberOr(raw.contentWidth, 0),\n contentHeight: numberOr(raw.contentHeight, 0),\n },\n }\n }\n } catch {\n // Scroll capture is best-effort — never block observation.\n }\n return {\n viewport: fallbackViewport,\n scroll: { offsetX: 0, offsetY: 0, contentWidth: 0, contentHeight: 0 },\n }\n}\n\n/**\n * Resolve exact per-element geometry, state, and labels through Playwright\n * `aria-ref=` locators (the engine's own ground truth) instead of the removed\n * in-page inferred-role heuristic. The ai-mode native refs stay adapter-private\n * handles; builder-minted refs remain the only public identity (D-03).\n *\n * Enrichment mutates the interim nodes in place and is best-effort: a node whose\n * ref fails to resolve (or has no ref) keeps `bounds` absent — the builder's\n * geometry rule turns that into no refMap entry, never zero-geometry fabrication\n * (D-08, Pitfall #3). Enrichment failure degrades to unenriched nodes; it never\n * throws out of observation.\n */\nexport async function enrichWebNodes(\n page: Page,\n nodes: InterimNode[],\n nativeRefs: (string | undefined)[],\n): Promise<void> {\n try {\n // Resolve element handles for nodes that carry a native ref.\n const handles: unknown[] = []\n const targetIndices: number[] = []\n for (let i = 0; i < nodes.length; i++) {\n const ref = nativeRefs[i]\n if (!ref) continue\n try {\n const handle = await page.locator('aria-ref=' + ref).elementHandle()\n if (handle) {\n handles.push(handle)\n targetIndices.push(i)\n }\n } catch {\n // Unresolved ref → node keeps bounds absent (honest absence).\n }\n }\n if (handles.length === 0) return\n\n // One batched page.evaluate reads bounds/state/labels for every resolved handle.\n const raw = await page.evaluate((els: any[]) => {\n const w = globalThis as any\n const active = w.document.activeElement\n return els.map((el: any) => {\n if (!el) return null\n const rect = typeof el.getBoundingClientRect === 'function'\n ? el.getBoundingClientRect()\n : null\n const style = typeof w.getComputedStyle === 'function' ? w.getComputedStyle(el) : null\n const hidden = style\n ? style.visibility === 'hidden' || style.display === 'none'\n : false\n const hasBox = !!rect && rect.width > 0 && rect.height > 0\n const disabled =\n el.disabled === true ||\n (typeof el.hasAttribute === 'function' && el.hasAttribute('disabled')) ||\n (typeof el.getAttribute === 'function' && el.getAttribute('aria-disabled') === 'true')\n const attr = (n: string) =>\n typeof el.getAttribute === 'function' ? el.getAttribute(n) : null\n const inputType = el.tagName === 'INPUT' && typeof el.type === 'string' ? el.type : ''\n const isRange = inputType === 'range'\n const isNumber = inputType === 'number'\n return {\n bounds: rect\n ? { x: rect.x, y: rect.y, width: rect.width, height: rect.height }\n : null,\n enabled: !disabled,\n focused: el === active,\n visible: hasBox && !hidden,\n testId: attr('data-testid'),\n ariaLabel: attr('aria-label'),\n placeholder: attr('placeholder'),\n title: attr('title'),\n valuenow: attr('aria-valuenow') ?? (isRange || isNumber ? String(el.value) : null),\n valuemin: attr('aria-valuemin') ?? (isRange ? el.min || '0' : isNumber ? el.min || null : null),\n valuemax: attr('aria-valuemax') ?? (isRange ? el.max || '100' : isNumber ? el.max || null : null),\n }\n })\n }, handles)\n\n if (!Array.isArray(raw)) return\n\n // Coerce untrusted evaluate results to expected primitives before writing them\n // into the interim nodes (T-352-05): numbers for geometry, strings for labels;\n // malformed entries degrade to absent fields.\n for (let k = 0; k < targetIndices.length; k++) {\n const info = raw[k]\n if (!info || typeof info !== 'object') continue\n const node = nodes[targetIndices[k]]\n\n const bounds = coerceBounds((info as any).bounds)\n if (bounds) node.bounds = bounds\n\n const state: Partial<ElementState> = { ...(node.state ?? {}) }\n if (typeof (info as any).enabled === 'boolean') state.enabled = (info as any).enabled\n if (typeof (info as any).focused === 'boolean') state.focused = (info as any).focused\n if (typeof (info as any).visible === 'boolean') state.visible = (info as any).visible\n if (Object.keys(state).length > 0) node.state = state\n\n const labels: ElementLabels = { ...(node.labels ?? {}) }\n const testId = coerceString((info as any).testId)\n if (testId) labels.testId = testId\n const ariaLabel = coerceString((info as any).ariaLabel)\n if (ariaLabel) labels.ariaLabel = ariaLabel\n const placeholder = coerceString((info as any).placeholder)\n if (placeholder) labels.placeholder = placeholder\n const title = coerceString((info as any).title)\n if (title) labels.title = title\n if (Object.keys(labels).length > 0) node.labels = labels\n\n // 439 D-16: a control's reported value and limits; attributes are neither hashed nor rendered.\n const limits: Record<string, string> = {}\n for (const key of LIMIT_KEYS) {\n const value = coerceString((info as any)[key])\n if (value) limits[key] = value\n }\n if (Object.keys(limits).length > 0) node.attributes = { ...(node.attributes ?? {}), ...limits }\n }\n } catch {\n // Enrichment is best-effort — degrade to unenriched nodes, never throw.\n }\n}\n\nfunction coerceBounds(\n value: unknown,\n): { x: number; y: number; width: number; height: number } | undefined {\n if (!value || typeof value !== 'object') return undefined\n const v = value as Record<string, unknown>\n const x = v.x, y = v.y, width = v.width, height = v.height\n if (\n typeof x === 'number' && Number.isFinite(x) &&\n typeof y === 'number' && Number.isFinite(y) &&\n typeof width === 'number' && Number.isFinite(width) &&\n typeof height === 'number' && Number.isFinite(height)\n ) {\n return { x, y, width, height }\n }\n return undefined\n}\n\nfunction coerceString(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined\n}\n\nexport async function observePage(\n page: Page,\n options?: { filterSelector?: string; extractDom?: boolean },\n): Promise<ScreenState> {\n const locator = options?.filterSelector\n ? page.locator(options.filterSelector)\n : page.locator(':root')\n\n // Hide framework-injected elements from ARIA snapshot\n await page.evaluate(hideAgentQaElements)\n\n let ariaTree: string\n try {\n ariaTree = await locator.ariaSnapshot()\n } finally {\n // Restore framework-injected elements (always, even if snapshot fails)\n await page.evaluate(restoreAgentQaElements)\n }\n\n const timestamp = Date.now()\n const url = page.url()\n\n // Web scroll + viewport are EXACT (D-10, Pitfall #2).\n const { viewport: capturedViewport, scroll } = await captureWebScroll(page)\n\n let domContext: string | undefined\n if (options?.extractDom) {\n try {\n domContext = await extractDom(page)\n } catch {\n // DOM extraction is best-effort\n }\n }\n\n const { nodes, nativeRefs } = ariaTree\n ? parseAriaSnapshot(ariaTree)\n : { nodes: [] as InterimNode[], nativeRefs: [] as (string | undefined)[] }\n\n // Exact per-element enrichment via aria-ref locators (honest-absence fallback).\n if (nodes.length > 0) {\n await enrichWebNodes(page, nodes, nativeRefs)\n }\n\n const { state } = buildScreenState({\n platform: 'web',\n nodes,\n viewport: capturedViewport,\n scroll,\n coordSpace: 'viewport',\n timestamp,\n url,\n ...(domContext ? { domContext } : {}),\n })\n\n return state\n}\n\n/** Coerce an untrusted value to a finite number, falling back when malformed. */\nfunction numberOr(value: unknown, fallback: number): number {\n return typeof value === 'number' && Number.isFinite(value) ? value : fallback\n}\n","import type { Page } from 'playwright-core'\n\nconst SKIP_TAGS = new Set([\n 'SCRIPT', 'STYLE', 'SVG', 'NOSCRIPT', 'LINK', 'META',\n 'TEMPLATE', 'IFRAME',\n])\n\n// Browser-context functions use (globalThis as any) to access document\n// because the Node tsconfig has no DOM lib — these functions serialize and run in browser\nexport function extractDomTree(opts: { maxDepth: number; maxTextLen: number }): string {\n const { maxDepth, maxTextLen } = opts\n const doc = (globalThis as any).document\n const win = (globalThis as any).window\n const lines: string[] = []\n\n function isHidden(el: any): boolean {\n if (!el.offsetParent && el.tagName !== 'BODY' && el.tagName !== 'HTML') {\n const style = win.getComputedStyle(el)\n if (style.display === 'none' || style.visibility === 'hidden') return true\n }\n return false\n }\n\n function walk(node: any, depth: number, indent: string): void {\n if (depth > maxDepth) {\n lines.push(indent + '[... deeper content truncated]')\n return\n }\n\n for (let child = node.firstChild; child; child = child.nextSibling) {\n if (child.nodeType === 3) {\n const text = child.textContent.trim()\n if (text) {\n const truncated = text.length > maxTextLen\n ? text.slice(0, maxTextLen) + '...'\n : text\n lines.push(indent + truncated)\n }\n continue\n }\n\n if (child.nodeType !== 1) continue\n\n const tag = child.tagName\n if (SKIP_TAGS.has(tag)) continue\n if (isHidden(child)) continue\n\n const isCustom = tag.toLowerCase().includes('-')\n const annotation = child.getAttribute('aria-label')\n || child.getAttribute('role')\n || ''\n\n let label = tag.toLowerCase()\n if (isCustom) {\n if (!child.shadowRoot && !child.firstChild) {\n label += ' (custom element, closed shadow root)'\n } else {\n label += ' (custom element)'\n }\n }\n if (annotation) label += ` [${annotation}]`\n\n lines.push(indent + label)\n\n if (child.shadowRoot) {\n lines.push(indent + ' #shadow-root')\n walk(child.shadowRoot, depth + 1, indent + ' ')\n }\n\n walk(child, depth + 1, indent + ' ')\n }\n }\n\n walk(doc.body, 0, '')\n return lines.join('\\n')\n}\n\nexport interface ExtractDomOptions {\n maxDepth?: number\n maxTextLen?: number\n}\n\nexport async function extractDom(\n page: Page,\n opts?: ExtractDomOptions,\n): Promise<string | undefined> {\n const maxDepth = opts?.maxDepth ?? 20\n const maxTextLen = opts?.maxTextLen ?? 200\n\n try {\n return await page.evaluate(extractDomTree, { maxDepth, maxTextLen })\n } catch {\n return undefined\n }\n}\n","import type { Page, Locator } from 'playwright-core'\nimport type { Action, InterimNode, RefBinding } from '@vostride/agent-qa-runner'\nimport { rowTextOf } from '@vostride/agent-qa-runner'\nimport type { ElementInfo, Ref } from '@vostride/agent-qa-schema'\nimport type { RefMap } from './types.js'\n\nconst ACTIONS_WITHOUT_REF = new Set(['navigate', 'waitFor', 'delay', 'waitForUrl', 'assertValue'])\n\n/**\n * The adapter-private native binding of an observation (438 D-06). Each builder ref whose node\n * carried a Playwright ai-mode ref keeps that native ref plus the observed role, exact name and\n * row text; a node without one gets no entry. `elements` is the built state's element list, index\n * aligned with `nodes`.\n */\nexport function buildRefMap(\n binding: Record<Ref, RefBinding>,\n nodes: InterimNode[],\n nativeRefs: (string | undefined)[],\n elements: readonly ElementInfo[],\n): RefMap {\n const refs: RefMap = {}\n for (const [ref, bind] of Object.entries(binding)) {\n const node = nodes[bind.index]\n const nativeRef = nativeRefs[bind.index]\n const element = elements[bind.index]\n if (!node || nativeRef === undefined || !element) continue\n const entry: RefMap[string] = { nativeRef, role: node.role, name: node.name ?? '' }\n const rowText = rowTextOf(element, elements)\n if (rowText !== undefined) entry.rowText = rowText\n if (node.bounds !== undefined) entry.bounds = node.bounds\n refs[ref] = entry\n }\n return refs\n}\n\n/** Resolves a ref to the aria-ref locator of the element observed under it; never by position. */\nexport class ElementResolver {\n constructor(\n private page: Page,\n private refs: RefMap,\n ) {}\n\n resolve(ref: string): Locator {\n const data = this.refs[ref]\n if (!data) {\n throw new Error(`Unknown ref \"${ref}\". Available refs: ${Object.keys(this.refs).join(', ') || 'none'}`)\n }\n return this.page.locator('aria-ref=' + data.nativeRef)\n }\n\n resolveAction(action: Action): Locator | null {\n if (ACTIONS_WITHOUT_REF.has(action.type)) {\n return null\n }\n\n if ('ref' in action && typeof action.ref === 'string') {\n return this.resolve(action.ref)\n }\n\n return null\n }\n\n async getBoundingBox(ref: string): Promise<{ x: number; y: number; width: number; height: number } | null> {\n try {\n const locator = this.resolve(ref)\n return await locator.boundingBox()\n } catch {\n return null\n }\n }\n}\n","// The web native binding (438 D-06, D-07, D-09). Each observed ref keeps Playwright's native\n// aria-ref plus the observed role, exact name and row text; the observation keeps a main-frame\n// document handle as its epoch. Before a ref-bearing dispatch the adapter re-checks the bound\n// element through one fresh `:root` ai snapshot, which also refreshes Playwright's ref map for the\n// aria-ref locator that follows. Every snapshot goes through snapshotRoot: a default-mode or\n// sub-locator snapshot would replace that map and unbind every ref (RESEARCH Pitfall 2).\n// `(globalThis as any).document` is used because the Node tsconfig carries no DOM lib; those\n// functions run in the browser.\n\nimport type { JSHandle, Page } from 'playwright-core'\nimport type { ActionResult } from '@vostride/agent-qa-runner'\nimport { buildScreenState, rowTextOf } from '@vostride/agent-qa-runner'\nimport { parseAriaSnapshot } from './observer.js'\nimport type { RefMap } from './types.js'\n\nexport type BindingOutcome =\n | 'stale-observation'\n | 'frame-detached'\n | 'binding-lost'\n | 'binding-changed'\n\nexport type BindingCheck = { outcome: 'ok' } | { outcome: BindingOutcome }\n\n/** The document an observation was taken from, on the page it was taken from. */\nexport interface ObservationEpoch {\n page: Page\n document: JSHandle\n}\n\nexport interface SnapshotRootOptions {\n /** The first attempt's bound; absent means Playwright's default and no retry. */\n timeoutMs?: number\n /** The bound of the one retry after a TimeoutError on the first attempt. */\n retryTimeoutMs?: number\n}\n\ntype BindingEntry = RefMap[string]\n\n// The action lanes that name an observed element; each is re-checked before dispatch (D-07).\nconst BINDING_LANES = ['ref', 'fromRef', 'toRef'] as const\n\nconst FRAME_REF = /^f\\d+e/\nconst INVALID_FRAME = /invalid frame/i\n\nconst WHAT_CHANGED: Record<BindingOutcome, string> = {\n 'stale-observation': 'the page holds a new document since the observation',\n 'frame-detached': 'the frame that held the observed element is gone',\n 'binding-lost': 'the observed element is no longer on the page',\n 'binding-changed': 'the observed element now has a different role, name or row',\n}\n\n// Hide framework-injected [data-agent-qa-internal] overlays from the snapshot (they would\n// otherwise get ai-mode refs and pollute the state), then restore them.\nfunction hideAgentQaElements() {\n const doc = (globalThis as any).document\n doc.querySelectorAll('[data-agent-qa-internal]').forEach((el: any) => {\n el.style.display = 'none'\n el.setAttribute('aria-hidden', 'true')\n })\n}\n\nfunction restoreAgentQaElements() {\n const doc = (globalThis as any).document\n doc.querySelectorAll('[data-agent-qa-internal]').forEach((el: any) => {\n el.style.display = ''\n el.removeAttribute('aria-hidden')\n })\n}\n\n/** The page's `:root` ai-mode snapshot with overlays hidden, always restoring them. */\nexport async function snapshotRoot(page: Page, options: SnapshotRootOptions = {}): Promise<string> {\n const { timeoutMs, retryTimeoutMs } = options\n await page.evaluate(hideAgentQaElements)\n try {\n if (timeoutMs === undefined) return await page.locator(':root').ariaSnapshot({ mode: 'ai' })\n return await page.locator(':root').ariaSnapshot({ mode: 'ai', timeout: timeoutMs })\n .catch((error: unknown) => {\n if (!(error instanceof Error && error.name === 'TimeoutError')) throw error\n return page.locator(':root').ariaSnapshot({\n mode: 'ai',\n ...(retryTimeoutMs !== undefined ? { timeout: retryTimeoutMs } : {}),\n })\n })\n } finally {\n await page.evaluate(restoreAgentQaElements)\n }\n}\n\n/** The page's current main-frame document; it is destroyed when the page loads a new one. */\nexport async function captureEpoch(page: Page): Promise<ObservationEpoch> {\n const document = await page.evaluateHandle(() => (globalThis as any).document)\n return { page, document }\n}\n\nexport async function disposeEpoch(epoch: ObservationEpoch | undefined): Promise<void> {\n try {\n await epoch?.document.dispose()\n } catch {\n // The document is already gone with its context.\n }\n}\n\n/** Whether a native ref names an element inside a child frame (`f<n>e<m>`). */\nexport function isChildFrameRef(nativeRef: string): boolean {\n return FRAME_REF.test(nativeRef)\n}\n\n/** Whether the page still holds the document the observation was taken from (D-09). */\nexport async function checkDocument(\n page: Page,\n epoch: ObservationEpoch | undefined,\n): Promise<BindingCheck> {\n if (epoch === undefined || epoch.page !== page) return { outcome: 'stale-observation' }\n try {\n const same = await epoch.document.evaluate((d) => d === (globalThis as any).document)\n return same === true ? { outcome: 'ok' } : { outcome: 'stale-observation' }\n } catch {\n return { outcome: 'stale-observation' }\n }\n}\n\nasync function frameDetached(page: Page, nativeRef: string): Promise<boolean> {\n if (!isChildFrameRef(nativeRef)) return false\n try {\n await page.locator('aria-ref=' + nativeRef).count()\n return false\n } catch (error) {\n return error instanceof Error && INVALID_FRAME.test(error.message)\n }\n}\n\nfunction tidy(text: string | undefined): string | undefined {\n return text?.replace(/\\s+/g, ' ').trim()\n}\n\n/**\n * Whether the element bound at observation is still the one the planner saw: the same document,\n * the native ref still present, and the same role, tidied exact name and row text (both rows\n * unknown counts as the same row).\n */\nexport async function checkBinding(\n page: Page,\n epoch: ObservationEpoch | undefined,\n entry: BindingEntry,\n snapshot?: SnapshotRootOptions,\n): Promise<BindingCheck> {\n const document = await checkDocument(page, epoch)\n if (document.outcome !== 'ok') return document\n\n const { nodes, nativeRefs } = parseAriaSnapshot(await snapshotRoot(page, snapshot))\n const index = nativeRefs.indexOf(entry.nativeRef)\n if (index < 0) {\n const detached = await frameDetached(page, entry.nativeRef)\n return { outcome: detached ? 'frame-detached' : 'binding-lost' }\n }\n\n const { state } = buildScreenState({\n platform: 'web',\n nodes,\n viewport: { width: 0, height: 0 },\n scroll: { offsetX: 0, offsetY: 0, contentWidth: 0, contentHeight: 0 },\n coordSpace: 'viewport',\n timestamp: 0,\n })\n const current = state.elements[index]\n if (\n current === undefined\n || current.role !== entry.role\n || tidy(current.name) !== tidy(entry.name)\n || tidy(rowTextOf(current, state.elements)) !== tidy(entry.rowText)\n ) {\n return { outcome: 'binding-changed' }\n }\n return { outcome: 'ok' }\n}\n\n/** The refs an action names in its ref, fromRef and toRef lanes, in that order. */\nexport function laneRefs(action: object): string[] {\n const refs: string[] = []\n for (const lane of BINDING_LANES) {\n const ref: unknown = Reflect.get(action, lane)\n if (typeof ref === 'string') refs.push(ref)\n }\n return refs\n}\n\n/** The typed result of a refused dispatch: nothing reached the page. */\nexport function bindingRefusal(outcome: BindingOutcome, ref: string): ActionResult {\n return {\n success: false,\n error: `${outcome}: ref ${ref} — ${WHAT_CHANGED[outcome]}; nothing was sent`,\n metadata: { binding: { outcome, ref, inputSent: false } },\n }\n}\n","import type { ActionsFor } from '@vostride/agent-qa-runner'\n\nexport type ValidationResult =\n | { valid: true }\n | { valid: false; error: string; suggestion?: string }\n\nexport class ActionValidationError extends Error {\n readonly suggestion?: string\n\n constructor(message: string, suggestion?: string) {\n super(message)\n this.name = 'ActionValidationError'\n this.suggestion = suggestion\n }\n}\n\nconst FILL_ROLES = new Set(['textbox', 'searchbox', 'spinbutton', 'combobox'])\nconst SELECT_ROLES = new Set(['listbox', 'combobox'])\n\n// Actions that don't target elements — always valid (re-keyed to the schema/folded verbs; the\n// retired verb names — assert/keyDown/keyUp/refresh/navigateHistory/read* — are gone, D-19).\nconst NO_REF_ACTIONS = new Set(['scroll', 'navigate', 'waitFor', 'delay', 'waitForUrl', 'tab', 'inspect', 'route', 'unroute', 'networkState', 'storageState', 'handleDialog', 'uniqueValue', 'assertValue', 'assertAI', 'extractAI', 'reportValue', 'setCookies', 'setLocalStorage', 'executeScript', 'setVariable'])\n\n// Actions valid for any role\nconst ANY_ROLE_ACTIONS = new Set(['click', 'hover', 'keypress', 'paste', 'doubleClick', 'rightClick', 'focus'])\n\nexport function validateAction(action: ActionsFor<'web'>, elementRole: string | undefined): ValidationResult {\n // Actions that don't require an element ref are always valid\n if (NO_REF_ACTIONS.has(action.type)) {\n return { valid: true }\n }\n\n // Actions valid for any role\n if (ANY_ROLE_ACTIONS.has(action.type)) {\n return { valid: true }\n }\n\n // Unknown or missing role — allow with permissive pass (LLM might know better)\n if (!elementRole) {\n return { valid: true }\n }\n\n const role = elementRole.toLowerCase()\n\n if (action.type === 'fill') {\n if (FILL_ROLES.has(role)) {\n return { valid: true }\n }\n if (SELECT_ROLES.has(role)) {\n return {\n valid: false,\n error: `Cannot fill() on a '${role}' element — fill is for text inputs. Try 'select' to choose an option.`,\n suggestion: 'select',\n }\n }\n return {\n valid: false,\n error: `Element ${(action as any).ref} is not fillable (role: ${role}). Use a textbox or input element instead.`,\n suggestion: 'click',\n }\n }\n\n if (action.type === 'clearText') {\n if (FILL_ROLES.has(role)) {\n return { valid: true }\n }\n return {\n valid: false,\n error: `Element ${(action as any).ref} is not fillable (role: ${role}). clearText only works on text inputs. Use a textbox or input element instead.`,\n suggestion: 'click',\n }\n }\n\n if (action.type === 'select') {\n if (SELECT_ROLES.has(role)) {\n return { valid: true }\n }\n if (FILL_ROLES.has(role)) {\n return {\n valid: false,\n error: `Cannot select() on a '${role}' element — select is for lists. Try 'fill' to type a value instead.`,\n suggestion: 'fill',\n }\n }\n return {\n valid: false,\n error: `Cannot select() on a '${role}' element — select is for list/combo elements.`,\n suggestion: 'click',\n }\n }\n\n // Unknown action type — allow (forward-compatible)\n return { valid: true }\n}\n","import type { Page } from 'playwright-core'\n\nexport interface SmartWaitOptions {\n timeout?: number\n}\n\nconst LOADING_SELECTORS = [\n '[aria-busy=\"true\"]',\n '[aria-label*=\"loading\" i]',\n '.loading', '.spinner', '.skeleton',\n '[data-loading]', '[data-testid=\"loading\"]',\n 'progress:not([value])',\n]\n\nexport async function waitForPageReady(page: Page, options?: SmartWaitOptions): Promise<void> {\n const timeout = options?.timeout ?? 10000\n\n await Promise.race([\n runReadinessChecks(page),\n new Promise<void>(resolve => setTimeout(resolve, timeout)),\n ])\n}\n\n// Browser-context functions use (globalThis as any) to access document\n// because the Node tsconfig has no DOM lib — these functions serialize and run in browser\nfunction checkLoadingIndicators(selectors: string[]): boolean {\n const doc = (globalThis as any).document\n return selectors.some((sel: string) => doc.querySelector(sel) !== null)\n}\n\nfunction checkLoadingGone(selectors: string[]): boolean {\n const doc = (globalThis as any).document\n return !selectors.some((sel: string) => doc.querySelector(sel))\n}\n\nfunction checkAnimationsRunning(): boolean {\n const doc = (globalThis as any).document\n return doc.getAnimations().filter((a: any) => a.playState === 'running').length > 0\n}\n\nfunction checkAnimationsSettled(): boolean {\n const doc = (globalThis as any).document\n return doc.getAnimations().filter((a: any) => a.playState === 'running').length === 0\n}\n\nasync function runReadinessChecks(page: Page): Promise<void> {\n // 1. Document ready\n try {\n await page.waitForLoadState('domcontentloaded', { timeout: 5000 })\n } catch {\n // Already loaded or timed out — continue\n }\n\n // 2. Network settle (best effort)\n try {\n await page.waitForLoadState('networkidle', { timeout: 5000 })\n } catch {\n // SPA with websockets or long-polling — proceed anyway\n }\n\n // 3. Loading indicators gone\n try {\n const hasIndicators = await page.evaluate(checkLoadingIndicators, LOADING_SELECTORS)\n\n if (hasIndicators) {\n try {\n await page.waitForFunction(checkLoadingGone, LOADING_SELECTORS, { timeout: 3000 })\n } catch {\n // Indicators didn't clear in 3s — proceed anyway\n }\n }\n } catch {\n // page.evaluate failed (navigation in progress, context destroyed) — continue\n }\n\n // 4. Animations settled\n try {\n const hasRunning = await page.evaluate(checkAnimationsRunning)\n\n if (hasRunning) {\n try {\n await page.waitForFunction(checkAnimationsSettled, undefined, { timeout: 2000 })\n } catch {\n // Animations didn't settle in 2s — proceed anyway\n }\n }\n } catch {\n // page.evaluate failed — continue\n }\n}\n","// Web execute() compound behaviors shared by both web execute surfaces (adapter.ts +\n// farm-adapter.ts). Phase 359 · EXEC-01/02/03 · D-05..D-09. The runner owns the pure verdict\n// machine (compareFillReread) and loop discipline (runUntilVisibleLoop / runDirectionScroll /\n// runToEndScroll over injected ScrollPrimitives); this module supplies the Playwright primitives\n// and stitches them into ONE ActionResult per compound. Extracted here (inside packages/web/src)\n// so the two adapter classes reuse one implementation instead of copy-pasting the compound.\n\nimport type { Frame, JSHandle, Locator, Page } from 'playwright-core'\nimport type { ActionResult } from '@vostride/agent-qa-runner'\nimport {\n compareFillReread,\n runUntilVisibleLoop,\n runDirectionScroll,\n runToEndScroll,\n swipeSignalFromOffsets,\n scrollerSetSwipeSignal,\n type DocumentScrollOffsets,\n type ScrollPrimitives,\n type SwipeSignal,\n type Direction,\n type TargetVisibility,\n} from '@vostride/agent-qa-runner'\nimport type { Fill, Scroll, Ref } from '@vostride/agent-qa-schema'\nimport { parseAriaSnapshot } from './observer.js'\nimport { scrollWithRef } from './scroll-helper.js'\nimport type { RefMap } from './types.js'\n\ntype BoundingBox = { x: number; y: number; width: number; height: number }\n\n// A value read of the SAME live handle. inputValue() throws for non-input/textarea/select\n// targets (Pitfall 8) — fall back to an element value/textContent evaluate; if nothing is\n// readable, return undefined so the caller degrades honestly (signal-presence law: never\n// fabricate a re-read pair).\nexport async function safeInputValue(locator: Locator): Promise<string | undefined> {\n try {\n return await locator.inputValue()\n } catch {\n try {\n const value = await locator.evaluate((el) => {\n const node = el as unknown as { value?: unknown; textContent?: unknown }\n return (node.value ?? node.textContent) as unknown\n })\n return typeof value === 'string' ? value : undefined\n } catch {\n return undefined\n }\n }\n}\n\n// EXEC-01: clear→type→RE-READ→(Enter) as one compound (D-05/D-06/D-07/D-08).\nexport async function runWebFillCompound(\n locator: Locator,\n boundingBox: BoundingBox | undefined,\n action: Pick<Fill, 'text' | 'clearMode' | 'submit'>,\n): Promise<ActionResult> {\n const isAppend = action.clearMode === 'append'\n // Prior value FIRST (append expects prior + typed, D-07) — before any typing or type probe.\n const prior = isAppend ? (await safeInputValue(locator)) ?? '' : ''\n // Secure detection is web-live: the ARIA snapshot carries no input type (Pitfall 6).\n const secure = (await locator.getAttribute('type')) === 'password'\n\n if (isAppend) {\n await locator.click()\n await locator.press('End')\n await locator.pressSequentially(action.text)\n } else {\n await locator.fill(action.text)\n }\n\n const expected = isAppend ? prior + action.text : action.text\n const actual = await safeInputValue(locator)\n const box = boundingBox ? { boundingBox } : {}\n\n // Unreadable value: success with no fillReread block and no Enter, recorded unverified (437 D-06).\n if (actual === undefined) {\n return { success: true, ...box, metadata: { fillVerdict: { verb: 'fill', verdict: 'unverified' } } }\n }\n\n const verdict = compareFillReread({ expected, actual, secure })\n if (verdict.ok && action.submit) {\n await locator.press('Enter')\n }\n const metadata = {\n ...(verdict.meta ? { fillReread: verdict.meta } : {}),\n fillVerdict: {\n verb: 'fill',\n verdict: verdict.verdict,\n ...(verdict.secure ? { secure: true } : {}),\n },\n }\n return verdict.ok\n ? { success: true, ...box, metadata }\n : { success: false, error: verdict.selfCorrectingError, ...box, metadata }\n}\n\nfunction deltaFor(direction: Direction, magnitude: number): { dx: number; dy: number; axis: 'horizontal' | 'vertical' } {\n switch (direction) {\n case 'down':\n return { dx: 0, dy: magnitude, axis: 'vertical' }\n case 'up':\n return { dx: 0, dy: -magnitude, axis: 'vertical' }\n case 'right':\n return { dx: magnitude, dy: 0, axis: 'horizontal' }\n case 'left':\n return { dx: -magnitude, dy: 0, axis: 'horizontal' }\n }\n}\n\n// rAF settle between gestures — reuses the pre-flip scroll settle discipline.\nasync function settle(page: Page): Promise<void> {\n await page.evaluate(`new Promise(resolve => {\n const t = setTimeout(() => resolve('timeout'), 500);\n requestAnimationFrame(() => requestAnimationFrame(() => {\n clearTimeout(t);\n resolve('raf');\n }));\n })`)\n}\n\ntype Axis = 'horizontal' | 'vertical'\ntype PointerChain = { before: DocumentScrollOffsets[]; after: DocumentScrollOffsets[] }\n\n// In-page, before the wheel: every element that can scroll on the swiped axis (range above 0 and\n// a scrolling overflow) plus the document scroller, mapped to its offsets, and a once-only passive\n// wheel listener on window that records the event target. The state is returned as a handle only;\n// nothing is written to window or the DOM.\nfunction snapshotScrollers(axis: Axis): unknown {\n type El = {\n scrollLeft: number\n scrollTop: number\n scrollWidth: number\n scrollHeight: number\n clientWidth: number\n clientHeight: number\n }\n const g = globalThis as unknown as {\n document: {\n scrollingElement: El | null\n documentElement: El\n body: El | null\n querySelectorAll(selector: string): ArrayLike<El>\n }\n getComputedStyle(el: El): { overflowX: string; overflowY: string }\n addEventListener(type: string, listener: (event: { target: unknown }) => void, options: object): void\n }\n const doc = g.document\n const root = doc.scrollingElement ?? doc.documentElement\n const read = (el: El) => ({\n x: el.scrollLeft,\n y: el.scrollTop,\n maxX: el.scrollWidth - el.clientWidth,\n maxY: el.scrollHeight - el.clientHeight,\n })\n const scrolls = (value: string): boolean => value === 'auto' || value === 'scroll' || value === 'overlay'\n const rootStyle = g.getComputedStyle(doc.documentElement)\n const bodyPropagates = rootStyle.overflowX === 'visible' && rootStyle.overflowY === 'visible'\n const offsets = new Map<El, ReturnType<typeof read>>()\n offsets.set(root, read(root))\n const all = doc.querySelectorAll('*')\n for (let i = 0; i < all.length; i += 1) {\n const el = all[i]\n if (el === root || el === doc.documentElement) continue\n if (el === doc.body && bodyPropagates) continue\n const o = read(el)\n if (!((axis === 'vertical' ? o.maxY : o.maxX) > 0)) continue\n const style = g.getComputedStyle(el)\n if (!scrolls(axis === 'vertical' ? style.overflowY : style.overflowX)) continue\n offsets.set(el, o)\n }\n const state: { offsets: typeof offsets; target: unknown; listener: (event: { target: unknown }) => void } = {\n offsets,\n target: null,\n listener: () => undefined,\n }\n state.listener = (event) => {\n state.target = event.target\n }\n g.addEventListener('wheel', state.listener, { capture: true, once: true, passive: true })\n return state\n}\n\n// In-page, after the wheel: the chain is the recorded target and its ancestors that were\n// snapshotted, in order, then the document scroller. Returns the aligned before/after offsets, or\n// nothing (and removes the listener) when no wheel event was observed.\nfunction readPointerChain(state: unknown): unknown {\n type El = {\n scrollLeft: number\n scrollTop: number\n scrollWidth: number\n scrollHeight: number\n clientWidth: number\n clientHeight: number\n parentElement: El | null\n }\n const g = globalThis as unknown as {\n document: { scrollingElement: El | null; documentElement: El }\n removeEventListener(type: string, listener: unknown, options: object): void\n }\n const s = state as { offsets: Map<El, unknown>; target: El | null; listener: unknown }\n if (!s.target) {\n g.removeEventListener('wheel', s.listener, { capture: true })\n return undefined\n }\n const root = g.document.scrollingElement ?? g.document.documentElement\n const chain: El[] = []\n for (let el: El | null = s.target; el; el = el.parentElement) {\n if (s.offsets.has(el) && !chain.includes(el)) chain.push(el)\n }\n if (!chain.includes(root)) chain.push(root)\n return {\n before: chain.map((el) => s.offsets.get(el)),\n after: chain.map((el) => ({\n x: el.scrollLeft,\n y: el.scrollTop,\n maxX: el.scrollWidth - el.clientWidth,\n maxY: el.scrollHeight - el.clientHeight,\n })),\n }\n}\n\n// The no-ref wheel lands on whatever is under the pointer, so it is judged by the scrollers under\n// it: the wheel event's target up to the document scroller (436-18 · D-25, review CR-02). The\n// pointer position is not readable through Playwright and a passive listener runs after the\n// compositor has scrolled, so the \"before\" offsets are a snapshot taken before the wheel and the\n// listener only names the chain. No snapshot or no observed wheel event is unknown.\nasync function wheelPointerChain(page: Page, dx: number, dy: number, axis: Axis): Promise<PointerChain | undefined> {\n let handle: JSHandle | undefined\n try {\n handle = await page.evaluateHandle(snapshotScrollers, axis)\n } catch {\n handle = undefined\n }\n await page.mouse.wheel(dx, dy)\n await settle(page)\n if (!handle) return undefined\n try {\n const chain = (await handle.evaluate(readPointerChain)) as Partial<PointerChain> | undefined\n if (!chain || typeof chain !== 'object' || !Array.isArray(chain.before) || !Array.isArray(chain.after)) {\n return undefined\n }\n return { before: chain.before, after: chain.after }\n } catch {\n return undefined\n } finally {\n await handle.dispose().catch(() => undefined)\n }\n}\n\ntype ProbeBox = { left: number; top: number; right: number; bottom: number }\ntype Judged = { state: TargetVisibility; rect?: ProbeBox }\n\n// 2026-10-08 (436-26): the longest a child frame may take to answer its liveness check (CR-08).\nexport const FRAME_PROBE_TIMEOUT_MS = 1_000\n\n// In-page judge for every candidate of one frame, in that frame's own viewport. Ancestors are\n// walked over the flat tree (assigned slot, parent element, shadow host), skipping a body whose\n// overflow propagates to the viewport. Self-contained: Playwright serializes it.\n// - hidden: computed visibility other than `visible`, opacity 0 on the element or an ancestor, a\n// non-empty own box under 2x2 CSS px, or a box outside the viewport;\n// - unknown: a box a clipping ancestor (a nested scroller the search may not have moved) empties\n// or shrinks under 2x2, or a hit test at its centre that lands on anything but the element (an\n// overlay, a point removed by clip or clip-path, an approximate clip);\n// - visible: the hit lands on the element, inside it, or on an ancestor of a pointer-events:none\n// or text-judged element. A clip is skipped once the element or a node below the clipping\n// ancestor is fixed or absolutely positioned, since it may escape the clip; the hit test decides.\n// 2026-10-19 (444.1-01, D-04): a display:contents or zero-area element is judged by its contents'\n// client rects, and is unknown when they have no area or its own box clips them.\n// 2026-10-19 (444.1-01, D-04): the hit walks elementsFromPoint from the top, past elements that\n// are transparent: opacity 0, or unpainted (with their ::before and ::after) with no text there.\nfunction judgeCandidates(elements: unknown[]): unknown {\n const g = globalThis as any\n const doc = g.document\n const root = doc.documentElement\n const rootStyle = g.getComputedStyle(root)\n const bodyPropagates = rootStyle.overflowX === 'visible' && rootStyle.overflowY === 'visible'\n const parentOf = (node: any): any => node.assignedSlot ?? node.parentElement ?? node.parentNode?.host ?? null\n const clips = (node: any): boolean => {\n const style = g.getComputedStyle(node)\n return style.overflowX !== 'visible' || style.overflowY !== 'visible'\n }\n const escapes = (node: any): boolean => {\n const position = g.getComputedStyle(node).position\n return position === 'fixed' || position === 'absolute'\n }\n const contentRects = (node: any): any[] => {\n const range = doc.createRange()\n range.selectNodeContents(node)\n return Array.from(range.getClientRects())\n }\n const replaced = /^(IMG|VIDEO|CANVAS|IFRAME|EMBED|OBJECT|SVG|INPUT|TEXTAREA|SELECT)$/\n const unpainted = (s: any): boolean =>\n s.backgroundImage === 'none' && /^(transparent|rgba\\(.*,\\s*0\\))$/.test(s.backgroundColor)\n const emptyPseudo = (p: any): boolean =>\n p.content === 'none' || p.content === 'normal' || (p.content === '\"\"' && unpainted(p))\n const transparent = (node: any, x: number, y: number): boolean => {\n const s = g.getComputedStyle(node)\n if (s.opacity === '0') return true\n if (node.namespaceURI !== 'http://www.w3.org/1999/xhtml') return false\n if (replaced.test(node.tagName)) return false\n // A shadow tree's boxes are retargeted to its host, so a host is never seen through.\n if (node.shadowRoot || node.tagName.includes('-')) return false\n if (!unpainted(s) || s.backdropFilter !== 'none') return false\n if (!emptyPseudo(g.getComputedStyle(node, '::before'))) return false\n if (!emptyPseudo(g.getComputedStyle(node, '::after'))) return false\n return !contentRects(node).some(\n (t) => t.left <= x && x <= t.right && t.top <= y && y <= t.bottom,\n )\n }\n const judge = (el: any): unknown => {\n const style = g.getComputedStyle(el)\n if (style.visibility !== 'visible') return { state: 'hidden' }\n for (let n = el; n; n = parentOf(n)) {\n if (g.getComputedStyle(n).opacity === '0') return { state: 'hidden' }\n }\n let r = el.getBoundingClientRect()\n const byText = style.display === 'contents' || r.width === 0 || r.height === 0\n if (byText) {\n // A zero-area box that clips its own content shows none of its text.\n const clipped = clips(el) || style.clip !== 'auto' || style.clipPath !== 'none'\n if (style.display !== 'contents' && clipped) return { state: 'unknown' }\n const rects = contentRects(el).filter((t) => t.width > 0 && t.height > 0)\n if (rects.length === 0) return { state: 'unknown' }\n r = {\n left: Math.min(...rects.map((t) => t.left)),\n top: Math.min(...rects.map((t) => t.top)),\n right: Math.max(...rects.map((t) => t.right)),\n bottom: Math.max(...rects.map((t) => t.bottom)),\n }\n } else if (r.width < 2 || r.height < 2) {\n return { state: 'hidden' }\n }\n let left = Math.max(r.left, 0)\n let top = Math.max(r.top, 0)\n let right = Math.min(r.right, g.innerWidth)\n let bottom = Math.min(r.bottom, g.innerHeight)\n if (!(right > left && bottom > top)) return { state: 'hidden' }\n let positioned = escapes(el)\n for (let a = parentOf(el); a && a !== root; a = parentOf(a)) {\n if (!(a === doc.body && bodyPropagates) && !positioned && clips(a)) {\n const b = a.getBoundingClientRect()\n const cl = b.left + a.clientLeft\n const ct = b.top + a.clientTop\n left = Math.max(left, cl)\n top = Math.max(top, ct)\n right = Math.min(right, cl + a.clientWidth)\n bottom = Math.min(bottom, ct + a.clientHeight)\n if (!(right > left && bottom > top)) return { state: 'unknown' }\n }\n if (escapes(a)) positioned = true\n }\n if (right - left < 2 || bottom - top < 2) return { state: 'unknown' }\n const x = (left + right) / 2\n const y = (top + bottom) / 2\n const seen = { state: 'visible', rect: { left, top, right, bottom } }\n for (const hit of el.getRootNode().elementsFromPoint(x, y)) {\n if (hit === el || el.contains(hit)) return seen\n if (style.pointerEvents === 'none' || byText) {\n for (let a = parentOf(el); a; a = parentOf(a)) {\n if (a === hit) return seen\n }\n }\n if (!transparent(hit, x, y)) return { state: 'unknown' }\n }\n return { state: 'unknown' }\n }\n return elements.map(judge)\n}\n\n// In-page, in the parent frame: projects a box from a child frame's viewport through its frame\n// element into the parent's viewport, or null when it cannot be judged: a frame element whose\n// computed visibility is not `visible`, opacity 0 or a transform or zoom on the frame element or a\n// flat-tree ancestor, an empty result after the content box, clipping ancestors and the viewport,\n// or a hit test at its centre that lands on anything but the frame element.\n// Its flat-tree walk and clip rules are a copy of judgeCandidates', without the positioned skip.\nfunction projectThroughFrame(frameElement: unknown, box: ProbeBox): unknown {\n const g = globalThis as any\n const doc = g.document\n const root = doc.documentElement\n const el = frameElement as any\n const rootStyle = g.getComputedStyle(root)\n const bodyPropagates = rootStyle.overflowX === 'visible' && rootStyle.overflowY === 'visible'\n const parentOf = (node: any): any => node.assignedSlot ?? node.parentElement ?? node.parentNode?.host ?? null\n const clips = (node: any): boolean => {\n const style = g.getComputedStyle(node)\n return style.overflowX !== 'visible' || style.overflowY !== 'visible'\n }\n if (g.getComputedStyle(el).visibility !== 'visible') return null\n for (let n = el; n; n = parentOf(n)) {\n if (g.getComputedStyle(n).opacity === '0') return null\n }\n for (let n = el; n; n = parentOf(n)) {\n const style = g.getComputedStyle(n)\n if (style.transform !== 'none') return null\n const zoom = Number.parseFloat(style.zoom)\n if (Number.isFinite(zoom) && zoom !== 1) return null\n }\n const style = g.getComputedStyle(el)\n const padLeft = Number.parseFloat(style.paddingLeft) || 0\n const padTop = Number.parseFloat(style.paddingTop) || 0\n const padRight = Number.parseFloat(style.paddingRight) || 0\n const padBottom = Number.parseFloat(style.paddingBottom) || 0\n const r = el.getBoundingClientRect()\n const ox = r.left + el.clientLeft + padLeft\n const oy = r.top + el.clientTop + padTop\n let left = Math.max(box.left + ox, ox, 0)\n let top = Math.max(box.top + oy, oy, 0)\n let right = Math.min(box.right + ox, ox + el.clientWidth - padLeft - padRight, g.innerWidth)\n let bottom = Math.min(box.bottom + oy, oy + el.clientHeight - padTop - padBottom, g.innerHeight)\n if (!(right > left && bottom > top)) return null\n for (let a = parentOf(el); a && a !== root; a = parentOf(a)) {\n if (a === doc.body && bodyPropagates) continue\n if (!clips(a)) continue\n const b = a.getBoundingClientRect()\n const cl = b.left + a.clientLeft\n const ct = b.top + a.clientTop\n left = Math.max(left, cl)\n top = Math.max(top, ct)\n right = Math.min(right, cl + a.clientWidth)\n bottom = Math.min(bottom, ct + a.clientHeight)\n if (!(right > left && bottom > top)) return null\n }\n const hit = el.getRootNode().elementFromPoint((left + right) / 2, (top + bottom) / 2)\n if (hit !== el) return null\n return { left, top, right, bottom }\n}\n\nfunction candidatesIn(scope: Page | Frame, target: string): Locator {\n return scope\n .getByText(target)\n .or(scope.getByLabel(target))\n .or(scope.getByAltText(target))\n .or(scope.getByTitle(target))\n}\n\nasync function judgeIn(scope: Page | Frame, target: string): Promise<Judged[]> {\n const judged = await candidatesIn(scope, target).evaluateAll(judgeCandidates)\n if (!Array.isArray(judged)) throw new Error('probe answered no list')\n return judged.map((candidate: Partial<Judged> | null) => {\n const state = candidate?.state\n if (state === 'visible' && candidate?.rect) return { state, rect: candidate.rect }\n return { state: state === 'hidden' ? 'hidden' : 'unknown' }\n })\n}\n\nfunction combine(states: readonly TargetVisibility[]): TargetVisibility {\n if (states.includes('visible')) return 'visible'\n if (states.includes('unknown')) return 'unknown'\n return 'hidden'\n}\n\n// A child frame's box, projected through each ancestor frame element up to the main frame.\nasync function projectToMainFrame(frame: Frame, box: ProbeBox): Promise<boolean> {\n let current = frame\n let projected = box\n for (let parent = current.parentFrame(); parent; parent = current.parentFrame()) {\n const handle = await current.frameElement()\n try {\n const next = (await handle.evaluate(projectThroughFrame, projected)) as ProbeBox | null\n if (!next || typeof next !== 'object') return false\n projected = next\n } finally {\n await handle.dispose().catch(() => undefined)\n }\n current = parent\n }\n return true\n}\n\n// A candidate that is not visible inside its own frame may sit where the page search cannot move\n// it, so it is unknown, never hidden; so is one the projection cannot follow to the main frame.\nasync function probeChildFrame(frame: Frame, target: string): Promise<TargetVisibility> {\n try {\n const states: TargetVisibility[] = []\n for (const candidate of await judgeIn(frame, target)) {\n if (candidate.state === 'visible' && candidate.rect && (await projectToMainFrame(frame, candidate.rect))) {\n return 'visible'\n }\n states.push('unknown')\n }\n return combine(states)\n } catch {\n return 'unknown'\n }\n}\n\n// Child-frame liveness checks still running after their bound, per search.\ntype PendingFrames = WeakMap<Frame, Promise<unknown>>\n\n// A frame with no committed document, or with a liveness check still pending from earlier in this\n// search, is unknown with no evaluate. Otherwise the bound covers the liveness check only: a frame\n// that has not answered `1` within FRAME_PROBE_TIMEOUT_MS is unknown and its check is parked in\n// `pending` until it settles; a frame that answers is judged and projected with no bound.\n// 2026-10-19 (444.1-02, D-06): a slow but healthy frame is judged, not cut off (WR-24).\nasync function probeChildFrameBounded(frame: Frame, target: string, pending: PendingFrames): Promise<TargetVisibility> {\n if (frame.url() === '' || pending.has(frame)) return 'unknown'\n const liveness = frame.evaluate('1')\n let timer: ReturnType<typeof setTimeout> | undefined\n const bound = new Promise<'timeout'>((resolve) => {\n timer = setTimeout(() => { resolve('timeout') }, FRAME_PROBE_TIMEOUT_MS)\n })\n let answer: 'alive' | 'timeout'\n try {\n answer = await Promise.race([liveness.then(() => 'alive' as const), bound])\n } catch {\n return 'unknown'\n } finally {\n clearTimeout(timer)\n }\n if (answer === 'alive') return await probeChildFrame(frame, target)\n pending.set(frame, liveness)\n const release = (): void => {\n if (pending.get(frame) === liveness) pending.delete(frame)\n }\n liveness.then(release, release)\n return 'unknown'\n}\n\n// Is any element carrying `target` (text, label, alt or title; Playwright's case-insensitive,\n// whitespace-normalized substring match) on screen now, in the main frame or any child frame?\n// Any visible candidate is visible; else any unknown is unknown; else hidden. An error on the main\n// frame answers unknown, and on a child frame makes that frame unknown (436-17 · D-24/D-25).\n// 2026-10-08 (436-22): tri-state over every frame, each child frame's candidates projected through\n// its frame elements (review CR-07). Hidden: visibility, opacity 0, a box under 2x2 or outside the\n// viewport. Unknown: a nested-scroller clip, a covered or clipped centre point, a frame target not\n// on screen inside its frame, a transformed, zoomed or covered frame (review WR-16).\n// 2026-10-08 (436-26): evaluateAll waits for a child frame's execution context, which a frame that\n// never answers never gets (review CR-08). Child frames are judged at once, each frame's liveness\n// check bounded by FRAME_PROBE_TIMEOUT_MS and sent once while it is pending; a frame with no\n// committed document is unknown at once. The main frame and a live frame's judge are unbounded.\nasync function probeOnScreen(page: Page, target: string, pending: PendingFrames): Promise<TargetVisibility> {\n let states: TargetVisibility[]\n try {\n states = (await judgeIn(page, target)).map((candidate) => candidate.state)\n } catch {\n return 'unknown'\n }\n if (combine(states) === 'visible') return 'visible'\n try {\n const main = page.mainFrame()\n const children = page.frames().filter((frame) => frame !== main && !frame.isDetached())\n states.push(...(await Promise.all(children.map((frame) => probeChildFrameBounded(frame, target, pending)))))\n } catch {\n states.push('unknown')\n }\n return combine(states)\n}\n\n// Light probe + swipe/native primitives. readInterimTree re-runs ONLY the aria-snapshot harvest\n// → parseAriaSnapshot(text).nodes — NO buildScreenState, NO refMap mint, NO screenshot; lastRefs\n// stays bound to the pre-compound observation. probeTargetVisible decides target visibility for\n// the loop: page-wide, every frame, and it ignores the container ref. swipeOnce reports what the\n// offsets proved; the no-ref wheel measures the scrollers under the pointer before and after.\n// 2026-10-08 (436-22): probeTargetVisible answers visible, hidden or unknown.\n// 2026-10-08 (436-26): one pending-frame memo per primitives instance, so per search (CR-08).\nexport function buildScrollPrimitives(page: Page, lastRefs: RefMap, magnitude: number): ScrollPrimitives {\n const pending: PendingFrames = new WeakMap()\n return {\n async swipeOnce(direction: Direction, ref?: Ref): Promise<SwipeSignal> {\n const { dx, dy, axis } = deltaFor(direction, magnitude)\n if (ref) {\n // A ref that does not resolve moves nothing and carries no offsets: the signal is unknown.\n const scrolled = await scrollWithRef(page, lastRefs, ref, dx, dy, axis)\n if (scrolled.scrolledContainer !== 'notFound') await settle(page)\n return swipeSignalFromOffsets(direction, scrolled.offsets)\n }\n const chain = await wheelPointerChain(page, dx, dy, axis)\n return scrollerSetSwipeSignal(direction, chain?.before, chain?.after)\n },\n async nativeSearchScroll(target: string): Promise<boolean> {\n try {\n await page.getByText(target).first().scrollIntoViewIfNeeded()\n return true\n } catch {\n return false\n }\n },\n async readInterimTree() {\n const tree = await page.locator(':root').ariaSnapshot({ mode: 'ai' })\n return parseAriaSnapshot(tree).nodes\n },\n async probeTargetVisible(target: string): Promise<TargetVisibility> {\n return probeOnScreen(page, target, pending)\n },\n }\n}\n\n// EXEC-02: both schema Scroll modes over the shared loops. ONE ActionResult carrying\n// metadata.scrollUntilVisible; the gesture itself succeeds — the outcome and what ended it ride\n// the metadata, not the success flag.\nexport async function runWebScrollCompound(page: Page, lastRefs: RefMap, action: Scroll): Promise<ActionResult> {\n const viewport = page.viewportSize() ?? { width: 1280, height: 720 }\n const horizontal = action.direction === 'left' || action.direction === 'right'\n\n if (action.mode === 'untilVisible') {\n const magnitude = horizontal ? viewport.width : viewport.height\n const primitives = buildScrollPrimitives(page, lastRefs, magnitude)\n const { meta } = await runUntilVisibleLoop(primitives, {\n target: action.text,\n direction: action.direction,\n maxSwipes: action.maxSwipes,\n retryOpposite: action.retryOpposite,\n ...(action.ref ? { ref: action.ref } : {}),\n })\n return { success: true, metadata: { scrollUntilVisible: meta } }\n }\n\n const factor = action.amount === 'halfPage' ? 0.5 : 1\n const magnitude = Math.round((horizontal ? viewport.width : viewport.height) * factor)\n const primitives = buildScrollPrimitives(page, lastRefs, magnitude)\n\n if (action.amount === 'toEnd') {\n const { meta } = await runToEndScroll(primitives, action.direction, action.ref)\n return { success: true, metadata: { scrollUntilVisible: meta } }\n }\n\n const { meta } = await runDirectionScroll(primitives, {\n direction: action.direction,\n ...(action.ref ? { ref: action.ref } : {}),\n })\n return { success: true, metadata: { scrollUntilVisible: meta } }\n}\n\n// EXEC-03 web lane (D-09): openApp is not executable on web — self-correct to navigate(url).\nexport function webOpenAppError(): ActionResult {\n return {\n success: false,\n error: 'openApp is not executable on web — use navigate(url) with the target app\\'s web address instead.',\n }\n}\n","// Container scroll for a ref (436-17 · D-25, review CR-03). The ref resolves through\n// ElementResolver, the aria-ref locator every other web action uses. A ref that does not resolve,\n// or names an element in a child frame (frames are deferred, 438 D-09), performs no gesture and\n// reports no offsets, so the swipe reads `unknown`. Offsets always belong\n// to the container that was actually scrolled: the element, its nearest scrolling ancestor over\n// the flat tree, or document.scrollingElement, which reports them only when it has scroll range on\n// the swiped axis.\n// 2026-10-08 (436-22): the walk follows the flat tree (slot, parent, shadow host), never takes a\n// body whose overflow propagates to the viewport as a container, and the document fallback scrolls\n// and measures document.scrollingElement; with none, it reports no offsets (review CR-06).\n\nimport type { Page } from 'playwright-core'\nimport type { Ref } from '@vostride/agent-qa-schema'\nimport { isChildFrameRef } from './binding.js'\nimport { ElementResolver } from './element-resolver.js'\nimport type { RefMap } from './types.js'\n\nexport interface ScrollResult {\n bounds: { x: number; y: number; width: number; height: number } | null\n scrolledContainer: 'element' | 'ancestor' | 'documentElement' | 'notFound'\n scrolled: boolean\n /** The scrolled container's offset on the swiped axis before and after, and its largest offset. */\n offsets?: { before: number; after: number; max: number }\n}\n\nconst NOT_FOUND: ScrollResult = { bounds: null, scrolledContainer: 'notFound', scrolled: false }\n\n// Bounds the evaluate's own wait if the element detaches between count() and evaluate().\nconst EVALUATE_TIMEOUT_MS = 1_000\n\nexport async function scrollWithRef(\n page: Page,\n lastRefs: RefMap,\n ref: Ref,\n deltaX: number,\n deltaY: number,\n scrollAxis: 'horizontal' | 'vertical',\n): Promise<ScrollResult> {\n const nativeRef = lastRefs[ref]?.nativeRef\n if (nativeRef !== undefined && isChildFrameRef(nativeRef)) return NOT_FOUND\n try {\n const locator = new ElementResolver(page, lastRefs).resolve(ref)\n if ((await locator.count()) === 0) return NOT_FOUND\n const scrolled = await locator.evaluate(\n (target: unknown, args: [number, number, string]) => {\n const [dx, dy, axis] = args\n const win = globalThis as any\n const doc = win.document\n const el = target as any\n\n const prop = axis === 'horizontal' ? 'scrollLeft' : 'scrollTop'\n const maxOf = (node: any): number => axis === 'horizontal'\n ? node.scrollWidth - node.clientWidth\n : node.scrollHeight - node.clientHeight\n const boundsOf = () => {\n const rect = el.getBoundingClientRect()\n return { x: Math.round(rect.x), y: Math.round(rect.y), width: Math.round(rect.width), height: Math.round(rect.height) }\n }\n const scrollable = (node: any): boolean => {\n const style = win.getComputedStyle(node)\n const overflow = axis === 'horizontal' ? style.overflowX : style.overflowY\n return (overflow === 'auto' || overflow === 'scroll' || overflow === 'hidden') && maxOf(node) > 0\n }\n\n // A body whose overflow propagates to the viewport is not a scroll container; the\n // document scroller stands for the page in standards and quirks mode alike.\n const scroller = doc.scrollingElement\n const rootStyle = win.getComputedStyle(doc.documentElement)\n const bodyPropagates = rootStyle.overflowX === 'visible' && rootStyle.overflowY === 'visible'\n const isDocumentScroller = (node: any): boolean =>\n node === doc.documentElement || node === scroller || (bodyPropagates && node === doc.body)\n const parentOf = (node: any): any => {\n if (node.assignedSlot) return node.assignedSlot\n if (node.parentElement) return node.parentElement\n const parent = node.parentNode\n return parent && parent.host ? parent.host : null\n }\n\n // The element itself, then its nearest scrollable ancestor over the flat tree.\n if (!isDocumentScroller(el)) {\n if (scrollable(el)) {\n const before = el[prop]\n el.scrollBy(dx, dy)\n const after = el[prop]\n return { bounds: boundsOf(), scrolledContainer: 'element', scrolled: before !== after, offsets: { before, after, max: maxOf(el) } }\n }\n for (let parent = parentOf(el); parent && !isDocumentScroller(parent); parent = parentOf(parent)) {\n if (!scrollable(parent)) continue\n const before = parent[prop]\n parent.scrollBy(dx, dy)\n const after = parent[prop]\n return { bounds: boundsOf(), scrolledContainer: 'ancestor', scrolled: before !== after, offsets: { before, after, max: maxOf(parent) } }\n }\n }\n\n // The document scroller, whose offsets prove something only when it has range on this axis.\n if (!scroller) {\n const x = win.scrollX\n const y = win.scrollY\n win.scrollBy(dx, dy)\n return { bounds: boundsOf(), scrolledContainer: 'documentElement', scrolled: x !== win.scrollX || y !== win.scrollY }\n }\n const before = scroller[prop]\n scroller.scrollBy(dx, dy)\n const after = scroller[prop]\n const max = maxOf(scroller)\n return {\n bounds: boundsOf(),\n scrolledContainer: 'documentElement',\n scrolled: before !== after,\n ...(max > 0 ? { offsets: { before, after, max } } : {}),\n }\n },\n [deltaX, deltaY, scrollAxis] as [number, number, string],\n { timeout: EVALUATE_TIMEOUT_MS },\n )\n return scrolled && typeof scrolled === 'object' ? (scrolled as ScrollResult) : NOT_FOUND\n } catch {\n return NOT_FOUND\n }\n}\n","type BrowserName = 'chromium' | 'firefox' | 'webkit'\n\nfunction displayBrowserName(browserName: BrowserName): string {\n if (browserName === 'chromium') return 'Chromium'\n if (browserName === 'firefox') return 'Firefox'\n return 'WebKit'\n}\n\nexport function isPlaywrightMissingBrowserError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error)\n const lower = message.toLowerCase()\n return lower.includes(\"executable doesn't exist\")\n && lower.includes('playwright')\n && lower.includes('install')\n}\n\nexport function formatMissingBrowserError(browserName: BrowserName): string {\n return [\n `agent-qa browser support is not installed for ${displayBrowserName(browserName)}.`,\n '',\n 'Install the browser managed by agent-qa, then rerun the test:',\n ` agent-qa install-browsers --${browserName}`,\n '',\n 'This can happen after upgrading agent-qa or Playwright because browser binaries live outside the package install.',\n ].join('\\n')\n}\n","import { randomUUID } from 'node:crypto'\nimport { mkdir, rm } from 'node:fs/promises'\nimport { join } from 'node:path'\nimport type { Page } from 'playwright-core'\nimport type { PlatformConfig, RecordingCapability } from '@vostride/agent-qa-runner'\n\nexport const RECORDING_DEFAULT_SIZE = { width: 1280, height: 720 }\n\n// Read only JPEG SOF dimensions; never retain or publish frame bytes for this witness.\nfunction jpegSize(bytes: Buffer): { width: number; height: number } | undefined {\n if (bytes[0] !== 0xff || bytes[1] !== 0xd8) return undefined\n for (let i = 2; i + 8 < bytes.length;) {\n if (bytes[i++] !== 0xff) return undefined\n const marker = bytes[i++]!\n const length = bytes.readUInt16BE(i)\n if (length < 2 || i + length > bytes.length) return undefined\n if ([0xc0, 0xc1, 0xc2].includes(marker)) {\n return { height: bytes.readUInt16BE(i + 3), width: bytes.readUInt16BE(i + 5) }\n }\n i += length\n }\n return undefined\n}\n\nexport interface ScreencastRecording extends RecordingCapability {\n /** The bracketed action itself has ended; waits the adapter runs after it are not execution. */\n endAction(): void\n}\n\nexport function createScreencastRecording(\n getPage: () => Page | null,\n config: NonNullable<PlatformConfig['recording']>,\n getPageRevision?: () => number,\n): ScreencastRecording {\n let active: { page: Page; stagingPath: string } | undefined\n let recovery: typeof active\n let busy = false\n let firstFrameEpoch: number | undefined\n let scene: { width: number; height: number } | undefined\n let sceneRevision = 0\n let bracket: { end(): void } | undefined\n async function recover() {\n if (!recovery) return\n // Keep the failed session quarantined until the driver confirms it stopped.\n // A subsequent start retries this real cleanup, never publishes these bytes.\n await recovery.page.screencast.stop()\n await rm(recovery.stagingPath, { force: true })\n recovery = undefined\n }\n return {\n async start() {\n if (busy || active) throw new Error('Recording already started')\n busy = true\n try {\n await recover()\n const page = getPage()\n if (!page) throw new Error('Recording requires an initialized page')\n const stagingPath = join(config.videoDir, `${randomUUID()}.webm`)\n const size = config.videoSize ?? page.viewportSize() ?? RECORDING_DEFAULT_SIZE\n firstFrameEpoch = undefined\n scene = undefined\n sceneRevision++\n recovery = { page, stagingPath }\n try {\n await mkdir(config.videoDir, { recursive: true })\n await page.screencast.start({\n path: stagingPath,\n size,\n onFrame: async frame => {\n firstFrameEpoch ??= frame.timestamp\n const pixels = jpegSize(frame.data)\n // Only an observed 1:1 mapping is supported. Shared screencasts, custom sizes,\n // odd encoder dimensions and resized pages must never inherit guessed scaling.\n const next = pixels?.width === size.width && pixels.height === size.height\n && frame.viewportWidth === size.width && frame.viewportHeight === size.height\n ? { width: size.width, height: size.height } : undefined\n if (next?.width !== scene?.width || next?.height !== scene?.height) sceneRevision++\n scene = next\n },\n })\n } catch (error) {\n try { await recover() } catch { /* Retry cleanup before the next start. */ }\n throw error\n }\n active = recovery\n recovery = undefined\n return { zeroMs: performance.now() }\n } finally { busy = false }\n },\n beginAnnotation() {\n const recording = active\n const before = scene\n const epoch = firstFrameEpoch\n const revision = sceneRevision\n // Remote farm clocks are not proven to share this process's epoch.\n if (!getPageRevision) return undefined\n const pageRevision = getPageRevision()\n if (!recording || !before || epoch === undefined || getPage() !== recording.page) return undefined\n const viewport = recording.page.viewportSize()\n if (viewport?.width !== before.width || viewport.height !== before.height) return undefined\n const startMs = performance.timeOrigin + performance.now() - epoch\n const settle = () => {\n const after = recording.page.viewportSize()\n const endMs = performance.timeOrigin + performance.now() - epoch\n if (active !== recording || getPage() !== recording.page || revision !== sceneRevision\n || pageRevision !== getPageRevision() || after?.width !== before.width || after.height !== before.height\n || !Number.isFinite(startMs) || !Number.isFinite(endMs) || startMs < 0 || endMs <= startMs) return undefined\n return { startMs, endMs, scene: 'recorded-page' as const, transform: 'identity' as const, ...before }\n }\n let ended: { witness: ReturnType<typeof settle> } | undefined\n bracket = { end() { ended = { witness: settle() } } }\n return () => ended ? ended.witness : settle()\n },\n endAction() {\n bracket?.end()\n },\n async stop() {\n if (busy) throw new Error('Recording operation already in progress')\n busy = true\n try {\n const recording = active\n if (!recording) { await recover(); return undefined }\n active = undefined\n try {\n await recording.page.screencast.stop()\n } catch (error) {\n recovery = recording\n try { await recover() } catch { /* Retry cleanup before the next start. */ }\n throw error\n }\n return { stagingPath: recording.stagingPath, contentType: 'video/webm' }\n } finally { busy = false }\n },\n }\n}\n","// Chromium download and app-clipboard capture, armed per action (436 D-19..D-21). A download is\n// awaited, streamed into sha-256 and deleted here; only its name, extension, size, digest and\n// state leave. `path()` and `saveAs()` are never called and no path is ever recorded.\n//\n// Clipboard: a page-world hook reports the text the app writes through the binding. Only while an\n// action other than agent-qa's own `copy` / `paste` is armed is a write kept, and only after a\n// kept write is the clipboard read back. The text leaves raw; the loop masks and bounds it\n// (CLIPBOARD_TEXT_LIMIT).\n// 2026-10-08 (436-14): the read-back runs in an agent-qa-owned probe context at a reserved origin,\n// never on an app origin, and only the index of the claimed write equal to the clipboard leaves\n// the probe page (CR-01, IN-08). No app origin is ever granted `clipboard-read`.\n// 2026-10-08 (436-15): the download wait of one action ends at the step's remaining time when the\n// loop hands one over, else at DOWNLOAD_COMPLETION_CAP_MS, and at once when the step is aborted\n// (WR-07). A download ended there is cancelled and deleted.\n// 2026-10-08 (436-16): every download-starting web action is armed (fill only with submit, tab\n// only when it opens one), the start window stays open while a navigation the action started is\n// unanswered, and a download that starts outside the window is held for the next action, marked\n// late, or cancelled and deleted at dispose (WR-05). The clipboard is disarmed when the start\n// window closes, before any completion wait (IN-09).\n// 2026-10-08 (436-21): a closed or crashed probe is reset (only the probe context closes) and\n// opened once more; held downloads survive it and only dispose() cancels them (WR-18).\n// 2026-10-08 (436-21): a headed or undetermined launch never reads the clipboard and opens no\n// probe (owner ruling on D-21); its app writes are recorded `unavailable`.\n// 2026-10-08 (436-21): in a headless launch the probe page takes a pre-image of the run-local\n// clipboard before each clipboard-armed action, and only the final claim is compared after it:\n// `matched` needs the clipboard to have changed during the action and to equal that claim (WR-17).\n// The pre-image stays in the probe page; only status words and numbers leave it. At most\n// CLIPBOARD_CLAIMS_PER_ACTION claims are kept per action in either mode, and a probe whose read\n// does not settle is skipped until it is replaced.\n// 2026-10-08 (436-24): navigations that do not answer, from any frame or popup, keep the start\n// window open at most NAVIGATION_WINDOW_CAP_MS and never past half the action's time left, so a\n// started download keeps the other half to finish. They are bounded, not dropped: a download that\n// starts after the window is held and recorded late. The 120 s no-deadline wait is gone (CR-05).\n// 2026-10-08 (436-27): the acting page's own main-frame navigation waits up to half the action's\n// time left, so a slow export is recorded on its click (WR-21); subframes and popups keep the cap.\n// With no step deadline the main frame waits up to half DOWNLOAD_COMPLETION_CAP_MS (60 s). A\n// capture armed without an acting page caps every navigation.\n// 2026-10-11 (439-07): a completed download's bytes are also kept in memory, keyed by sha256, when\n// the file is at most DOWNLOAD_HOLD_FILE_CAP; the hold keeps at most DOWNLOAD_HOLD_TOTAL_CAP,\n// evicting the oldest first, and dispose() clears it (D-04). The file is still deleted.\n\nimport { createHash } from 'node:crypto'\nimport { extname } from 'node:path'\nimport type { BrowserContext, Download, Frame, Page, Request } from 'playwright-core'\nimport type { ClipboardEvidence, DownloadEvidence } from '@vostride/agent-qa-schema'\nimport type { ExecuteOptions } from '@vostride/agent-qa-runner'\n\nexport { CLIPBOARD_TEXT_LIMIT } from '@vostride/agent-qa-runner'\n\n/** How long an activation action is given to start a download after it returns. */\nexport const DOWNLOAD_START_GRACE_MS = 500\n/** How long the start window stays open after a navigation the action started is answered; the download event follows the response. */\nexport const NAVIGATION_SETTLE_MS = 250\n/** The download wait's bound for an action dispatched with no step deadline. */\nexport const DOWNLOAD_COMPLETION_CAP_MS = 120_000\n/** The longest the start window stays open for subframe and popup navigations; never more than half the action's time left. */\nexport const NAVIGATION_WINDOW_CAP_MS = 5_000\n/** The largest downloaded file whose bytes are held in memory (439 D-04). */\nexport const DOWNLOAD_HOLD_FILE_CAP = 1024 * 1024\n/** The most downloaded bytes held at once; the oldest files are evicted first. */\nexport const DOWNLOAD_HOLD_TOTAL_CAP = 8 * 1024 * 1024\n\n/** The web actions that can start a download; see isDownloadActivation for tab and fill. */\nexport const DOWNLOAD_ACTIVATION_ACTIONS: ReadonlySet<string> = new Set([\n 'click',\n 'doubleClick',\n 'rightClick',\n 'keypress',\n 'select',\n 'navigate',\n 'executeScript',\n 'handleDialog',\n 'fileUpload',\n 'tab',\n])\n\nexport interface DownloadActivationInput {\n type: string\n submit?: unknown\n action?: unknown\n}\n\n/** Whether the action is given the download start window: a `tab` only when it opens one, a `fill` only when it submits. */\nexport function isDownloadActivation(action: DownloadActivationInput): boolean {\n if (action.type === 'fill') return action.submit === true\n if (action.type === 'tab') return action.action === 'new'\n return DOWNLOAD_ACTIVATION_ACTIONS.has(action.type)\n}\n\ninterface PendingNavigation {\n page: Page | undefined\n /** The acting page's own main-frame navigation. */\n main: boolean\n}\n\ninterface TrackedDownload {\n download: Download\n late: boolean\n}\n\nconst UNFINISHED = Symbol('unfinished')\n\n/** The binding the page-world hook reports app clipboard writes through. */\nexport const CLIPBOARD_BINDING = '__agentQaAppClipboardWrite'\n/** agent-qa's own clipboard actions; their writes are never the app's. */\nconst CLIPBOARD_EXCLUDED_ACTIONS: ReadonlySet<string> = new Set(['copy', 'paste'])\nconst CLIPBOARD_SOURCES: ReadonlySet<string> = new Set(['writeText', 'write', 'copy-event'])\nexport const READ_BACK_TIMEOUT_MS = 2_000\n/** The most recent app clipboard claims kept per action; older ones are dropped. */\nexport const CLIPBOARD_CLAIMS_PER_ACTION = 8\n/** The reserved origin of the read-back probe page; nothing else loads in the probe context. */\nexport const CLIPBOARD_READBACK_ORIGIN = 'https://agent-qa-readback.invalid'\n// The probe page's compare() answers that confirm anything; -2 (no pre-image or unreadable) and\n// -3 (unchanged) confirm nothing.\nconst PROBE_MATCHED = 1\nconst PROBE_DIFFERENT = 0\n\ntype ProbeStatus = 'none' | 'read' | 'unreadable'\n\ninterface ProbeReadback {\n readonly status: ProbeStatus\n snapshot(): Promise<ProbeStatus>\n compare(finalText: string): Promise<number>\n}\n\ntype ProbeScope = typeof globalThis & { __agentQaReadback: ProbeReadback }\n\n// Runs once in the probe page. The pre-image lives only in this closure; readText is looked up at\n// call time.\nfunction installProbeReadback(): void {\n const scope = globalThis as unknown as {\n navigator: { clipboard: { readText: () => Promise<unknown> } }\n }\n let preImage: string | undefined\n let status: ProbeStatus = 'none'\n const read = async (): Promise<string | undefined> => {\n try {\n const text = await scope.navigator.clipboard.readText()\n return typeof text === 'string' ? text : undefined\n } catch {\n return undefined\n }\n }\n Object.defineProperty(globalThis, '__agentQaReadback', {\n value: Object.freeze({\n get status() { return status },\n async snapshot() {\n preImage = undefined\n status = 'none'\n const text = await read()\n if (text === undefined) {\n status = 'unreadable'\n } else {\n preImage = text\n status = 'read'\n }\n return status\n },\n async compare(finalText: string) {\n if (status !== 'read') return -2\n const now = await read()\n if (now === undefined) return -2\n if (now === preImage) return -3\n return now === finalText ? 1 : 0\n },\n }),\n })\n}\n\nexport type CapturedClipboardWrite = Pick<ClipboardEvidence, 'source' | 'text' | 'readBack'>\n\n/** What one armed action produced; the clipboard text is raw until the loop masks it. */\nexport interface CapturedOperations {\n downloads?: DownloadEvidence[]\n clipboard?: CapturedClipboardWrite[]\n}\n\ninterface PendingClipboardWrite {\n source: ClipboardEvidence['source']\n text: string\n frame: Frame\n}\n\nconst CLIPBOARD_HOOK = `(() => {\n const binding = ${JSON.stringify(CLIPBOARD_BINDING)};\n const report = (via, text) => {\n const send = window[binding];\n if (typeof send !== 'function' || typeof text !== 'string' || text.length === 0) return;\n try { Promise.resolve(send({ via, text })).catch(() => {}); } catch {}\n };\n // 2026-10-08 (436-14): a write is reported only once the browser accepted it; the app still\n // gets the original promise, rejections included.\n const proto = typeof Clipboard === 'function' ? Clipboard.prototype : undefined;\n if (proto && typeof proto.writeText === 'function') {\n const writeText = proto.writeText;\n proto.writeText = function (data) {\n let text;\n try { text = String(data); } catch {}\n const result = writeText.apply(this, arguments);\n try { Promise.resolve(result).then(() => report('writeText', text), () => {}); } catch {}\n return result;\n };\n }\n if (proto && typeof proto.write === 'function') {\n const write = proto.write;\n proto.write = function (items) {\n const texts = [];\n try {\n for (const item of Array.from(items || [])) {\n if (!item || !Array.from(item.types || []).includes('text/plain')) continue;\n texts.push(item.getType('text/plain').then((blob) => blob.text()).catch(() => undefined));\n }\n } catch {}\n const result = write.apply(this, arguments);\n try {\n Promise.resolve(result).then(\n () => Promise.all(texts).then((all) => { for (const text of all) report('write', text); }),\n () => {},\n );\n } catch {}\n return result;\n };\n }\n // A copy event is tracked from window's capture phase, which runs before any app handler can\n // stop propagation, and settled once dispatch is over: a prevented copy writes what the app\n // set (seen through setData), an unprevented one writes the selection taken at dispatch.\n let pending = null;\n const selected = (event) => {\n for (const el of [event.target, document.activeElement]) {\n if (!el || (el.tagName !== 'TEXTAREA' && el.tagName !== 'INPUT')) continue;\n try {\n const start = el.selectionStart, end = el.selectionEnd;\n if (typeof start === 'number' && typeof end === 'number' && end > start) return el.value.slice(start, end);\n } catch {}\n }\n const selection = document.getSelection();\n return selection ? selection.toString() : '';\n };\n const settle = () => {\n const copy = pending;\n pending = null;\n if (!copy) return;\n if (!copy.event.defaultPrevented) return report('copy-event', copy.selection);\n if (copy.set !== undefined) return report('copy-event', copy.set);\n try { report('copy-event', copy.event.clipboardData ? copy.event.clipboardData.getData('text/plain') : ''); } catch {}\n };\n if (typeof DataTransfer === 'function' && typeof DataTransfer.prototype.setData === 'function') {\n const setData = DataTransfer.prototype.setData;\n DataTransfer.prototype.setData = function (format, data) {\n if (pending && this === pending.event.clipboardData && /^text(\\\\/plain)?$/i.test(String(format))) pending.set = String(data);\n return setData.apply(this, arguments);\n };\n }\n window.addEventListener('copy', (event) => {\n settle();\n pending = { event, selection: selected(event), set: undefined };\n setTimeout(settle, 0);\n }, true);\n})();`\n\nconst PLAYWRIGHT_DEBUG_ENV = ['PWDEBUG', 'npm_config_pwdebug', 'npm_package_config_pwdebug'] as const\nconst DEBUG_OFF: ReadonlySet<string> = new Set(['', '0', 'false'])\n\n/** True only for a plain headless launch: `headless: true`, no channel and no Playwright debug mode. */\nexport function isHeadlessLaunch(\n launch: { headless?: unknown; channel?: unknown },\n env: Record<string, string | undefined>,\n): boolean {\n if (launch.headless !== true || launch.channel !== undefined) return false\n // Playwright's inspector debug mode forces a headed launch whatever `headless` says.\n return PLAYWRIGHT_DEBUG_ENV.every((name) => env[name] === undefined || DEBUG_OFF.has(env[name]))\n}\n\nexport interface OperationCaptureOptions {\n /** The bound when the action carries no remaining step time. */\n completionCapMs?: number\n startGraceMs?: number\n /** True only when the adapter launched headless; anything else never reads the clipboard. */\n headless?: boolean\n}\n\nexport class OperationCapture {\n private readonly completionCapMs: number\n private readonly startGraceMs: number\n private readonly attachedPages = new WeakSet<Page>()\n private downloads: TrackedDownload[] = []\n /** Downloads that started while no start window was open, kept for the next action. */\n private held: Download[] = []\n /** Completed downloads' bytes by sha256, oldest first; memory only (439 D-04). */\n private readonly heldBytes = new Map<string, Uint8Array>()\n private heldByteTotal = 0\n private readonly pendingNavigations = new Map<Request, PendingNavigation>()\n private clipboardWrites: PendingClipboardWrite[] = []\n private armed = false\n private startWindow = false\n private navigationWindow = false\n private navigationSettledAt = 0\n private navigationSettledMain = false\n private actingPage: Page | undefined\n private clipboardArmed = false\n private activation = false\n private boundAt = 0\n private abortSignal: AbortSignal | undefined\n private notify: (() => void) | null = null\n private appContext: BrowserContext | null = null\n private probe: Promise<Page | undefined> | null = null\n private probeContext: BrowserContext | null = null\n private probeGeneration = 0\n private readonly readsClipboard: boolean\n /** The probe generation holding this action's pre-image; -1 when none was read. */\n private preImageGeneration = -1\n /** A probe generation whose read did not settle; skipped until resetProbe() replaces it. */\n private unreadableGeneration = -1\n\n constructor(options: OperationCaptureOptions = {}) {\n this.completionCapMs = options.completionCapMs ?? DOWNLOAD_COMPLETION_CAP_MS\n this.startGraceMs = options.startGraceMs ?? DOWNLOAD_START_GRACE_MS\n this.readsClipboard = options.headless === true\n }\n\n async attach(context: BrowserContext): Promise<void> {\n this.appContext = context\n for (const page of context.pages()) this.attachPage(page)\n context.on('page', (page) => this.attachPage(page))\n context.on('request', (request) => this.onRequest(request))\n context.on('response', (response) => { this.settleNavigation(response.request()) })\n context.on('requestfailed', (request) => { this.settleNavigation(request) })\n await context.exposeBinding(CLIPBOARD_BINDING, (source, payload: unknown) => {\n this.onClipboardWrite(source.frame, payload)\n })\n await context.addInitScript(CLIPBOARD_HOOK)\n }\n\n async arm(action: DownloadActivationInput, options: ExecuteOptions = {}, actingPage?: Page): Promise<void> {\n const carried = [...this.downloads.map((entry) => entry.download), ...this.held]\n this.held = []\n this.downloads = carried.map((download) => ({ download, late: true }))\n this.clipboardWrites = []\n this.armed = true\n this.startWindow = true\n this.clipboardArmed = false\n this.activation = isDownloadActivation(action)\n this.navigationWindow = this.activation\n this.navigationSettledAt = 0\n this.navigationSettledMain = false\n this.actingPage = actingPage\n this.pendingNavigations.clear()\n const remaining = options.remainingStepMs\n this.boundAt = Date.now()\n + (typeof remaining === 'number' && Number.isFinite(remaining) ? Math.max(0, remaining) : this.completionCapMs)\n this.abortSignal = options.abortSignal\n this.preImageGeneration = -1\n const clipboardAction = !CLIPBOARD_EXCLUDED_ACTIONS.has(action.type)\n if (this.readsClipboard && clipboardAction && this.timeLeft() > 0) await this.takePreImage()\n // Claims count only once the pre-image step settled, so a write made during it is not attributed.\n this.clipboardArmed = this.armed && clipboardAction\n }\n\n private timeLeft(): number {\n return this.abortSignal?.aborted ? 0 : this.boundAt - Date.now()\n }\n\n // Calls `fire` once when the action's abort signal fires; the returned function removes it.\n private onAbort(fire: () => void): () => void {\n const signal = this.abortSignal\n if (!signal) return () => undefined\n if (signal.aborted) {\n queueMicrotask(fire)\n return () => undefined\n }\n signal.addEventListener('abort', fire, { once: true })\n return () => { signal.removeEventListener('abort', fire) }\n }\n\n async collect(): Promise<CapturedOperations | undefined> {\n if (!this.armed) return undefined\n let next = 0\n try {\n await this.waitForStartWindow()\n this.closeStartWindow()\n const writes = this.clipboardWrites\n this.clipboardArmed = false\n this.clipboardWrites = []\n const clipboard = !this.readsClipboard\n ? writes.map(({ source, text }): CapturedClipboardWrite => ({ source, text, readBack: 'unavailable' }))\n : writes.length > 0 ? await this.readBack(writes) : []\n const evidence: DownloadEvidence[] = []\n while (next < this.downloads.length) {\n const { download, late } = this.downloads[next++]!\n const finished = await this.finish(download)\n evidence.push(late ? { ...finished, late: true } : finished)\n }\n if (evidence.length === 0 && clipboard.length === 0) return undefined\n return {\n ...(evidence.length > 0 ? { downloads: evidence } : {}),\n ...(clipboard.length > 0 ? { clipboard } : {}),\n }\n } finally {\n this.held.push(...this.downloads.slice(next).map((entry) => entry.download))\n this.closeStartWindow()\n this.armed = false\n this.clipboardArmed = false\n this.downloads = []\n this.clipboardWrites = []\n this.abortSignal = undefined\n this.actingPage = undefined\n this.preImageGeneration = -1\n }\n }\n\n // The grace after an activation action, then for as long as a navigation it started has neither\n // a response nor a failure, plus NAVIGATION_SETTLE_MS after the last answer; all bounded by the\n // action's time left. Fixed when the wait begins: the acting page's main-frame navigation ends at\n // mainEnd (half the time left), any other at capEnd (also NAVIGATION_WINDOW_CAP_MS).\n private async waitForStartWindow(): Promise<void> {\n if (!this.activation) return\n const start = Date.now()\n const graceEnd = start + Math.min(this.startGraceMs, Math.max(0, this.timeLeft()))\n const reserve = Math.max(0, this.timeLeft()) / 2\n const capEnd = start + Math.min(NAVIGATION_WINDOW_CAP_MS, reserve)\n const mainEnd = start + reserve\n for (;;) {\n const left = this.timeLeft()\n if (left <= 0) return\n const now = Date.now()\n const settleEnd = Math.min(\n this.navigationSettledAt + NAVIGATION_SETTLE_MS,\n this.navigationSettledMain ? mainEnd : capEnd,\n )\n const openFor = Math.max(graceEnd, settleEnd) - now\n const pendingEnd = this.pendingNavigationEnd(mainEnd, capEnd)\n if (openFor > 0) await this.waitForSignal(Math.min(openFor, left))\n else if (now < pendingEnd) await this.waitForSignal(Math.min(pendingEnd - now, left))\n else return\n }\n }\n\n // mainEnd while a main-frame navigation of the acting page is pending, else capEnd while any\n // other is, else 0.\n private pendingNavigationEnd(mainEnd: number, capEnd: number): number {\n let end = 0\n for (const { main } of this.pendingNavigations.values()) {\n if (main) return mainEnd\n end = capEnd\n }\n return end\n }\n\n private closeStartWindow(): void {\n this.startWindow = false\n this.navigationWindow = false\n this.pendingNavigations.clear()\n }\n\n private onRequest(request: Request): void {\n if (!this.navigationWindow || !request.isNavigationRequest()) return\n let page: Page | undefined\n let main = false\n try {\n const frame = request.frame()\n page = frame.page()\n main = this.actingPage !== undefined && frame === this.actingPage.mainFrame()\n } catch { /* not a frame request */ }\n this.pendingNavigations.set(request, { page, main })\n }\n\n private settleNavigation(request: Request): void {\n const pending = this.pendingNavigations.get(request)\n if (!pending) return\n this.pendingNavigations.delete(request)\n this.navigationSettledAt = Date.now()\n this.navigationSettledMain = pending.main\n this.notify?.()\n }\n\n private onClipboardWrite(frame: Frame, payload: unknown): void {\n if (!this.armed || !this.clipboardArmed) return\n if (!payload || typeof payload !== 'object') return\n const { via, text } = payload as Record<string, unknown>\n if (typeof via !== 'string' || !CLIPBOARD_SOURCES.has(via) || typeof text !== 'string') return\n this.clipboardWrites.push({ source: via as ClipboardEvidence['source'], text, frame })\n if (this.clipboardWrites.length > CLIPBOARD_CLAIMS_PER_ACTION) this.clipboardWrites.shift()\n }\n\n // Takes the probe page's pre-image of the clipboard; a closed or crashed probe is replaced once.\n private async takePreImage(): Promise<void> {\n for (let attempt = 0; attempt < 2; attempt += 1) {\n const probe = await this.openProbe()\n if (!probe) return\n if (probe.isClosed()) {\n await this.resetProbe()\n continue\n }\n const generation = this.probeGeneration\n const bound = Math.min(READ_BACK_TIMEOUT_MS, this.timeLeft())\n if (generation === this.unreadableGeneration || bound <= 0) return\n try {\n const status = await this.bounded(\n probe.evaluate(() => (globalThis as ProbeScope).__agentQaReadback.snapshot()),\n bound,\n )\n if (status === undefined) this.markUnreadable(generation, bound)\n else if (status === 'read' && generation === this.probeGeneration) this.preImageGeneration = generation\n return\n } catch {\n await this.resetProbe()\n }\n }\n }\n\n // Only the final claim is compared, against a clipboard that changed during the action; an\n // earlier claim is matched only when its text equals a matched final claim.\n private async readBack(writes: PendingClipboardWrite[]): Promise<CapturedClipboardWrite[]> {\n const last = writes.length - 1\n const final = writes[last]!\n const answer = await this.readClipboard(final.frame, final.text)\n return writes.map(({ source, text }, position) => ({\n source,\n text,\n readBack: answer === PROBE_MATCHED && text === final.text\n ? 'matched'\n : answer === PROBE_DIFFERENT && position === last ? 'mismatched' : 'unavailable',\n }))\n }\n\n // PROBE_MATCHED or PROBE_DIFFERENT when the clipboard changed during the action, else undefined.\n // Only the final claim's text enters the probe page and only a number comes back.\n private async readClipboard(frame: Frame, finalText: string): Promise<number | undefined> {\n const generation = this.preImageGeneration\n if (generation < 0 || generation !== this.probeGeneration || generation === this.unreadableGeneration) {\n return undefined\n }\n if (frame.isDetached()) return undefined\n try {\n if (new URL(frame.url()).origin === 'null') return undefined\n } catch {\n return undefined\n }\n const frameBound = Math.min(READ_BACK_TIMEOUT_MS, this.timeLeft())\n if (frameBound <= 0) return undefined\n const secure = await this.bounded(\n frame.evaluate('window.isSecureContext && !!(navigator.clipboard && navigator.clipboard.readText)'),\n frameBound,\n ).catch(() => false)\n if (secure !== true) return undefined\n const probe = await this.openProbe()\n const bound = Math.min(READ_BACK_TIMEOUT_MS, this.timeLeft())\n if (!probe || generation !== this.probeGeneration || bound <= 0) return undefined\n let answer: number | undefined\n try {\n if (probe.isClosed()) throw new Error('probe closed')\n answer = await this.bounded(\n probe.evaluate((text: string) => (globalThis as ProbeScope).__agentQaReadback.compare(text), finalText),\n bound,\n )\n } catch {\n // The probe page closed or crashed, or its context went away; its pre-image went with it.\n await this.resetProbe()\n return undefined\n }\n if (answer === undefined) this.markUnreadable(generation, bound)\n return answer === PROBE_MATCHED || answer === PROBE_DIFFERENT ? answer : undefined\n }\n\n // A read cut short by the step's time or its abort says nothing about the probe.\n private markUnreadable(generation: number, bound: number): void {\n if (bound >= READ_BACK_TIMEOUT_MS && !this.abortSignal?.aborted) this.unreadableGeneration = generation\n }\n\n // Resolves undefined after `ms` or on the action's abort; rejects when `promise` rejects.\n private async bounded<T>(promise: Promise<T>, ms: number): Promise<T | undefined> {\n let off = (): void => undefined\n try {\n return await Promise.race([\n withTimeout(promise, ms),\n new Promise<undefined>((resolve) => { off = this.onAbort(() => { resolve(undefined) }) }),\n ])\n } finally {\n off()\n }\n }\n\n private openProbe(): Promise<Page | undefined> {\n if (!this.readsClipboard) return Promise.resolve(undefined)\n this.probe ??= this.createProbe(this.probeGeneration)\n return this.probe\n }\n\n // A separate context of the app's browser: only the reserved origin loads (a blank document, no\n // init script), every other request is aborted, and only that origin may read the clipboard.\n private async createProbe(generation: number): Promise<Page | undefined> {\n let context: BrowserContext | undefined\n try {\n const browser = this.appContext?.browser()\n if (!browser) return undefined\n context = await browser.newContext()\n if (generation !== this.probeGeneration) {\n await context.close().catch(() => undefined)\n return undefined\n }\n this.probeContext = context\n await context.route('**/*', (route) => {\n let origin = ''\n try {\n origin = new URL(route.request().url()).origin\n } catch { /* aborted below */ }\n return origin === CLIPBOARD_READBACK_ORIGIN\n ? route.fulfill({ contentType: 'text/html', body: '<!doctype html>' })\n : route.abort()\n })\n await context.grantPermissions(['clipboard-read'], { origin: CLIPBOARD_READBACK_ORIGIN })\n const page = await context.newPage()\n page.once('crash', () => {\n if (generation === this.probeGeneration) void this.resetProbe()\n })\n await page.goto(`${CLIPBOARD_READBACK_ORIGIN}/`)\n await page.evaluate(installProbeReadback)\n return page\n } catch {\n if (generation === this.probeGeneration) {\n this.probe = null\n this.probeContext = null\n }\n await context?.close().catch(() => undefined)\n return undefined\n }\n }\n\n /** The bytes of a completed download with this sha256 while the hold keeps them. */\n readDownloadBytes(sha256: string): Uint8Array | undefined {\n return this.heldBytes.get(sha256)\n }\n\n private holdBytes(sha256: string, bytes: Uint8Array): void {\n if (bytes.length > DOWNLOAD_HOLD_FILE_CAP) return\n const previous = this.heldBytes.get(sha256)\n if (previous !== undefined) {\n this.heldBytes.delete(sha256)\n this.heldByteTotal -= previous.length\n }\n this.heldBytes.set(sha256, bytes)\n this.heldByteTotal += bytes.length\n for (const [key, value] of this.heldBytes) {\n if (this.heldByteTotal <= DOWNLOAD_HOLD_TOTAL_CAP) break\n this.heldBytes.delete(key)\n this.heldByteTotal -= value.length\n }\n }\n\n /** Cancels and deletes every held download, clears the held bytes, then closes the read-back probe context. */\n async dispose(): Promise<void> {\n this.heldBytes.clear()\n this.heldByteTotal = 0\n const held = this.held\n this.held = []\n for (const download of held) {\n await download.cancel().catch(() => undefined)\n await download.delete().catch(() => undefined)\n }\n await this.resetProbe()\n }\n\n // Closes only the probe context; held downloads are never touched here.\n private async resetProbe(): Promise<void> {\n const context = this.probeContext\n this.probeGeneration += 1\n this.unreadableGeneration = -1\n this.probe = null\n this.probeContext = null\n await context?.close().catch(() => undefined)\n }\n\n private attachPage(page: Page): void {\n if (this.attachedPages.has(page)) return\n this.attachedPages.add(page)\n page.on('download', (download) => {\n if (!this.startWindow) {\n this.held.push(download)\n return\n }\n this.downloads.push({ download, late: false })\n this.notify?.()\n })\n page.on('close', () => {\n for (const [request, pending] of this.pendingNavigations) if (pending.page === page) this.settleNavigation(request)\n })\n }\n\n // Resolves on a download start, a settled navigation, the abort, or after `ms`.\n private async waitForSignal(ms: number): Promise<void> {\n let off = (): void => undefined\n await new Promise<void>((resolve) => {\n const timer = setTimeout(done, ms)\n function done(): void {\n clearTimeout(timer)\n resolve()\n }\n this.notify = done\n off = this.onAbort(done)\n })\n off()\n this.notify = null\n }\n\n private async finish(download: Download): Promise<DownloadEvidence> {\n const suggestedFilename = download.suggestedFilename()\n const base: Pick<DownloadEvidence, 'suggestedFilename' | 'extension'> = {\n suggestedFilename,\n extension: extname(suggestedFilename),\n }\n let timer: ReturnType<typeof setTimeout> | undefined\n let off = (): void => undefined\n const outcome = await Promise.race([\n download.failure().catch((error: unknown) => (error instanceof Error ? error.message : String(error))),\n new Promise<typeof UNFINISHED>((resolve) => {\n const end = (): void => { resolve(UNFINISHED) }\n timer = setTimeout(end, Math.max(0, this.timeLeft()))\n off = this.onAbort(end)\n }),\n ])\n clearTimeout(timer)\n off()\n if (outcome === UNFINISHED) {\n await download.cancel().catch(() => undefined)\n await download.delete().catch(() => undefined)\n return { ...base, state: 'unfinished' }\n }\n if (outcome !== null) {\n await download.delete().catch(() => undefined)\n return { ...base, state: outcome === 'canceled' ? 'canceled' : 'failed', failure: outcome }\n }\n try {\n const { size, sha256, bytes } = await digest(download)\n if (bytes !== undefined) this.holdBytes(sha256, bytes)\n return { ...base, size, sha256, state: 'completed' }\n } catch (error) {\n return { ...base, state: 'failed', failure: error instanceof Error ? error.message : String(error) }\n } finally {\n await download.delete().catch(() => undefined)\n }\n }\n}\n\nasync function withTimeout<T>(promise: Promise<T>, ms: number): Promise<T | undefined> {\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n return await Promise.race([\n promise,\n new Promise<undefined>((resolve) => { timer = setTimeout(() => resolve(undefined), ms) }),\n ])\n } finally {\n clearTimeout(timer)\n }\n}\n\n// Hashes the stream and tees it into memory while the running size stays within the file cap.\nasync function digest(download: Download): Promise<{ size: number; sha256: string; bytes?: Uint8Array }> {\n const stream = await download.createReadStream()\n const hash = createHash('sha256')\n let size = 0\n let chunks: Buffer[] | undefined = []\n for await (const chunk of stream) {\n const bytes = chunk as Buffer\n size += bytes.length\n hash.update(bytes)\n if (size > DOWNLOAD_HOLD_FILE_CAP) chunks = undefined\n else chunks?.push(bytes)\n }\n const sha256 = hash.digest('hex')\n return chunks === undefined ? { size, sha256 } : { size, sha256, bytes: new Uint8Array(Buffer.concat(chunks)) }\n}\n","import type { Browser, BrowserContext, Dialog, Page } from 'playwright-core'\nimport type {\n ActionsFor,\n ActionResult,\n ConsoleLogEntry,\n NetworkLogEntry,\n ObserveOptions,\n PlatformAdapter,\n PlatformConfig,\n RecordingCapability,\n} from '@vostride/agent-qa-runner'\nimport { assertNever, buildScreenState } from '@vostride/agent-qa-runner'\nimport type { ScreenState } from '@vostride/agent-qa-schema'\nimport { getProvider, registerAllProviders } from '@vostride/agent-qa-core'\nimport { convertKeysForPlatform, isMacPlatform } from '@vostride/agent-qa-runner'\nimport type { FarmWebConfig } from '@vostride/agent-qa-core'\nimport { parseAriaSnapshot, enrichWebNodes, captureWebScroll } from './observer.js'\nimport { extractDom } from './dom-extractor.js'\nimport { ElementResolver, buildRefMap } from './element-resolver.js'\nimport {\n bindingRefusal,\n captureEpoch,\n checkBinding,\n checkDocument,\n disposeEpoch,\n laneRefs,\n snapshotRoot,\n} from './binding.js'\nimport type { ObservationEpoch } from './binding.js'\nimport { validateAction } from './action-validator.js'\nimport { waitForPageReady } from './smart-wait.js'\nimport { runWebFillCompound, runWebScrollCompound, webOpenAppError } from './compound-web.js'\nimport type { RefMap } from './types.js'\nimport { createScreencastRecording } from './recording.js'\n\ninterface PageLogBuffers {\n consoleLogs: ConsoleLogEntry[]\n networkLogs: NetworkLogEntry[]\n consoleDrainIndex: number\n networkDrainIndex: number\n pendingRequests: Map<string, { url: string; method: string; headers: Record<string, string>; startTime: number; postData?: string }>\n}\n\nfunction clickDelayOption(clickDelay?: number): { delay?: number } {\n return clickDelay !== undefined && clickDelay > 0 ? { delay: clickDelay } : {}\n}\n\n// The Plan 10 dispatch seam injects the persisted raw Playwright storage-state blob onto a\n// `storageState`/restore action before it reaches the adapter (the schema restore shape carries\n// only `{op,name}`; the adapter never reads it off disk — D-14). Reading that seam field lives in\n// this `unknown`-typed helper so no cast leaks into the execute switch (no-shims law).\nfunction readSeamStorageState(action: unknown): Parameters<BrowserContext['setStorageState']>[0] {\n return (action as { state: Parameters<BrowserContext['setStorageState']>[0] }).state\n}\n\nexport class FarmWebAdapter implements PlatformAdapter<'web'> {\n readonly platform = 'web' as const\n\n private browser: Browser | null = null\n private context: BrowserContext | null = null\n private page: Page | null = null\n // The native binding of the last observation and its document (438 D-06).\n private lastRefs: RefMap = {}\n private epoch: ObservationEpoch | undefined\n private sessionUrl: string | undefined\n private sessionId: string | undefined\n private testFailed = false\n private exitHandler: (() => void) | null = null\n private credentials: { username: string; accessKey: string } | null = null\n private pageLogBuffers = new Map<Page, PageLogBuffers>()\n private logCaptureConfig: { console: boolean; network: boolean } = { console: true, network: true }\n // Persistent route interception + one-shot dialog arms live until an explicit unroute or\n // test teardown (D-12/D-18); cleanup() drains both so nothing bleeds across tests (Pitfall 7).\n private armedRoutes = new Set<string>()\n private pendingDialogArm: ((dialog: Dialog) => void) | null = null\n private recordingCapability: RecordingCapability | undefined\n private recordingConfig: PlatformConfig['recording']\n\n async setup(config: PlatformConfig): Promise<void> {\n this.recordingConfig = config.recording\n if (!config.farmSession) {\n throw new Error('FarmWebAdapter requires config.farmSession to be set')\n }\n\n registerAllProviders()\n const provider = getProvider('browserstack')\n if (!provider) {\n throw new Error('Unknown farm provider: browserstack')\n }\n\n this.credentials = provider.resolveCredentials(config.farmSession.capabilities as any)\n if (!config.browser?.name) {\n throw new Error('FarmWebAdapter requires config.browser.name to be set')\n }\n const credentials = this.credentials\n\n const farmWebConfig: FarmWebConfig = {\n browser: config.browser,\n credentials,\n testName: (config.farmSession.capabilities as any)?.testName,\n }\n\n const { wsEndpoint } = await provider.resolveWebEndpoint(farmWebConfig)\n\n const { chromium } = await import('playwright-core')\n this.browser = await chromium.connect({ wsEndpoint })\n\n const contextOptions: Record<string, unknown> = {\n viewport: config.browser?.viewport ?? { width: 1280, height: 720 },\n }\n if (config.authState?.storageStatePath) {\n contextOptions.storageState = config.authState.storageStatePath\n }\n this.context = await this.browser.newContext(contextOptions)\n\n // Clipboard write permission — farm-adapter always uses chromium (see chromium.connect above)\n await this.context.grantPermissions(['clipboard-write'])\n\n this.page = await this.context.newPage()\n\n try {\n const cdpSession = await this.page.context().newCDPSession(this.page)\n const result = await cdpSession.send('Browser.getVersion') as Record<string, string>\n await cdpSession.detach()\n // BrowserStack includes session info in the debugger URL or we extract from the WSS endpoint\n // Use REST API to get session details\n const auth = Buffer.from(`${credentials.username}:${credentials.accessKey}`).toString('base64')\n const resp = await fetch('https://api.browserstack.com/automate/builds.json?limit=1&status=running', {\n headers: { Authorization: `Basic ${auth}` },\n })\n if (resp.ok) {\n const builds = await resp.json() as Array<{ automation_build: { hashed_id: string; name: string } }>\n if (builds.length > 0) {\n const buildId = builds[0].automation_build.hashed_id\n const sessResp = await fetch(`https://api.browserstack.com/automate/builds/${buildId}/sessions.json?limit=1`, {\n headers: { Authorization: `Basic ${auth}` },\n })\n if (sessResp.ok) {\n const sessions = await sessResp.json() as Array<{ automation_session: { hashed_id: string; browser_url: string } }>\n if (sessions.length > 0) {\n this.sessionId = sessions[0].automation_session.hashed_id\n this.sessionUrl = sessions[0].automation_session.browser_url\n }\n }\n }\n }\n } catch {\n // Session details extraction is best-effort\n }\n\n this.exitHandler = () => {\n try {\n this.browser?.close()\n } catch {\n // Best-effort cleanup on exit\n }\n }\n process.on('exit', this.exitHandler)\n\n this.logCaptureConfig = { console: config.logCapture?.console !== false, network: config.logCapture?.network !== false }\n this.attachLogListeners(this.page)\n }\n\n get recording(): RecordingCapability | undefined {\n if (!this.page || !this.context || !this.recordingConfig) return undefined\n return this.recordingCapability ??= createScreencastRecording(\n () => this.page,\n this.recordingConfig,\n )\n }\n\n async cleanup(): Promise<void> {\n try { await this.recordingCapability?.stop() } catch { /* best-effort */ }\n this.recordingCapability = undefined\n this.recordingConfig = undefined\n // Pitfall 7: clear persistent route interception, network emulation, and any pending\n // dialog arm BEFORE closing the browser so state never bleeds into the next test.\n if (this.context) {\n try { await this.context.unrouteAll({ behavior: 'ignoreErrors' }) } catch { /* best-effort */ }\n try { await this.context.setOffline(false) } catch { /* best-effort */ }\n }\n if (this.page && this.pendingDialogArm) {\n try { this.page.off('dialog', this.pendingDialogArm) } catch { /* best-effort */ }\n }\n this.armedRoutes.clear()\n this.pendingDialogArm = null\n await disposeEpoch(this.epoch)\n this.epoch = undefined\n\n if (this.browser) {\n await this.browser.close()\n }\n\n // Set session status via REST API after browser is closed\n if (this.sessionId && this.credentials) {\n try {\n const status = this.testFailed ? 'failed' : 'passed'\n const reason = this.testFailed ? 'Test failed' : 'Test passed'\n const auth = Buffer.from(`${this.credentials.username}:${this.credentials.accessKey}`).toString('base64')\n await fetch(`https://api.browserstack.com/automate/sessions/${this.sessionId}.json`, {\n method: 'PUT',\n headers: { Authorization: `Basic ${auth}`, 'Content-Type': 'application/json' },\n body: JSON.stringify({ status, reason }),\n })\n } catch {\n // Status reporting is best-effort\n }\n }\n\n if (this.exitHandler) {\n process.removeListener('exit', this.exitHandler)\n this.exitHandler = null\n }\n\n this.browser = null\n this.context = null\n this.page = null\n this.lastRefs = {}\n this.pageLogBuffers.clear()\n }\n\n async observe(options?: ObserveOptions): Promise<ScreenState> {\n if (!this.page) {\n throw new Error('FarmWebAdapter not initialized — call setup() first')\n }\n const page = this.page\n\n await waitForPageReady(page)\n\n // The epoch is taken before the snapshot, so a document replaced at any point after it is\n // refused as stale-observation at dispatch (438 D-09).\n const epoch = await captureEpoch(page)\n try {\n const state = await this.observeDocument(page, options)\n await disposeEpoch(this.epoch)\n this.epoch = epoch\n return state\n } catch (error) {\n await disposeEpoch(epoch)\n throw error\n }\n }\n\n private async observeDocument(\n page: Page,\n options: ObserveOptions | undefined,\n ): Promise<ScreenState> {\n const ariaTree = await snapshotRoot(page)\n\n const { nodes, nativeRefs } = parseAriaSnapshot(ariaTree)\n if (nodes.length > 0) {\n await enrichWebNodes(page, nodes, nativeRefs)\n }\n const { viewport, scroll } = await captureWebScroll(page)\n\n let domContext: string | undefined\n if (options?.extractDom) {\n try {\n domContext = await extractDom(page)\n } catch {\n // DOM extraction is best-effort — never block observation.\n }\n }\n\n const { state, binding } = buildScreenState({\n platform: 'web',\n nodes,\n viewport,\n scroll,\n coordSpace: 'viewport',\n timestamp: Date.now(),\n url: page.url(),\n ...(domContext !== undefined ? { domContext } : {}),\n })\n\n this.lastRefs = buildRefMap(binding, nodes, nativeRefs, state.elements)\n return state\n }\n\n async execute(action: ActionsFor<'web'>): Promise<ActionResult> {\n if (!this.page) {\n throw new Error('FarmWebAdapter not initialized — call setup() first')\n }\n\n try {\n return await this.executeAction(action)\n } catch (err) {\n let screenshot: Buffer | undefined\n let boundingBox: { x: number; y: number; width: number; height: number } | undefined\n try {\n screenshot = await this.page.screenshot()\n } catch {\n // ignore screenshot failure\n }\n try {\n if ('ref' in action && typeof (action as any).ref === 'string') {\n const resolver = new ElementResolver(this.page, this.lastRefs)\n const box = await resolver.getBoundingBox((action as any).ref)\n if (box) boundingBox = box\n }\n } catch {\n // ignore bounding box failure\n }\n return {\n success: false,\n error: err instanceof Error ? err.message : String(err),\n screenshot,\n boundingBox,\n }\n }\n }\n\n async screenshot(): Promise<Buffer | undefined> {\n try {\n if (this.page) {\n return await this.page.screenshot()\n }\n return undefined\n } catch {\n return undefined\n }\n }\n\n getPage(): Page | null {\n return this.page\n }\n\n markFailed(): void {\n this.testFailed = true\n }\n\n getSessionUrl(): string | undefined {\n return this.sessionUrl\n }\n\n getSessionId(): string | undefined {\n return this.sessionId\n }\n\n drainConsoleLogs(level?: string): ConsoleLogEntry[] {\n const all: ConsoleLogEntry[] = []\n for (const buffers of this.pageLogBuffers.values()) {\n const newLogs = buffers.consoleLogs.slice(buffers.consoleDrainIndex)\n buffers.consoleDrainIndex = buffers.consoleLogs.length\n all.push(...newLogs)\n }\n if (!level) return all\n return all.filter(e => e.level === level)\n }\n\n drainNetworkLogs(urlPattern?: string): NetworkLogEntry[] {\n const all: NetworkLogEntry[] = []\n for (const buffers of this.pageLogBuffers.values()) {\n const newLogs = buffers.networkLogs.slice(buffers.networkDrainIndex)\n buffers.networkDrainIndex = buffers.networkLogs.length\n all.push(...newLogs)\n }\n if (!urlPattern) return all\n return all.filter(e => e.url.includes(urlPattern))\n }\n\n peekNetworkLogs(urlPattern?: string): NetworkLogEntry[] {\n const all: NetworkLogEntry[] = []\n for (const buffers of this.pageLogBuffers.values()) {\n all.push(...buffers.networkLogs.slice(buffers.networkDrainIndex))\n }\n if (!urlPattern) return all\n return all.filter(e => e.url.includes(urlPattern))\n }\n\n private attachLogListeners(page: Page): void {\n const buffers: PageLogBuffers = {\n consoleLogs: [],\n networkLogs: [],\n consoleDrainIndex: 0,\n networkDrainIndex: 0,\n pendingRequests: new Map(),\n }\n this.pageLogBuffers.set(page, buffers)\n\n if (this.logCaptureConfig.console) {\n page.on('console', (msg) => {\n buffers.consoleLogs.push({\n level: msg.type(),\n text: msg.text(),\n location: msg.location(),\n timestamp: Date.now(),\n })\n if (buffers.consoleLogs.length > 1000) {\n buffers.consoleLogs = buffers.consoleLogs.slice(-500)\n }\n })\n }\n\n if (this.logCaptureConfig.network) {\n page.on('request', (request) => {\n buffers.pendingRequests.set(request.url() + request.method(), {\n url: request.url(),\n method: request.method(),\n headers: request.headers(),\n startTime: Date.now(),\n postData: request.postData() ?? undefined,\n })\n })\n\n page.on('response', async (response) => {\n const key = response.url() + response.request().method()\n const pending = buffers.pendingRequests.get(key)\n buffers.pendingRequests.delete(key)\n\n let body: string | undefined\n try {\n const buf = await response.body()\n const ct = response.headers()['content-type'] ?? ''\n if (ct.includes('image/') && !ct.includes('svg')) {\n body = buf.length > 32768 ? undefined : `data:${ct.split(';')[0]};base64,${buf.toString('base64')}`\n } else {\n const text = buf.toString('utf-8')\n body = text.length > 32768 ? text.slice(0, 32768) + '...[truncated]' : text\n }\n } catch {\n body = undefined\n }\n\n buffers.networkLogs.push({\n url: response.url(),\n method: response.request().method(),\n status: response.status(),\n requestHeaders: pending?.headers ?? response.request().headers(),\n responseHeaders: response.headers(),\n body,\n requestBody: pending?.postData,\n startTime: pending?.startTime ?? Date.now(),\n endTime: Date.now(),\n timing: response.request().timing(),\n })\n if (buffers.networkLogs.length > 500) {\n buffers.networkLogs = buffers.networkLogs.slice(-250)\n }\n })\n }\n }\n\n private async resolveTabTargetAsync(tab: { index?: number; title?: string; url?: string }): Promise<Page | undefined> {\n const pages = this.context!.pages()\n if (tab.index !== undefined) {\n return (tab.index >= 0 && tab.index < pages.length) ? pages[tab.index] : undefined\n }\n if (tab.title) {\n for (const p of pages) {\n const t = await p.title()\n if (t.includes(tab.title)) return p\n }\n return undefined\n }\n if (tab.url) {\n return pages.find(p => p.url().includes(tab.url!))\n }\n return undefined\n }\n\n private async executeAction(action: ActionsFor<'web'>): Promise<ActionResult> {\n const page = this.page!\n const resolver = new ElementResolver(page, this.lastRefs)\n\n // 438 D-07, D-09: the element each lane names must still be the one observed; anything else\n // is a typed refusal with no page interaction. A ref absent from the map keeps the Unknown\n // ref path.\n for (const ref of laneRefs(action)) {\n const entry = this.lastRefs[ref]\n if (entry === undefined) continue\n // A scroll's ref names its container, not an input target: only its document is checked,\n // and a lost or child-frame container reads unknown in the compound (436 D-25).\n const check = action.type === 'scroll'\n ? await checkDocument(page, this.epoch)\n : await checkBinding(page, this.epoch, entry)\n if (check.outcome !== 'ok') return bindingRefusal(check.outcome, ref)\n }\n\n if ('ref' in action && typeof (action as any).ref === 'string') {\n const refData = this.lastRefs[(action as any).ref]\n const role = refData?.role\n const validation = validateAction(action, role)\n if (!validation.valid) {\n return { success: false, error: validation.error }\n }\n }\n\n switch (action.type) {\n case 'click': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n const coordinates = box ? { x: box.x + box.width / 2, y: box.y + box.height / 2 } : undefined\n await locator.click({\n ...clickDelayOption(action.clickDelay),\n })\n return { success: true, coordinates, boundingBox: box ?? undefined }\n }\n\n case 'fill': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n return runWebFillCompound(locator, box ?? undefined, action)\n }\n\n case 'openApp': {\n return webOpenAppError()\n }\n\n case 'select': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.selectOption(action.value)\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'navigate': {\n // Fold re-key: the schema `to` discriminant drives url/history/reload on the proven\n // legacy bodies (goto / goBack|goForward / reload).\n switch (action.to) {\n case 'url':\n await page.goto(action.url, { waitUntil: 'domcontentloaded' })\n break\n case 'back':\n await page.goBack({ waitUntil: 'domcontentloaded' })\n break\n case 'forward':\n await page.goForward({ waitUntil: 'domcontentloaded' })\n break\n case 'reload':\n await page.reload({ waitUntil: 'domcontentloaded' })\n break\n }\n await waitForPageReady(page)\n return { success: true }\n }\n\n case 'scroll': {\n return runWebScrollCompound(page, this.lastRefs, action)\n }\n\n case 'waitFor': {\n const timeout = action.timeoutMs\n try {\n switch (action.on) {\n case 'text':\n await page.getByText(action.text).first().waitFor({ state: 'visible', timeout })\n break\n case 'gone':\n await page.getByText(action.text).first().waitFor({ state: 'hidden', timeout })\n break\n case 'selector':\n await page.waitForSelector(action.selector, { timeout })\n break\n }\n } catch {\n const what = action.on === 'selector' ? `selector \"${action.selector}\"` : `text \"${action.text}\"`\n const how = action.on === 'gone' ? 'was still present after' : 'did not appear within'\n return { success: false, error: `waitFor: ${what} ${how} ${timeout}ms.` }\n }\n return { success: true }\n }\n\n case 'delay': {\n await page.waitForTimeout(action.ms)\n return { success: true }\n }\n\n case 'waitForUrl': {\n try {\n // Explicit 30s timeout overrides Playwright's infinite default (Pitfall 2)\n await page.waitForURL(action.pattern, { timeout: 30_000 })\n return { success: true }\n } catch (err) {\n return {\n success: false,\n error: `URL pattern \"${action.pattern}\" did not match within 30s. Hint: use \"**\" wildcards for substring matching (e.g., \"**/dashboard**\"). ${err instanceof Error ? err.message : String(err)}`,\n }\n }\n }\n\n case 'keypress': {\n // Fold re-key of keyDown/keyUp: the schema `mode` selects press / down / up on the\n // platform-normalized keys.\n const effectiveKeys = convertKeysForPlatform(action.keys, {\n enabled: action.convertPlatformKeys !== false,\n isMac: isMacPlatform(),\n })\n for (const key of effectiveKeys) {\n if (action.mode === 'down') {\n await page.keyboard.down(key)\n } else if (action.mode === 'up') {\n await page.keyboard.up(key)\n } else {\n await page.keyboard.press(key)\n }\n }\n return { success: true }\n }\n\n case 'hover': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.hover()\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'paste': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.focus()\n await page.evaluate(`(() => {\n const el = document.activeElement;\n if (!el) return;\n const dt = new DataTransfer();\n dt.setData('text/plain', ${JSON.stringify(action.value)});\n el.dispatchEvent(new ClipboardEvent('paste', {\n clipboardData: dt,\n bubbles: true,\n cancelable: true,\n }));\n })()`)\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'fileUpload': {\n // Paths are pre-resolved to absolute by runner loop.ts (see Plan 01 Task 2)\n const { existsSync } = await import('node:fs')\n for (const filePath of action.files) {\n if (!existsSync(filePath)) {\n return { success: false, error: `File not found: ${filePath}` }\n }\n }\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.setInputFiles(action.files)\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'copy': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n const text = (await locator.textContent()) ?? ''\n await page.evaluate(`navigator.clipboard.writeText(${JSON.stringify(text)})`)\n return { success: true, boundingBox: box ?? undefined, data: { copied: text } }\n }\n\n case 'tab': {\n // Fold re-key of newTab/switchTab: `action` discriminant selects open-new vs switch.\n if (action.action === 'new') {\n const newPage = await this.context!.newPage()\n this.attachLogListeners(newPage)\n await newPage.goto(action.url, { waitUntil: 'domcontentloaded' })\n await waitForPageReady(newPage)\n this.page = newPage\n return { success: true }\n }\n const pages = this.context!.pages()\n let target: Page | undefined\n if (action.index !== undefined) {\n if (action.index < 0 || action.index >= pages.length) {\n return { success: false, error: `Tab index ${action.index} out of range (${pages.length} tabs open)` }\n }\n target = pages[action.index]\n } else if (action.title !== undefined) {\n for (const p of pages) {\n const t = await p.title()\n if (t.includes(action.title)) { target = p; break }\n }\n } else if (action.url !== undefined) {\n target = pages.find(p => p.url().includes(action.url!))\n }\n if (!target) {\n return { success: false, error: `No tab found matching ${JSON.stringify({ index: action.index, title: action.title, url: action.url })}` }\n }\n this.page = target\n return { success: true }\n }\n\n case 'inspect': {\n // Fold re-key of the four read* verbs; output rides ActionResult.data through the\n // existing guardActionData/guardBlob compaction path (no new compaction).\n switch (action.what) {\n case 'console': {\n let entries: ConsoleLogEntry[]\n if (action.tab) {\n const targetPage = await this.resolveTabTargetAsync(action.tab)\n if (!targetPage) {\n return { success: false, error: `No tab found matching ${JSON.stringify(action.tab)}` }\n }\n const buffers = this.pageLogBuffers.get(targetPage)\n entries = buffers ? [...buffers.consoleLogs] : []\n } else {\n entries = []\n for (const buffers of this.pageLogBuffers.values()) {\n entries.push(...buffers.consoleLogs)\n }\n }\n if (action.level) {\n entries = entries.filter(e => e.level === action.level)\n }\n return { success: true, data: entries }\n }\n case 'network': {\n let entries: NetworkLogEntry[]\n if (action.tab) {\n const targetPage = await this.resolveTabTargetAsync(action.tab)\n if (!targetPage) {\n return { success: false, error: `No tab found matching ${JSON.stringify(action.tab)}` }\n }\n const buffers = this.pageLogBuffers.get(targetPage)\n entries = buffers ? [...buffers.networkLogs] : []\n } else {\n entries = []\n for (const buffers of this.pageLogBuffers.values()) {\n entries.push(...buffers.networkLogs)\n }\n }\n if (action.urlPattern) {\n entries = entries.filter(e => e.url.includes(action.urlPattern!))\n }\n return { success: true, data: entries }\n }\n case 'cookies': {\n const cookies = await this.context!.cookies()\n if (action.name) {\n const cookie = cookies.find(c => c.name === action.name) ?? null\n return { success: true, data: cookie }\n }\n return { success: true, data: cookies }\n }\n case 'localStorage': {\n const pageUrl = page.url()\n if (pageUrl === 'about:blank') {\n return { success: true, data: action.key ? null : {} }\n }\n if (action.key) {\n const value = await page.evaluate(\n (k: string) => localStorage.getItem(k), action.key\n )\n return { success: true, data: value }\n }\n const all = await page.evaluate(\n () => Object.fromEntries(\n Object.keys(localStorage).map(k => [k, localStorage.getItem(k)])\n )\n )\n return { success: true, data: all }\n }\n }\n return { success: true }\n }\n\n case 'setCookies': {\n const cookiesWithDefaults = action.cookies.map(c => ({\n ...c,\n url: !c.domain ? page.url() : undefined,\n }))\n await this.context!.addCookies(cookiesWithDefaults)\n return { success: true }\n }\n\n case 'setLocalStorage': {\n await page.evaluate((entries: Array<{ key: string; value: string }>) => {\n for (const { key, value } of entries) {\n localStorage.setItem(key, value)\n }\n }, action.entries)\n return { success: true }\n }\n\n case 'focus': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n await locator.focus()\n return { success: true, boundingBox: box ?? undefined }\n }\n\n case 'assertValue': {\n // D-10: the adapter RESOLVES the requested source to a raw value on ActionResult.data;\n // the runner-side comparator applies the op and judges. The adapter never compares.\n let value: unknown\n if ('expr' in action) {\n value = await page.evaluate(action.expr)\n } else {\n switch (action.source) {\n case 'url':\n value = page.url()\n break\n case 'storage':\n value = page.url() === 'about:blank'\n ? {}\n : await page.evaluate(\n () => Object.fromEntries(\n Object.keys(localStorage).map(k => [k, localStorage.getItem(k)])\n )\n )\n break\n case 'network':\n value = this.peekNetworkLogs()\n break\n case 'expr-result':\n value = undefined\n break\n }\n }\n return { success: true, data: value }\n }\n\n case 'clearText': {\n const loc = resolver.resolve(action.ref)\n const clearBox = await resolver.getBoundingBox(action.ref)\n await loc.clear()\n return { success: true, boundingBox: clearBox ?? undefined }\n }\n\n case 'doubleClick': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n const coordinates = box\n ? action.relativePosition\n ? { x: box.x + action.relativePosition.x, y: box.y + action.relativePosition.y }\n : { x: box.x + box.width / 2, y: box.y + box.height / 2 }\n : undefined\n await locator.dblclick({\n ...(action.relativePosition && { position: action.relativePosition }),\n ...clickDelayOption(action.clickDelay),\n })\n return { success: true, coordinates, boundingBox: box ?? undefined }\n }\n\n case 'rightClick': {\n const locator = resolver.resolve(action.ref)\n const box = await resolver.getBoundingBox(action.ref)\n const coordinates = box\n ? action.relativePosition\n ? { x: box.x + action.relativePosition.x, y: box.y + action.relativePosition.y }\n : { x: box.x + box.width / 2, y: box.y + box.height / 2 }\n : undefined\n await locator.click({\n button: 'right',\n ...(action.relativePosition && { position: action.relativePosition }),\n ...clickDelayOption(action.clickDelay),\n })\n return { success: true, coordinates, boundingBox: box ?? undefined }\n }\n\n case 'route': {\n // D-18: persistent interception until an explicit unroute or teardown. Planner-authored\n // status/headers/body fulfil the matched request (a mocked response body crosses into\n // page context — declared destructive in the risk metadata, Plan 09).\n await this.context!.route(action.urlPattern, async (route) => {\n await route.fulfill({\n status: 200,\n ...(action.contentType !== undefined ? { contentType: action.contentType } : {}),\n ...(action.headers !== undefined ? { headers: action.headers } : {}),\n ...(action.body !== undefined ? { body: action.body } : {}),\n })\n })\n this.armedRoutes.add(action.urlPattern)\n return { success: true }\n }\n\n case 'unroute': {\n if (action.urlPattern !== undefined) {\n await this.context!.unroute(action.urlPattern)\n this.armedRoutes.delete(action.urlPattern)\n } else {\n await this.context!.unrouteAll({ behavior: 'ignoreErrors' })\n this.armedRoutes.clear()\n }\n return { success: true }\n }\n\n case 'networkState': {\n if (action.mode === 'offline') {\n await this.context!.setOffline(true)\n return { success: true }\n }\n // throttle: Chromium-only via CDP; non-Chromium contexts reject newCDPSession (D-18).\n try {\n const cdp = await this.context!.newCDPSession(page)\n await cdp.send('Network.emulateNetworkConditions', {\n offline: false,\n latency: action.latencyMs,\n downloadThroughput: (action.downloadKbps * 1000) / 8,\n uploadThroughput: (action.uploadKbps * 1000) / 8,\n })\n return { success: true }\n } catch (err) {\n return {\n success: false,\n error: `Network throttling is only available on Chromium (via CDP); this context does not support it. ${err instanceof Error ? err.message : String(err)}`,\n }\n }\n }\n\n case 'storageState': {\n // D-14: the adapter only PRODUCES/CONSUMES the raw blob. On save it returns the state +\n // name (the Plan 10 seam strips + persists it — never fs here); on restore it applies the\n // seam-injected blob via setStorageState (present in pinned 1.59.1 — never hand-rolled).\n if (action.op === 'save') {\n const state = await this.context!.storageState()\n return { success: true, data: { name: action.name, state } }\n }\n await this.context!.setStorageState(readSeamStorageState(action))\n return { success: true }\n }\n\n case 'handleDialog': {\n // D-12: one-shot arm for the NEXT dialog; a re-arm REPLACES the pending arm (never stacks).\n if (this.pendingDialogArm) {\n page.off('dialog', this.pendingDialogArm)\n this.pendingDialogArm = null\n }\n const accept = action.accept\n const promptText = action.promptText\n const handler = (dialog: Dialog): void => {\n this.pendingDialogArm = null\n if (accept) {\n void dialog.accept(promptText)\n } else {\n void dialog.dismiss()\n }\n }\n this.pendingDialogArm = handler\n page.once('dialog', handler)\n return { success: true }\n }\n\n case 'executeScript': {\n return { success: false, error: 'executeScript not supported on farm adapter' }\n }\n\n // Runner-minted / author-channel verbs (D-01/D-15/D-16): reportValue, uniqueValue, assertAI,\n // extractAI, and setVariable are intercepted at the dispatch seam and never reach the adapter.\n // A grouped §7.1 defensive case surfaces a dispatch-routing error if one arrives here;\n // assertNever remains the backstop for a genuinely unknown schema verb.\n case 'reportValue':\n case 'uniqueValue':\n case 'assertAI':\n case 'extractAI':\n case 'setVariable':\n return {\n success: false,\n error: `Action \"${action.type}\" is handled by the runner dispatch seam and must not reach the web adapter (runner-minted/author-channel verb). This indicates a dispatch routing error.`,\n }\n\n default:\n return assertNever(action)\n }\n }\n}\n","import { AxeBuilder } from '@axe-core/playwright'\nimport type { Page } from 'playwright-core'\nimport type { AccessibilityViolation } from '@vostride/agent-qa-runner'\n\nexport interface AccessibilityOptions {\n standard?: 'wcag2a' | 'wcag2aa' | 'wcag2aaa'\n disableRules?: string[]\n exclude?: string[]\n}\n\nexport async function runAccessibilityCheck(\n page: Page,\n options?: AccessibilityOptions,\n): Promise<AccessibilityViolation[]> {\n let builder = new AxeBuilder({ page })\n\n if (options?.standard) {\n const tagMap: Record<string, string[]> = {\n 'wcag2a': ['wcag2a'],\n 'wcag2aa': ['wcag2a', 'wcag2aa'],\n 'wcag2aaa': ['wcag2a', 'wcag2aa', 'wcag2aaa'],\n }\n builder = builder.withTags(tagMap[options.standard] ?? ['wcag2a', 'wcag2aa'])\n }\n\n if (options?.disableRules?.length) {\n builder = builder.disableRules(options.disableRules)\n }\n\n if (options?.exclude?.length) {\n for (const selector of options.exclude) {\n builder = builder.exclude(selector)\n }\n }\n\n const results = await builder.analyze()\n\n return results.violations.map(v => ({\n ruleId: v.id,\n impact: v.impact as AccessibilityViolation['impact'],\n description: v.description,\n help: v.help,\n helpUrl: v.helpUrl,\n nodes: v.nodes.slice(0, 10).map(n => ({\n html: n.html,\n target: n.target as string[],\n })),\n }))\n}\n"],"mappings":";AAeA;AAAA,EACE;AAAA,EACA,oBAAAA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,wBAAwB,qBAAqB;;;ACpBtD,SAAS,wBAA0C;;;ACAnD,IAAM,YAAY,oBAAI,IAAI;AAAA,EACxB;AAAA,EAAU;AAAA,EAAS;AAAA,EAAO;AAAA,EAAY;AAAA,EAAQ;AAAA,EAC9C;AAAA,EAAY;AACd,CAAC;AAIM,SAAS,eAAe,MAAwD;AACrF,QAAM,EAAE,UAAU,WAAW,IAAI;AACjC,QAAM,MAAO,WAAmB;AAChC,QAAM,MAAO,WAAmB;AAChC,QAAM,QAAkB,CAAC;AAEzB,WAAS,SAAS,IAAkB;AAClC,QAAI,CAAC,GAAG,gBAAgB,GAAG,YAAY,UAAU,GAAG,YAAY,QAAQ;AACtE,YAAM,QAAQ,IAAI,iBAAiB,EAAE;AACrC,UAAI,MAAM,YAAY,UAAU,MAAM,eAAe,SAAU,QAAO;AAAA,IACxE;AACA,WAAO;AAAA,EACT;AAEA,WAAS,KAAK,MAAW,OAAe,QAAsB;AAC5D,QAAI,QAAQ,UAAU;AACpB,YAAM,KAAK,SAAS,gCAAgC;AACpD;AAAA,IACF;AAEA,aAAS,QAAQ,KAAK,YAAY,OAAO,QAAQ,MAAM,aAAa;AAClE,UAAI,MAAM,aAAa,GAAG;AACxB,cAAM,OAAO,MAAM,YAAY,KAAK;AACpC,YAAI,MAAM;AACR,gBAAM,YAAY,KAAK,SAAS,aAC5B,KAAK,MAAM,GAAG,UAAU,IAAI,QAC5B;AACJ,gBAAM,KAAK,SAAS,SAAS;AAAA,QAC/B;AACA;AAAA,MACF;AAEA,UAAI,MAAM,aAAa,EAAG;AAE1B,YAAM,MAAM,MAAM;AAClB,UAAI,UAAU,IAAI,GAAG,EAAG;AACxB,UAAI,SAAS,KAAK,EAAG;AAErB,YAAM,WAAW,IAAI,YAAY,EAAE,SAAS,GAAG;AAC/C,YAAM,aAAa,MAAM,aAAa,YAAY,KAC7C,MAAM,aAAa,MAAM,KACzB;AAEL,UAAI,QAAQ,IAAI,YAAY;AAC5B,UAAI,UAAU;AACZ,YAAI,CAAC,MAAM,cAAc,CAAC,MAAM,YAAY;AAC1C,mBAAS;AAAA,QACX,OAAO;AACL,mBAAS;AAAA,QACX;AAAA,MACF;AACA,UAAI,WAAY,UAAS,KAAK,UAAU;AAExC,YAAM,KAAK,SAAS,KAAK;AAEzB,UAAI,MAAM,YAAY;AACpB,cAAM,KAAK,SAAS,gBAAgB;AACpC,aAAK,MAAM,YAAY,QAAQ,GAAG,SAAS,MAAM;AAAA,MACnD;AAEA,WAAK,OAAO,QAAQ,GAAG,SAAS,IAAI;AAAA,IACtC;AAAA,EACF;AAEA,OAAK,IAAI,MAAM,GAAG,EAAE;AACpB,SAAO,MAAM,KAAK,IAAI;AACxB;AAOA,eAAsB,WACpB,MACA,MAC6B;AAC7B,QAAM,WAAW,MAAM,YAAY;AACnC,QAAM,aAAa,MAAM,cAAc;AAEvC,MAAI;AACF,WAAO,MAAM,KAAK,SAAS,gBAAgB,EAAE,UAAU,WAAW,CAAC;AAAA,EACrE,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;ADzFA,IAAM,oBAAoB,oBAAI,IAAI;AAAA,EAChC;AAAA,EAAU;AAAA,EAAQ;AAAA,EAAW;AAAA,EAAY;AAAA,EAAS;AAAA,EAAY;AAAA,EAC9D;AAAA,EAAY;AAAA,EAAiB;AAAA,EAAoB;AAAA,EACjD;AAAA,EAAa;AAAA,EAAU;AAAA,EAAc;AAAA,EAAU;AAAA,EAAO;AAAA;AAAA,EAEtD;AAAA,EAAY;AAAA,EAAa;AAAA;AAAA,EAEzB;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAW;AAAA,EAAQ;AACrC,CAAC;AAGD,IAAM,gBAAgB,oBAAI,IAAI;AAAA,EAC5B;AAAA,EAAW;AAAA,EAAQ;AAAA,EAAY;AAAA,EAAW;AAAA,EAAU;AAAA,EACpD;AAAA,EAAe;AAAA,EAAY;AAAA,EAAO;AAAA,EAAU;AAC9C,CAAC;AAED,IAAM,aAAa,CAAC,YAAY,YAAY,UAAU;AAEtD,IAAM,eAAe;AAIrB,IAAM,sBAAsB;AAI5B,IAAM,iBAAiB;AACvB,IAAM,eAAe;AAErB,IAAM,cAAc;AAEpB,SAAS,WAAW,QAAgD;AAClE,QAAM,MAAM,QAAQ,MAAM,WAAW,IAAI,CAAC,GAAG,KAAK;AAClD,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,IAAI,UAAU,KAAK,IAAI,WAAW,GAAG,KAAK,IAAI,SAAS,GAAG,GAAG;AAC/D,QAAI;AACF,YAAM,SAAkB,KAAK,MAAM,GAAG;AACtC,UAAI,OAAO,WAAW,SAAU,QAAO;AAAA,IACzC,QAAQ;AACN,aAAO,IAAI,MAAM,GAAG,EAAE;AAAA,IACxB;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,WAAW,MAAmB,MAAgC;AACrE,QAAMC,QAAO,MAAM,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAC7C,MAAI,CAACA,MAAM;AACX,OAAK,OAAO,KAAK,SAAS,SAAYA,QAAO,GAAG,KAAK,IAAI,IAAIA,KAAI;AACnE;AAkBO,SAAS,kBAAkB,UAGhC;AACA,QAAM,QAAQ,SAAS,MAAM,IAAI;AACjC,QAAM,QAAuB,CAAC;AAC9B,QAAM,aAAqC,CAAC;AAE5C,QAAM,YAAsD,CAAC;AAE7D,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,KAAK,MAAM,YAAY,KAAK,KAAK,MAAM,mBAAmB;AACxE,QAAI,CAAC,MAAO;AAEZ,UAAM,CAAC,EAAE,EAAE,MAAM,MAAM,MAAM,IAAI;AACjC,UAAM,YAAY,KAAK,YAAY;AAGnC,UAAM,gBAAgB,KAAK,SAAS,KAAK,UAAU,EAAE;AACrD,UAAM,QAAQ,KAAK,MAAM,gBAAgB,CAAC;AAE1C,WAAO,UAAU,SAAS,KAAK,UAAU,UAAU,SAAS,CAAC,EAAE,SAAS,OAAO;AAC7E,gBAAU,IAAI;AAAA,IAChB;AACA,QAAI;AACJ,aAAS,IAAI,UAAU,SAAS,GAAG,KAAK,GAAG,KAAK;AAC9C,UAAI,UAAU,CAAC,EAAE,UAAU,QAAW;AACpC,uBAAe,UAAU,CAAC,EAAE;AAC5B;AAAA,MACF;AAAA,IACF;AAEA,QAAI,CAAC,kBAAkB,IAAI,SAAS,KAAK,CAAC,cAAc,IAAI,SAAS,GAAG;AACtE,UAAI,iBAAiB,QAAW;AAC9B,mBAAW,MAAM,YAAY,GAAG,IAAI;AACpC,mBAAW,MAAM,YAAY,GAAG,WAAW,MAAM,CAAC;AAAA,MACpD;AACA,gBAAU,KAAK,EAAE,MAAM,CAAC;AACxB;AAAA,IACF;AAEA,UAAM,cAAc;AAGpB,UAAM,WAAW,QAAQ,MAAM,cAAc;AAC7C,UAAM,YAAY,WAAW,SAAS,CAAC,IAAI;AAG3C,UAAM,aAAqC,CAAC;AAC5C,QAAI,QAAQ;AACV,iBAAW,MAAM,OAAO,SAAS,YAAY,GAAG;AAC9C,YAAI,GAAG,CAAC,MAAM,MAAO;AACrB,mBAAW,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK;AAAA,MAC/B;AAAA,IACF;AAEA,UAAM,OAAoB,EAAE,MAAM,UAAU;AAC5C,QAAI,KAAM,MAAK,OAAO;AACtB,QAAI,gBAAgB,OAAW,MAAK,cAAc;AAClD,QAAI,OAAO,KAAK,UAAU,EAAE,SAAS,EAAG,MAAK,aAAa;AAI1D,QAAI,cAAc,WAAY,MAAK,QAAQ,EAAE,SAAS,MAAM;AAE5D,QAAI,cAAc,IAAI,SAAS,EAAG,YAAW,MAAM,WAAW,MAAM,CAAC;AAErE,UAAM,QAAQ,MAAM;AACpB,UAAM,KAAK,IAAI;AACf,eAAW,KAAK,SAAS;AACzB,cAAU,KAAK,EAAE,OAAO,MAAM,CAAC;AAAA,EACjC;AAEA,SAAO,EAAE,OAAO,WAAW;AAC7B;AAIA,SAAS,sBAAsB;AAC7B,QAAM,MAAO,WAAmB;AAChC,MAAI,iBAAiB,0BAA0B,EAAE,QAAQ,CAAC,OAAY;AACpE,OAAG,MAAM,UAAU;AACnB,OAAG,aAAa,eAAe,MAAM;AAAA,EACvC,CAAC;AACH;AAEA,SAAS,yBAAyB;AAChC,QAAM,MAAO,WAAmB;AAChC,MAAI,iBAAiB,0BAA0B,EAAE,QAAQ,CAAC,OAAY;AACpE,OAAG,MAAM,UAAU;AACnB,OAAG,gBAAgB,aAAa;AAAA,EAClC,CAAC;AACH;AAQA,eAAsB,iBAAiB,MAGpC;AACD,QAAM,mBAAmB,KAAK,aAAa,KAAK,EAAE,OAAO,GAAG,QAAQ,EAAE;AACtE,MAAI;AACF,UAAM,MAAM,MAAM,KAAK,SAAS,MAAM;AACpC,YAAM,IAAI;AACV,YAAM,QAAQ,EAAE,SAAS;AACzB,aAAO;AAAA,QACL,OAAO,EAAE;AAAA,QACT,QAAQ,EAAE;AAAA,QACV,SAAS,EAAE;AAAA,QACX,SAAS,EAAE;AAAA,QACX,cAAc,MAAM;AAAA,QACpB,eAAe,MAAM;AAAA,MACvB;AAAA,IACF,CAAC;AACD,QAAI,OAAO,OAAO,QAAQ,UAAU;AAClC,aAAO;AAAA,QACL,UAAU;AAAA,UACR,OAAO,SAAS,IAAI,OAAO,iBAAiB,KAAK;AAAA,UACjD,QAAQ,SAAS,IAAI,QAAQ,iBAAiB,MAAM;AAAA,QACtD;AAAA,QACA,QAAQ;AAAA,UACN,SAAS,SAAS,IAAI,SAAS,CAAC;AAAA,UAChC,SAAS,SAAS,IAAI,SAAS,CAAC;AAAA,UAChC,cAAc,SAAS,IAAI,cAAc,CAAC;AAAA,UAC1C,eAAe,SAAS,IAAI,eAAe,CAAC;AAAA,QAC9C;AAAA,MACF;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,QAAQ,EAAE,SAAS,GAAG,SAAS,GAAG,cAAc,GAAG,eAAe,EAAE;AAAA,EACtE;AACF;AAcA,eAAsB,eACpB,MACA,OACA,YACe;AACf,MAAI;AAEF,UAAM,UAAqB,CAAC;AAC5B,UAAM,gBAA0B,CAAC;AACjC,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,MAAM,WAAW,CAAC;AACxB,UAAI,CAAC,IAAK;AACV,UAAI;AACF,cAAM,SAAS,MAAM,KAAK,QAAQ,cAAc,GAAG,EAAE,cAAc;AACnE,YAAI,QAAQ;AACV,kBAAQ,KAAK,MAAM;AACnB,wBAAc,KAAK,CAAC;AAAA,QACtB;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AACA,QAAI,QAAQ,WAAW,EAAG;AAG1B,UAAM,MAAM,MAAM,KAAK,SAAS,CAAC,QAAe;AAC9C,YAAM,IAAI;AACV,YAAM,SAAS,EAAE,SAAS;AAC1B,aAAO,IAAI,IAAI,CAAC,OAAY;AAC1B,YAAI,CAAC,GAAI,QAAO;AAChB,cAAM,OAAO,OAAO,GAAG,0BAA0B,aAC7C,GAAG,sBAAsB,IACzB;AACJ,cAAM,QAAQ,OAAO,EAAE,qBAAqB,aAAa,EAAE,iBAAiB,EAAE,IAAI;AAClF,cAAM,SAAS,QACX,MAAM,eAAe,YAAY,MAAM,YAAY,SACnD;AACJ,cAAM,SAAS,CAAC,CAAC,QAAQ,KAAK,QAAQ,KAAK,KAAK,SAAS;AACzD,cAAM,WACJ,GAAG,aAAa,QACf,OAAO,GAAG,iBAAiB,cAAc,GAAG,aAAa,UAAU,KACnE,OAAO,GAAG,iBAAiB,cAAc,GAAG,aAAa,eAAe,MAAM;AACjF,cAAM,OAAO,CAAC,MACZ,OAAO,GAAG,iBAAiB,aAAa,GAAG,aAAa,CAAC,IAAI;AAC/D,cAAM,YAAY,GAAG,YAAY,WAAW,OAAO,GAAG,SAAS,WAAW,GAAG,OAAO;AACpF,cAAM,UAAU,cAAc;AAC9B,cAAM,WAAW,cAAc;AAC/B,eAAO;AAAA,UACL,QAAQ,OACJ,EAAE,GAAG,KAAK,GAAG,GAAG,KAAK,GAAG,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO,IAC/D;AAAA,UACJ,SAAS,CAAC;AAAA,UACV,SAAS,OAAO;AAAA,UAChB,SAAS,UAAU,CAAC;AAAA,UACpB,QAAQ,KAAK,aAAa;AAAA,UAC1B,WAAW,KAAK,YAAY;AAAA,UAC5B,aAAa,KAAK,aAAa;AAAA,UAC/B,OAAO,KAAK,OAAO;AAAA,UACnB,UAAU,KAAK,eAAe,MAAM,WAAW,WAAW,OAAO,GAAG,KAAK,IAAI;AAAA,UAC7E,UAAU,KAAK,eAAe,MAAM,UAAU,GAAG,OAAO,MAAM,WAAW,GAAG,OAAO,OAAO;AAAA,UAC1F,UAAU,KAAK,eAAe,MAAM,UAAU,GAAG,OAAO,QAAQ,WAAW,GAAG,OAAO,OAAO;AAAA,QAC9F;AAAA,MACF,CAAC;AAAA,IACH,GAAG,OAAO;AAEV,QAAI,CAAC,MAAM,QAAQ,GAAG,EAAG;AAKzB,aAAS,IAAI,GAAG,IAAI,cAAc,QAAQ,KAAK;AAC7C,YAAM,OAAO,IAAI,CAAC;AAClB,UAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;AACvC,YAAM,OAAO,MAAM,cAAc,CAAC,CAAC;AAEnC,YAAM,SAAS,aAAc,KAAa,MAAM;AAChD,UAAI,OAAQ,MAAK,SAAS;AAE1B,YAAM,QAA+B,EAAE,GAAI,KAAK,SAAS,CAAC,EAAG;AAC7D,UAAI,OAAQ,KAAa,YAAY,UAAW,OAAM,UAAW,KAAa;AAC9E,UAAI,OAAQ,KAAa,YAAY,UAAW,OAAM,UAAW,KAAa;AAC9E,UAAI,OAAQ,KAAa,YAAY,UAAW,OAAM,UAAW,KAAa;AAC9E,UAAI,OAAO,KAAK,KAAK,EAAE,SAAS,EAAG,MAAK,QAAQ;AAEhD,YAAM,SAAwB,EAAE,GAAI,KAAK,UAAU,CAAC,EAAG;AACvD,YAAM,SAAS,aAAc,KAAa,MAAM;AAChD,UAAI,OAAQ,QAAO,SAAS;AAC5B,YAAM,YAAY,aAAc,KAAa,SAAS;AACtD,UAAI,UAAW,QAAO,YAAY;AAClC,YAAM,cAAc,aAAc,KAAa,WAAW;AAC1D,UAAI,YAAa,QAAO,cAAc;AACtC,YAAM,QAAQ,aAAc,KAAa,KAAK;AAC9C,UAAI,MAAO,QAAO,QAAQ;AAC1B,UAAI,OAAO,KAAK,MAAM,EAAE,SAAS,EAAG,MAAK,SAAS;AAGlD,YAAM,SAAiC,CAAC;AACxC,iBAAW,OAAO,YAAY;AAC5B,cAAM,QAAQ,aAAc,KAAa,GAAG,CAAC;AAC7C,YAAI,MAAO,QAAO,GAAG,IAAI;AAAA,MAC3B;AACA,UAAI,OAAO,KAAK,MAAM,EAAE,SAAS,EAAG,MAAK,aAAa,EAAE,GAAI,KAAK,cAAc,CAAC,GAAI,GAAG,OAAO;AAAA,IAChG;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAEA,SAAS,aACP,OACqE;AACrE,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,IAAI;AACV,QAAM,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,EAAE,OAAO,SAAS,EAAE;AACpD,MACE,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC,KAC1C,OAAO,MAAM,YAAY,OAAO,SAAS,CAAC,KAC1C,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,KAClD,OAAO,WAAW,YAAY,OAAO,SAAS,MAAM,GACpD;AACA,WAAO,EAAE,GAAG,GAAG,OAAO,OAAO;AAAA,EAC/B;AACA,SAAO;AACT;AAEA,SAAS,aAAa,OAAoC;AACxD,SAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ;AACjE;AAEA,eAAsB,YACpB,MACA,SACsB;AACtB,QAAM,UAAU,SAAS,iBACrB,KAAK,QAAQ,QAAQ,cAAc,IACnC,KAAK,QAAQ,OAAO;AAGxB,QAAM,KAAK,SAAS,mBAAmB;AAEvC,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,QAAQ,aAAa;AAAA,EACxC,UAAE;AAEA,UAAM,KAAK,SAAS,sBAAsB;AAAA,EAC5C;AAEA,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,MAAM,KAAK,IAAI;AAGrB,QAAM,EAAE,UAAU,kBAAkB,OAAO,IAAI,MAAM,iBAAiB,IAAI;AAE1E,MAAI;AACJ,MAAI,SAAS,YAAY;AACvB,QAAI;AACF,mBAAa,MAAM,WAAW,IAAI;AAAA,IACpC,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,QAAM,EAAE,OAAO,WAAW,IAAI,WAC1B,kBAAkB,QAAQ,IAC1B,EAAE,OAAO,CAAC,GAAoB,YAAY,CAAC,EAA4B;AAG3E,MAAI,MAAM,SAAS,GAAG;AACpB,UAAM,eAAe,MAAM,OAAO,UAAU;AAAA,EAC9C;AAEA,QAAM,EAAE,MAAM,IAAI,iBAAiB;AAAA,IACjC,UAAU;AAAA,IACV;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA,GAAI,aAAa,EAAE,WAAW,IAAI,CAAC;AAAA,EACrC,CAAC;AAED,SAAO;AACT;AAGA,SAAS,SAAS,OAAgB,UAA0B;AAC1D,SAAO,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK,IAAI,QAAQ;AACvE;;;AE5ZA,SAAS,iBAAiB;AAI1B,IAAM,sBAAsB,oBAAI,IAAI,CAAC,YAAY,WAAW,SAAS,cAAc,aAAa,CAAC;AAQ1F,SAAS,YACd,SACA,OACA,YACA,UACQ;AACR,QAAM,OAAe,CAAC;AACtB,aAAW,CAAC,KAAK,IAAI,KAAK,OAAO,QAAQ,OAAO,GAAG;AACjD,UAAM,OAAO,MAAM,KAAK,KAAK;AAC7B,UAAM,YAAY,WAAW,KAAK,KAAK;AACvC,UAAM,UAAU,SAAS,KAAK,KAAK;AACnC,QAAI,CAAC,QAAQ,cAAc,UAAa,CAAC,QAAS;AAClD,UAAM,QAAwB,EAAE,WAAW,MAAM,KAAK,MAAM,MAAM,KAAK,QAAQ,GAAG;AAClF,UAAM,UAAU,UAAU,SAAS,QAAQ;AAC3C,QAAI,YAAY,OAAW,OAAM,UAAU;AAC3C,QAAI,KAAK,WAAW,OAAW,OAAM,SAAS,KAAK;AACnD,SAAK,GAAG,IAAI;AAAA,EACd;AACA,SAAO;AACT;AAGO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YACU,MACA,MACR;AAFQ;AACA;AAAA,EACP;AAAA,EAEH,QAAQ,KAAsB;AAC5B,UAAM,OAAO,KAAK,KAAK,GAAG;AAC1B,QAAI,CAAC,MAAM;AACT,YAAM,IAAI,MAAM,gBAAgB,GAAG,sBAAsB,OAAO,KAAK,KAAK,IAAI,EAAE,KAAK,IAAI,KAAK,MAAM,EAAE;AAAA,IACxG;AACA,WAAO,KAAK,KAAK,QAAQ,cAAc,KAAK,SAAS;AAAA,EACvD;AAAA,EAEA,cAAc,QAAgC;AAC5C,QAAI,oBAAoB,IAAI,OAAO,IAAI,GAAG;AACxC,aAAO;AAAA,IACT;AAEA,QAAI,SAAS,UAAU,OAAO,OAAO,QAAQ,UAAU;AACrD,aAAO,KAAK,QAAQ,OAAO,GAAG;AAAA,IAChC;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,eAAe,KAAsF;AACzG,QAAI;AACF,YAAM,UAAU,KAAK,QAAQ,GAAG;AAChC,aAAO,MAAM,QAAQ,YAAY;AAAA,IACnC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC3DA,SAAS,oBAAAC,mBAAkB,aAAAC,kBAAiB;AA4B5C,IAAM,gBAAgB,CAAC,OAAO,WAAW,OAAO;AAEhD,IAAM,YAAY;AAClB,IAAM,gBAAgB;AAEtB,IAAM,eAA+C;AAAA,EACnD,qBAAqB;AAAA,EACrB,kBAAkB;AAAA,EAClB,gBAAgB;AAAA,EAChB,mBAAmB;AACrB;AAIA,SAASC,uBAAsB;AAC7B,QAAM,MAAO,WAAmB;AAChC,MAAI,iBAAiB,0BAA0B,EAAE,QAAQ,CAAC,OAAY;AACpE,OAAG,MAAM,UAAU;AACnB,OAAG,aAAa,eAAe,MAAM;AAAA,EACvC,CAAC;AACH;AAEA,SAASC,0BAAyB;AAChC,QAAM,MAAO,WAAmB;AAChC,MAAI,iBAAiB,0BAA0B,EAAE,QAAQ,CAAC,OAAY;AACpE,OAAG,MAAM,UAAU;AACnB,OAAG,gBAAgB,aAAa;AAAA,EAClC,CAAC;AACH;AAGA,eAAsB,aAAa,MAAY,UAA+B,CAAC,GAAoB;AACjG,QAAM,EAAE,WAAW,eAAe,IAAI;AACtC,QAAM,KAAK,SAASD,oBAAmB;AACvC,MAAI;AACF,QAAI,cAAc,OAAW,QAAO,MAAM,KAAK,QAAQ,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAC3F,WAAO,MAAM,KAAK,QAAQ,OAAO,EAAE,aAAa,EAAE,MAAM,MAAM,SAAS,UAAU,CAAC,EAC/E,MAAM,CAAC,UAAmB;AACzB,UAAI,EAAE,iBAAiB,SAAS,MAAM,SAAS,gBAAiB,OAAM;AACtE,aAAO,KAAK,QAAQ,OAAO,EAAE,aAAa;AAAA,QACxC,MAAM;AAAA,QACN,GAAI,mBAAmB,SAAY,EAAE,SAAS,eAAe,IAAI,CAAC;AAAA,MACpE,CAAC;AAAA,IACH,CAAC;AAAA,EACL,UAAE;AACA,UAAM,KAAK,SAASC,uBAAsB;AAAA,EAC5C;AACF;AAGA,eAAsB,aAAa,MAAuC;AACxE,QAAM,WAAW,MAAM,KAAK,eAAe,MAAO,WAAmB,QAAQ;AAC7E,SAAO,EAAE,MAAM,SAAS;AAC1B;AAEA,eAAsB,aAAa,OAAoD;AACrF,MAAI;AACF,UAAM,OAAO,SAAS,QAAQ;AAAA,EAChC,QAAQ;AAAA,EAER;AACF;AAGO,SAAS,gBAAgB,WAA4B;AAC1D,SAAO,UAAU,KAAK,SAAS;AACjC;AAGA,eAAsB,cACpB,MACA,OACuB;AACvB,MAAI,UAAU,UAAa,MAAM,SAAS,KAAM,QAAO,EAAE,SAAS,oBAAoB;AACtF,MAAI;AACF,UAAM,OAAO,MAAM,MAAM,SAAS,SAAS,CAAC,MAAM,MAAO,WAAmB,QAAQ;AACpF,WAAO,SAAS,OAAO,EAAE,SAAS,KAAK,IAAI,EAAE,SAAS,oBAAoB;AAAA,EAC5E,QAAQ;AACN,WAAO,EAAE,SAAS,oBAAoB;AAAA,EACxC;AACF;AAEA,eAAe,cAAc,MAAY,WAAqC;AAC5E,MAAI,CAAC,gBAAgB,SAAS,EAAG,QAAO;AACxC,MAAI;AACF,UAAM,KAAK,QAAQ,cAAc,SAAS,EAAE,MAAM;AAClD,WAAO;AAAA,EACT,SAAS,OAAO;AACd,WAAO,iBAAiB,SAAS,cAAc,KAAK,MAAM,OAAO;AAAA,EACnE;AACF;AAEA,SAAS,KAAK,MAA8C;AAC1D,SAAO,MAAM,QAAQ,QAAQ,GAAG,EAAE,KAAK;AACzC;AAOA,eAAsB,aACpB,MACA,OACA,OACA,UACuB;AACvB,QAAM,WAAW,MAAM,cAAc,MAAM,KAAK;AAChD,MAAI,SAAS,YAAY,KAAM,QAAO;AAEtC,QAAM,EAAE,OAAO,WAAW,IAAI,kBAAkB,MAAM,aAAa,MAAM,QAAQ,CAAC;AAClF,QAAM,QAAQ,WAAW,QAAQ,MAAM,SAAS;AAChD,MAAI,QAAQ,GAAG;AACb,UAAM,WAAW,MAAM,cAAc,MAAM,MAAM,SAAS;AAC1D,WAAO,EAAE,SAAS,WAAW,mBAAmB,eAAe;AAAA,EACjE;AAEA,QAAM,EAAE,MAAM,IAAIC,kBAAiB;AAAA,IACjC,UAAU;AAAA,IACV;AAAA,IACA,UAAU,EAAE,OAAO,GAAG,QAAQ,EAAE;AAAA,IAChC,QAAQ,EAAE,SAAS,GAAG,SAAS,GAAG,cAAc,GAAG,eAAe,EAAE;AAAA,IACpE,YAAY;AAAA,IACZ,WAAW;AAAA,EACb,CAAC;AACD,QAAM,UAAU,MAAM,SAAS,KAAK;AACpC,MACE,YAAY,UACT,QAAQ,SAAS,MAAM,QACvB,KAAK,QAAQ,IAAI,MAAM,KAAK,MAAM,IAAI,KACtC,KAAKC,WAAU,SAAS,MAAM,QAAQ,CAAC,MAAM,KAAK,MAAM,OAAO,GAClE;AACA,WAAO,EAAE,SAAS,kBAAkB;AAAA,EACtC;AACA,SAAO,EAAE,SAAS,KAAK;AACzB;AAGO,SAAS,SAAS,QAA0B;AACjD,QAAM,OAAiB,CAAC;AACxB,aAAW,QAAQ,eAAe;AAChC,UAAM,MAAe,QAAQ,IAAI,QAAQ,IAAI;AAC7C,QAAI,OAAO,QAAQ,SAAU,MAAK,KAAK,GAAG;AAAA,EAC5C;AACA,SAAO;AACT;AAGO,SAAS,eAAe,SAAyB,KAA2B;AACjF,SAAO;AAAA,IACL,SAAS;AAAA,IACT,OAAO,GAAG,OAAO,SAAS,GAAG,WAAM,aAAa,OAAO,CAAC;AAAA,IACxD,UAAU,EAAE,SAAS,EAAE,SAAS,KAAK,WAAW,MAAM,EAAE;AAAA,EAC1D;AACF;;;AC3LO,IAAM,wBAAN,cAAoC,MAAM;AAAA,EACtC;AAAA,EAET,YAAY,SAAiB,YAAqB;AAChD,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,aAAa;AAAA,EACpB;AACF;AAEA,IAAM,aAAa,oBAAI,IAAI,CAAC,WAAW,aAAa,cAAc,UAAU,CAAC;AAC7E,IAAM,eAAe,oBAAI,IAAI,CAAC,WAAW,UAAU,CAAC;AAIpD,IAAM,iBAAiB,oBAAI,IAAI,CAAC,UAAU,YAAY,WAAW,SAAS,cAAc,OAAO,WAAW,SAAS,WAAW,gBAAgB,gBAAgB,gBAAgB,eAAe,eAAe,YAAY,aAAa,eAAe,cAAc,mBAAmB,iBAAiB,aAAa,CAAC;AAGpT,IAAM,mBAAmB,oBAAI,IAAI,CAAC,SAAS,SAAS,YAAY,SAAS,eAAe,cAAc,OAAO,CAAC;AAEvG,SAAS,eAAe,QAA2B,aAAmD;AAE3G,MAAI,eAAe,IAAI,OAAO,IAAI,GAAG;AACnC,WAAO,EAAE,OAAO,KAAK;AAAA,EACvB;AAGA,MAAI,iBAAiB,IAAI,OAAO,IAAI,GAAG;AACrC,WAAO,EAAE,OAAO,KAAK;AAAA,EACvB;AAGA,MAAI,CAAC,aAAa;AAChB,WAAO,EAAE,OAAO,KAAK;AAAA,EACvB;AAEA,QAAM,OAAO,YAAY,YAAY;AAErC,MAAI,OAAO,SAAS,QAAQ;AAC1B,QAAI,WAAW,IAAI,IAAI,GAAG;AACxB,aAAO,EAAE,OAAO,KAAK;AAAA,IACvB;AACA,QAAI,aAAa,IAAI,IAAI,GAAG;AAC1B,aAAO;AAAA,QACL,OAAO;AAAA,QACP,OAAO,uBAAuB,IAAI;AAAA,QAClC,YAAY;AAAA,MACd;AAAA,IACF;AACA,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO,WAAY,OAAe,GAAG,2BAA2B,IAAI;AAAA,MACpE,YAAY;AAAA,IACd;AAAA,EACF;AAEA,MAAI,OAAO,SAAS,aAAa;AAC/B,QAAI,WAAW,IAAI,IAAI,GAAG;AACxB,aAAO,EAAE,OAAO,KAAK;AAAA,IACvB;AACA,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO,WAAY,OAAe,GAAG,2BAA2B,IAAI;AAAA,MACpE,YAAY;AAAA,IACd;AAAA,EACF;AAEA,MAAI,OAAO,SAAS,UAAU;AAC5B,QAAI,aAAa,IAAI,IAAI,GAAG;AAC1B,aAAO,EAAE,OAAO,KAAK;AAAA,IACvB;AACA,QAAI,WAAW,IAAI,IAAI,GAAG;AACxB,aAAO;AAAA,QACL,OAAO;AAAA,QACP,OAAO,yBAAyB,IAAI;AAAA,QACpC,YAAY;AAAA,MACd;AAAA,IACF;AACA,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO,yBAAyB,IAAI;AAAA,MACpC,YAAY;AAAA,IACd;AAAA,EACF;AAGA,SAAO,EAAE,OAAO,KAAK;AACvB;;;ACvFA,IAAM,oBAAoB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EAAY;AAAA,EAAY;AAAA,EACxB;AAAA,EAAkB;AAAA,EAClB;AACF;AAEA,eAAsB,iBAAiB,MAAY,SAA2C;AAC5F,QAAM,UAAU,SAAS,WAAW;AAEpC,QAAM,QAAQ,KAAK;AAAA,IACjB,mBAAmB,IAAI;AAAA,IACvB,IAAI,QAAc,aAAW,WAAW,SAAS,OAAO,CAAC;AAAA,EAC3D,CAAC;AACH;AAIA,SAAS,uBAAuB,WAA8B;AAC5D,QAAM,MAAO,WAAmB;AAChC,SAAO,UAAU,KAAK,CAAC,QAAgB,IAAI,cAAc,GAAG,MAAM,IAAI;AACxE;AAEA,SAAS,iBAAiB,WAA8B;AACtD,QAAM,MAAO,WAAmB;AAChC,SAAO,CAAC,UAAU,KAAK,CAAC,QAAgB,IAAI,cAAc,GAAG,CAAC;AAChE;AAEA,SAAS,yBAAkC;AACzC,QAAM,MAAO,WAAmB;AAChC,SAAO,IAAI,cAAc,EAAE,OAAO,CAAC,MAAW,EAAE,cAAc,SAAS,EAAE,SAAS;AACpF;AAEA,SAAS,yBAAkC;AACzC,QAAM,MAAO,WAAmB;AAChC,SAAO,IAAI,cAAc,EAAE,OAAO,CAAC,MAAW,EAAE,cAAc,SAAS,EAAE,WAAW;AACtF;AAEA,eAAe,mBAAmB,MAA2B;AAE3D,MAAI;AACF,UAAM,KAAK,iBAAiB,oBAAoB,EAAE,SAAS,IAAK,CAAC;AAAA,EACnE,QAAQ;AAAA,EAER;AAGA,MAAI;AACF,UAAM,KAAK,iBAAiB,eAAe,EAAE,SAAS,IAAK,CAAC;AAAA,EAC9D,QAAQ;AAAA,EAER;AAGA,MAAI;AACF,UAAM,gBAAgB,MAAM,KAAK,SAAS,wBAAwB,iBAAiB;AAEnF,QAAI,eAAe;AACjB,UAAI;AACF,cAAM,KAAK,gBAAgB,kBAAkB,mBAAmB,EAAE,SAAS,IAAK,CAAC;AAAA,MACnF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAGA,MAAI;AACF,UAAM,aAAa,MAAM,KAAK,SAAS,sBAAsB;AAE7D,QAAI,YAAY;AACd,UAAI;AACF,cAAM,KAAK,gBAAgB,wBAAwB,QAAW,EAAE,SAAS,IAAK,CAAC;AAAA,MACjF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AACF;;;AChFA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAMK;;;ACIP,IAAM,YAA0B,EAAE,QAAQ,MAAM,mBAAmB,YAAY,UAAU,MAAM;AAG/F,IAAM,sBAAsB;AAE5B,eAAsB,cACpB,MACA,UACA,KACA,QACA,QACA,YACuB;AACvB,QAAM,YAAY,SAAS,GAAG,GAAG;AACjC,MAAI,cAAc,UAAa,gBAAgB,SAAS,EAAG,QAAO;AAClE,MAAI;AACF,UAAM,UAAU,IAAI,gBAAgB,MAAM,QAAQ,EAAE,QAAQ,GAAG;AAC/D,QAAK,MAAM,QAAQ,MAAM,MAAO,EAAG,QAAO;AAC1C,UAAM,WAAW,MAAM,QAAQ;AAAA,MAC7B,CAAC,QAAiB,SAAmC;AACnD,cAAM,CAAC,IAAI,IAAI,IAAI,IAAI;AACvB,cAAM,MAAM;AACZ,cAAM,MAAM,IAAI;AAChB,cAAM,KAAK;AAEX,cAAM,OAAO,SAAS,eAAe,eAAe;AACpD,cAAM,QAAQ,CAAC,SAAsB,SAAS,eAC1C,KAAK,cAAc,KAAK,cACxB,KAAK,eAAe,KAAK;AAC7B,cAAM,WAAW,MAAM;AACrB,gBAAM,OAAO,GAAG,sBAAsB;AACtC,iBAAO,EAAE,GAAG,KAAK,MAAM,KAAK,CAAC,GAAG,GAAG,KAAK,MAAM,KAAK,CAAC,GAAG,OAAO,KAAK,MAAM,KAAK,KAAK,GAAG,QAAQ,KAAK,MAAM,KAAK,MAAM,EAAE;AAAA,QACxH;AACA,cAAM,aAAa,CAAC,SAAuB;AACzC,gBAAM,QAAQ,IAAI,iBAAiB,IAAI;AACvC,gBAAM,WAAW,SAAS,eAAe,MAAM,YAAY,MAAM;AACjE,kBAAQ,aAAa,UAAU,aAAa,YAAY,aAAa,aAAa,MAAM,IAAI,IAAI;AAAA,QAClG;AAIA,cAAM,WAAW,IAAI;AACrB,cAAM,YAAY,IAAI,iBAAiB,IAAI,eAAe;AAC1D,cAAM,iBAAiB,UAAU,cAAc,aAAa,UAAU,cAAc;AACpF,cAAM,qBAAqB,CAAC,SAC1B,SAAS,IAAI,mBAAmB,SAAS,YAAa,kBAAkB,SAAS,IAAI;AACvF,cAAM,WAAW,CAAC,SAAmB;AACnC,cAAI,KAAK,aAAc,QAAO,KAAK;AACnC,cAAI,KAAK,cAAe,QAAO,KAAK;AACpC,gBAAM,SAAS,KAAK;AACpB,iBAAO,UAAU,OAAO,OAAO,OAAO,OAAO;AAAA,QAC/C;AAGA,YAAI,CAAC,mBAAmB,EAAE,GAAG;AAC3B,cAAI,WAAW,EAAE,GAAG;AAClB,kBAAMC,UAAS,GAAG,IAAI;AACtB,eAAG,SAAS,IAAI,EAAE;AAClB,kBAAMC,SAAQ,GAAG,IAAI;AACrB,mBAAO,EAAE,QAAQ,SAAS,GAAG,mBAAmB,WAAW,UAAUD,YAAWC,QAAO,SAAS,EAAE,QAAAD,SAAQ,OAAAC,QAAO,KAAK,MAAM,EAAE,EAAE,EAAE;AAAA,UACpI;AACA,mBAAS,SAAS,SAAS,EAAE,GAAG,UAAU,CAAC,mBAAmB,MAAM,GAAG,SAAS,SAAS,MAAM,GAAG;AAChG,gBAAI,CAAC,WAAW,MAAM,EAAG;AACzB,kBAAMD,UAAS,OAAO,IAAI;AAC1B,mBAAO,SAAS,IAAI,EAAE;AACtB,kBAAMC,SAAQ,OAAO,IAAI;AACzB,mBAAO,EAAE,QAAQ,SAAS,GAAG,mBAAmB,YAAY,UAAUD,YAAWC,QAAO,SAAS,EAAE,QAAAD,SAAQ,OAAAC,QAAO,KAAK,MAAM,MAAM,EAAE,EAAE;AAAA,UACzI;AAAA,QACF;AAGA,YAAI,CAAC,UAAU;AACb,gBAAM,IAAI,IAAI;AACd,gBAAM,IAAI,IAAI;AACd,cAAI,SAAS,IAAI,EAAE;AACnB,iBAAO,EAAE,QAAQ,SAAS,GAAG,mBAAmB,mBAAmB,UAAU,MAAM,IAAI,WAAW,MAAM,IAAI,QAAQ;AAAA,QACtH;AACA,cAAM,SAAS,SAAS,IAAI;AAC5B,iBAAS,SAAS,IAAI,EAAE;AACxB,cAAM,QAAQ,SAAS,IAAI;AAC3B,cAAM,MAAM,MAAM,QAAQ;AAC1B,eAAO;AAAA,UACL,QAAQ,SAAS;AAAA,UACjB,mBAAmB;AAAA,UACnB,UAAU,WAAW;AAAA,UACrB,GAAI,MAAM,IAAI,EAAE,SAAS,EAAE,QAAQ,OAAO,IAAI,EAAE,IAAI,CAAC;AAAA,QACvD;AAAA,MACF;AAAA,MACA,CAAC,QAAQ,QAAQ,UAAU;AAAA,MAC3B,EAAE,SAAS,oBAAoB;AAAA,IACjC;AACA,WAAO,YAAY,OAAO,aAAa,WAAY,WAA4B;AAAA,EACjF,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;ADvFA,eAAsB,eAAe,SAA+C;AAClF,MAAI;AACF,WAAO,MAAM,QAAQ,WAAW;AAAA,EAClC,QAAQ;AACN,QAAI;AACF,YAAM,QAAQ,MAAM,QAAQ,SAAS,CAAC,OAAO;AAC3C,cAAM,OAAO;AACb,eAAQ,KAAK,SAAS,KAAK;AAAA,MAC7B,CAAC;AACD,aAAO,OAAO,UAAU,WAAW,QAAQ;AAAA,IAC7C,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAGA,eAAsB,mBACpB,SACA,aACA,QACuB;AACvB,QAAM,WAAW,OAAO,cAAc;AAEtC,QAAM,QAAQ,WAAY,MAAM,eAAe,OAAO,KAAM,KAAK;AAEjE,QAAM,SAAU,MAAM,QAAQ,aAAa,MAAM,MAAO;AAExD,MAAI,UAAU;AACZ,UAAM,QAAQ,MAAM;AACpB,UAAM,QAAQ,MAAM,KAAK;AACzB,UAAM,QAAQ,kBAAkB,OAAO,IAAI;AAAA,EAC7C,OAAO;AACL,UAAM,QAAQ,KAAK,OAAO,IAAI;AAAA,EAChC;AAEA,QAAM,WAAW,WAAW,QAAQ,OAAO,OAAO,OAAO;AACzD,QAAM,SAAS,MAAM,eAAe,OAAO;AAC3C,QAAM,MAAM,cAAc,EAAE,YAAY,IAAI,CAAC;AAG7C,MAAI,WAAW,QAAW;AACxB,WAAO,EAAE,SAAS,MAAM,GAAG,KAAK,UAAU,EAAE,aAAa,EAAE,MAAM,QAAQ,SAAS,aAAa,EAAE,EAAE;AAAA,EACrG;AAEA,QAAM,UAAU,kBAAkB,EAAE,UAAU,QAAQ,OAAO,CAAC;AAC9D,MAAI,QAAQ,MAAM,OAAO,QAAQ;AAC/B,UAAM,QAAQ,MAAM,OAAO;AAAA,EAC7B;AACA,QAAM,WAAW;AAAA,IACf,GAAI,QAAQ,OAAO,EAAE,YAAY,QAAQ,KAAK,IAAI,CAAC;AAAA,IACnD,aAAa;AAAA,MACX,MAAM;AAAA,MACN,SAAS,QAAQ;AAAA,MACjB,GAAI,QAAQ,SAAS,EAAE,QAAQ,KAAK,IAAI,CAAC;AAAA,IAC3C;AAAA,EACF;AACA,SAAO,QAAQ,KACX,EAAE,SAAS,MAAM,GAAG,KAAK,SAAS,IAClC,EAAE,SAAS,OAAO,OAAO,QAAQ,qBAAqB,GAAG,KAAK,SAAS;AAC7E;AAEA,SAAS,SAAS,WAAsB,WAAgF;AACtH,UAAQ,WAAW;AAAA,IACjB,KAAK;AACH,aAAO,EAAE,IAAI,GAAG,IAAI,WAAW,MAAM,WAAW;AAAA,IAClD,KAAK;AACH,aAAO,EAAE,IAAI,GAAG,IAAI,CAAC,WAAW,MAAM,WAAW;AAAA,IACnD,KAAK;AACH,aAAO,EAAE,IAAI,WAAW,IAAI,GAAG,MAAM,aAAa;AAAA,IACpD,KAAK;AACH,aAAO,EAAE,IAAI,CAAC,WAAW,IAAI,GAAG,MAAM,aAAa;AAAA,EACvD;AACF;AAGA,eAAe,OAAO,MAA2B;AAC/C,QAAM,KAAK,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAMjB;AACL;AASA,SAAS,kBAAkB,MAAqB;AAS9C,QAAM,IAAI;AAUV,QAAM,MAAM,EAAE;AACd,QAAM,OAAO,IAAI,oBAAoB,IAAI;AACzC,QAAM,OAAO,CAAC,QAAY;AAAA,IACxB,GAAG,GAAG;AAAA,IACN,GAAG,GAAG;AAAA,IACN,MAAM,GAAG,cAAc,GAAG;AAAA,IAC1B,MAAM,GAAG,eAAe,GAAG;AAAA,EAC7B;AACA,QAAM,UAAU,CAAC,UAA2B,UAAU,UAAU,UAAU,YAAY,UAAU;AAChG,QAAM,YAAY,EAAE,iBAAiB,IAAI,eAAe;AACxD,QAAM,iBAAiB,UAAU,cAAc,aAAa,UAAU,cAAc;AACpF,QAAM,UAAU,oBAAI,IAAiC;AACrD,UAAQ,IAAI,MAAM,KAAK,IAAI,CAAC;AAC5B,QAAM,MAAM,IAAI,iBAAiB,GAAG;AACpC,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK,GAAG;AACtC,UAAM,KAAK,IAAI,CAAC;AAChB,QAAI,OAAO,QAAQ,OAAO,IAAI,gBAAiB;AAC/C,QAAI,OAAO,IAAI,QAAQ,eAAgB;AACvC,UAAM,IAAI,KAAK,EAAE;AACjB,QAAI,GAAG,SAAS,aAAa,EAAE,OAAO,EAAE,QAAQ,GAAI;AACpD,UAAM,QAAQ,EAAE,iBAAiB,EAAE;AACnC,QAAI,CAAC,QAAQ,SAAS,aAAa,MAAM,YAAY,MAAM,SAAS,EAAG;AACvE,YAAQ,IAAI,IAAI,CAAC;AAAA,EACnB;AACA,QAAM,QAAsG;AAAA,IAC1G;AAAA,IACA,QAAQ;AAAA,IACR,UAAU,MAAM;AAAA,EAClB;AACA,QAAM,WAAW,CAAC,UAAU;AAC1B,UAAM,SAAS,MAAM;AAAA,EACvB;AACA,IAAE,iBAAiB,SAAS,MAAM,UAAU,EAAE,SAAS,MAAM,MAAM,MAAM,SAAS,KAAK,CAAC;AACxF,SAAO;AACT;AAKA,SAAS,iBAAiB,OAAyB;AAUjD,QAAM,IAAI;AAIV,QAAM,IAAI;AACV,MAAI,CAAC,EAAE,QAAQ;AACb,MAAE,oBAAoB,SAAS,EAAE,UAAU,EAAE,SAAS,KAAK,CAAC;AAC5D,WAAO;AAAA,EACT;AACA,QAAM,OAAO,EAAE,SAAS,oBAAoB,EAAE,SAAS;AACvD,QAAM,QAAc,CAAC;AACrB,WAAS,KAAgB,EAAE,QAAQ,IAAI,KAAK,GAAG,eAAe;AAC5D,QAAI,EAAE,QAAQ,IAAI,EAAE,KAAK,CAAC,MAAM,SAAS,EAAE,EAAG,OAAM,KAAK,EAAE;AAAA,EAC7D;AACA,MAAI,CAAC,MAAM,SAAS,IAAI,EAAG,OAAM,KAAK,IAAI;AAC1C,SAAO;AAAA,IACL,QAAQ,MAAM,IAAI,CAAC,OAAO,EAAE,QAAQ,IAAI,EAAE,CAAC;AAAA,IAC3C,OAAO,MAAM,IAAI,CAAC,QAAQ;AAAA,MACxB,GAAG,GAAG;AAAA,MACN,GAAG,GAAG;AAAA,MACN,MAAM,GAAG,cAAc,GAAG;AAAA,MAC1B,MAAM,GAAG,eAAe,GAAG;AAAA,IAC7B,EAAE;AAAA,EACJ;AACF;AAOA,eAAe,kBAAkB,MAAY,IAAY,IAAY,MAA+C;AAClH,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,KAAK,eAAe,mBAAmB,IAAI;AAAA,EAC5D,QAAQ;AACN,aAAS;AAAA,EACX;AACA,QAAM,KAAK,MAAM,MAAM,IAAI,EAAE;AAC7B,QAAM,OAAO,IAAI;AACjB,MAAI,CAAC,OAAQ,QAAO;AACpB,MAAI;AACF,UAAM,QAAS,MAAM,OAAO,SAAS,gBAAgB;AACrD,QAAI,CAAC,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,MAAM,MAAM,KAAK,CAAC,MAAM,QAAQ,MAAM,KAAK,GAAG;AACtG,aAAO;AAAA,IACT;AACA,WAAO,EAAE,QAAQ,MAAM,QAAQ,OAAO,MAAM,MAAM;AAAA,EACpD,QAAQ;AACN,WAAO;AAAA,EACT,UAAE;AACA,UAAM,OAAO,QAAQ,EAAE,MAAM,MAAM,MAAS;AAAA,EAC9C;AACF;AAMO,IAAM,yBAAyB;AAiBtC,SAAS,gBAAgB,UAA8B;AACrD,QAAM,IAAI;AACV,QAAM,MAAM,EAAE;AACd,QAAM,OAAO,IAAI;AACjB,QAAM,YAAY,EAAE,iBAAiB,IAAI;AACzC,QAAM,iBAAiB,UAAU,cAAc,aAAa,UAAU,cAAc;AACpF,QAAM,WAAW,CAAC,SAAmB,KAAK,gBAAgB,KAAK,iBAAiB,KAAK,YAAY,QAAQ;AACzG,QAAM,QAAQ,CAAC,SAAuB;AACpC,UAAM,QAAQ,EAAE,iBAAiB,IAAI;AACrC,WAAO,MAAM,cAAc,aAAa,MAAM,cAAc;AAAA,EAC9D;AACA,QAAM,UAAU,CAAC,SAAuB;AACtC,UAAM,WAAW,EAAE,iBAAiB,IAAI,EAAE;AAC1C,WAAO,aAAa,WAAW,aAAa;AAAA,EAC9C;AACA,QAAM,eAAe,CAAC,SAAqB;AACzC,UAAM,QAAQ,IAAI,YAAY;AAC9B,UAAM,mBAAmB,IAAI;AAC7B,WAAO,MAAM,KAAK,MAAM,eAAe,CAAC;AAAA,EAC1C;AACA,QAAM,WAAW;AACjB,QAAM,YAAY,CAAC,MACjB,EAAE,oBAAoB,UAAU,kCAAkC,KAAK,EAAE,eAAe;AAC1F,QAAM,cAAc,CAAC,MACnB,EAAE,YAAY,UAAU,EAAE,YAAY,YAAa,EAAE,YAAY,QAAQ,UAAU,CAAC;AACtF,QAAM,cAAc,CAAC,MAAW,GAAW,MAAuB;AAChE,UAAM,IAAI,EAAE,iBAAiB,IAAI;AACjC,QAAI,EAAE,YAAY,IAAK,QAAO;AAC9B,QAAI,KAAK,iBAAiB,+BAAgC,QAAO;AACjE,QAAI,SAAS,KAAK,KAAK,OAAO,EAAG,QAAO;AAExC,QAAI,KAAK,cAAc,KAAK,QAAQ,SAAS,GAAG,EAAG,QAAO;AAC1D,QAAI,CAAC,UAAU,CAAC,KAAK,EAAE,mBAAmB,OAAQ,QAAO;AACzD,QAAI,CAAC,YAAY,EAAE,iBAAiB,MAAM,UAAU,CAAC,EAAG,QAAO;AAC/D,QAAI,CAAC,YAAY,EAAE,iBAAiB,MAAM,SAAS,CAAC,EAAG,QAAO;AAC9D,WAAO,CAAC,aAAa,IAAI,EAAE;AAAA,MACzB,CAAC,MAAM,EAAE,QAAQ,KAAK,KAAK,EAAE,SAAS,EAAE,OAAO,KAAK,KAAK,EAAE;AAAA,IAC7D;AAAA,EACF;AACA,QAAM,QAAQ,CAAC,OAAqB;AAClC,UAAM,QAAQ,EAAE,iBAAiB,EAAE;AACnC,QAAI,MAAM,eAAe,UAAW,QAAO,EAAE,OAAO,SAAS;AAC7D,aAAS,IAAI,IAAI,GAAG,IAAI,SAAS,CAAC,GAAG;AACnC,UAAI,EAAE,iBAAiB,CAAC,EAAE,YAAY,IAAK,QAAO,EAAE,OAAO,SAAS;AAAA,IACtE;AACA,QAAI,IAAI,GAAG,sBAAsB;AACjC,UAAM,SAAS,MAAM,YAAY,cAAc,EAAE,UAAU,KAAK,EAAE,WAAW;AAC7E,QAAI,QAAQ;AAEV,YAAM,UAAU,MAAM,EAAE,KAAK,MAAM,SAAS,UAAU,MAAM,aAAa;AACzE,UAAI,MAAM,YAAY,cAAc,QAAS,QAAO,EAAE,OAAO,UAAU;AACvE,YAAM,QAAQ,aAAa,EAAE,EAAE,OAAO,CAAC,MAAM,EAAE,QAAQ,KAAK,EAAE,SAAS,CAAC;AACxE,UAAI,MAAM,WAAW,EAAG,QAAO,EAAE,OAAO,UAAU;AAClD,UAAI;AAAA,QACF,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAAA,QAC1C,KAAK,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC;AAAA,QACxC,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AAAA,QAC5C,QAAQ,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;AAAA,MAChD;AAAA,IACF,WAAW,EAAE,QAAQ,KAAK,EAAE,SAAS,GAAG;AACtC,aAAO,EAAE,OAAO,SAAS;AAAA,IAC3B;AACA,QAAI,OAAO,KAAK,IAAI,EAAE,MAAM,CAAC;AAC7B,QAAI,MAAM,KAAK,IAAI,EAAE,KAAK,CAAC;AAC3B,QAAI,QAAQ,KAAK,IAAI,EAAE,OAAO,EAAE,UAAU;AAC1C,QAAI,SAAS,KAAK,IAAI,EAAE,QAAQ,EAAE,WAAW;AAC7C,QAAI,EAAE,QAAQ,QAAQ,SAAS,KAAM,QAAO,EAAE,OAAO,SAAS;AAC9D,QAAI,aAAa,QAAQ,EAAE;AAC3B,aAAS,IAAI,SAAS,EAAE,GAAG,KAAK,MAAM,MAAM,IAAI,SAAS,CAAC,GAAG;AAC3D,UAAI,EAAE,MAAM,IAAI,QAAQ,mBAAmB,CAAC,cAAc,MAAM,CAAC,GAAG;AAClE,cAAM,IAAI,EAAE,sBAAsB;AAClC,cAAM,KAAK,EAAE,OAAO,EAAE;AACtB,cAAM,KAAK,EAAE,MAAM,EAAE;AACrB,eAAO,KAAK,IAAI,MAAM,EAAE;AACxB,cAAM,KAAK,IAAI,KAAK,EAAE;AACtB,gBAAQ,KAAK,IAAI,OAAO,KAAK,EAAE,WAAW;AAC1C,iBAAS,KAAK,IAAI,QAAQ,KAAK,EAAE,YAAY;AAC7C,YAAI,EAAE,QAAQ,QAAQ,SAAS,KAAM,QAAO,EAAE,OAAO,UAAU;AAAA,MACjE;AACA,UAAI,QAAQ,CAAC,EAAG,cAAa;AAAA,IAC/B;AACA,QAAI,QAAQ,OAAO,KAAK,SAAS,MAAM,EAAG,QAAO,EAAE,OAAO,UAAU;AACpE,UAAM,KAAK,OAAO,SAAS;AAC3B,UAAM,KAAK,MAAM,UAAU;AAC3B,UAAM,OAAO,EAAE,OAAO,WAAW,MAAM,EAAE,MAAM,KAAK,OAAO,OAAO,EAAE;AACpE,eAAW,OAAO,GAAG,YAAY,EAAE,kBAAkB,GAAG,CAAC,GAAG;AAC1D,UAAI,QAAQ,MAAM,GAAG,SAAS,GAAG,EAAG,QAAO;AAC3C,UAAI,MAAM,kBAAkB,UAAU,QAAQ;AAC5C,iBAAS,IAAI,SAAS,EAAE,GAAG,GAAG,IAAI,SAAS,CAAC,GAAG;AAC7C,cAAI,MAAM,IAAK,QAAO;AAAA,QACxB;AAAA,MACF;AACA,UAAI,CAAC,YAAY,KAAK,GAAG,CAAC,EAAG,QAAO,EAAE,OAAO,UAAU;AAAA,IACzD;AACA,WAAO,EAAE,OAAO,UAAU;AAAA,EAC5B;AACA,SAAO,SAAS,IAAI,KAAK;AAC3B;AAQA,SAAS,oBAAoB,cAAuB,KAAwB;AAC1E,QAAM,IAAI;AACV,QAAM,MAAM,EAAE;AACd,QAAM,OAAO,IAAI;AACjB,QAAM,KAAK;AACX,QAAM,YAAY,EAAE,iBAAiB,IAAI;AACzC,QAAM,iBAAiB,UAAU,cAAc,aAAa,UAAU,cAAc;AACpF,QAAM,WAAW,CAAC,SAAmB,KAAK,gBAAgB,KAAK,iBAAiB,KAAK,YAAY,QAAQ;AACzG,QAAM,QAAQ,CAAC,SAAuB;AACpC,UAAMC,SAAQ,EAAE,iBAAiB,IAAI;AACrC,WAAOA,OAAM,cAAc,aAAaA,OAAM,cAAc;AAAA,EAC9D;AACA,MAAI,EAAE,iBAAiB,EAAE,EAAE,eAAe,UAAW,QAAO;AAC5D,WAAS,IAAI,IAAI,GAAG,IAAI,SAAS,CAAC,GAAG;AACnC,QAAI,EAAE,iBAAiB,CAAC,EAAE,YAAY,IAAK,QAAO;AAAA,EACpD;AACA,WAAS,IAAI,IAAI,GAAG,IAAI,SAAS,CAAC,GAAG;AACnC,UAAMA,SAAQ,EAAE,iBAAiB,CAAC;AAClC,QAAIA,OAAM,cAAc,OAAQ,QAAO;AACvC,UAAM,OAAO,OAAO,WAAWA,OAAM,IAAI;AACzC,QAAI,OAAO,SAAS,IAAI,KAAK,SAAS,EAAG,QAAO;AAAA,EAClD;AACA,QAAM,QAAQ,EAAE,iBAAiB,EAAE;AACnC,QAAM,UAAU,OAAO,WAAW,MAAM,WAAW,KAAK;AACxD,QAAM,SAAS,OAAO,WAAW,MAAM,UAAU,KAAK;AACtD,QAAM,WAAW,OAAO,WAAW,MAAM,YAAY,KAAK;AAC1D,QAAM,YAAY,OAAO,WAAW,MAAM,aAAa,KAAK;AAC5D,QAAM,IAAI,GAAG,sBAAsB;AACnC,QAAM,KAAK,EAAE,OAAO,GAAG,aAAa;AACpC,QAAM,KAAK,EAAE,MAAM,GAAG,YAAY;AAClC,MAAI,OAAO,KAAK,IAAI,IAAI,OAAO,IAAI,IAAI,CAAC;AACxC,MAAI,MAAM,KAAK,IAAI,IAAI,MAAM,IAAI,IAAI,CAAC;AACtC,MAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,IAAI,KAAK,GAAG,cAAc,UAAU,UAAU,EAAE,UAAU;AAC3F,MAAI,SAAS,KAAK,IAAI,IAAI,SAAS,IAAI,KAAK,GAAG,eAAe,SAAS,WAAW,EAAE,WAAW;AAC/F,MAAI,EAAE,QAAQ,QAAQ,SAAS,KAAM,QAAO;AAC5C,WAAS,IAAI,SAAS,EAAE,GAAG,KAAK,MAAM,MAAM,IAAI,SAAS,CAAC,GAAG;AAC3D,QAAI,MAAM,IAAI,QAAQ,eAAgB;AACtC,QAAI,CAAC,MAAM,CAAC,EAAG;AACf,UAAM,IAAI,EAAE,sBAAsB;AAClC,UAAM,KAAK,EAAE,OAAO,EAAE;AACtB,UAAM,KAAK,EAAE,MAAM,EAAE;AACrB,WAAO,KAAK,IAAI,MAAM,EAAE;AACxB,UAAM,KAAK,IAAI,KAAK,EAAE;AACtB,YAAQ,KAAK,IAAI,OAAO,KAAK,EAAE,WAAW;AAC1C,aAAS,KAAK,IAAI,QAAQ,KAAK,EAAE,YAAY;AAC7C,QAAI,EAAE,QAAQ,QAAQ,SAAS,KAAM,QAAO;AAAA,EAC9C;AACA,QAAM,MAAM,GAAG,YAAY,EAAE,kBAAkB,OAAO,SAAS,IAAI,MAAM,UAAU,CAAC;AACpF,MAAI,QAAQ,GAAI,QAAO;AACvB,SAAO,EAAE,MAAM,KAAK,OAAO,OAAO;AACpC;AAEA,SAAS,aAAa,OAAqB,QAAyB;AAClE,SAAO,MACJ,UAAU,MAAM,EAChB,GAAG,MAAM,WAAW,MAAM,CAAC,EAC3B,GAAG,MAAM,aAAa,MAAM,CAAC,EAC7B,GAAG,MAAM,WAAW,MAAM,CAAC;AAChC;AAEA,eAAe,QAAQ,OAAqB,QAAmC;AAC7E,QAAM,SAAS,MAAM,aAAa,OAAO,MAAM,EAAE,YAAY,eAAe;AAC5E,MAAI,CAAC,MAAM,QAAQ,MAAM,EAAG,OAAM,IAAI,MAAM,wBAAwB;AACpE,SAAO,OAAO,IAAI,CAAC,cAAsC;AACvD,UAAM,QAAQ,WAAW;AACzB,QAAI,UAAU,aAAa,WAAW,KAAM,QAAO,EAAE,OAAO,MAAM,UAAU,KAAK;AACjF,WAAO,EAAE,OAAO,UAAU,WAAW,WAAW,UAAU;AAAA,EAC5D,CAAC;AACH;AAEA,SAAS,QAAQ,QAAuD;AACtE,MAAI,OAAO,SAAS,SAAS,EAAG,QAAO;AACvC,MAAI,OAAO,SAAS,SAAS,EAAG,QAAO;AACvC,SAAO;AACT;AAGA,eAAe,mBAAmB,OAAc,KAAiC;AAC/E,MAAI,UAAU;AACd,MAAI,YAAY;AAChB,WAAS,SAAS,QAAQ,YAAY,GAAG,QAAQ,SAAS,QAAQ,YAAY,GAAG;AAC/E,UAAM,SAAS,MAAM,QAAQ,aAAa;AAC1C,QAAI;AACF,YAAM,OAAQ,MAAM,OAAO,SAAS,qBAAqB,SAAS;AAClE,UAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAC9C,kBAAY;AAAA,IACd,UAAE;AACA,YAAM,OAAO,QAAQ,EAAE,MAAM,MAAM,MAAS;AAAA,IAC9C;AACA,cAAU;AAAA,EACZ;AACA,SAAO;AACT;AAIA,eAAe,gBAAgB,OAAc,QAA2C;AACtF,MAAI;AACF,UAAM,SAA6B,CAAC;AACpC,eAAW,aAAa,MAAM,QAAQ,OAAO,MAAM,GAAG;AACpD,UAAI,UAAU,UAAU,aAAa,UAAU,QAAS,MAAM,mBAAmB,OAAO,UAAU,IAAI,GAAI;AACxG,eAAO;AAAA,MACT;AACA,aAAO,KAAK,SAAS;AAAA,IACvB;AACA,WAAO,QAAQ,MAAM;AAAA,EACvB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAUA,eAAe,uBAAuB,OAAc,QAAgB,SAAmD;AACrH,MAAI,MAAM,IAAI,MAAM,MAAM,QAAQ,IAAI,KAAK,EAAG,QAAO;AACrD,QAAM,WAAW,MAAM,SAAS,GAAG;AACnC,MAAI;AACJ,QAAM,QAAQ,IAAI,QAAmB,CAAC,YAAY;AAChD,YAAQ,WAAW,MAAM;AAAE,cAAQ,SAAS;AAAA,IAAE,GAAG,sBAAsB;AAAA,EACzE,CAAC;AACD,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,QAAQ,KAAK,CAAC,SAAS,KAAK,MAAM,OAAgB,GAAG,KAAK,CAAC;AAAA,EAC5E,QAAQ;AACN,WAAO;AAAA,EACT,UAAE;AACA,iBAAa,KAAK;AAAA,EACpB;AACA,MAAI,WAAW,QAAS,QAAO,MAAM,gBAAgB,OAAO,MAAM;AAClE,UAAQ,IAAI,OAAO,QAAQ;AAC3B,QAAM,UAAU,MAAY;AAC1B,QAAI,QAAQ,IAAI,KAAK,MAAM,SAAU,SAAQ,OAAO,KAAK;AAAA,EAC3D;AACA,WAAS,KAAK,SAAS,OAAO;AAC9B,SAAO;AACT;AAcA,eAAe,cAAc,MAAY,QAAgB,SAAmD;AAC1G,MAAI;AACJ,MAAI;AACF,cAAU,MAAM,QAAQ,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,UAAU,KAAK;AAAA,EAC3E,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,MAAM,MAAM,UAAW,QAAO;AAC1C,MAAI;AACF,UAAM,OAAO,KAAK,UAAU;AAC5B,UAAM,WAAW,KAAK,OAAO,EAAE,OAAO,CAAC,UAAU,UAAU,QAAQ,CAAC,MAAM,WAAW,CAAC;AACtF,WAAO,KAAK,GAAI,MAAM,QAAQ,IAAI,SAAS,IAAI,CAAC,UAAU,uBAAuB,OAAO,QAAQ,OAAO,CAAC,CAAC,CAAE;AAAA,EAC7G,QAAQ;AACN,WAAO,KAAK,SAAS;AAAA,EACvB;AACA,SAAO,QAAQ,MAAM;AACvB;AASO,SAAS,sBAAsB,MAAY,UAAkB,WAAqC;AACvG,QAAM,UAAyB,oBAAI,QAAQ;AAC3C,SAAO;AAAA,IACL,MAAM,UAAU,WAAsB,KAAiC;AACrE,YAAM,EAAE,IAAI,IAAI,KAAK,IAAI,SAAS,WAAW,SAAS;AACtD,UAAI,KAAK;AAEP,cAAM,WAAW,MAAM,cAAc,MAAM,UAAU,KAAK,IAAI,IAAI,IAAI;AACtE,YAAI,SAAS,sBAAsB,WAAY,OAAM,OAAO,IAAI;AAChE,eAAO,uBAAuB,WAAW,SAAS,OAAO;AAAA,MAC3D;AACA,YAAM,QAAQ,MAAM,kBAAkB,MAAM,IAAI,IAAI,IAAI;AACxD,aAAO,uBAAuB,WAAW,OAAO,QAAQ,OAAO,KAAK;AAAA,IACtE;AAAA,IACA,MAAM,mBAAmB,QAAkC;AACzD,UAAI;AACF,cAAM,KAAK,UAAU,MAAM,EAAE,MAAM,EAAE,uBAAuB;AAC5D,eAAO;AAAA,MACT,QAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,MAAM,kBAAkB;AACtB,YAAM,OAAO,MAAM,KAAK,QAAQ,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpE,aAAO,kBAAkB,IAAI,EAAE;AAAA,IACjC;AAAA,IACA,MAAM,mBAAmB,QAA2C;AAClE,aAAO,cAAc,MAAM,QAAQ,OAAO;AAAA,IAC5C;AAAA,EACF;AACF;AAKA,eAAsB,qBAAqB,MAAY,UAAkB,QAAuC;AAC9G,QAAM,WAAW,KAAK,aAAa,KAAK,EAAE,OAAO,MAAM,QAAQ,IAAI;AACnE,QAAM,aAAa,OAAO,cAAc,UAAU,OAAO,cAAc;AAEvE,MAAI,OAAO,SAAS,gBAAgB;AAClC,UAAMC,aAAY,aAAa,SAAS,QAAQ,SAAS;AACzD,UAAMC,cAAa,sBAAsB,MAAM,UAAUD,UAAS;AAClE,UAAM,EAAE,MAAAE,MAAK,IAAI,MAAM,oBAAoBD,aAAY;AAAA,MACrD,QAAQ,OAAO;AAAA,MACf,WAAW,OAAO;AAAA,MAClB,WAAW,OAAO;AAAA,MAClB,eAAe,OAAO;AAAA,MACtB,GAAI,OAAO,MAAM,EAAE,KAAK,OAAO,IAAI,IAAI,CAAC;AAAA,IAC1C,CAAC;AACD,WAAO,EAAE,SAAS,MAAM,UAAU,EAAE,oBAAoBC,MAAK,EAAE;AAAA,EACjE;AAEA,QAAM,SAAS,OAAO,WAAW,aAAa,MAAM;AACpD,QAAM,YAAY,KAAK,OAAO,aAAa,SAAS,QAAQ,SAAS,UAAU,MAAM;AACrF,QAAM,aAAa,sBAAsB,MAAM,UAAU,SAAS;AAElE,MAAI,OAAO,WAAW,SAAS;AAC7B,UAAM,EAAE,MAAAA,MAAK,IAAI,MAAM,eAAe,YAAY,OAAO,WAAW,OAAO,GAAG;AAC9E,WAAO,EAAE,SAAS,MAAM,UAAU,EAAE,oBAAoBA,MAAK,EAAE;AAAA,EACjE;AAEA,QAAM,EAAE,KAAK,IAAI,MAAM,mBAAmB,YAAY;AAAA,IACpD,WAAW,OAAO;AAAA,IAClB,GAAI,OAAO,MAAM,EAAE,KAAK,OAAO,IAAI,IAAI,CAAC;AAAA,EAC1C,CAAC;AACD,SAAO,EAAE,SAAS,MAAM,UAAU,EAAE,oBAAoB,KAAK,EAAE;AACjE;AAGO,SAAS,kBAAgC;AAC9C,SAAO;AAAA,IACL,SAAS;AAAA,IACT,OAAO;AAAA,EACT;AACF;;;AElnBA,SAAS,mBAAmB,aAAkC;AAC5D,MAAI,gBAAgB,WAAY,QAAO;AACvC,MAAI,gBAAgB,UAAW,QAAO;AACtC,SAAO;AACT;AAEO,SAAS,gCAAgC,OAAyB;AACvE,QAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,QAAM,QAAQ,QAAQ,YAAY;AAClC,SAAO,MAAM,SAAS,0BAA0B,KAC3C,MAAM,SAAS,YAAY,KAC3B,MAAM,SAAS,SAAS;AAC/B;AAEO,SAAS,0BAA0B,aAAkC;AAC1E,SAAO;AAAA,IACL,iDAAiD,mBAAmB,WAAW,CAAC;AAAA,IAChF;AAAA,IACA;AAAA,IACA,iCAAiC,WAAW;AAAA,IAC5C;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;;;ACzBA,SAAS,kBAAkB;AAC3B,SAAS,OAAO,UAAU;AAC1B,SAAS,YAAY;AAId,IAAM,yBAAyB,EAAE,OAAO,MAAM,QAAQ,IAAI;AAGjE,SAAS,SAAS,OAA8D;AAC9E,MAAI,MAAM,CAAC,MAAM,OAAQ,MAAM,CAAC,MAAM,IAAM,QAAO;AACnD,WAAS,IAAI,GAAG,IAAI,IAAI,MAAM,UAAS;AACrC,QAAI,MAAM,GAAG,MAAM,IAAM,QAAO;AAChC,UAAM,SAAS,MAAM,GAAG;AACxB,UAAM,SAAS,MAAM,aAAa,CAAC;AACnC,QAAI,SAAS,KAAK,IAAI,SAAS,MAAM,OAAQ,QAAO;AACpD,QAAI,CAAC,KAAM,KAAM,GAAI,EAAE,SAAS,MAAM,GAAG;AACvC,aAAO,EAAE,QAAQ,MAAM,aAAa,IAAI,CAAC,GAAG,OAAO,MAAM,aAAa,IAAI,CAAC,EAAE;AAAA,IAC/E;AACA,SAAK;AAAA,EACP;AACA,SAAO;AACT;AAOO,SAAS,0BACd,SACA,QACA,iBACqB;AACrB,MAAI;AACJ,MAAI;AACJ,MAAI,OAAO;AACX,MAAI;AACJ,MAAI;AACJ,MAAI,gBAAgB;AACpB,MAAI;AACJ,iBAAe,UAAU;AACvB,QAAI,CAAC,SAAU;AAGf,UAAM,SAAS,KAAK,WAAW,KAAK;AACpC,UAAM,GAAG,SAAS,aAAa,EAAE,OAAO,KAAK,CAAC;AAC9C,eAAW;AAAA,EACb;AACA,SAAO;AAAA,IACL,MAAM,QAAQ;AACZ,UAAI,QAAQ,OAAQ,OAAM,IAAI,MAAM,2BAA2B;AAC/D,aAAO;AACP,UAAI;AACF,cAAM,QAAQ;AACd,cAAM,OAAO,QAAQ;AACrB,YAAI,CAAC,KAAM,OAAM,IAAI,MAAM,wCAAwC;AACnE,cAAM,cAAc,KAAK,OAAO,UAAU,GAAG,WAAW,CAAC,OAAO;AAChE,cAAM,OAAO,OAAO,aAAa,KAAK,aAAa,KAAK;AACxD,0BAAkB;AAClB,gBAAQ;AACR;AACA,mBAAW,EAAE,MAAM,YAAY;AAC/B,YAAI;AACF,gBAAM,MAAM,OAAO,UAAU,EAAE,WAAW,KAAK,CAAC;AAChD,gBAAM,KAAK,WAAW,MAAM;AAAA,YAC1B,MAAM;AAAA,YACN;AAAA,YACA,SAAS,OAAM,UAAS;AACtB,kCAAoB,MAAM;AAC1B,oBAAM,SAAS,SAAS,MAAM,IAAI;AAGlC,oBAAM,OAAO,QAAQ,UAAU,KAAK,SAAS,OAAO,WAAW,KAAK,UAC/D,MAAM,kBAAkB,KAAK,SAAS,MAAM,mBAAmB,KAAK,SACrE,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO,IAAI;AACjD,kBAAI,MAAM,UAAU,OAAO,SAAS,MAAM,WAAW,OAAO,OAAQ;AACpE,sBAAQ;AAAA,YACV;AAAA,UACF,CAAC;AAAA,QACH,SAAS,OAAO;AACd,cAAI;AAAE,kBAAM,QAAQ;AAAA,UAAE,QAAQ;AAAA,UAA6C;AAC3E,gBAAM;AAAA,QACR;AACA,iBAAS;AACT,mBAAW;AACX,eAAO,EAAE,QAAQ,YAAY,IAAI,EAAE;AAAA,MACrC,UAAE;AAAU,eAAO;AAAA,MAAM;AAAA,IAC3B;AAAA,IACA,kBAAkB;AAChB,YAAM,YAAY;AAClB,YAAM,SAAS;AACf,YAAM,QAAQ;AACd,YAAM,WAAW;AAEjB,UAAI,CAAC,gBAAiB,QAAO;AAC7B,YAAM,eAAe,gBAAgB;AACrC,UAAI,CAAC,aAAa,CAAC,UAAU,UAAU,UAAa,QAAQ,MAAM,UAAU,KAAM,QAAO;AACzF,YAAM,WAAW,UAAU,KAAK,aAAa;AAC7C,UAAI,UAAU,UAAU,OAAO,SAAS,SAAS,WAAW,OAAO,OAAQ,QAAO;AAClF,YAAM,UAAU,YAAY,aAAa,YAAY,IAAI,IAAI;AAC7D,YAAMC,UAAS,MAAM;AACnB,cAAM,QAAQ,UAAU,KAAK,aAAa;AAC1C,cAAM,QAAQ,YAAY,aAAa,YAAY,IAAI,IAAI;AAC3D,YAAI,WAAW,aAAa,QAAQ,MAAM,UAAU,QAAQ,aAAa,iBACpE,iBAAiB,gBAAgB,KAAK,OAAO,UAAU,OAAO,SAAS,MAAM,WAAW,OAAO,UAC/F,CAAC,OAAO,SAAS,OAAO,KAAK,CAAC,OAAO,SAAS,KAAK,KAAK,UAAU,KAAK,SAAS,QAAS,QAAO;AACrG,eAAO,EAAE,SAAS,OAAO,OAAO,iBAA0B,WAAW,YAAqB,GAAG,OAAO;AAAA,MACtG;AACA,UAAI;AACJ,gBAAU,EAAE,MAAM;AAAE,gBAAQ,EAAE,SAASA,QAAO,EAAE;AAAA,MAAE,EAAE;AACpD,aAAO,MAAM,QAAQ,MAAM,UAAUA,QAAO;AAAA,IAC9C;AAAA,IACA,YAAY;AACV,eAAS,IAAI;AAAA,IACf;AAAA,IACA,MAAM,OAAO;AACX,UAAI,KAAM,OAAM,IAAI,MAAM,yCAAyC;AACnE,aAAO;AACP,UAAI;AACF,cAAM,YAAY;AAClB,YAAI,CAAC,WAAW;AAAE,gBAAM,QAAQ;AAAG,iBAAO;AAAA,QAAU;AACpD,iBAAS;AACT,YAAI;AACF,gBAAM,UAAU,KAAK,WAAW,KAAK;AAAA,QACvC,SAAS,OAAO;AACd,qBAAW;AACX,cAAI;AAAE,kBAAM,QAAQ;AAAA,UAAE,QAAQ;AAAA,UAA6C;AAC3E,gBAAM;AAAA,QACR;AACA,eAAO,EAAE,aAAa,UAAU,aAAa,aAAa,aAAa;AAAA,MACzE,UAAE;AAAU,eAAO;AAAA,MAAM;AAAA,IAC3B;AAAA,EACF;AACF;;;AC7FA,SAAS,kBAAkB;AAC3B,SAAS,eAAe;AAKxB,SAAS,4BAA4B;AAG9B,IAAM,0BAA0B;AAEhC,IAAM,uBAAuB;AAE7B,IAAM,6BAA6B;AAEnC,IAAM,2BAA2B;AAEjC,IAAM,yBAAyB,OAAO;AAEtC,IAAM,0BAA0B,IAAI,OAAO;AAG3C,IAAM,8BAAmD,oBAAI,IAAI;AAAA,EACtE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AASM,SAAS,qBAAqB,QAA0C;AAC7E,MAAI,OAAO,SAAS,OAAQ,QAAO,OAAO,WAAW;AACrD,MAAI,OAAO,SAAS,MAAO,QAAO,OAAO,WAAW;AACpD,SAAO,4BAA4B,IAAI,OAAO,IAAI;AACpD;AAaA,IAAM,aAAa,uBAAO,YAAY;AAG/B,IAAM,oBAAoB;AAEjC,IAAM,6BAAkD,oBAAI,IAAI,CAAC,QAAQ,OAAO,CAAC;AACjF,IAAM,oBAAyC,oBAAI,IAAI,CAAC,aAAa,SAAS,YAAY,CAAC;AACpF,IAAM,uBAAuB;AAE7B,IAAM,8BAA8B;AAEpC,IAAM,4BAA4B;AAGzC,IAAM,gBAAgB;AACtB,IAAM,kBAAkB;AAcxB,SAAS,uBAA6B;AACpC,QAAM,QAAQ;AAGd,MAAI;AACJ,MAAI,SAAsB;AAC1B,QAAM,OAAO,YAAyC;AACpD,QAAI;AACF,YAAM,OAAO,MAAM,MAAM,UAAU,UAAU,SAAS;AACtD,aAAO,OAAO,SAAS,WAAW,OAAO;AAAA,IAC3C,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO,eAAe,YAAY,qBAAqB;AAAA,IACrD,OAAO,OAAO,OAAO;AAAA,MACnB,IAAI,SAAS;AAAE,eAAO;AAAA,MAAO;AAAA,MAC7B,MAAM,WAAW;AACf,mBAAW;AACX,iBAAS;AACT,cAAM,OAAO,MAAM,KAAK;AACxB,YAAI,SAAS,QAAW;AACtB,mBAAS;AAAA,QACX,OAAO;AACL,qBAAW;AACX,mBAAS;AAAA,QACX;AACA,eAAO;AAAA,MACT;AAAA,MACA,MAAM,QAAQ,WAAmB;AAC/B,YAAI,WAAW,OAAQ,QAAO;AAC9B,cAAM,MAAM,MAAM,KAAK;AACvB,YAAI,QAAQ,OAAW,QAAO;AAC9B,YAAI,QAAQ,SAAU,QAAO;AAC7B,eAAO,QAAQ,YAAY,IAAI;AAAA,MACjC;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH;AAgBA,IAAM,iBAAiB;AAAA,oBACH,KAAK,UAAU,iBAAiB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA4ErD,IAAM,uBAAuB,CAAC,WAAW,sBAAsB,4BAA4B;AAC3F,IAAM,YAAiC,oBAAI,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC;AAG1D,SAAS,iBACd,QACA,KACS;AACT,MAAI,OAAO,aAAa,QAAQ,OAAO,YAAY,OAAW,QAAO;AAErE,SAAO,qBAAqB,MAAM,CAAC,SAAS,IAAI,IAAI,MAAM,UAAa,UAAU,IAAI,IAAI,IAAI,CAAC,CAAC;AACjG;AAUO,IAAM,mBAAN,MAAuB;AAAA,EACX;AAAA,EACA;AAAA,EACA,gBAAgB,oBAAI,QAAc;AAAA,EAC3C,YAA+B,CAAC;AAAA;AAAA,EAEhC,OAAmB,CAAC;AAAA;AAAA,EAEX,YAAY,oBAAI,IAAwB;AAAA,EACjD,gBAAgB;AAAA,EACP,qBAAqB,oBAAI,IAAgC;AAAA,EAClE,kBAA2C,CAAC;AAAA,EAC5C,QAAQ;AAAA,EACR,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,sBAAsB;AAAA,EACtB,wBAAwB;AAAA,EACxB;AAAA,EACA,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,UAAU;AAAA,EACV;AAAA,EACA,SAA8B;AAAA,EAC9B,aAAoC;AAAA,EACpC,QAA0C;AAAA,EAC1C,eAAsC;AAAA,EACtC,kBAAkB;AAAA,EACT;AAAA;AAAA,EAET,qBAAqB;AAAA;AAAA,EAErB,uBAAuB;AAAA,EAE/B,YAAY,UAAmC,CAAC,GAAG;AACjD,SAAK,kBAAkB,QAAQ,mBAAmB;AAClD,SAAK,eAAe,QAAQ,gBAAgB;AAC5C,SAAK,iBAAiB,QAAQ,aAAa;AAAA,EAC7C;AAAA,EAEA,MAAM,OAAO,SAAwC;AACnD,SAAK,aAAa;AAClB,eAAW,QAAQ,QAAQ,MAAM,EAAG,MAAK,WAAW,IAAI;AACxD,YAAQ,GAAG,QAAQ,CAAC,SAAS,KAAK,WAAW,IAAI,CAAC;AAClD,YAAQ,GAAG,WAAW,CAAC,YAAY,KAAK,UAAU,OAAO,CAAC;AAC1D,YAAQ,GAAG,YAAY,CAAC,aAAa;AAAE,WAAK,iBAAiB,SAAS,QAAQ,CAAC;AAAA,IAAE,CAAC;AAClF,YAAQ,GAAG,iBAAiB,CAAC,YAAY;AAAE,WAAK,iBAAiB,OAAO;AAAA,IAAE,CAAC;AAC3E,UAAM,QAAQ,cAAc,mBAAmB,CAAC,QAAQ,YAAqB;AAC3E,WAAK,iBAAiB,OAAO,OAAO,OAAO;AAAA,IAC7C,CAAC;AACD,UAAM,QAAQ,cAAc,cAAc;AAAA,EAC5C;AAAA,EAEA,MAAM,IAAI,QAAiC,UAA0B,CAAC,GAAG,YAAkC;AACzG,UAAM,UAAU,CAAC,GAAG,KAAK,UAAU,IAAI,CAAC,UAAU,MAAM,QAAQ,GAAG,GAAG,KAAK,IAAI;AAC/E,SAAK,OAAO,CAAC;AACb,SAAK,YAAY,QAAQ,IAAI,CAAC,cAAc,EAAE,UAAU,MAAM,KAAK,EAAE;AACrE,SAAK,kBAAkB,CAAC;AACxB,SAAK,QAAQ;AACb,SAAK,cAAc;AACnB,SAAK,iBAAiB;AACtB,SAAK,aAAa,qBAAqB,MAAM;AAC7C,SAAK,mBAAmB,KAAK;AAC7B,SAAK,sBAAsB;AAC3B,SAAK,wBAAwB;AAC7B,SAAK,aAAa;AAClB,SAAK,mBAAmB,MAAM;AAC9B,UAAM,YAAY,QAAQ;AAC1B,SAAK,UAAU,KAAK,IAAI,KACnB,OAAO,cAAc,YAAY,OAAO,SAAS,SAAS,IAAI,KAAK,IAAI,GAAG,SAAS,IAAI,KAAK;AACjG,SAAK,cAAc,QAAQ;AAC3B,SAAK,qBAAqB;AAC1B,UAAM,kBAAkB,CAAC,2BAA2B,IAAI,OAAO,IAAI;AACnE,QAAI,KAAK,kBAAkB,mBAAmB,KAAK,SAAS,IAAI,EAAG,OAAM,KAAK,aAAa;AAE3F,SAAK,iBAAiB,KAAK,SAAS;AAAA,EACtC;AAAA,EAEQ,WAAmB;AACzB,WAAO,KAAK,aAAa,UAAU,IAAI,KAAK,UAAU,KAAK,IAAI;AAAA,EACjE;AAAA;AAAA,EAGQ,QAAQ,MAA8B;AAC5C,UAAM,SAAS,KAAK;AACpB,QAAI,CAAC,OAAQ,QAAO,MAAM;AAC1B,QAAI,OAAO,SAAS;AAClB,qBAAe,IAAI;AACnB,aAAO,MAAM;AAAA,IACf;AACA,WAAO,iBAAiB,SAAS,MAAM,EAAE,MAAM,KAAK,CAAC;AACrD,WAAO,MAAM;AAAE,aAAO,oBAAoB,SAAS,IAAI;AAAA,IAAE;AAAA,EAC3D;AAAA,EAEA,MAAM,UAAmD;AACvD,QAAI,CAAC,KAAK,MAAO,QAAO;AACxB,QAAI,OAAO;AACX,QAAI;AACF,YAAM,KAAK,mBAAmB;AAC9B,WAAK,iBAAiB;AACtB,YAAM,SAAS,KAAK;AACpB,WAAK,iBAAiB;AACtB,WAAK,kBAAkB,CAAC;AACxB,YAAM,YAAY,CAAC,KAAK,iBACpB,OAAO,IAAI,CAAC,EAAE,QAAQ,KAAK,OAA+B,EAAE,QAAQ,MAAM,UAAU,cAAc,EAAE,IACpG,OAAO,SAAS,IAAI,MAAM,KAAK,SAAS,MAAM,IAAI,CAAC;AACvD,YAAM,WAA+B,CAAC;AACtC,aAAO,OAAO,KAAK,UAAU,QAAQ;AACnC,cAAM,EAAE,UAAU,KAAK,IAAI,KAAK,UAAU,MAAM;AAChD,cAAM,WAAW,MAAM,KAAK,OAAO,QAAQ;AAC3C,iBAAS,KAAK,OAAO,EAAE,GAAG,UAAU,MAAM,KAAK,IAAI,QAAQ;AAAA,MAC7D;AACA,UAAI,SAAS,WAAW,KAAK,UAAU,WAAW,EAAG,QAAO;AAC5D,aAAO;AAAA,QACL,GAAI,SAAS,SAAS,IAAI,EAAE,WAAW,SAAS,IAAI,CAAC;AAAA,QACrD,GAAI,UAAU,SAAS,IAAI,EAAE,UAAU,IAAI,CAAC;AAAA,MAC9C;AAAA,IACF,UAAE;AACA,WAAK,KAAK,KAAK,GAAG,KAAK,UAAU,MAAM,IAAI,EAAE,IAAI,CAAC,UAAU,MAAM,QAAQ,CAAC;AAC3E,WAAK,iBAAiB;AACtB,WAAK,QAAQ;AACb,WAAK,iBAAiB;AACtB,WAAK,YAAY,CAAC;AAClB,WAAK,kBAAkB,CAAC;AACxB,WAAK,cAAc;AACnB,WAAK,aAAa;AAClB,WAAK,qBAAqB;AAAA,IAC5B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,qBAAoC;AAChD,QAAI,CAAC,KAAK,WAAY;AACtB,UAAM,QAAQ,KAAK,IAAI;AACvB,UAAM,WAAW,QAAQ,KAAK,IAAI,KAAK,cAAc,KAAK,IAAI,GAAG,KAAK,SAAS,CAAC,CAAC;AACjF,UAAM,UAAU,KAAK,IAAI,GAAG,KAAK,SAAS,CAAC,IAAI;AAC/C,UAAM,SAAS,QAAQ,KAAK,IAAI,0BAA0B,OAAO;AACjE,UAAM,UAAU,QAAQ;AACxB,eAAS;AACP,YAAM,OAAO,KAAK,SAAS;AAC3B,UAAI,QAAQ,EAAG;AACf,YAAM,MAAM,KAAK,IAAI;AACrB,YAAM,YAAY,KAAK;AAAA,QACrB,KAAK,sBAAsB;AAAA,QAC3B,KAAK,wBAAwB,UAAU;AAAA,MACzC;AACA,YAAM,UAAU,KAAK,IAAI,UAAU,SAAS,IAAI;AAChD,YAAM,aAAa,KAAK,qBAAqB,SAAS,MAAM;AAC5D,UAAI,UAAU,EAAG,OAAM,KAAK,cAAc,KAAK,IAAI,SAAS,IAAI,CAAC;AAAA,eACxD,MAAM,WAAY,OAAM,KAAK,cAAc,KAAK,IAAI,aAAa,KAAK,IAAI,CAAC;AAAA,UAC/E;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA,EAIQ,qBAAqB,SAAiB,QAAwB;AACpE,QAAI,MAAM;AACV,eAAW,EAAE,KAAK,KAAK,KAAK,mBAAmB,OAAO,GAAG;AACvD,UAAI,KAAM,QAAO;AACjB,YAAM;AAAA,IACR;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,mBAAyB;AAC/B,SAAK,cAAc;AACnB,SAAK,mBAAmB;AACxB,SAAK,mBAAmB,MAAM;AAAA,EAChC;AAAA,EAEQ,UAAU,SAAwB;AACxC,QAAI,CAAC,KAAK,oBAAoB,CAAC,QAAQ,oBAAoB,EAAG;AAC9D,QAAI;AACJ,QAAI,OAAO;AACX,QAAI;AACF,YAAM,QAAQ,QAAQ,MAAM;AAC5B,aAAO,MAAM,KAAK;AAClB,aAAO,KAAK,eAAe,UAAa,UAAU,KAAK,WAAW,UAAU;AAAA,IAC9E,QAAQ;AAAA,IAA4B;AACpC,SAAK,mBAAmB,IAAI,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,EACrD;AAAA,EAEQ,iBAAiB,SAAwB;AAC/C,UAAM,UAAU,KAAK,mBAAmB,IAAI,OAAO;AACnD,QAAI,CAAC,QAAS;AACd,SAAK,mBAAmB,OAAO,OAAO;AACtC,SAAK,sBAAsB,KAAK,IAAI;AACpC,SAAK,wBAAwB,QAAQ;AACrC,SAAK,SAAS;AAAA,EAChB;AAAA,EAEQ,iBAAiB,OAAc,SAAwB;AAC7D,QAAI,CAAC,KAAK,SAAS,CAAC,KAAK,eAAgB;AACzC,QAAI,CAAC,WAAW,OAAO,YAAY,SAAU;AAC7C,UAAM,EAAE,KAAK,KAAK,IAAI;AACtB,QAAI,OAAO,QAAQ,YAAY,CAAC,kBAAkB,IAAI,GAAG,KAAK,OAAO,SAAS,SAAU;AACxF,SAAK,gBAAgB,KAAK,EAAE,QAAQ,KAAoC,MAAM,MAAM,CAAC;AACrF,QAAI,KAAK,gBAAgB,SAAS,4BAA6B,MAAK,gBAAgB,MAAM;AAAA,EAC5F;AAAA;AAAA,EAGA,MAAc,eAA8B;AAC1C,aAAS,UAAU,GAAG,UAAU,GAAG,WAAW,GAAG;AAC/C,YAAM,QAAQ,MAAM,KAAK,UAAU;AACnC,UAAI,CAAC,MAAO;AACZ,UAAI,MAAM,SAAS,GAAG;AACpB,cAAM,KAAK,WAAW;AACtB;AAAA,MACF;AACA,YAAM,aAAa,KAAK;AACxB,YAAM,QAAQ,KAAK,IAAI,sBAAsB,KAAK,SAAS,CAAC;AAC5D,UAAI,eAAe,KAAK,wBAAwB,SAAS,EAAG;AAC5D,UAAI;AACF,cAAM,SAAS,MAAM,KAAK;AAAA,UACxB,MAAM,SAAS,MAAO,WAA0B,kBAAkB,SAAS,CAAC;AAAA,UAC5E;AAAA,QACF;AACA,YAAI,WAAW,OAAW,MAAK,eAAe,YAAY,KAAK;AAAA,iBACtD,WAAW,UAAU,eAAe,KAAK,gBAAiB,MAAK,qBAAqB;AAC7F;AAAA,MACF,QAAQ;AACN,cAAM,KAAK,WAAW;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA,EAIA,MAAc,SAAS,QAAoE;AACzF,UAAM,OAAO,OAAO,SAAS;AAC7B,UAAM,QAAQ,OAAO,IAAI;AACzB,UAAM,SAAS,MAAM,KAAK,cAAc,MAAM,OAAO,MAAM,IAAI;AAC/D,WAAO,OAAO,IAAI,CAAC,EAAE,QAAQ,KAAK,GAAG,cAAc;AAAA,MACjD;AAAA,MACA;AAAA,MACA,UAAU,WAAW,iBAAiB,SAAS,MAAM,OACjD,YACA,WAAW,mBAAmB,aAAa,OAAO,eAAe;AAAA,IACvE,EAAE;AAAA,EACJ;AAAA;AAAA;AAAA,EAIA,MAAc,cAAc,OAAc,WAAgD;AACxF,UAAM,aAAa,KAAK;AACxB,QAAI,aAAa,KAAK,eAAe,KAAK,mBAAmB,eAAe,KAAK,sBAAsB;AACrG,aAAO;AAAA,IACT;AACA,QAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAI;AACF,UAAI,IAAI,IAAI,MAAM,IAAI,CAAC,EAAE,WAAW,OAAQ,QAAO;AAAA,IACrD,QAAQ;AACN,aAAO;AAAA,IACT;AACA,UAAM,aAAa,KAAK,IAAI,sBAAsB,KAAK,SAAS,CAAC;AACjE,QAAI,cAAc,EAAG,QAAO;AAC5B,UAAM,SAAS,MAAM,KAAK;AAAA,MACxB,MAAM,SAAS,mFAAmF;AAAA,MAClG;AAAA,IACF,EAAE,MAAM,MAAM,KAAK;AACnB,QAAI,WAAW,KAAM,QAAO;AAC5B,UAAM,QAAQ,MAAM,KAAK,UAAU;AACnC,UAAM,QAAQ,KAAK,IAAI,sBAAsB,KAAK,SAAS,CAAC;AAC5D,QAAI,CAAC,SAAS,eAAe,KAAK,mBAAmB,SAAS,EAAG,QAAO;AACxE,QAAI;AACJ,QAAI;AACF,UAAI,MAAM,SAAS,EAAG,OAAM,IAAI,MAAM,cAAc;AACpD,eAAS,MAAM,KAAK;AAAA,QAClB,MAAM,SAAS,CAAC,SAAkB,WAA0B,kBAAkB,QAAQ,IAAI,GAAG,SAAS;AAAA,QACtG;AAAA,MACF;AAAA,IACF,QAAQ;AAEN,YAAM,KAAK,WAAW;AACtB,aAAO;AAAA,IACT;AACA,QAAI,WAAW,OAAW,MAAK,eAAe,YAAY,KAAK;AAC/D,WAAO,WAAW,iBAAiB,WAAW,kBAAkB,SAAS;AAAA,EAC3E;AAAA;AAAA,EAGQ,eAAe,YAAoB,OAAqB;AAC9D,QAAI,SAAS,wBAAwB,CAAC,KAAK,aAAa,QAAS,MAAK,uBAAuB;AAAA,EAC/F;AAAA;AAAA,EAGA,MAAc,QAAW,SAAqB,IAAoC;AAChF,QAAI,MAAM,MAAY;AACtB,QAAI;AACF,aAAO,MAAM,QAAQ,KAAK;AAAA,QACxB,YAAY,SAAS,EAAE;AAAA,QACvB,IAAI,QAAmB,CAAC,YAAY;AAAE,gBAAM,KAAK,QAAQ,MAAM;AAAE,oBAAQ,MAAS;AAAA,UAAE,CAAC;AAAA,QAAE,CAAC;AAAA,MAC1F,CAAC;AAAA,IACH,UAAE;AACA,UAAI;AAAA,IACN;AAAA,EACF;AAAA,EAEQ,YAAuC;AAC7C,QAAI,CAAC,KAAK,eAAgB,QAAO,QAAQ,QAAQ,MAAS;AAC1D,SAAK,UAAU,KAAK,YAAY,KAAK,eAAe;AACpD,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA,EAIA,MAAc,YAAY,YAA+C;AACvE,QAAI;AACJ,QAAI;AACF,YAAM,UAAU,KAAK,YAAY,QAAQ;AACzC,UAAI,CAAC,QAAS,QAAO;AACrB,gBAAU,MAAM,QAAQ,WAAW;AACnC,UAAI,eAAe,KAAK,iBAAiB;AACvC,cAAM,QAAQ,MAAM,EAAE,MAAM,MAAM,MAAS;AAC3C,eAAO;AAAA,MACT;AACA,WAAK,eAAe;AACpB,YAAM,QAAQ,MAAM,QAAQ,CAAC,UAAU;AACrC,YAAI,SAAS;AACb,YAAI;AACF,mBAAS,IAAI,IAAI,MAAM,QAAQ,EAAE,IAAI,CAAC,EAAE;AAAA,QAC1C,QAAQ;AAAA,QAAsB;AAC9B,eAAO,WAAW,4BACd,MAAM,QAAQ,EAAE,aAAa,aAAa,MAAM,kBAAkB,CAAC,IACnE,MAAM,MAAM;AAAA,MAClB,CAAC;AACD,YAAM,QAAQ,iBAAiB,CAAC,gBAAgB,GAAG,EAAE,QAAQ,0BAA0B,CAAC;AACxF,YAAM,OAAO,MAAM,QAAQ,QAAQ;AACnC,WAAK,KAAK,SAAS,MAAM;AACvB,YAAI,eAAe,KAAK,gBAAiB,MAAK,KAAK,WAAW;AAAA,MAChE,CAAC;AACD,YAAM,KAAK,KAAK,GAAG,yBAAyB,GAAG;AAC/C,YAAM,KAAK,SAAS,oBAAoB;AACxC,aAAO;AAAA,IACT,QAAQ;AACN,UAAI,eAAe,KAAK,iBAAiB;AACvC,aAAK,QAAQ;AACb,aAAK,eAAe;AAAA,MACtB;AACA,YAAM,SAAS,MAAM,EAAE,MAAM,MAAM,MAAS;AAC5C,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGA,kBAAkB,QAAwC;AACxD,WAAO,KAAK,UAAU,IAAI,MAAM;AAAA,EAClC;AAAA,EAEQ,UAAU,QAAgB,OAAyB;AACzD,QAAI,MAAM,SAAS,uBAAwB;AAC3C,UAAM,WAAW,KAAK,UAAU,IAAI,MAAM;AAC1C,QAAI,aAAa,QAAW;AAC1B,WAAK,UAAU,OAAO,MAAM;AAC5B,WAAK,iBAAiB,SAAS;AAAA,IACjC;AACA,SAAK,UAAU,IAAI,QAAQ,KAAK;AAChC,SAAK,iBAAiB,MAAM;AAC5B,eAAW,CAAC,KAAK,KAAK,KAAK,KAAK,WAAW;AACzC,UAAI,KAAK,iBAAiB,wBAAyB;AACnD,WAAK,UAAU,OAAO,GAAG;AACzB,WAAK,iBAAiB,MAAM;AAAA,IAC9B;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,UAAyB;AAC7B,SAAK,UAAU,MAAM;AACrB,SAAK,gBAAgB;AACrB,UAAM,OAAO,KAAK;AAClB,SAAK,OAAO,CAAC;AACb,eAAW,YAAY,MAAM;AAC3B,YAAM,SAAS,OAAO,EAAE,MAAM,MAAM,MAAS;AAC7C,YAAM,SAAS,OAAO,EAAE,MAAM,MAAM,MAAS;AAAA,IAC/C;AACA,UAAM,KAAK,WAAW;AAAA,EACxB;AAAA;AAAA,EAGA,MAAc,aAA4B;AACxC,UAAM,UAAU,KAAK;AACrB,SAAK,mBAAmB;AACxB,SAAK,uBAAuB;AAC5B,SAAK,QAAQ;AACb,SAAK,eAAe;AACpB,UAAM,SAAS,MAAM,EAAE,MAAM,MAAM,MAAS;AAAA,EAC9C;AAAA,EAEQ,WAAW,MAAkB;AACnC,QAAI,KAAK,cAAc,IAAI,IAAI,EAAG;AAClC,SAAK,cAAc,IAAI,IAAI;AAC3B,SAAK,GAAG,YAAY,CAAC,aAAa;AAChC,UAAI,CAAC,KAAK,aAAa;AACrB,aAAK,KAAK,KAAK,QAAQ;AACvB;AAAA,MACF;AACA,WAAK,UAAU,KAAK,EAAE,UAAU,MAAM,MAAM,CAAC;AAC7C,WAAK,SAAS;AAAA,IAChB,CAAC;AACD,SAAK,GAAG,SAAS,MAAM;AACrB,iBAAW,CAAC,SAAS,OAAO,KAAK,KAAK,mBAAoB,KAAI,QAAQ,SAAS,KAAM,MAAK,iBAAiB,OAAO;AAAA,IACpH,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,MAAc,cAAc,IAA2B;AACrD,QAAI,MAAM,MAAY;AACtB,UAAM,IAAI,QAAc,CAAC,YAAY;AACnC,YAAM,QAAQ,WAAW,MAAM,EAAE;AACjC,eAAS,OAAa;AACpB,qBAAa,KAAK;AAClB,gBAAQ;AAAA,MACV;AACA,WAAK,SAAS;AACd,YAAM,KAAK,QAAQ,IAAI;AAAA,IACzB,CAAC;AACD,QAAI;AACJ,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,MAAc,OAAO,UAA+C;AAClE,UAAM,oBAAoB,SAAS,kBAAkB;AACrD,UAAM,OAAkE;AAAA,MACtE;AAAA,MACA,WAAW,QAAQ,iBAAiB;AAAA,IACtC;AACA,QAAI;AACJ,QAAI,MAAM,MAAY;AACtB,UAAM,UAAU,MAAM,QAAQ,KAAK;AAAA,MACjC,SAAS,QAAQ,EAAE,MAAM,CAAC,UAAoB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAE;AAAA,MACrG,IAAI,QAA2B,CAAC,YAAY;AAC1C,cAAM,MAAM,MAAY;AAAE,kBAAQ,UAAU;AAAA,QAAE;AAC9C,gBAAQ,WAAW,KAAK,KAAK,IAAI,GAAG,KAAK,SAAS,CAAC,CAAC;AACpD,cAAM,KAAK,QAAQ,GAAG;AAAA,MACxB,CAAC;AAAA,IACH,CAAC;AACD,iBAAa,KAAK;AAClB,QAAI;AACJ,QAAI,YAAY,YAAY;AAC1B,YAAM,SAAS,OAAO,EAAE,MAAM,MAAM,MAAS;AAC7C,YAAM,SAAS,OAAO,EAAE,MAAM,MAAM,MAAS;AAC7C,aAAO,EAAE,GAAG,MAAM,OAAO,aAAa;AAAA,IACxC;AACA,QAAI,YAAY,MAAM;AACpB,YAAM,SAAS,OAAO,EAAE,MAAM,MAAM,MAAS;AAC7C,aAAO,EAAE,GAAG,MAAM,OAAO,YAAY,aAAa,aAAa,UAAU,SAAS,QAAQ;AAAA,IAC5F;AACA,QAAI;AACF,YAAM,EAAE,MAAM,QAAQ,MAAM,IAAI,MAAM,OAAO,QAAQ;AACrD,UAAI,UAAU,OAAW,MAAK,UAAU,QAAQ,KAAK;AACrD,aAAO,EAAE,GAAG,MAAM,MAAM,QAAQ,OAAO,YAAY;AAAA,IACrD,SAAS,OAAO;AACd,aAAO,EAAE,GAAG,MAAM,OAAO,UAAU,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE;AAAA,IACrG,UAAE;AACA,YAAM,SAAS,OAAO,EAAE,MAAM,MAAM,MAAS;AAAA,IAC/C;AAAA,EACF;AACF;AAEA,eAAe,YAAe,SAAqB,IAAoC;AACrF,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,QAAQ,KAAK;AAAA,MACxB;AAAA,MACA,IAAI,QAAmB,CAAC,YAAY;AAAE,gBAAQ,WAAW,MAAM,QAAQ,MAAS,GAAG,EAAE;AAAA,MAAE,CAAC;AAAA,IAC1F,CAAC;AAAA,EACH,UAAE;AACA,iBAAa,KAAK;AAAA,EACpB;AACF;AAGA,eAAe,OAAO,UAAmF;AACvG,QAAM,SAAS,MAAM,SAAS,iBAAiB;AAC/C,QAAM,OAAO,WAAW,QAAQ;AAChC,MAAI,OAAO;AACX,MAAI,SAA+B,CAAC;AACpC,mBAAiB,SAAS,QAAQ;AAChC,UAAM,QAAQ;AACd,YAAQ,MAAM;AACd,SAAK,OAAO,KAAK;AACjB,QAAI,OAAO,uBAAwB,UAAS;AAAA,QACvC,SAAQ,KAAK,KAAK;AAAA,EACzB;AACA,QAAM,SAAS,KAAK,OAAO,KAAK;AAChC,SAAO,WAAW,SAAY,EAAE,MAAM,OAAO,IAAI,EAAE,MAAM,QAAQ,OAAO,IAAI,WAAW,OAAO,OAAO,MAAM,CAAC,EAAE;AAChH;;;AXnsBO,IAAM,8BAA8B;AAEpC,IAAM,oCAAoC;AACjD,IAAM,mBAAwC;AAAA,EAC5C,WAAW;AAAA,EACX,gBAAgB;AAClB;AAEO,IAAM,wBAAwB;AAKrC,SAAS,sBAAsB,QAAsB,UAAwD;AAC3G,QAAM,WAAW,UAAU,WAAW,SAAS,SAAS,YAAY;AACpE,QAAM,YAAY,UAAU,WAAW,SAAS,SAAS,YAAY;AACrE,MAAI,CAAC,YAAY,CAAC,UAAW,QAAO;AACpC,SAAO;AAAA,IACL,GAAG;AAAA,IACH,UAAU,EAAE,GAAG,OAAO,UAAU,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC,GAAI,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC,EAAG;AAAA,EACzG;AACF;AAEA,SAAS,iBAAiB,YAAyC;AACjE,SAAO,eAAe,UAAa,aAAa,IAAI,EAAE,OAAO,WAAW,IAAI,CAAC;AAC/E;AAMA,SAAS,qBAAqB,QAAmE;AAC/F,SAAQ,OAAuE;AACjF;AAuBO,IAAM,oBAAoB;AAAA,EAC/B,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,UAAU;AAAA,EACV,WAAW;AAAA,EACX,eAAe;AACjB;AAUA,IAAM,wBAAwB;AAU9B,IAAM,2BAA2B;AAO1B,IAAM,yBAAyB;AAGtC,SAAS,aAAa,MAA0B;AAC9C,QAAM,SAAS,KAAK,IAAI;AACxB,QAAM,QAAQ,IAAI,WAAW,OAAO,MAAM;AAC1C,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,IAAK,OAAM,CAAC,IAAI,OAAO,WAAW,CAAC;AACtE,SAAO;AACT;AAQO,IAAM,qBAAN,MAA2D;AAAA,EAGhE,YAA6B,UAAqC,CAAC,GAAG;AAAzC;AAAA,EAA0C;AAAA,EAF9D,WAAW;AAAA,EAIZ,UAA0B;AAAA,EAC1B,UAAiC;AAAA,EACjC,OAAoB;AAAA;AAAA;AAAA,EAGpB,WAAmB,CAAC;AAAA,EACpB;AAAA,EACA,iBAAiB,oBAAI,IAA0B;AAAA,EAC/C,mBAA2D,EAAE,SAAS,MAAM,SAAS,KAAK;AAAA,EAC1F,eAAe;AAAA,EACf,mBAAmB;AAAA;AAAA;AAAA,EAGnB,cAAc,oBAAI,IAAY;AAAA,EAC9B,mBAAsD;AAAA;AAAA,EAEtD,cAAiD;AAAA,EACjD,aAAgC;AAAA,EAChC,uBAAoD;AAAA,EACpD;AAAA,EACA,wBAAwB;AAAA,EACxB;AAAA;AAAA,EAEA,qBAAqB;AAAA,EACrB,sBAAsB,oBAAI,IAAoB;AAAA;AAAA;AAAA,EAG9C,oBAAyD;AAAA,EACzD,iBAAuD;AAAA,EACvD,qBAA+D;AAAA,EAC/D,wBAAuC;AAAA,EACvC,kBAAiC,QAAQ,QAAQ;AAAA;AAAA,EAEjD,oBAAiD;AAAA,EACjD,0BAAgE;AAAA;AAAA,EAEhE,mBAA4C;AAAA;AAAA,EAEpD;AAAA,EAEA,MAAM,MAAM,QAAuC;AACjD,SAAK,kBAAkB,OAAO;AAC9B,UAAM,EAAE,UAAU,SAAS,OAAO,IAAI,MAAM,OAAO,iBAAiB;AACpE,UAAM,YAAY,EAAE,UAAU,SAAS,OAAO;AAC9C,UAAM,cAAc,OAAO,SAAS,QAAQ;AAC5C,SAAK,cAAc;AACnB,UAAM,WAAW,UAAU,WAAW;AACtC,UAAM,WAAW,OAAO,SAAS,YAAY;AAE7C,QAAI;AACF,WAAK,UAAU,MAAM,SAAS,OAAO;AAAA,QACnC;AAAA,QACA,GAAI,gBAAgB,aAAa,EAAE,MAAM,CAAC,+CAA+C,EAAE,IAAI,CAAC;AAAA,QAChG,GAAI,KAAK,QAAQ,oBAAoB,OACjC,EAAE,cAAc,OAAO,eAAe,OAAO,cAAc,MAAM,IACjE,CAAC;AAAA,MACP,CAAC;AAAA,IACH,SAAS,OAAO;AACd,UAAI,gCAAgC,KAAK,GAAG;AAC1C,cAAM,IAAI,MAAM,0BAA0B,WAAW,CAAC;AAAA,MACxD;AACA,YAAM;AAAA,IACR;AAEA,SAAK,eAAe;AACpB,SAAK,mBAAmB;AACxB,SAAK,QAAQ,GAAG,gBAAgB,MAAM;AACpC,UAAI,CAAC,KAAK,kBAAkB;AAC1B,aAAK,eAAe;AAAA,MACtB;AAAA,IACF,CAAC;AAED,UAAM,iBAA0C;AAAA,MAC9C,UAAU,OAAO,SAAS,YAAY,EAAE,OAAO,MAAM,QAAQ,IAAI;AAAA,IACnE;AACA,QAAI,OAAO,WAAW,kBAAkB;AACtC,qBAAe,eAAe,OAAO,UAAU;AAAA,IACjD;AACA,SAAK,UAAU,MAAM,KAAK,QAAQ,WAAW,cAAc;AAG3D,QAAI,gBAAgB,YAAY;AAC9B,YAAM,KAAK,QAAQ,iBAAiB,CAAC,iBAAiB,CAAC;AAAA,IACzD;AAEA,SAAK,mBAAmB,EAAE,SAAS,OAAO,YAAY,YAAY,OAAO,SAAS,OAAO,YAAY,YAAY,MAAM;AAGvH,UAAM,KAAK,QAAQ,cAAc,MAAM;AACrC,aAAO,eAAe,WAAW,aAAa,EAAE,KAAK,MAAM,MAAM,CAAC;AAAA,IACpE,CAAC;AAED,SAAK,OAAO,MAAM,KAAK,QAAQ,QAAQ;AACvC,SAAK,mBAAmB,KAAK,IAAI;AAEjC,QAAI,gBAAgB,YAAY;AAG9B,WAAK,mBAAmB,IAAI,iBAAiB,EAAE,UAAU,iBAAiB,EAAE,SAAS,GAAG,QAAQ,GAAG,EAAE,CAAC;AACtG,YAAM,KAAK,iBAAiB,OAAO,KAAK,OAAO;AAC/C,WAAK,0BAA0B,EAAE,UAAU,MAAM,WAAW,KAAK;AAAA,IACnE,OAAO;AACL,WAAK,0BAA0B,EAAE,UAAU,OAAO,WAAW,OAAO,QAAQ,YAAY;AAAA,IAC1F;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,IAAI,aAA+C;AACjD,QAAI,KAAK,gBAAgB,WAAY,QAAO;AAC5C,QAAI,CAAC,KAAK,QAAQ,CAAC,KAAK,QAAS,QAAO;AACxC,QAAI,KAAK,qBAAsB,QAAO,KAAK;AAC3C,UAAM,aAAmC;AAAA,MACvC,MAAM;AAAA,MACN,OAAO,CAAC,YACN,KAAK,kBAAkB,YAAY;AACjC,YAAI,KAAK,sBAAsB,KAAM;AACrC,cAAM,OAAO,KAAK;AAClB,cAAM,UAAU,KAAK;AACrB,YAAI,CAAC,QAAQ,CAAC,QAAS;AACvB,cAAM,MAAM,MAAM,QAAQ,cAAc,IAAI;AAC5C,aAAK,aAAa;AAClB,aAAK,oBAAoB;AACzB,aAAK,oBAAoB,MAAM;AAC/B,aAAK,iBAAiB,KAAK,OAAO;AAClC,YAAI;AACF,gBAAM,IAAI,KAAK,wBAAwB,EAAE,GAAG,kBAAkB,CAAC;AAAA,QACjE,SAAS,OAAO;AAEd,eAAK,aAAa;AAClB,eAAK,oBAAoB;AACzB,cAAI;AAAE,kBAAM,IAAI,OAAO;AAAA,UAAE,QAAQ;AAAA,UAAoB;AACrD,gBAAM;AAAA,QACR;AACA,YAAI,KAAK,eAAe,IAAK,MAAK,aAAa,GAAG;AAAA,MACpD,CAAC;AAAA,MACH,KAAK,OAAO,YAAmC;AAC7C,cAAM,MAAM,KAAK;AACjB,YAAI,CAAC,IAAK;AACV,cAAM,YAAY,KAAK,oBAAoB,IAAI,OAAO;AACtD,aAAK,oBAAoB,OAAO,OAAO;AAIvC,YAAI,cAAc,OAAW;AAC7B,YAAI;AACF,gBAAM,IAAI,KAAK,2BAA2B,EAAE,UAAU,CAAC;AAAA,QACzD,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,MACA,MAAM,MACJ,KAAK,kBAAkB,YAAY;AACjC,aAAK,oBAAoB;AACzB,cAAM,KAAK,sBAAsB;AACjC,cAAM,KAAK,iBAAiB;AAAA,MAC9B,CAAC;AAAA,IACL;AACA,SAAK,uBAAuB;AAC5B,WAAO;AAAA,EACT;AAAA;AAAA,EAGQ,kBAAkB,MAA0C;AAClE,UAAM,MAAM,KAAK,gBAAgB,KAAK,IAAI;AAC1C,SAAK,kBAAkB,IAAI,MAAM,MAAM,MAAS;AAChD,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAc,mBAAkC;AAC9C,UAAM,MAAM,KAAK;AACjB,SAAK,aAAa;AAClB,SAAK,eAAe;AACpB,SAAK,wBAAwB;AAC7B,SAAK,oBAAoB,MAAM;AAC/B,QAAI,CAAC,IAAK;AACV,QAAI;AAAE,YAAM,IAAI,KAAK,qBAAqB;AAAA,IAAE,QAAQ;AAAA,IAAoB;AACxE,QAAI;AAAE,YAAM,IAAI,OAAO;AAAA,IAAE,QAAQ;AAAA,IAAoB;AAAA,EACvD;AAAA;AAAA,EAGQ,iBAAiB,KAAiB,SAA2C;AACnF,QAAI,GAAG,wBAAwB,CAAC,UAAU;AAExC,UAAI,KAAK,eAAe,IAAK;AAC7B,YAAM,WAAW,MAAM;AACvB,WAAK,qBAAqB,EAAE,OAAO,SAAS,aAAa,QAAQ,SAAS,aAAa;AACvF,WAAK,aAAa,GAAG;AACrB,YAAM,eAAe,KAAK;AAC1B,WAAK,wBAAwB;AAC7B,UAAI,iBAAiB,QAAQ,KAAK,IAAI,KAAK,cAAc;AACvD,aAAK,IAAI,KAAK,2BAA2B,EAAE,WAAW,MAAM,UAAU,CAAC,EAAE,MAAM,MAAM,MAAS;AAC9F;AAAA,MACF;AAaA,YAAM,KAAK,EAAE,KAAK;AAClB,WAAK,oBAAoB,IAAI,IAAI,MAAM,SAAS;AAGhD,aAAO,KAAK,oBAAoB,OAAO,uBAAuB;AAC5D,cAAM,SAAS,KAAK,oBAAoB,KAAK,EAAE,KAAK;AACpD,YAAI,OAAO,SAAS,KAAM;AAC1B,cAAM,QAAQ,KAAK,oBAAoB,IAAI,OAAO,KAAK;AACvD,aAAK,oBAAoB,OAAO,OAAO,KAAK;AAC5C,YAAI,UAAU,QAAW;AACvB,eAAK,IAAI,KAAK,2BAA2B,EAAE,WAAW,MAAM,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,QACtF;AAAA,MACF;AACA,cAAQ;AAAA,QACN;AAAA,QACA,OAAO,aAAa,MAAM,IAAI;AAAA,QAC9B,UAAU;AAAA,UACR,OAAO,SAAS;AAAA,UAChB,QAAQ,SAAS;AAAA;AAAA,UAEjB,GAAI,SAAS,cAAc,SACvB,CAAC,IACD,EAAE,WAAW,KAAK,MAAM,SAAS,YAAY,GAAI,EAAE;AAAA,UACvD,eAAe,SAAS;AAAA,UACxB,eAAe,SAAS;AAAA,QAC1B;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,cAAc,MAAkB;AACtC,SAAK,OAAO;AACZ,SAAK;AACL,QAAI,KAAK,sBAAsB,MAAM;AACnC,WAAK,KAAK,kBAAkB,MAAM,KAAK,iBAAiB,CAAC;AAAA,IAC3D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,iBAAiB,UAA+B,CAAC,GAAkB;AAC/E,UAAM,UAAU,KAAK;AACrB,UAAM,OAAO,KAAK;AAClB,UAAM,UAAU,KAAK;AACrB,QAAI,YAAY,QAAQ,CAAC,QAAQ,CAAC,QAAS;AAC3C,UAAM,KAAK,iBAAiB;AAC5B,SAAK,qBAAqB;AAG1B,QAAI,QAAQ,UAAU,OAAO;AAC3B,UAAI;AAAE,cAAM,KAAK,aAAa;AAAA,MAAE,QAAQ;AAAA,MAAoB;AAAA,IAC9D;AACA,QAAI;AACJ,QAAI;AACF,YAAM,MAAM,QAAQ,cAAc,IAAI;AAAA,IACxC,QAAQ;AACN,WAAK,0BAA0B,IAAI;AACnC;AAAA,IACF;AACA,SAAK,aAAa;AAClB,SAAK,iBAAiB,KAAK,OAAO;AAClC,QAAI;AACF,YAAM,IAAI,KAAK,wBAAwB,EAAE,GAAG,kBAAkB,CAAC;AAAA,IACjE,QAAQ;AACN,WAAK,0BAA0B,GAAG;AAClC;AAAA,IACF;AACA,QAAI,KAAK,eAAe,IAAK;AAC7B,SAAK,aAAa,GAAG;AACrB,UAAM,KAAK,sBAAsB;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,0BAA0B,KAA8B;AAC9D,SAAK,KAAK,kBAAkB,YAAY;AACtC,UAAI,KAAK,eAAe,IAAK;AAC7B,YAAM,UAAU,KAAK;AACrB,UAAI,YAAY,QAAQ,KAAK,sBAAsB,QAAQ,CAAC,KAAK,cAAc,EAAG;AAClF,YAAM,KAAK,iBAAiB;AAC5B,YAAM,WAAW,yBAAyB,EAAE,SAAS,MAAM,KAAK,WAAW,EAAE,CAAC;AAC9E,WAAK,oBAAoB;AAEzB,YAAM,SAAS,MAAM,CAAC,UAAU;AAC9B,YAAI,KAAK,sBAAsB,SAAU;AACzC,gBAAQ,EAAE,GAAG,OAAO,IAAI,EAAE,KAAK,mBAAmB,CAAC;AAAA,MACrD,CAAC;AACD,WAAK,sBAAsB;AAAA,IAC7B,CAAC;AAAA,EACH;AAAA;AAAA,EAGQ,wBAA8B;AACpC,SAAK,wBAAwB;AAC7B,UAAM,QAAQ,WAAW,MAAM;AAC7B,WAAK,0BAA0B;AAC/B,WAAK,KAAK,kBAAkB,YAAY;AACtC,YAAI,KAAK,sBAAsB,QAAQ,KAAK,sBAAsB,QAAQ,CAAC,KAAK,cAAc,EAAG;AACjG,cAAM,KAAK,iBAAiB,EAAE,OAAO,MAAM,CAAC;AAC5C,YAAI,KAAK,sBAAsB,KAAM,MAAK,sBAAsB;AAAA,MAClE,CAAC;AAAA,IACH,GAAG,sBAAsB;AACzB,UAAM,QAAQ;AACd,SAAK,0BAA0B;AAAA,EACjC;AAAA,EAEQ,0BAAgC;AACtC,QAAI,KAAK,4BAA4B,KAAM,cAAa,KAAK,uBAAuB;AACpF,SAAK,0BAA0B;AAAA,EACjC;AAAA,EAEQ,gBAAyB;AAC/B,WAAO,CAAC,KAAK,oBAAoB,CAAC,KAAK,gBAAgB,KAAK,SAAS,YAAY,MAAM;AAAA,EACzF;AAAA,EAEA,MAAc,wBAAuC;AACnD,SAAK,wBAAwB;AAC7B,UAAM,WAAW,KAAK;AACtB,SAAK,oBAAoB;AACzB,QAAI;AAAE,YAAM,UAAU,KAAK;AAAA,IAAE,QAAQ;AAAA,IAAoB;AAAA,EAC3D;AAAA,EAEQ,iBAAuB;AAC7B,QAAI,KAAK,mBAAmB,KAAM,cAAa,KAAK,cAAc;AAClE,SAAK,iBAAiB;AAAA,EACxB;AAAA;AAAA,EAGQ,aAAa,KAAuB;AAC1C,SAAK,eAAe;AACpB,UAAM,QAAQ,WAAW,MAAM;AAAE,WAAK,KAAK,cAAc,GAAG;AAAA,IAAE,GAAG,uBAAuB;AACxF,UAAM,QAAQ;AACd,SAAK,iBAAiB;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAc,cAAc,KAAgC;AAC1D,SAAK,iBAAiB;AACtB,QAAI,KAAK,eAAe,IAAK;AAC7B,UAAM,eAAe,KAAK;AAC1B,QAAI;AACJ,QAAI;AACF,YAAM,SAAS,MAAM,IAAI,KAAK,0BAA0B,EAAE,QAAQ,QAAQ,SAAS,GAAG,CAAC;AACvF,aAAO,OAAO;AAAA,IAChB,QAAQ;AACN,UAAI,KAAK,eAAe,IAAK;AAC7B,YAAM,YAAY,KAAK,sBAAsB,QAAQ,KAAK,cAAc,KAAK,CAAE,MAAM,KAAK,eAAe,GAAG;AAC5G,UAAI,KAAK,eAAe,IAAK;AAC7B,UAAI,UAAW,MAAK,0BAA0B,GAAG;AAAA,UAC5C,MAAK,aAAa,GAAG;AAC1B;AAAA,IACF;AACA,QAAI,KAAK,eAAe,IAAK;AAC7B,UAAM,UAAU,KAAK;AACrB,QAAI,YAAY,KAAM;AAEtB,QAAI,KAAK,uBAAuB,aAAc;AAC9C,UAAM,OAAO,KAAK,sBAAsB,KAAK,MAAM,aAAa,KAAK,EAAE,OAAO,GAAG,QAAQ,EAAE;AAC3F,YAAQ;AAAA,MACN,IAAI,EAAE,KAAK;AAAA,MACX,OAAO,aAAa,IAAI;AAAA,MACxB,UAAU,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,QAAQ,WAAW,KAAK,IAAI,EAAE;AAAA,IAC5E,CAAC;AACD,SAAK,wBAAwB,KAAK,IAAI,IAAI;AAC1C,SAAK,aAAa,GAAG;AAAA,EACvB;AAAA;AAAA,EAGA,MAAc,eAAe,KAAmC;AAC9D,QAAI;AACF,YAAM,IAAI,KAAK,oBAAoB,EAAE,YAAY,IAAI,CAAC;AACtD,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,IAAI,YAA6C;AAC/C,QAAI,CAAC,KAAK,QAAQ,CAAC,KAAK,WAAW,CAAC,KAAK,gBAAiB,QAAO;AACjE,WAAO,KAAK,wBAAwB;AAAA,MAClC,MAAM,KAAK;AAAA,MACX,KAAK;AAAA,MACL,MAAM,KAAK;AAAA,IACb;AAAA,EACF;AAAA,EAEA,MAAM,UAAyB;AAC7B,SAAK,mBAAmB;AACxB,QAAI;AAAE,YAAM,KAAK,qBAAqB,KAAK;AAAA,IAAE,QAAQ;AAAA,IAAoB;AACzE,SAAK,sBAAsB;AAC3B,SAAK,kBAAkB;AAGvB,SAAK,oBAAoB;AACzB,UAAM,KAAK,sBAAsB;AACjC,QAAI;AAAE,YAAM,KAAK,sBAAsB,KAAK;AAAA,IAAE,QAAQ;AAAA,IAAoB;AAC1E,SAAK,uBAAuB;AAE5B,QAAI;AAAE,YAAM,KAAK,kBAAkB,QAAQ;AAAA,IAAE,QAAQ;AAAA,IAAoB;AAGzE,QAAI,KAAK,SAAS;AAChB,UAAI;AAAE,cAAM,KAAK,QAAQ,WAAW,EAAE,UAAU,eAAe,CAAC;AAAA,MAAE,QAAQ;AAAA,MAAoB;AAC9F,UAAI;AAAE,cAAM,KAAK,QAAQ,WAAW,KAAK;AAAA,MAAE,QAAQ;AAAA,MAAoB;AAAA,IACzE;AACA,QAAI,KAAK,QAAQ,KAAK,kBAAkB;AACtC,UAAI;AAAE,aAAK,KAAK,IAAI,UAAU,KAAK,gBAAgB;AAAA,MAAE,QAAQ;AAAA,MAAoB;AAAA,IACnF;AACA,SAAK,YAAY,MAAM;AACvB,SAAK,mBAAmB;AACxB,UAAM,aAAa,KAAK,KAAK;AAC7B,SAAK,QAAQ;AACb,QAAI,KAAK,SAAS;AAChB,YAAM,KAAK,QAAQ,MAAM;AAAA,IAC3B;AACA,SAAK,UAAU;AACf,SAAK,UAAU;AACf,SAAK,OAAO;AACZ,SAAK,mBAAmB;AACxB,SAAK,0BAA0B;AAC/B,SAAK,WAAW,CAAC;AACjB,SAAK,eAAe,MAAM;AAC1B,SAAK,eAAe;AACpB,SAAK,mBAAmB;AACxB,SAAK,aAAa;AAClB,SAAK,oBAAoB;AACzB,SAAK,eAAe;AACpB,SAAK,qBAAqB;AAC1B,SAAK,oBAAoB,MAAM;AAC/B,SAAK,kBAAkB,QAAQ,QAAQ;AAAA,EACzC;AAAA,EAEA,IAAI,wBAAiC;AACnC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,QAAQ,SAAgD;AAC5D,QAAI,CAAC,KAAK,MAAM;AACd,YAAM,IAAI,MAAM,8DAAyD;AAAA,IAC3E;AACA,UAAM,OAAO,KAAK;AAElB,UAAM,iBAAiB,IAAI;AAI3B,UAAM,QAAQ,MAAM,aAAa,IAAI;AACrC,QAAI;AACF,YAAM,QAAQ,MAAM,KAAK,gBAAgB,MAAM,OAAO;AACtD,YAAM,aAAa,KAAK,KAAK;AAC7B,WAAK,QAAQ;AACb,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,aAAa,KAAK;AACxB,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAc,gBACZ,MACA,SACsB;AAItB,UAAM,WAAW,MAAM,aAAa,MAAM,gBAAgB;AAI1D,UAAM,EAAE,OAAO,WAAW,IAAI,kBAAkB,QAAQ;AACxD,QAAI,MAAM,SAAS,GAAG;AACpB,YAAM,eAAe,MAAM,OAAO,UAAU;AAAA,IAC9C;AACA,UAAM,EAAE,UAAU,OAAO,IAAI,MAAM,iBAAiB,IAAI;AAGxD,QAAI;AACJ,QAAI,SAAS,YAAY;AACvB,UAAI;AACF,qBAAa,MAAM,WAAW,IAAI;AAAA,MACpC,QAAQ;AAAA,MAER;AAAA,IACF;AAIA,UAAM,EAAE,OAAO,QAAQ,IAAIC,kBAAiB;AAAA,MAC1C,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY;AAAA,MACZ,WAAW,KAAK,IAAI;AAAA,MACpB,KAAK,KAAK,IAAI;AAAA,MACd,GAAI,eAAe,SAAY,EAAE,WAAW,IAAI,CAAC;AAAA,IACnD,CAAC;AAED,SAAK,WAAW,YAAY,SAAS,OAAO,YAAY,MAAM,QAAQ;AACtE,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAAQ,QAA2B,SAAiD;AACxF,QAAI,CAAC,KAAK,MAAM;AACd,YAAM,IAAI,MAAM,8DAAyD;AAAA,IAC3E;AAEA,UAAM,UAAU,KAAK;AACrB,UAAM,SAAS,IAAI,QAAQ,SAAS,KAAK,IAAI;AAC7C,UAAM,SAAS,MAAM,KAAK,uBAAuB,MAAM;AAGvD,SAAK,qBAAqB,UAAU;AACpC,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,SAAS,QAAQ;AAAA,IACpC,QAAQ;AACN,iBAAW;AAAA,IACb;AACA,WAAO,sBAAsB,QAAQ,QAAQ;AAAA,EAC/C;AAAA,EAEA,MAAc,uBAAuB,QAAkD;AACrF,QAAI,CAAC,KAAK,MAAM;AACd,YAAM,IAAI,MAAM,8DAAyD;AAAA,IAC3E;AACA,QAAI;AACF,aAAO,MAAM,KAAK,cAAc,MAAM;AAAA,IACxC,SAAS,KAAK;AACZ,UAAI;AACJ,UAAI;AACJ,UAAI;AACF,qBAAa,MAAM,KAAK,KAAK,WAAW,EAAE,OAAO,MAAM,CAAC;AAAA,MAC1D,QAAQ;AAAA,MAER;AACA,UAAI;AACF,YAAI,SAAS,UAAU,OAAQ,OAAe,QAAQ,UAAU;AAC9D,gBAAM,WAAW,IAAI,gBAAgB,KAAK,MAAM,KAAK,QAAQ;AAC7D,gBAAM,MAAM,MAAM,SAAS,eAAgB,OAAe,GAAG;AAC7D,cAAI,IAAK,eAAc;AAAA,QACzB;AAAA,MACF,QAAQ;AAAA,MAER;AACA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,QACtD;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,aAA0C;AAC9C,QAAI;AACF,UAAI,KAAK,MAAM;AACb,eAAO,MAAM,KAAK,KAAK,WAAW,EAAE,OAAO,OAAO,SAAS,sBAAsB,CAAC;AAAA,MACpF;AACA,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,UAAuB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,iBAAiB,OAAmC;AAClD,UAAM,MAAyB,CAAC;AAChC,eAAW,WAAW,KAAK,eAAe,OAAO,GAAG;AAClD,YAAM,UAAU,QAAQ,YAAY,MAAM,QAAQ,iBAAiB;AACnE,cAAQ,oBAAoB,QAAQ,YAAY;AAChD,UAAI,KAAK,GAAG,OAAO;AAAA,IACrB;AACA,QAAI,CAAC,MAAO,QAAO;AACnB,WAAO,IAAI,OAAO,OAAK,EAAE,UAAU,KAAK;AAAA,EAC1C;AAAA,EAEA,iBAAiB,YAAwC;AACvD,UAAM,MAAyB,CAAC;AAChC,eAAW,WAAW,KAAK,eAAe,OAAO,GAAG;AAClD,YAAM,UAAU,QAAQ,YAAY,MAAM,QAAQ,iBAAiB;AACnE,cAAQ,oBAAoB,QAAQ,YAAY;AAChD,UAAI,KAAK,GAAG,OAAO;AAAA,IACrB;AACA,QAAI,CAAC,WAAY,QAAO;AACxB,WAAO,IAAI,OAAO,OAAK,EAAE,IAAI,SAAS,UAAU,CAAC;AAAA,EACnD;AAAA;AAAA,EAGA,kBAAkB,QAAwC;AACxD,WAAO,KAAK,kBAAkB,kBAAkB,MAAM;AAAA,EACxD;AAAA,EAEA,gBAAgB,YAAwC;AACtD,UAAM,MAAyB,CAAC;AAChC,eAAW,WAAW,KAAK,eAAe,OAAO,GAAG;AAClD,UAAI,KAAK,GAAG,QAAQ,YAAY,MAAM,QAAQ,iBAAiB,CAAC;AAAA,IAClE;AACA,QAAI,CAAC,WAAY,QAAO;AACxB,WAAO,IAAI,OAAO,OAAK,EAAE,IAAI,SAAS,UAAU,CAAC;AAAA,EACnD;AAAA,EAEQ,mBAAmB,MAAkB;AAC3C,UAAM,UAA0B;AAAA,MAC9B,aAAa,CAAC;AAAA,MACd,aAAa,CAAC;AAAA,MACd,mBAAmB;AAAA,MACnB,mBAAmB;AAAA,MACnB,iBAAiB,oBAAI,IAAI;AAAA,IAC3B;AACA,SAAK,eAAe,IAAI,MAAM,OAAO;AAErC,QAAI,KAAK,iBAAiB,SAAS;AACjC,WAAK,GAAG,WAAW,CAAC,QAAQ;AAC1B,gBAAQ,YAAY,KAAK;AAAA,UACvB,OAAO,IAAI,KAAK;AAAA,UAChB,MAAM,IAAI,KAAK;AAAA,UACf,UAAU,IAAI,SAAS;AAAA,UACvB,WAAW,KAAK,IAAI;AAAA,QACtB,CAAC;AACD,YAAI,QAAQ,YAAY,SAAS,KAAM;AACrC,kBAAQ,cAAc,QAAQ,YAAY,MAAM,IAAI;AAAA,QACtD;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI,KAAK,iBAAiB,SAAS;AACjC,WAAK,GAAG,WAAW,CAAC,YAAY;AAC9B,gBAAQ,gBAAgB,IAAI,QAAQ,IAAI,IAAI,QAAQ,OAAO,GAAG;AAAA,UAC5D,KAAK,QAAQ,IAAI;AAAA,UACjB,QAAQ,QAAQ,OAAO;AAAA,UACvB,SAAS,QAAQ,QAAQ;AAAA,UACzB,WAAW,KAAK,IAAI;AAAA,UACpB,UAAU,QAAQ,SAAS,KAAK;AAAA,QAClC,CAAC;AAAA,MACH,CAAC;AAED,WAAK,GAAG,YAAY,OAAO,aAAa;AACtC,cAAM,MAAM,SAAS,IAAI,IAAI,SAAS,QAAQ,EAAE,OAAO;AACvD,cAAM,UAAU,QAAQ,gBAAgB,IAAI,GAAG;AAC/C,gBAAQ,gBAAgB,OAAO,GAAG;AAElC,YAAI;AACJ,YAAI;AACF,gBAAM,MAAM,MAAM,SAAS,KAAK;AAChC,gBAAM,KAAK,SAAS,QAAQ,EAAE,cAAc,KAAK;AACjD,cAAI,GAAG,SAAS,QAAQ,KAAK,CAAC,GAAG,SAAS,KAAK,GAAG;AAChD,mBAAO,IAAI,SAAS,QAAQ,SAAY,QAAQ,GAAG,MAAM,GAAG,EAAE,CAAC,CAAC,WAAW,IAAI,SAAS,QAAQ,CAAC;AAAA,UACnG,OAAO;AACL,kBAAM,OAAO,IAAI,SAAS,OAAO;AACjC,mBAAO,KAAK,SAAS,QAAQ,KAAK,MAAM,GAAG,KAAK,IAAI,mBAAmB;AAAA,UACzE;AAAA,QACF,QAAQ;AACN,iBAAO;AAAA,QACT;AAEA,gBAAQ,YAAY,KAAK;AAAA,UACvB,KAAK,SAAS,IAAI;AAAA,UAClB,QAAQ,SAAS,QAAQ,EAAE,OAAO;AAAA,UAClC,QAAQ,SAAS,OAAO;AAAA,UACxB,gBAAgB,SAAS,WAAW,SAAS,QAAQ,EAAE,QAAQ;AAAA,UAC/D,iBAAiB,SAAS,QAAQ;AAAA,UAClC;AAAA,UACA,aAAa,SAAS;AAAA,UACtB,WAAW,SAAS,aAAa,KAAK,IAAI;AAAA,UAC1C,SAAS,KAAK,IAAI;AAAA,UAClB,QAAQ,SAAS,QAAQ,EAAE,OAAO;AAAA,QACpC,CAAC;AACD,YAAI,QAAQ,YAAY,SAAS,KAAK;AACpC,kBAAQ,cAAc,QAAQ,YAAY,MAAM,IAAI;AAAA,QACtD;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAc,sBAAsB,KAAkF;AACpH,UAAM,QAAQ,KAAK,QAAS,MAAM;AAClC,QAAI,IAAI,UAAU,QAAW;AAC3B,aAAQ,IAAI,SAAS,KAAK,IAAI,QAAQ,MAAM,SAAU,MAAM,IAAI,KAAK,IAAI;AAAA,IAC3E;AACA,QAAI,IAAI,OAAO;AACb,iBAAW,KAAK,OAAO;AACrB,cAAM,IAAI,MAAM,EAAE,MAAM;AACxB,YAAI,EAAE,SAAS,IAAI,KAAK,EAAG,QAAO;AAAA,MACpC;AACA,aAAO;AAAA,IACT;AACA,QAAI,IAAI,KAAK;AACX,aAAO,MAAM,KAAK,OAAK,EAAE,IAAI,EAAE,SAAS,IAAI,GAAI,CAAC;AAAA,IACnD;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,cAAc,QAAkD;AAC5E,UAAM,OAAO,KAAK;AAClB,UAAM,WAAW,IAAI,gBAAgB,MAAM,KAAK,QAAQ;AAKxD,eAAW,OAAO,SAAS,MAAM,GAAG;AAClC,YAAM,QAAQ,KAAK,SAAS,GAAG;AAC/B,UAAI,UAAU,OAAW;AAGzB,YAAM,QAAQ,OAAO,SAAS,WAC1B,MAAM,cAAc,MAAM,KAAK,KAAK,IACpC,MAAM,aAAa,MAAM,KAAK,OAAO,OAAO,gBAAgB;AAChE,UAAI,MAAM,YAAY,KAAM,QAAO,eAAe,MAAM,SAAS,GAAG;AAAA,IACtE;AAGA,QAAI,SAAS,UAAU,OAAQ,OAAe,QAAQ,UAAU;AAC9D,YAAM,UAAU,KAAK,SAAU,OAAe,GAAG;AACjD,YAAM,OAAO,SAAS;AACtB,YAAM,aAAa,eAAe,QAAQ,IAAI;AAC9C,UAAI,CAAC,WAAW,OAAO;AACrB,eAAO,EAAE,SAAS,OAAO,OAAO,WAAW,MAAM;AAAA,MACnD;AAAA,IACF;AAEA,YAAQ,OAAO,MAAM;AAAA,MACnB,KAAK,SAAS;AACZ,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,cAAM,cAAc,MAAM,EAAE,GAAG,IAAI,IAAI,IAAI,QAAQ,GAAG,GAAG,IAAI,IAAI,IAAI,SAAS,EAAE,IAAI;AACpF,cAAM,QAAQ,MAAM;AAAA,UAClB,GAAG,iBAAiB,OAAO,UAAU;AAAA,UACrC,GAAI,KAAK,mBAAmB,EAAE,aAAa,KAAK,IAAI,CAAC;AAAA,QACvD,CAAC;AACD,eAAO,EAAE,SAAS,MAAM,aAAa,aAAa,OAAO,OAAU;AAAA,MACrE;AAAA,MAEA,KAAK,QAAQ;AACX,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,eAAO,mBAAmB,SAAS,OAAO,QAAW,MAAM;AAAA,MAC7D;AAAA,MAEA,KAAK,WAAW;AACd,eAAO,gBAAgB;AAAA,MACzB;AAAA,MAEA,KAAK,UAAU;AACb,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,cAAM,QAAQ,aAAa,OAAO,KAAK;AACvC,eAAO,EAAE,SAAS,MAAM,aAAa,OAAO,OAAU;AAAA,MACxD;AAAA,MAEA,KAAK,YAAY;AAGf,gBAAQ,OAAO,IAAI;AAAA,UACjB,KAAK;AACH,kBAAM,KAAK,KAAK,OAAO,KAAK,EAAE,WAAW,mBAAmB,CAAC;AAC7D;AAAA,UACF,KAAK;AACH,kBAAM,KAAK,OAAO,EAAE,WAAW,mBAAmB,CAAC;AACnD;AAAA,UACF,KAAK;AACH,kBAAM,KAAK,UAAU,EAAE,WAAW,mBAAmB,CAAC;AACtD;AAAA,UACF,KAAK;AACH,kBAAM,KAAK,OAAO,EAAE,WAAW,mBAAmB,CAAC;AACnD;AAAA,QACJ;AACA,cAAM,iBAAiB,IAAI;AAC3B,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,UAAU;AACb,eAAO,qBAAqB,MAAM,KAAK,UAAU,MAAM;AAAA,MACzD;AAAA,MAEA,KAAK,WAAW;AACd,cAAM,UAAU,OAAO;AACvB,YAAI;AACF,kBAAQ,OAAO,IAAI;AAAA,YACjB,KAAK;AACH,oBAAM,KAAK,UAAU,OAAO,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,WAAW,QAAQ,CAAC;AAC/E;AAAA,YACF,KAAK;AACH,oBAAM,KAAK,UAAU,OAAO,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,UAAU,QAAQ,CAAC;AAC9E;AAAA,YACF,KAAK;AACH,oBAAM,KAAK,gBAAgB,OAAO,UAAU,EAAE,QAAQ,CAAC;AACvD;AAAA,UACJ;AAAA,QACF,QAAQ;AACN,gBAAM,OAAO,OAAO,OAAO,aAAa,aAAa,OAAO,QAAQ,MAAM,SAAS,OAAO,IAAI;AAC9F,gBAAM,MAAM,OAAO,OAAO,SAAS,4BAA4B;AAC/D,iBAAO,EAAE,SAAS,OAAO,OAAO,YAAY,IAAI,IAAI,GAAG,IAAI,OAAO,MAAM;AAAA,QAC1E;AACA,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,SAAS;AACZ,cAAM,KAAK,eAAe,OAAO,EAAE;AACnC,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,cAAc;AACjB,YAAI;AAEF,gBAAM,KAAK,WAAW,OAAO,SAAS,EAAE,SAAS,IAAO,CAAC;AACzD,iBAAO,EAAE,SAAS,KAAK;AAAA,QACzB,SAAS,KAAK;AACZ,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,OAAO,gBAAgB,OAAO,OAAO,yGAAyG,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,UAChM;AAAA,QACF;AAAA,MACF;AAAA,MAEA,KAAK,YAAY;AAGf,cAAM,gBAAgB,uBAAuB,OAAO,MAAM;AAAA,UACxD,SAAS,OAAO,wBAAwB;AAAA,UACxC,OAAO,cAAc;AAAA,QACvB,CAAC;AACD,mBAAW,OAAO,eAAe;AAC/B,cAAI,OAAO,SAAS,QAAQ;AAC1B,kBAAM,KAAK,SAAS,KAAK,GAAG;AAAA,UAC9B,WAAW,OAAO,SAAS,MAAM;AAC/B,kBAAM,KAAK,SAAS,GAAG,GAAG;AAAA,UAC5B,OAAO;AACL,kBAAM,KAAK,SAAS,MAAM,GAAG;AAAA,UAC/B;AAAA,QACF;AACA,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,SAAS;AACZ,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,cAAM,QAAQ,MAAM;AACpB,eAAO,EAAE,SAAS,MAAM,aAAa,OAAO,OAAU;AAAA,MACxD;AAAA,MAEA,KAAK,SAAS;AACZ,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,cAAM,QAAQ,MAAM;AACpB,cAAM,KAAK,SAAS;AAAA;AAAA;AAAA;AAAA,qCAIS,KAAK,UAAU,OAAO,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aAMpD;AACL,eAAO,EAAE,SAAS,MAAM,aAAa,OAAO,OAAU;AAAA,MACxD;AAAA,MAEA,KAAK,cAAc;AAEjB,cAAM,EAAE,WAAW,IAAI,MAAM,OAAO,IAAS;AAC7C,mBAAW,YAAY,OAAO,OAAO;AACnC,cAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,mBAAO,EAAE,SAAS,OAAO,OAAO,mBAAmB,QAAQ,GAAG;AAAA,UAChE;AAAA,QACF;AACA,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,cAAM,QAAQ,cAAc,OAAO,KAAK;AACxC,eAAO,EAAE,SAAS,MAAM,aAAa,OAAO,OAAU;AAAA,MACxD;AAAA,MAEA,KAAK,QAAQ;AACX,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,cAAM,OAAQ,MAAM,QAAQ,YAAY,KAAM;AAC9C,cAAM,KAAK,SAAS,iCAAiC,KAAK,UAAU,IAAI,CAAC,GAAG;AAC5E,eAAO,EAAE,SAAS,MAAM,aAAa,OAAO,QAAW,MAAM,EAAE,QAAQ,KAAK,EAAE;AAAA,MAChF;AAAA,MAEA,KAAK,OAAO;AAEV,YAAI,OAAO,WAAW,OAAO;AAC3B,gBAAM,UAAU,MAAM,KAAK,QAAS,QAAQ;AAC5C,eAAK,mBAAmB,OAAO;AAC/B,gBAAM,QAAQ,KAAK,OAAO,KAAK,EAAE,WAAW,mBAAmB,CAAC;AAChE,gBAAM,iBAAiB,OAAO;AAC9B,eAAK,cAAc,OAAO;AAC1B,iBAAO,EAAE,SAAS,KAAK;AAAA,QACzB;AACA,cAAM,QAAQ,KAAK,QAAS,MAAM;AAClC,YAAI;AACJ,YAAI,OAAO,UAAU,QAAW;AAC9B,cAAI,OAAO,QAAQ,KAAK,OAAO,SAAS,MAAM,QAAQ;AACpD,mBAAO,EAAE,SAAS,OAAO,OAAO,aAAa,OAAO,KAAK,kBAAkB,MAAM,MAAM,cAAc;AAAA,UACvG;AACA,mBAAS,MAAM,OAAO,KAAK;AAAA,QAC7B,WAAW,OAAO,UAAU,QAAW;AACrC,qBAAW,KAAK,OAAO;AACrB,kBAAM,IAAI,MAAM,EAAE,MAAM;AACxB,gBAAI,EAAE,SAAS,OAAO,KAAK,GAAG;AAAE,uBAAS;AAAG;AAAA,YAAM;AAAA,UACpD;AAAA,QACF,WAAW,OAAO,QAAQ,QAAW;AACnC,mBAAS,MAAM,KAAK,OAAK,EAAE,IAAI,EAAE,SAAS,OAAO,GAAI,CAAC;AAAA,QACxD;AACA,YAAI,CAAC,QAAQ;AACX,iBAAO,EAAE,SAAS,OAAO,OAAO,yBAAyB,KAAK,UAAU,EAAE,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG;AAAA,QAC3I;AACA,aAAK,cAAc,MAAM;AACzB,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,WAAW;AAGd,gBAAQ,OAAO,MAAM;AAAA,UACnB,KAAK,WAAW;AACd,gBAAI;AACJ,gBAAI,OAAO,KAAK;AACd,oBAAM,aAAa,MAAM,KAAK,sBAAsB,OAAO,GAAG;AAC9D,kBAAI,CAAC,YAAY;AACf,uBAAO,EAAE,SAAS,OAAO,OAAO,yBAAyB,KAAK,UAAU,OAAO,GAAG,CAAC,GAAG;AAAA,cACxF;AACA,oBAAM,UAAU,KAAK,eAAe,IAAI,UAAU;AAClD,wBAAU,UAAU,CAAC,GAAG,QAAQ,WAAW,IAAI,CAAC;AAAA,YAClD,OAAO;AACL,wBAAU,CAAC;AACX,yBAAW,WAAW,KAAK,eAAe,OAAO,GAAG;AAClD,wBAAQ,KAAK,GAAG,QAAQ,WAAW;AAAA,cACrC;AAAA,YACF;AACA,gBAAI,OAAO,OAAO;AAChB,wBAAU,QAAQ,OAAO,OAAK,EAAE,UAAU,OAAO,KAAK;AAAA,YACxD;AACA,mBAAO,EAAE,SAAS,MAAM,MAAM,QAAQ;AAAA,UACxC;AAAA,UACA,KAAK,WAAW;AACd,gBAAI;AACJ,gBAAI,OAAO,KAAK;AACd,oBAAM,aAAa,MAAM,KAAK,sBAAsB,OAAO,GAAG;AAC9D,kBAAI,CAAC,YAAY;AACf,uBAAO,EAAE,SAAS,OAAO,OAAO,yBAAyB,KAAK,UAAU,OAAO,GAAG,CAAC,GAAG;AAAA,cACxF;AACA,oBAAM,UAAU,KAAK,eAAe,IAAI,UAAU;AAClD,wBAAU,UAAU,CAAC,GAAG,QAAQ,WAAW,IAAI,CAAC;AAAA,YAClD,OAAO;AACL,wBAAU,CAAC;AACX,yBAAW,WAAW,KAAK,eAAe,OAAO,GAAG;AAClD,wBAAQ,KAAK,GAAG,QAAQ,WAAW;AAAA,cACrC;AAAA,YACF;AACA,gBAAI,OAAO,YAAY;AACrB,wBAAU,QAAQ,OAAO,OAAK,EAAE,IAAI,SAAS,OAAO,UAAW,CAAC;AAAA,YAClE;AACA,mBAAO,EAAE,SAAS,MAAM,MAAM,QAAQ;AAAA,UACxC;AAAA,UACA,KAAK,WAAW;AACd,kBAAM,UAAU,MAAM,KAAK,QAAS,QAAQ;AAC5C,gBAAI,OAAO,MAAM;AACf,oBAAM,SAAS,QAAQ,KAAK,OAAK,EAAE,SAAS,OAAO,IAAI,KAAK;AAC5D,qBAAO,EAAE,SAAS,MAAM,MAAM,OAAO;AAAA,YACvC;AACA,mBAAO,EAAE,SAAS,MAAM,MAAM,QAAQ;AAAA,UACxC;AAAA,UACA,KAAK,gBAAgB;AACnB,kBAAM,UAAU,KAAK,IAAI;AACzB,gBAAI,YAAY,eAAe;AAC7B,qBAAO,EAAE,SAAS,MAAM,MAAM,OAAO,MAAM,OAAO,CAAC,EAAE;AAAA,YACvD;AACA,gBAAI,OAAO,KAAK;AACd,oBAAM,QAAQ,MAAM,KAAK;AAAA,gBACvB,CAAC,MAAc,aAAa,QAAQ,CAAC;AAAA,gBAAG,OAAO;AAAA,cACjD;AACA,qBAAO,EAAE,SAAS,MAAM,MAAM,MAAM;AAAA,YACtC;AACA,kBAAM,MAAM,MAAM,KAAK;AAAA,cACrB,MAAM,OAAO;AAAA,gBACX,OAAO,KAAK,YAAY,EAAE,IAAI,OAAK,CAAC,GAAG,aAAa,QAAQ,CAAC,CAAC,CAAC;AAAA,cACjE;AAAA,YACF;AACA,mBAAO,EAAE,SAAS,MAAM,MAAM,IAAI;AAAA,UACpC;AAAA,QACF;AACA,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,cAAc;AACjB,cAAM,sBAAsB,OAAO,QAAQ,IAAI,QAAM;AAAA,UACnD,GAAG;AAAA,UACH,KAAK,CAAC,EAAE,SAAS,KAAK,IAAI,IAAI;AAAA,QAChC,EAAE;AACF,cAAM,KAAK,QAAS,WAAW,mBAAmB;AAClD,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,mBAAmB;AACtB,cAAM,KAAK,SAAS,CAAC,YAAmD;AACtE,qBAAW,EAAE,KAAK,MAAM,KAAK,SAAS;AACpC,yBAAa,QAAQ,KAAK,KAAK;AAAA,UACjC;AAAA,QACF,GAAG,OAAO,OAAO;AACjB,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,SAAS;AACZ,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,cAAM,QAAQ,MAAM;AACpB,eAAO,EAAE,SAAS,MAAM,aAAa,OAAO,OAAU;AAAA,MACxD;AAAA,MAEA,KAAK,eAAe;AAGlB,YAAI;AACJ,YAAI,UAAU,QAAQ;AACpB,kBAAQ,MAAM,KAAK,SAAS,OAAO,IAAI;AAAA,QACzC,OAAO;AACL,kBAAQ,OAAO,QAAQ;AAAA,YACrB,KAAK;AACH,sBAAQ,KAAK,IAAI;AACjB;AAAA,YACF,KAAK;AACH,sBAAQ,KAAK,IAAI,MAAM,gBACnB,CAAC,IACD,MAAM,KAAK;AAAA,gBACT,MAAM,OAAO;AAAA,kBACX,OAAO,KAAK,YAAY,EAAE,IAAI,OAAK,CAAC,GAAG,aAAa,QAAQ,CAAC,CAAC,CAAC;AAAA,gBACjE;AAAA,cACF;AACJ;AAAA,YACF,KAAK;AACH,sBAAQ,KAAK,gBAAgB;AAC7B;AAAA,YACF,KAAK;AACH,sBAAQ;AACR;AAAA,UACJ;AAAA,QACF;AACA,eAAO,EAAE,SAAS,MAAM,MAAM,MAAM;AAAA,MACtC;AAAA,MAEA,KAAK,aAAa;AAChB,cAAM,MAAM,SAAS,QAAQ,OAAO,GAAG;AACvC,cAAM,WAAW,MAAM,SAAS,eAAe,OAAO,GAAG;AACzD,cAAM,IAAI,MAAM;AAChB,eAAO,EAAE,SAAS,MAAM,aAAa,YAAY,OAAU;AAAA,MAC7D;AAAA,MAEA,KAAK,eAAe;AAClB,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,cAAM,cAAc,MAChB,OAAO,mBACL,EAAE,GAAG,IAAI,IAAI,OAAO,iBAAiB,GAAG,GAAG,IAAI,IAAI,OAAO,iBAAiB,EAAE,IAC7E,EAAE,GAAG,IAAI,IAAI,IAAI,QAAQ,GAAG,GAAG,IAAI,IAAI,IAAI,SAAS,EAAE,IACxD;AACJ,cAAM,QAAQ,SAAS;AAAA,UACrB,GAAI,OAAO,oBAAoB,EAAE,UAAU,OAAO,iBAAiB;AAAA,UACnE,GAAG,iBAAiB,OAAO,UAAU;AAAA,QACvC,CAAC;AACD,eAAO,EAAE,SAAS,MAAM,aAAa,aAAa,OAAO,OAAU;AAAA,MACrE;AAAA,MAEA,KAAK,cAAc;AACjB,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,cAAM,cAAc,MAChB,OAAO,mBACL,EAAE,GAAG,IAAI,IAAI,OAAO,iBAAiB,GAAG,GAAG,IAAI,IAAI,OAAO,iBAAiB,EAAE,IAC7E,EAAE,GAAG,IAAI,IAAI,IAAI,QAAQ,GAAG,GAAG,IAAI,IAAI,IAAI,SAAS,EAAE,IACxD;AACJ,cAAM,QAAQ,MAAM;AAAA,UAClB,QAAQ;AAAA,UACR,GAAI,OAAO,oBAAoB,EAAE,UAAU,OAAO,iBAAiB;AAAA,UACnE,GAAG,iBAAiB,OAAO,UAAU;AAAA,QACvC,CAAC;AACD,eAAO,EAAE,SAAS,MAAM,aAAa,aAAa,OAAO,OAAU;AAAA,MACrE;AAAA,MAEA,KAAK,SAAS;AAIZ,cAAM,KAAK,QAAS,MAAM,OAAO,YAAY,OAAO,UAAU;AAC5D,gBAAM,MAAM,QAAQ;AAAA,YAClB,QAAQ;AAAA,YACR,GAAI,OAAO,gBAAgB,SAAY,EAAE,aAAa,OAAO,YAAY,IAAI,CAAC;AAAA,YAC9E,GAAI,OAAO,YAAY,SAAY,EAAE,SAAS,OAAO,QAAQ,IAAI,CAAC;AAAA,YAClE,GAAI,OAAO,SAAS,SAAY,EAAE,MAAM,OAAO,KAAK,IAAI,CAAC;AAAA,UAC3D,CAAC;AAAA,QACH,CAAC;AACD,aAAK,YAAY,IAAI,OAAO,UAAU;AACtC,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,WAAW;AACd,YAAI,OAAO,eAAe,QAAW;AACnC,gBAAM,KAAK,QAAS,QAAQ,OAAO,UAAU;AAC7C,eAAK,YAAY,OAAO,OAAO,UAAU;AAAA,QAC3C,OAAO;AACL,gBAAM,KAAK,QAAS,WAAW,EAAE,UAAU,eAAe,CAAC;AAC3D,eAAK,YAAY,MAAM;AAAA,QACzB;AACA,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,gBAAgB;AACnB,YAAI,OAAO,SAAS,WAAW;AAC7B,gBAAM,KAAK,QAAS,WAAW,IAAI;AACnC,iBAAO,EAAE,SAAS,KAAK;AAAA,QACzB;AAEA,YAAI;AACF,gBAAM,MAAM,MAAM,KAAK,QAAS,cAAc,IAAI;AAClD,gBAAM,IAAI,KAAK,oCAAoC;AAAA,YACjD,SAAS;AAAA,YACT,SAAS,OAAO;AAAA,YAChB,oBAAqB,OAAO,eAAe,MAAQ;AAAA,YACnD,kBAAmB,OAAO,aAAa,MAAQ;AAAA,UACjD,CAAC;AACD,iBAAO,EAAE,SAAS,KAAK;AAAA,QACzB,SAAS,KAAK;AACZ,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,OAAO,iGAAiG,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,UAC1J;AAAA,QACF;AAAA,MACF;AAAA,MAEA,KAAK,gBAAgB;AAInB,YAAI,OAAO,OAAO,QAAQ;AACxB,gBAAM,QAAQ,MAAM,KAAK,QAAS,aAAa;AAC/C,iBAAO,EAAE,SAAS,MAAM,MAAM,EAAE,MAAM,OAAO,MAAM,MAAM,EAAE;AAAA,QAC7D;AACA,cAAM,KAAK,QAAS,gBAAgB,qBAAqB,MAAM,CAAC;AAChE,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,gBAAgB;AAEnB,YAAI,KAAK,kBAAkB;AACzB,eAAK,IAAI,UAAU,KAAK,gBAAgB;AACxC,eAAK,mBAAmB;AAAA,QAC1B;AACA,cAAM,SAAS,OAAO;AACtB,cAAM,aAAa,OAAO;AAC1B,cAAM,UAAU,CAAC,WAAyB;AACxC,eAAK,mBAAmB;AACxB,cAAI,QAAQ;AACV,iBAAK,OAAO,OAAO,UAAU;AAAA,UAC/B,OAAO;AACL,iBAAK,OAAO,QAAQ;AAAA,UACtB;AAAA,QACF;AACA,aAAK,mBAAmB;AACxB,aAAK,KAAK,UAAU,OAAO;AAC3B,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,iBAAiB;AACpB,eAAO,EAAE,SAAS,OAAO,OAAO,wCAAwC;AAAA,MAC1E;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACH,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO,WAAW,OAAO,IAAI;AAAA,QAC/B;AAAA,MAEF;AACE,eAAO,YAAY,MAAM;AAAA,IAC7B;AAAA,EACF;AACF;;;AYl3CA,SAAS,eAAAC,cAAa,oBAAAC,yBAAwB;AAE9C,SAAS,aAAa,4BAA4B;AAClD,SAAS,0BAAAC,yBAAwB,iBAAAC,sBAAqB;AA6BtD,SAASC,kBAAiB,YAAyC;AACjE,SAAO,eAAe,UAAa,aAAa,IAAI,EAAE,OAAO,WAAW,IAAI,CAAC;AAC/E;AAMA,SAASC,sBAAqB,QAAmE;AAC/F,SAAQ,OAAuE;AACjF;AAEO,IAAM,iBAAN,MAAuD;AAAA,EACnD,WAAW;AAAA,EAEZ,UAA0B;AAAA,EAC1B,UAAiC;AAAA,EACjC,OAAoB;AAAA;AAAA,EAEpB,WAAmB,CAAC;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,cAAmC;AAAA,EACnC,cAA8D;AAAA,EAC9D,iBAAiB,oBAAI,IAA0B;AAAA,EAC/C,mBAA2D,EAAE,SAAS,MAAM,SAAS,KAAK;AAAA;AAAA;AAAA,EAG1F,cAAc,oBAAI,IAAY;AAAA,EAC9B,mBAAsD;AAAA,EACtD;AAAA,EACA;AAAA,EAER,MAAM,MAAM,QAAuC;AACjD,SAAK,kBAAkB,OAAO;AAC9B,QAAI,CAAC,OAAO,aAAa;AACvB,YAAM,IAAI,MAAM,sDAAsD;AAAA,IACxE;AAEA,yBAAqB;AACrB,UAAM,WAAW,YAAY,cAAc;AAC3C,QAAI,CAAC,UAAU;AACb,YAAM,IAAI,MAAM,qCAAqC;AAAA,IACvD;AAEA,SAAK,cAAc,SAAS,mBAAmB,OAAO,YAAY,YAAmB;AACrF,QAAI,CAAC,OAAO,SAAS,MAAM;AACzB,YAAM,IAAI,MAAM,uDAAuD;AAAA,IACzE;AACA,UAAM,cAAc,KAAK;AAEzB,UAAM,gBAA+B;AAAA,MACnC,SAAS,OAAO;AAAA,MAChB;AAAA,MACA,UAAW,OAAO,YAAY,cAAsB;AAAA,IACtD;AAEA,UAAM,EAAE,WAAW,IAAI,MAAM,SAAS,mBAAmB,aAAa;AAEtE,UAAM,EAAE,SAAS,IAAI,MAAM,OAAO,iBAAiB;AACnD,SAAK,UAAU,MAAM,SAAS,QAAQ,EAAE,WAAW,CAAC;AAEpD,UAAM,iBAA0C;AAAA,MAC9C,UAAU,OAAO,SAAS,YAAY,EAAE,OAAO,MAAM,QAAQ,IAAI;AAAA,IACnE;AACA,QAAI,OAAO,WAAW,kBAAkB;AACtC,qBAAe,eAAe,OAAO,UAAU;AAAA,IACjD;AACA,SAAK,UAAU,MAAM,KAAK,QAAQ,WAAW,cAAc;AAG3D,UAAM,KAAK,QAAQ,iBAAiB,CAAC,iBAAiB,CAAC;AAEvD,SAAK,OAAO,MAAM,KAAK,QAAQ,QAAQ;AAEvC,QAAI;AACF,YAAM,aAAa,MAAM,KAAK,KAAK,QAAQ,EAAE,cAAc,KAAK,IAAI;AACpE,YAAM,SAAS,MAAM,WAAW,KAAK,oBAAoB;AACzD,YAAM,WAAW,OAAO;AAGxB,YAAM,OAAO,OAAO,KAAK,GAAG,YAAY,QAAQ,IAAI,YAAY,SAAS,EAAE,EAAE,SAAS,QAAQ;AAC9F,YAAM,OAAO,MAAM,MAAM,4EAA4E;AAAA,QACnG,SAAS,EAAE,eAAe,SAAS,IAAI,GAAG;AAAA,MAC5C,CAAC;AACD,UAAI,KAAK,IAAI;AACX,cAAM,SAAS,MAAM,KAAK,KAAK;AAC/B,YAAI,OAAO,SAAS,GAAG;AACrB,gBAAM,UAAU,OAAO,CAAC,EAAE,iBAAiB;AAC3C,gBAAM,WAAW,MAAM,MAAM,gDAAgD,OAAO,0BAA0B;AAAA,YAC5G,SAAS,EAAE,eAAe,SAAS,IAAI,GAAG;AAAA,UAC5C,CAAC;AACD,cAAI,SAAS,IAAI;AACf,kBAAM,WAAW,MAAM,SAAS,KAAK;AACrC,gBAAI,SAAS,SAAS,GAAG;AACvB,mBAAK,YAAY,SAAS,CAAC,EAAE,mBAAmB;AAChD,mBAAK,aAAa,SAAS,CAAC,EAAE,mBAAmB;AAAA,YACnD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAEA,SAAK,cAAc,MAAM;AACvB,UAAI;AACF,aAAK,SAAS,MAAM;AAAA,MACtB,QAAQ;AAAA,MAER;AAAA,IACF;AACA,YAAQ,GAAG,QAAQ,KAAK,WAAW;AAEnC,SAAK,mBAAmB,EAAE,SAAS,OAAO,YAAY,YAAY,OAAO,SAAS,OAAO,YAAY,YAAY,MAAM;AACvH,SAAK,mBAAmB,KAAK,IAAI;AAAA,EACnC;AAAA,EAEA,IAAI,YAA6C;AAC/C,QAAI,CAAC,KAAK,QAAQ,CAAC,KAAK,WAAW,CAAC,KAAK,gBAAiB,QAAO;AACjE,WAAO,KAAK,wBAAwB;AAAA,MAClC,MAAM,KAAK;AAAA,MACX,KAAK;AAAA,IACP;AAAA,EACF;AAAA,EAEA,MAAM,UAAyB;AAC7B,QAAI;AAAE,YAAM,KAAK,qBAAqB,KAAK;AAAA,IAAE,QAAQ;AAAA,IAAoB;AACzE,SAAK,sBAAsB;AAC3B,SAAK,kBAAkB;AAGvB,QAAI,KAAK,SAAS;AAChB,UAAI;AAAE,cAAM,KAAK,QAAQ,WAAW,EAAE,UAAU,eAAe,CAAC;AAAA,MAAE,QAAQ;AAAA,MAAoB;AAC9F,UAAI;AAAE,cAAM,KAAK,QAAQ,WAAW,KAAK;AAAA,MAAE,QAAQ;AAAA,MAAoB;AAAA,IACzE;AACA,QAAI,KAAK,QAAQ,KAAK,kBAAkB;AACtC,UAAI;AAAE,aAAK,KAAK,IAAI,UAAU,KAAK,gBAAgB;AAAA,MAAE,QAAQ;AAAA,MAAoB;AAAA,IACnF;AACA,SAAK,YAAY,MAAM;AACvB,SAAK,mBAAmB;AACxB,UAAM,aAAa,KAAK,KAAK;AAC7B,SAAK,QAAQ;AAEb,QAAI,KAAK,SAAS;AAChB,YAAM,KAAK,QAAQ,MAAM;AAAA,IAC3B;AAGA,QAAI,KAAK,aAAa,KAAK,aAAa;AACtC,UAAI;AACF,cAAM,SAAS,KAAK,aAAa,WAAW;AAC5C,cAAM,SAAS,KAAK,aAAa,gBAAgB;AACjD,cAAM,OAAO,OAAO,KAAK,GAAG,KAAK,YAAY,QAAQ,IAAI,KAAK,YAAY,SAAS,EAAE,EAAE,SAAS,QAAQ;AACxG,cAAM,MAAM,kDAAkD,KAAK,SAAS,SAAS;AAAA,UACnF,QAAQ;AAAA,UACR,SAAS,EAAE,eAAe,SAAS,IAAI,IAAI,gBAAgB,mBAAmB;AAAA,UAC9E,MAAM,KAAK,UAAU,EAAE,QAAQ,OAAO,CAAC;AAAA,QACzC,CAAC;AAAA,MACH,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,QAAI,KAAK,aAAa;AACpB,cAAQ,eAAe,QAAQ,KAAK,WAAW;AAC/C,WAAK,cAAc;AAAA,IACrB;AAEA,SAAK,UAAU;AACf,SAAK,UAAU;AACf,SAAK,OAAO;AACZ,SAAK,WAAW,CAAC;AACjB,SAAK,eAAe,MAAM;AAAA,EAC5B;AAAA,EAEA,MAAM,QAAQ,SAAgD;AAC5D,QAAI,CAAC,KAAK,MAAM;AACd,YAAM,IAAI,MAAM,0DAAqD;AAAA,IACvE;AACA,UAAM,OAAO,KAAK;AAElB,UAAM,iBAAiB,IAAI;AAI3B,UAAM,QAAQ,MAAM,aAAa,IAAI;AACrC,QAAI;AACF,YAAM,QAAQ,MAAM,KAAK,gBAAgB,MAAM,OAAO;AACtD,YAAM,aAAa,KAAK,KAAK;AAC7B,WAAK,QAAQ;AACb,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,aAAa,KAAK;AACxB,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAc,gBACZ,MACA,SACsB;AACtB,UAAM,WAAW,MAAM,aAAa,IAAI;AAExC,UAAM,EAAE,OAAO,WAAW,IAAI,kBAAkB,QAAQ;AACxD,QAAI,MAAM,SAAS,GAAG;AACpB,YAAM,eAAe,MAAM,OAAO,UAAU;AAAA,IAC9C;AACA,UAAM,EAAE,UAAU,OAAO,IAAI,MAAM,iBAAiB,IAAI;AAExD,QAAI;AACJ,QAAI,SAAS,YAAY;AACvB,UAAI;AACF,qBAAa,MAAM,WAAW,IAAI;AAAA,MACpC,QAAQ;AAAA,MAER;AAAA,IACF;AAEA,UAAM,EAAE,OAAO,QAAQ,IAAIC,kBAAiB;AAAA,MAC1C,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA,YAAY;AAAA,MACZ,WAAW,KAAK,IAAI;AAAA,MACpB,KAAK,KAAK,IAAI;AAAA,MACd,GAAI,eAAe,SAAY,EAAE,WAAW,IAAI,CAAC;AAAA,IACnD,CAAC;AAED,SAAK,WAAW,YAAY,SAAS,OAAO,YAAY,MAAM,QAAQ;AACtE,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAAQ,QAAkD;AAC9D,QAAI,CAAC,KAAK,MAAM;AACd,YAAM,IAAI,MAAM,0DAAqD;AAAA,IACvE;AAEA,QAAI;AACF,aAAO,MAAM,KAAK,cAAc,MAAM;AAAA,IACxC,SAAS,KAAK;AACZ,UAAI;AACJ,UAAI;AACJ,UAAI;AACF,qBAAa,MAAM,KAAK,KAAK,WAAW;AAAA,MAC1C,QAAQ;AAAA,MAER;AACA,UAAI;AACF,YAAI,SAAS,UAAU,OAAQ,OAAe,QAAQ,UAAU;AAC9D,gBAAM,WAAW,IAAI,gBAAgB,KAAK,MAAM,KAAK,QAAQ;AAC7D,gBAAM,MAAM,MAAM,SAAS,eAAgB,OAAe,GAAG;AAC7D,cAAI,IAAK,eAAc;AAAA,QACzB;AAAA,MACF,QAAQ;AAAA,MAER;AACA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAAA,QACtD;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,aAA0C;AAC9C,QAAI;AACF,UAAI,KAAK,MAAM;AACb,eAAO,MAAM,KAAK,KAAK,WAAW;AAAA,MACpC;AACA,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,UAAuB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,aAAmB;AACjB,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,gBAAoC;AAClC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,eAAmC;AACjC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,iBAAiB,OAAmC;AAClD,UAAM,MAAyB,CAAC;AAChC,eAAW,WAAW,KAAK,eAAe,OAAO,GAAG;AAClD,YAAM,UAAU,QAAQ,YAAY,MAAM,QAAQ,iBAAiB;AACnE,cAAQ,oBAAoB,QAAQ,YAAY;AAChD,UAAI,KAAK,GAAG,OAAO;AAAA,IACrB;AACA,QAAI,CAAC,MAAO,QAAO;AACnB,WAAO,IAAI,OAAO,OAAK,EAAE,UAAU,KAAK;AAAA,EAC1C;AAAA,EAEA,iBAAiB,YAAwC;AACvD,UAAM,MAAyB,CAAC;AAChC,eAAW,WAAW,KAAK,eAAe,OAAO,GAAG;AAClD,YAAM,UAAU,QAAQ,YAAY,MAAM,QAAQ,iBAAiB;AACnE,cAAQ,oBAAoB,QAAQ,YAAY;AAChD,UAAI,KAAK,GAAG,OAAO;AAAA,IACrB;AACA,QAAI,CAAC,WAAY,QAAO;AACxB,WAAO,IAAI,OAAO,OAAK,EAAE,IAAI,SAAS,UAAU,CAAC;AAAA,EACnD;AAAA,EAEA,gBAAgB,YAAwC;AACtD,UAAM,MAAyB,CAAC;AAChC,eAAW,WAAW,KAAK,eAAe,OAAO,GAAG;AAClD,UAAI,KAAK,GAAG,QAAQ,YAAY,MAAM,QAAQ,iBAAiB,CAAC;AAAA,IAClE;AACA,QAAI,CAAC,WAAY,QAAO;AACxB,WAAO,IAAI,OAAO,OAAK,EAAE,IAAI,SAAS,UAAU,CAAC;AAAA,EACnD;AAAA,EAEQ,mBAAmB,MAAkB;AAC3C,UAAM,UAA0B;AAAA,MAC9B,aAAa,CAAC;AAAA,MACd,aAAa,CAAC;AAAA,MACd,mBAAmB;AAAA,MACnB,mBAAmB;AAAA,MACnB,iBAAiB,oBAAI,IAAI;AAAA,IAC3B;AACA,SAAK,eAAe,IAAI,MAAM,OAAO;AAErC,QAAI,KAAK,iBAAiB,SAAS;AACjC,WAAK,GAAG,WAAW,CAAC,QAAQ;AAC1B,gBAAQ,YAAY,KAAK;AAAA,UACvB,OAAO,IAAI,KAAK;AAAA,UAChB,MAAM,IAAI,KAAK;AAAA,UACf,UAAU,IAAI,SAAS;AAAA,UACvB,WAAW,KAAK,IAAI;AAAA,QACtB,CAAC;AACD,YAAI,QAAQ,YAAY,SAAS,KAAM;AACrC,kBAAQ,cAAc,QAAQ,YAAY,MAAM,IAAI;AAAA,QACtD;AAAA,MACF,CAAC;AAAA,IACH;AAEA,QAAI,KAAK,iBAAiB,SAAS;AACjC,WAAK,GAAG,WAAW,CAAC,YAAY;AAC9B,gBAAQ,gBAAgB,IAAI,QAAQ,IAAI,IAAI,QAAQ,OAAO,GAAG;AAAA,UAC5D,KAAK,QAAQ,IAAI;AAAA,UACjB,QAAQ,QAAQ,OAAO;AAAA,UACvB,SAAS,QAAQ,QAAQ;AAAA,UACzB,WAAW,KAAK,IAAI;AAAA,UACpB,UAAU,QAAQ,SAAS,KAAK;AAAA,QAClC,CAAC;AAAA,MACH,CAAC;AAED,WAAK,GAAG,YAAY,OAAO,aAAa;AACtC,cAAM,MAAM,SAAS,IAAI,IAAI,SAAS,QAAQ,EAAE,OAAO;AACvD,cAAM,UAAU,QAAQ,gBAAgB,IAAI,GAAG;AAC/C,gBAAQ,gBAAgB,OAAO,GAAG;AAElC,YAAI;AACJ,YAAI;AACF,gBAAM,MAAM,MAAM,SAAS,KAAK;AAChC,gBAAM,KAAK,SAAS,QAAQ,EAAE,cAAc,KAAK;AACjD,cAAI,GAAG,SAAS,QAAQ,KAAK,CAAC,GAAG,SAAS,KAAK,GAAG;AAChD,mBAAO,IAAI,SAAS,QAAQ,SAAY,QAAQ,GAAG,MAAM,GAAG,EAAE,CAAC,CAAC,WAAW,IAAI,SAAS,QAAQ,CAAC;AAAA,UACnG,OAAO;AACL,kBAAM,OAAO,IAAI,SAAS,OAAO;AACjC,mBAAO,KAAK,SAAS,QAAQ,KAAK,MAAM,GAAG,KAAK,IAAI,mBAAmB;AAAA,UACzE;AAAA,QACF,QAAQ;AACN,iBAAO;AAAA,QACT;AAEA,gBAAQ,YAAY,KAAK;AAAA,UACvB,KAAK,SAAS,IAAI;AAAA,UAClB,QAAQ,SAAS,QAAQ,EAAE,OAAO;AAAA,UAClC,QAAQ,SAAS,OAAO;AAAA,UACxB,gBAAgB,SAAS,WAAW,SAAS,QAAQ,EAAE,QAAQ;AAAA,UAC/D,iBAAiB,SAAS,QAAQ;AAAA,UAClC;AAAA,UACA,aAAa,SAAS;AAAA,UACtB,WAAW,SAAS,aAAa,KAAK,IAAI;AAAA,UAC1C,SAAS,KAAK,IAAI;AAAA,UAClB,QAAQ,SAAS,QAAQ,EAAE,OAAO;AAAA,QACpC,CAAC;AACD,YAAI,QAAQ,YAAY,SAAS,KAAK;AACpC,kBAAQ,cAAc,QAAQ,YAAY,MAAM,IAAI;AAAA,QACtD;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAc,sBAAsB,KAAkF;AACpH,UAAM,QAAQ,KAAK,QAAS,MAAM;AAClC,QAAI,IAAI,UAAU,QAAW;AAC3B,aAAQ,IAAI,SAAS,KAAK,IAAI,QAAQ,MAAM,SAAU,MAAM,IAAI,KAAK,IAAI;AAAA,IAC3E;AACA,QAAI,IAAI,OAAO;AACb,iBAAW,KAAK,OAAO;AACrB,cAAM,IAAI,MAAM,EAAE,MAAM;AACxB,YAAI,EAAE,SAAS,IAAI,KAAK,EAAG,QAAO;AAAA,MACpC;AACA,aAAO;AAAA,IACT;AACA,QAAI,IAAI,KAAK;AACX,aAAO,MAAM,KAAK,OAAK,EAAE,IAAI,EAAE,SAAS,IAAI,GAAI,CAAC;AAAA,IACnD;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,cAAc,QAAkD;AAC5E,UAAM,OAAO,KAAK;AAClB,UAAM,WAAW,IAAI,gBAAgB,MAAM,KAAK,QAAQ;AAKxD,eAAW,OAAO,SAAS,MAAM,GAAG;AAClC,YAAM,QAAQ,KAAK,SAAS,GAAG;AAC/B,UAAI,UAAU,OAAW;AAGzB,YAAM,QAAQ,OAAO,SAAS,WAC1B,MAAM,cAAc,MAAM,KAAK,KAAK,IACpC,MAAM,aAAa,MAAM,KAAK,OAAO,KAAK;AAC9C,UAAI,MAAM,YAAY,KAAM,QAAO,eAAe,MAAM,SAAS,GAAG;AAAA,IACtE;AAEA,QAAI,SAAS,UAAU,OAAQ,OAAe,QAAQ,UAAU;AAC9D,YAAM,UAAU,KAAK,SAAU,OAAe,GAAG;AACjD,YAAM,OAAO,SAAS;AACtB,YAAM,aAAa,eAAe,QAAQ,IAAI;AAC9C,UAAI,CAAC,WAAW,OAAO;AACrB,eAAO,EAAE,SAAS,OAAO,OAAO,WAAW,MAAM;AAAA,MACnD;AAAA,IACF;AAEA,YAAQ,OAAO,MAAM;AAAA,MACnB,KAAK,SAAS;AACZ,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,cAAM,cAAc,MAAM,EAAE,GAAG,IAAI,IAAI,IAAI,QAAQ,GAAG,GAAG,IAAI,IAAI,IAAI,SAAS,EAAE,IAAI;AACpF,cAAM,QAAQ,MAAM;AAAA,UAClB,GAAGF,kBAAiB,OAAO,UAAU;AAAA,QACvC,CAAC;AACD,eAAO,EAAE,SAAS,MAAM,aAAa,aAAa,OAAO,OAAU;AAAA,MACrE;AAAA,MAEA,KAAK,QAAQ;AACX,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,eAAO,mBAAmB,SAAS,OAAO,QAAW,MAAM;AAAA,MAC7D;AAAA,MAEA,KAAK,WAAW;AACd,eAAO,gBAAgB;AAAA,MACzB;AAAA,MAEA,KAAK,UAAU;AACb,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,cAAM,QAAQ,aAAa,OAAO,KAAK;AACvC,eAAO,EAAE,SAAS,MAAM,aAAa,OAAO,OAAU;AAAA,MACxD;AAAA,MAEA,KAAK,YAAY;AAGf,gBAAQ,OAAO,IAAI;AAAA,UACjB,KAAK;AACH,kBAAM,KAAK,KAAK,OAAO,KAAK,EAAE,WAAW,mBAAmB,CAAC;AAC7D;AAAA,UACF,KAAK;AACH,kBAAM,KAAK,OAAO,EAAE,WAAW,mBAAmB,CAAC;AACnD;AAAA,UACF,KAAK;AACH,kBAAM,KAAK,UAAU,EAAE,WAAW,mBAAmB,CAAC;AACtD;AAAA,UACF,KAAK;AACH,kBAAM,KAAK,OAAO,EAAE,WAAW,mBAAmB,CAAC;AACnD;AAAA,QACJ;AACA,cAAM,iBAAiB,IAAI;AAC3B,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,UAAU;AACb,eAAO,qBAAqB,MAAM,KAAK,UAAU,MAAM;AAAA,MACzD;AAAA,MAEA,KAAK,WAAW;AACd,cAAM,UAAU,OAAO;AACvB,YAAI;AACF,kBAAQ,OAAO,IAAI;AAAA,YACjB,KAAK;AACH,oBAAM,KAAK,UAAU,OAAO,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,WAAW,QAAQ,CAAC;AAC/E;AAAA,YACF,KAAK;AACH,oBAAM,KAAK,UAAU,OAAO,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,UAAU,QAAQ,CAAC;AAC9E;AAAA,YACF,KAAK;AACH,oBAAM,KAAK,gBAAgB,OAAO,UAAU,EAAE,QAAQ,CAAC;AACvD;AAAA,UACJ;AAAA,QACF,QAAQ;AACN,gBAAM,OAAO,OAAO,OAAO,aAAa,aAAa,OAAO,QAAQ,MAAM,SAAS,OAAO,IAAI;AAC9F,gBAAM,MAAM,OAAO,OAAO,SAAS,4BAA4B;AAC/D,iBAAO,EAAE,SAAS,OAAO,OAAO,YAAY,IAAI,IAAI,GAAG,IAAI,OAAO,MAAM;AAAA,QAC1E;AACA,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,SAAS;AACZ,cAAM,KAAK,eAAe,OAAO,EAAE;AACnC,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,cAAc;AACjB,YAAI;AAEF,gBAAM,KAAK,WAAW,OAAO,SAAS,EAAE,SAAS,IAAO,CAAC;AACzD,iBAAO,EAAE,SAAS,KAAK;AAAA,QACzB,SAAS,KAAK;AACZ,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,OAAO,gBAAgB,OAAO,OAAO,yGAAyG,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,UAChM;AAAA,QACF;AAAA,MACF;AAAA,MAEA,KAAK,YAAY;AAGf,cAAM,gBAAgBG,wBAAuB,OAAO,MAAM;AAAA,UACxD,SAAS,OAAO,wBAAwB;AAAA,UACxC,OAAOC,eAAc;AAAA,QACvB,CAAC;AACD,mBAAW,OAAO,eAAe;AAC/B,cAAI,OAAO,SAAS,QAAQ;AAC1B,kBAAM,KAAK,SAAS,KAAK,GAAG;AAAA,UAC9B,WAAW,OAAO,SAAS,MAAM;AAC/B,kBAAM,KAAK,SAAS,GAAG,GAAG;AAAA,UAC5B,OAAO;AACL,kBAAM,KAAK,SAAS,MAAM,GAAG;AAAA,UAC/B;AAAA,QACF;AACA,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,SAAS;AACZ,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,cAAM,QAAQ,MAAM;AACpB,eAAO,EAAE,SAAS,MAAM,aAAa,OAAO,OAAU;AAAA,MACxD;AAAA,MAEA,KAAK,SAAS;AACZ,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,cAAM,QAAQ,MAAM;AACpB,cAAM,KAAK,SAAS;AAAA;AAAA;AAAA;AAAA,qCAIS,KAAK,UAAU,OAAO,KAAK,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aAMpD;AACL,eAAO,EAAE,SAAS,MAAM,aAAa,OAAO,OAAU;AAAA,MACxD;AAAA,MAEA,KAAK,cAAc;AAEjB,cAAM,EAAE,WAAW,IAAI,MAAM,OAAO,IAAS;AAC7C,mBAAW,YAAY,OAAO,OAAO;AACnC,cAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,mBAAO,EAAE,SAAS,OAAO,OAAO,mBAAmB,QAAQ,GAAG;AAAA,UAChE;AAAA,QACF;AACA,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,cAAM,QAAQ,cAAc,OAAO,KAAK;AACxC,eAAO,EAAE,SAAS,MAAM,aAAa,OAAO,OAAU;AAAA,MACxD;AAAA,MAEA,KAAK,QAAQ;AACX,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,cAAM,OAAQ,MAAM,QAAQ,YAAY,KAAM;AAC9C,cAAM,KAAK,SAAS,iCAAiC,KAAK,UAAU,IAAI,CAAC,GAAG;AAC5E,eAAO,EAAE,SAAS,MAAM,aAAa,OAAO,QAAW,MAAM,EAAE,QAAQ,KAAK,EAAE;AAAA,MAChF;AAAA,MAEA,KAAK,OAAO;AAEV,YAAI,OAAO,WAAW,OAAO;AAC3B,gBAAM,UAAU,MAAM,KAAK,QAAS,QAAQ;AAC5C,eAAK,mBAAmB,OAAO;AAC/B,gBAAM,QAAQ,KAAK,OAAO,KAAK,EAAE,WAAW,mBAAmB,CAAC;AAChE,gBAAM,iBAAiB,OAAO;AAC9B,eAAK,OAAO;AACZ,iBAAO,EAAE,SAAS,KAAK;AAAA,QACzB;AACA,cAAM,QAAQ,KAAK,QAAS,MAAM;AAClC,YAAI;AACJ,YAAI,OAAO,UAAU,QAAW;AAC9B,cAAI,OAAO,QAAQ,KAAK,OAAO,SAAS,MAAM,QAAQ;AACpD,mBAAO,EAAE,SAAS,OAAO,OAAO,aAAa,OAAO,KAAK,kBAAkB,MAAM,MAAM,cAAc;AAAA,UACvG;AACA,mBAAS,MAAM,OAAO,KAAK;AAAA,QAC7B,WAAW,OAAO,UAAU,QAAW;AACrC,qBAAW,KAAK,OAAO;AACrB,kBAAM,IAAI,MAAM,EAAE,MAAM;AACxB,gBAAI,EAAE,SAAS,OAAO,KAAK,GAAG;AAAE,uBAAS;AAAG;AAAA,YAAM;AAAA,UACpD;AAAA,QACF,WAAW,OAAO,QAAQ,QAAW;AACnC,mBAAS,MAAM,KAAK,OAAK,EAAE,IAAI,EAAE,SAAS,OAAO,GAAI,CAAC;AAAA,QACxD;AACA,YAAI,CAAC,QAAQ;AACX,iBAAO,EAAE,SAAS,OAAO,OAAO,yBAAyB,KAAK,UAAU,EAAE,OAAO,OAAO,OAAO,OAAO,OAAO,OAAO,KAAK,OAAO,IAAI,CAAC,CAAC,GAAG;AAAA,QAC3I;AACA,aAAK,OAAO;AACZ,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,WAAW;AAGd,gBAAQ,OAAO,MAAM;AAAA,UACnB,KAAK,WAAW;AACd,gBAAI;AACJ,gBAAI,OAAO,KAAK;AACd,oBAAM,aAAa,MAAM,KAAK,sBAAsB,OAAO,GAAG;AAC9D,kBAAI,CAAC,YAAY;AACf,uBAAO,EAAE,SAAS,OAAO,OAAO,yBAAyB,KAAK,UAAU,OAAO,GAAG,CAAC,GAAG;AAAA,cACxF;AACA,oBAAM,UAAU,KAAK,eAAe,IAAI,UAAU;AAClD,wBAAU,UAAU,CAAC,GAAG,QAAQ,WAAW,IAAI,CAAC;AAAA,YAClD,OAAO;AACL,wBAAU,CAAC;AACX,yBAAW,WAAW,KAAK,eAAe,OAAO,GAAG;AAClD,wBAAQ,KAAK,GAAG,QAAQ,WAAW;AAAA,cACrC;AAAA,YACF;AACA,gBAAI,OAAO,OAAO;AAChB,wBAAU,QAAQ,OAAO,OAAK,EAAE,UAAU,OAAO,KAAK;AAAA,YACxD;AACA,mBAAO,EAAE,SAAS,MAAM,MAAM,QAAQ;AAAA,UACxC;AAAA,UACA,KAAK,WAAW;AACd,gBAAI;AACJ,gBAAI,OAAO,KAAK;AACd,oBAAM,aAAa,MAAM,KAAK,sBAAsB,OAAO,GAAG;AAC9D,kBAAI,CAAC,YAAY;AACf,uBAAO,EAAE,SAAS,OAAO,OAAO,yBAAyB,KAAK,UAAU,OAAO,GAAG,CAAC,GAAG;AAAA,cACxF;AACA,oBAAM,UAAU,KAAK,eAAe,IAAI,UAAU;AAClD,wBAAU,UAAU,CAAC,GAAG,QAAQ,WAAW,IAAI,CAAC;AAAA,YAClD,OAAO;AACL,wBAAU,CAAC;AACX,yBAAW,WAAW,KAAK,eAAe,OAAO,GAAG;AAClD,wBAAQ,KAAK,GAAG,QAAQ,WAAW;AAAA,cACrC;AAAA,YACF;AACA,gBAAI,OAAO,YAAY;AACrB,wBAAU,QAAQ,OAAO,OAAK,EAAE,IAAI,SAAS,OAAO,UAAW,CAAC;AAAA,YAClE;AACA,mBAAO,EAAE,SAAS,MAAM,MAAM,QAAQ;AAAA,UACxC;AAAA,UACA,KAAK,WAAW;AACd,kBAAM,UAAU,MAAM,KAAK,QAAS,QAAQ;AAC5C,gBAAI,OAAO,MAAM;AACf,oBAAM,SAAS,QAAQ,KAAK,OAAK,EAAE,SAAS,OAAO,IAAI,KAAK;AAC5D,qBAAO,EAAE,SAAS,MAAM,MAAM,OAAO;AAAA,YACvC;AACA,mBAAO,EAAE,SAAS,MAAM,MAAM,QAAQ;AAAA,UACxC;AAAA,UACA,KAAK,gBAAgB;AACnB,kBAAM,UAAU,KAAK,IAAI;AACzB,gBAAI,YAAY,eAAe;AAC7B,qBAAO,EAAE,SAAS,MAAM,MAAM,OAAO,MAAM,OAAO,CAAC,EAAE;AAAA,YACvD;AACA,gBAAI,OAAO,KAAK;AACd,oBAAM,QAAQ,MAAM,KAAK;AAAA,gBACvB,CAAC,MAAc,aAAa,QAAQ,CAAC;AAAA,gBAAG,OAAO;AAAA,cACjD;AACA,qBAAO,EAAE,SAAS,MAAM,MAAM,MAAM;AAAA,YACtC;AACA,kBAAM,MAAM,MAAM,KAAK;AAAA,cACrB,MAAM,OAAO;AAAA,gBACX,OAAO,KAAK,YAAY,EAAE,IAAI,OAAK,CAAC,GAAG,aAAa,QAAQ,CAAC,CAAC,CAAC;AAAA,cACjE;AAAA,YACF;AACA,mBAAO,EAAE,SAAS,MAAM,MAAM,IAAI;AAAA,UACpC;AAAA,QACF;AACA,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,cAAc;AACjB,cAAM,sBAAsB,OAAO,QAAQ,IAAI,QAAM;AAAA,UACnD,GAAG;AAAA,UACH,KAAK,CAAC,EAAE,SAAS,KAAK,IAAI,IAAI;AAAA,QAChC,EAAE;AACF,cAAM,KAAK,QAAS,WAAW,mBAAmB;AAClD,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,mBAAmB;AACtB,cAAM,KAAK,SAAS,CAAC,YAAmD;AACtE,qBAAW,EAAE,KAAK,MAAM,KAAK,SAAS;AACpC,yBAAa,QAAQ,KAAK,KAAK;AAAA,UACjC;AAAA,QACF,GAAG,OAAO,OAAO;AACjB,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,SAAS;AACZ,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,cAAM,QAAQ,MAAM;AACpB,eAAO,EAAE,SAAS,MAAM,aAAa,OAAO,OAAU;AAAA,MACxD;AAAA,MAEA,KAAK,eAAe;AAGlB,YAAI;AACJ,YAAI,UAAU,QAAQ;AACpB,kBAAQ,MAAM,KAAK,SAAS,OAAO,IAAI;AAAA,QACzC,OAAO;AACL,kBAAQ,OAAO,QAAQ;AAAA,YACrB,KAAK;AACH,sBAAQ,KAAK,IAAI;AACjB;AAAA,YACF,KAAK;AACH,sBAAQ,KAAK,IAAI,MAAM,gBACnB,CAAC,IACD,MAAM,KAAK;AAAA,gBACT,MAAM,OAAO;AAAA,kBACX,OAAO,KAAK,YAAY,EAAE,IAAI,OAAK,CAAC,GAAG,aAAa,QAAQ,CAAC,CAAC,CAAC;AAAA,gBACjE;AAAA,cACF;AACJ;AAAA,YACF,KAAK;AACH,sBAAQ,KAAK,gBAAgB;AAC7B;AAAA,YACF,KAAK;AACH,sBAAQ;AACR;AAAA,UACJ;AAAA,QACF;AACA,eAAO,EAAE,SAAS,MAAM,MAAM,MAAM;AAAA,MACtC;AAAA,MAEA,KAAK,aAAa;AAChB,cAAM,MAAM,SAAS,QAAQ,OAAO,GAAG;AACvC,cAAM,WAAW,MAAM,SAAS,eAAe,OAAO,GAAG;AACzD,cAAM,IAAI,MAAM;AAChB,eAAO,EAAE,SAAS,MAAM,aAAa,YAAY,OAAU;AAAA,MAC7D;AAAA,MAEA,KAAK,eAAe;AAClB,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,cAAM,cAAc,MAChB,OAAO,mBACL,EAAE,GAAG,IAAI,IAAI,OAAO,iBAAiB,GAAG,GAAG,IAAI,IAAI,OAAO,iBAAiB,EAAE,IAC7E,EAAE,GAAG,IAAI,IAAI,IAAI,QAAQ,GAAG,GAAG,IAAI,IAAI,IAAI,SAAS,EAAE,IACxD;AACJ,cAAM,QAAQ,SAAS;AAAA,UACrB,GAAI,OAAO,oBAAoB,EAAE,UAAU,OAAO,iBAAiB;AAAA,UACnE,GAAGJ,kBAAiB,OAAO,UAAU;AAAA,QACvC,CAAC;AACD,eAAO,EAAE,SAAS,MAAM,aAAa,aAAa,OAAO,OAAU;AAAA,MACrE;AAAA,MAEA,KAAK,cAAc;AACjB,cAAM,UAAU,SAAS,QAAQ,OAAO,GAAG;AAC3C,cAAM,MAAM,MAAM,SAAS,eAAe,OAAO,GAAG;AACpD,cAAM,cAAc,MAChB,OAAO,mBACL,EAAE,GAAG,IAAI,IAAI,OAAO,iBAAiB,GAAG,GAAG,IAAI,IAAI,OAAO,iBAAiB,EAAE,IAC7E,EAAE,GAAG,IAAI,IAAI,IAAI,QAAQ,GAAG,GAAG,IAAI,IAAI,IAAI,SAAS,EAAE,IACxD;AACJ,cAAM,QAAQ,MAAM;AAAA,UAClB,QAAQ;AAAA,UACR,GAAI,OAAO,oBAAoB,EAAE,UAAU,OAAO,iBAAiB;AAAA,UACnE,GAAGA,kBAAiB,OAAO,UAAU;AAAA,QACvC,CAAC;AACD,eAAO,EAAE,SAAS,MAAM,aAAa,aAAa,OAAO,OAAU;AAAA,MACrE;AAAA,MAEA,KAAK,SAAS;AAIZ,cAAM,KAAK,QAAS,MAAM,OAAO,YAAY,OAAO,UAAU;AAC5D,gBAAM,MAAM,QAAQ;AAAA,YAClB,QAAQ;AAAA,YACR,GAAI,OAAO,gBAAgB,SAAY,EAAE,aAAa,OAAO,YAAY,IAAI,CAAC;AAAA,YAC9E,GAAI,OAAO,YAAY,SAAY,EAAE,SAAS,OAAO,QAAQ,IAAI,CAAC;AAAA,YAClE,GAAI,OAAO,SAAS,SAAY,EAAE,MAAM,OAAO,KAAK,IAAI,CAAC;AAAA,UAC3D,CAAC;AAAA,QACH,CAAC;AACD,aAAK,YAAY,IAAI,OAAO,UAAU;AACtC,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,WAAW;AACd,YAAI,OAAO,eAAe,QAAW;AACnC,gBAAM,KAAK,QAAS,QAAQ,OAAO,UAAU;AAC7C,eAAK,YAAY,OAAO,OAAO,UAAU;AAAA,QAC3C,OAAO;AACL,gBAAM,KAAK,QAAS,WAAW,EAAE,UAAU,eAAe,CAAC;AAC3D,eAAK,YAAY,MAAM;AAAA,QACzB;AACA,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,gBAAgB;AACnB,YAAI,OAAO,SAAS,WAAW;AAC7B,gBAAM,KAAK,QAAS,WAAW,IAAI;AACnC,iBAAO,EAAE,SAAS,KAAK;AAAA,QACzB;AAEA,YAAI;AACF,gBAAM,MAAM,MAAM,KAAK,QAAS,cAAc,IAAI;AAClD,gBAAM,IAAI,KAAK,oCAAoC;AAAA,YACjD,SAAS;AAAA,YACT,SAAS,OAAO;AAAA,YAChB,oBAAqB,OAAO,eAAe,MAAQ;AAAA,YACnD,kBAAmB,OAAO,aAAa,MAAQ;AAAA,UACjD,CAAC;AACD,iBAAO,EAAE,SAAS,KAAK;AAAA,QACzB,SAAS,KAAK;AACZ,iBAAO;AAAA,YACL,SAAS;AAAA,YACT,OAAO,iGAAiG,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,UAC1J;AAAA,QACF;AAAA,MACF;AAAA,MAEA,KAAK,gBAAgB;AAInB,YAAI,OAAO,OAAO,QAAQ;AACxB,gBAAM,QAAQ,MAAM,KAAK,QAAS,aAAa;AAC/C,iBAAO,EAAE,SAAS,MAAM,MAAM,EAAE,MAAM,OAAO,MAAM,MAAM,EAAE;AAAA,QAC7D;AACA,cAAM,KAAK,QAAS,gBAAgBC,sBAAqB,MAAM,CAAC;AAChE,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,gBAAgB;AAEnB,YAAI,KAAK,kBAAkB;AACzB,eAAK,IAAI,UAAU,KAAK,gBAAgB;AACxC,eAAK,mBAAmB;AAAA,QAC1B;AACA,cAAM,SAAS,OAAO;AACtB,cAAM,aAAa,OAAO;AAC1B,cAAM,UAAU,CAAC,WAAyB;AACxC,eAAK,mBAAmB;AACxB,cAAI,QAAQ;AACV,iBAAK,OAAO,OAAO,UAAU;AAAA,UAC/B,OAAO;AACL,iBAAK,OAAO,QAAQ;AAAA,UACtB;AAAA,QACF;AACA,aAAK,mBAAmB;AACxB,aAAK,KAAK,UAAU,OAAO;AAC3B,eAAO,EAAE,SAAS,KAAK;AAAA,MACzB;AAAA,MAEA,KAAK,iBAAiB;AACpB,eAAO,EAAE,SAAS,OAAO,OAAO,8CAA8C;AAAA,MAChF;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACH,eAAO;AAAA,UACL,SAAS;AAAA,UACT,OAAO,WAAW,OAAO,IAAI;AAAA,QAC/B;AAAA,MAEF;AACE,eAAOI,aAAY,MAAM;AAAA,IAC7B;AAAA,EACF;AACF;;;ACx7BA,SAAS,kBAAkB;AAU3B,eAAsB,sBACpB,MACA,SACmC;AACnC,MAAI,UAAU,IAAI,WAAW,EAAE,KAAK,CAAC;AAErC,MAAI,SAAS,UAAU;AACrB,UAAM,SAAmC;AAAA,MACvC,UAAU,CAAC,QAAQ;AAAA,MACnB,WAAW,CAAC,UAAU,SAAS;AAAA,MAC/B,YAAY,CAAC,UAAU,WAAW,UAAU;AAAA,IAC9C;AACA,cAAU,QAAQ,SAAS,OAAO,QAAQ,QAAQ,KAAK,CAAC,UAAU,SAAS,CAAC;AAAA,EAC9E;AAEA,MAAI,SAAS,cAAc,QAAQ;AACjC,cAAU,QAAQ,aAAa,QAAQ,YAAY;AAAA,EACrD;AAEA,MAAI,SAAS,SAAS,QAAQ;AAC5B,eAAW,YAAY,QAAQ,SAAS;AACtC,gBAAU,QAAQ,QAAQ,QAAQ;AAAA,IACpC;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,QAAQ,QAAQ;AAEtC,SAAO,QAAQ,WAAW,IAAI,QAAM;AAAA,IAClC,QAAQ,EAAE;AAAA,IACV,QAAQ,EAAE;AAAA,IACV,aAAa,EAAE;AAAA,IACf,MAAM,EAAE;AAAA,IACR,SAAS,EAAE;AAAA,IACX,OAAO,EAAE,MAAM,MAAM,GAAG,EAAE,EAAE,IAAI,QAAM;AAAA,MACpC,MAAM,EAAE;AAAA,MACR,QAAQ,EAAE;AAAA,IACZ,EAAE;AAAA,EACJ,EAAE;AACJ;","names":["buildScreenState","tidy","buildScreenState","rowTextOf","hideAgentQaElements","restoreAgentQaElements","buildScreenState","rowTextOf","before","after","style","magnitude","primitives","meta","settle","buildScreenState","assertNever","buildScreenState","convertKeysForPlatform","isMacPlatform","clickDelayOption","readSeamStorageState","buildScreenState","convertKeysForPlatform","isMacPlatform","assertNever"]}
|