@narumitw/pi-chrome-devtools 0.54.0 → 0.54.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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/tool-names.ts", "../../src/settings.ts", "../../src/runtime.ts", "../../src/browser-manager.ts", "../../src/browser-candidates.ts", "../../src/browser-startup.ts"],
4
+ "sourcesContent": ["export const CORE_CHROME_DEVTOOLS_TOOL_NAMES = [\n \"chrome_devtools_list_pages\",\n \"chrome_devtools_select_page\",\n \"chrome_devtools_navigate\",\n \"chrome_devtools_evaluate\",\n \"chrome_devtools_screenshot\",\n] as const;\n\nexport const WEBMCP_TOOL_NAMES = [\"chrome_devtools_webmcp_list_tools\", \"chrome_devtools_webmcp_call_tool\"] as const;\n\nexport const CHROME_DEVTOOLS_TOOL_NAMES = [...CORE_CHROME_DEVTOOLS_TOOL_NAMES, ...WEBMCP_TOOL_NAMES] as const;\n\nexport type ChromeDevToolsToolName = (typeof CHROME_DEVTOOLS_TOOL_NAMES)[number];\nexport type WebMcpToolName = (typeof WEBMCP_TOOL_NAMES)[number];\n\nexport function isWebMcpToolName(value: string): value is WebMcpToolName {\n return WEBMCP_TOOL_NAMES.includes(value as WebMcpToolName);\n}\n", "import { randomUUID } from \"node:crypto\";\nimport { constants } from \"node:fs\";\nimport { access, lstat, mkdir, readFile, realpath, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"@earendil-works/pi-coding-agent\";\nimport { CHROME_DEVTOOLS_TOOL_NAMES, type ChromeDevToolsToolName } from \"./tool-names.js\";\n\nconst NEW_SETTINGS_FILE_NAME = \"pi-chrome-devtools.json\";\nconst LEGACY_SETTINGS_FILE_NAME = \"pi-chrome-devtools-settings.json\";\n\nexport type ChromeDevToolsToolMode = \"codemode\" | \"lazy\" | \"direct\";\n\nexport function isChromeDevtoolsToolMode(value: unknown): value is ChromeDevToolsToolMode {\n return value === \"codemode\" || value === \"lazy\" || value === \"direct\";\n}\n\nexport interface ChromeDevToolsSettings {\n tools: ChromeDevToolsToolName[];\n updatedAt: number;\n}\n\nexport const DEFAULT_BROWSER_HOST = \"127.0.0.1\";\nexport const DEFAULT_BROWSER_PORT = 9222;\nexport const DEFAULT_BROWSER_ENDPOINT = `http://${DEFAULT_BROWSER_HOST}:${DEFAULT_BROWSER_PORT}`;\n\nexport type BrowserSettingsSource = \"default\" | \"environment\" | \"project\" | \"user\";\n\nexport interface UserBrowserSettings {\n endpoint?: string;\n autoLaunch?: boolean;\n executablePath?: string;\n extensionPaths?: string[];\n}\n\nexport interface BrowserSettingsPatch {\n endpoint?: string | null;\n autoLaunch?: boolean | null;\n executablePath?: string | null;\n}\n\nexport interface EffectiveBrowserSettings {\n endpoint: string;\n host: string;\n port: number;\n hostConfigured: boolean;\n portConfigured: boolean;\n autoLaunchEnabled: boolean;\n executablePath?: string;\n extensionPaths: string[];\n endpointSource: BrowserSettingsSource;\n autoLaunchSource: BrowserSettingsSource;\n executablePathSource: BrowserSettingsSource;\n extensionPathsSource: BrowserSettingsSource;\n}\n\nexport interface ResolvedChromeDevToolsSettings {\n toolMode: ChromeDevToolsToolMode;\n tools?: ChromeDevToolsToolName[];\n updatedAt?: number;\n browser: EffectiveBrowserSettings;\n webmcp: { enabled: boolean };\n}\n\nexport interface SettingsLoadOptions {\n cwd?: string;\n projectTrusted?: boolean;\n}\n\nexport type UserSettingsFileStatus = { kind: \"missing\" | \"valid\" } | { kind: \"invalid\"; reason: string };\n\ninterface SettingsLoadBase {\n effectiveBrowser: EffectiveBrowserSettings;\n effectiveWebMcpEnabled: boolean;\n paths: { user: string; project?: string };\n userFile: UserSettingsFileStatus;\n warnings: string[];\n notice?: string;\n}\n\nexport type SettingsLoadResult =\n | (SettingsLoadBase & { kind: \"missing\"; settings?: undefined })\n | (SettingsLoadBase & { kind: \"invalid\"; reason: string; settings?: undefined })\n | (SettingsLoadBase & { kind: \"loaded\"; settings: ResolvedChromeDevToolsSettings });\n\nexport interface SettingsFileOperations {\n write(path: string, data: string): Promise<void>;\n rename(source: string, destination: string): Promise<void>;\n}\n\ninterface NormalizedSettingsDocument {\n toolMode?: ChromeDevToolsToolMode;\n tools?: ChromeDevToolsToolName[];\n updatedAt?: number;\n browser?: UserBrowserSettings;\n webmcp?: { enabled: boolean };\n}\n\ninterface SettingsDocumentResult {\n kind: \"missing\" | \"invalid\" | \"valid\";\n reason?: string;\n document?: Record<string, unknown>;\n normalized?: NormalizedSettingsDocument;\n warnings: string[];\n}\n\nconst DEFAULT_FILE_OPERATIONS: SettingsFileOperations = {\n write: (path, data) => writeFile(path, data, \"utf8\").then(() => undefined),\n rename,\n};\n\nlet settingsSaveQueue = Promise.resolve();\n\nexport async function waitForSettingsWrites() {\n await settingsSaveQueue;\n}\n\nexport async function loadSettings(options: SettingsLoadOptions = {}): Promise<SettingsLoadResult> {\n await settingsSaveQueue;\n const userPath = settingsFilePath();\n const projectPath = options.cwd ? projectSettingsFilePath(options.cwd) : undefined;\n const paths = { user: userPath, ...(projectPath ? { project: projectPath } : {}) };\n const warnings: string[] = [];\n\n let user = await readSettingsDocument(userPath, \"user\");\n const legacyExists = await fileExists(legacySettingsFilePath());\n if (user.kind !== \"missing\" && legacyExists) {\n warnings.push(\n `Chrome DevTools legacy settings ignored: ${legacySettingsFilePath()} exists, but ${userPath} takes precedence. Delete ${LEGACY_SETTINGS_FILE_NAME} after confirming your settings.`,\n );\n }\n if (user.kind === \"missing\") {\n const legacy = await readSettingsDocument(legacySettingsFilePath(), \"user\");\n const concurrentlyCreated = await readSettingsDocument(userPath, \"user\");\n if (concurrentlyCreated.kind !== \"missing\") {\n user = concurrentlyCreated;\n if (legacy.kind !== \"missing\") {\n warnings.push(\n `Chrome DevTools legacy settings ignored: ${legacySettingsFilePath()} exists, but ${userPath} takes precedence. Delete ${LEGACY_SETTINGS_FILE_NAME} after confirming your settings.`,\n );\n }\n } else if (legacy.kind !== \"missing\") {\n user = legacy;\n if (legacy.kind === \"valid\") {\n warnings.push(\n `Using legacy ${LEGACY_SETTINGS_FILE_NAME}; rename it to ${NEW_SETTINGS_FILE_NAME}. Future saves write ${NEW_SETTINGS_FILE_NAME} without modifying the legacy file.`,\n );\n }\n }\n }\n warnings.push(...user.warnings);\n\n let project: SettingsDocumentResult = { kind: \"missing\", warnings: [] };\n if (projectPath && options.projectTrusted) {\n project = await readSettingsDocument(projectPath, \"project\", options.cwd);\n warnings.push(...project.warnings);\n }\n\n const environmentWarning = deprecatedEnvironmentWarning();\n if (environmentWarning) warnings.push(environmentWarning);\n\n const userBrowser = user.normalized?.browser ?? {};\n const effectiveBrowser = resolveEffectiveBrowser(userBrowser, project.normalized?.browser);\n const settings = resolveSettings(user.normalized, project.normalized, effectiveBrowser);\n const recognized =\n user.normalized?.toolMode !== undefined ||\n settings.tools !== undefined ||\n user.normalized?.browser !== undefined ||\n project.normalized?.browser !== undefined ||\n user.normalized?.webmcp !== undefined;\n const invalidReasons = [user, project]\n .filter((result) => result.kind === \"invalid\")\n .map((result) => result.reason)\n .filter((reason): reason is string => Boolean(reason));\n const userFile: UserSettingsFileStatus =\n user.kind === \"invalid\"\n ? {\n kind: \"invalid\",\n reason: user.reason ?? `${userPath}: invalid settings`,\n }\n : { kind: user.kind };\n const base = {\n effectiveBrowser,\n effectiveWebMcpEnabled: settings.webmcp.enabled,\n paths,\n userFile,\n warnings,\n ...(warnings.length > 0 ? { notice: warnings.join(\"\\n\") } : {}),\n };\n\n if (recognized) return { ...base, kind: \"loaded\", settings };\n if (invalidReasons.length > 0) {\n return { ...base, kind: \"invalid\", reason: invalidReasons.join(\"; \") };\n }\n return { ...base, kind: \"missing\" };\n}\n\nfunction resolveSettings(\n user: NormalizedSettingsDocument | undefined,\n _project: NormalizedSettingsDocument | undefined,\n browser: EffectiveBrowserSettings,\n): ResolvedChromeDevToolsSettings {\n return {\n toolMode: user?.toolMode ?? \"codemode\",\n ...(user?.tools ? { tools: user.tools, updatedAt: user.updatedAt } : {}),\n browser,\n webmcp: { enabled: user?.webmcp?.enabled ?? false },\n };\n}\n\nfunction resolveEffectiveBrowser(\n user: UserBrowserSettings,\n project: UserBrowserSettings | undefined,\n): EffectiveBrowserSettings {\n const configuredEndpoint = parseBrowserEndpoint(user.endpoint ?? DEFAULT_BROWSER_ENDPOINT);\n const environmentHost = process.env.PI_CHROME_DEVTOOLS_HOST;\n const environmentPortValue = process.env.PI_CHROME_DEVTOOLS_PORT;\n const environmentPort = parseConfiguredPort(environmentPortValue);\n const environmentEndpointConfigured = environmentHost !== undefined || environmentPort !== undefined;\n const host = environmentHost ?? configuredEndpoint.host;\n const port = environmentPort ?? configuredEndpoint.port;\n const environmentAutoLaunch = process.env.PI_CHROME_DEVTOOLS_AUTO_LAUNCH;\n const environmentExecutable = process.env.PI_CHROME_DEVTOOLS_BROWSER;\n const executablePath = environmentExecutable || user.executablePath;\n const extensionPaths = project?.extensionPaths ?? user.extensionPaths ?? [];\n const endpointSource: BrowserSettingsSource = environmentEndpointConfigured\n ? \"environment\"\n : user.endpoint\n ? \"user\"\n : \"default\";\n return {\n endpoint: formatBrowserEndpoint(host, port),\n host,\n port,\n hostConfigured: environmentHost !== undefined || user.endpoint !== undefined,\n portConfigured: environmentPort !== undefined || user.endpoint !== undefined,\n autoLaunchEnabled: environmentAutoLaunch === undefined ? (user.autoLaunch ?? true) : environmentAutoLaunch !== \"0\",\n ...(executablePath ? { executablePath } : {}),\n extensionPaths: [...extensionPaths],\n endpointSource,\n autoLaunchSource:\n environmentAutoLaunch !== undefined ? \"environment\" : user.autoLaunch !== undefined ? \"user\" : \"default\",\n executablePathSource: environmentExecutable ? \"environment\" : user.executablePath ? \"user\" : \"default\",\n extensionPathsSource: project?.extensionPaths ? \"project\" : user.extensionPaths ? \"user\" : \"default\",\n };\n}\n\nfunction deprecatedEnvironmentWarning() {\n const configuredNames = [\n \"PI_CHROME_DEVTOOLS_HOST\",\n \"PI_CHROME_DEVTOOLS_PORT\",\n \"PI_CHROME_DEVTOOLS_AUTO_LAUNCH\",\n \"PI_CHROME_DEVTOOLS_BROWSER\",\n ].filter((name) => process.env[name] !== undefined);\n if (configuredNames.length === 0) return undefined;\n return `Chrome DevTools environment settings are deprecated and will be removed in a future version: ${configuredNames.join(\", \")}. Move them to browser.endpoint, browser.autoLaunch, and browser.executablePath in ${settingsFilePath()}. Environment values remain active overrides during the deprecation period.`;\n}\n\nasync function readSettingsDocument(\n filePath: string,\n scope: \"project\" | \"user\",\n cwd?: string,\n): Promise<SettingsDocumentResult> {\n let text: string;\n try {\n text = await readFile(filePath, \"utf8\");\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") return { kind: \"missing\", warnings: [] };\n const reason = `${filePath}: ${formatError(error)}`;\n return { kind: \"invalid\", reason, warnings: [`Chrome DevTools settings ignored: ${reason}`] };\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(text) as unknown;\n } catch {\n const reason = `${filePath}: invalid JSON`;\n return { kind: \"invalid\", reason, warnings: [`Chrome DevTools settings ignored: ${reason}`] };\n }\n if (!isRecord(parsed)) {\n const reason = `${filePath}: expected a JSON object`;\n return { kind: \"invalid\", reason, warnings: [`Chrome DevTools settings ignored: ${reason}`] };\n }\n\n const scopeWarnings = projectOwnedSettingsWarnings(parsed, scope, filePath);\n try {\n const normalized = await normalizeSettingsDocument(parsed, scope, filePath, cwd);\n return { kind: \"valid\", document: { ...parsed }, normalized, warnings: scopeWarnings };\n } catch (error) {\n const reason = `${filePath}: ${formatError(error)}`;\n return {\n kind: \"invalid\",\n reason,\n warnings: [...scopeWarnings, `Chrome DevTools settings ignored: ${reason}`],\n };\n }\n}\n\nfunction projectOwnedSettingsWarnings(document: Record<string, unknown>, scope: \"project\" | \"user\", filePath: string) {\n if (scope !== \"project\") return [];\n const browser = isRecord(document.browser) ? document.browser : undefined;\n const warnings = browser\n ? [\"endpoint\", \"autoLaunch\", \"executablePath\"]\n .filter((field) => browser[field] !== undefined)\n .map(\n (field) =>\n `Chrome DevTools project browser.${field} ignored in ${filePath}; configure this machine-owned setting in ${settingsFilePath()}.`,\n )\n : [];\n if (document.webmcp !== undefined) {\n warnings.push(\n `Chrome DevTools project webmcp settings ignored in ${filePath}; only the user settings file may enable experimental WebMCP.`,\n );\n }\n return warnings;\n}\n\nasync function normalizeSettingsDocument(\n document: Record<string, unknown>,\n scope: \"project\" | \"user\",\n filePath: string,\n cwd?: string,\n): Promise<NormalizedSettingsDocument> {\n const normalized: NormalizedSettingsDocument = {};\n if (scope === \"user\" && document.toolMode !== undefined) {\n if (!isChromeDevtoolsToolMode(document.toolMode))\n throw new Error(\"expected toolMode to be codemode, lazy, or direct\");\n normalized.toolMode = document.toolMode;\n }\n\n if (scope === \"user\" && (document.tools !== undefined || document.updatedAt !== undefined)) {\n const toolSettings = normalizeChromeDevtoolsSettings(document);\n if (!toolSettings) {\n throw new Error(\"expected tools to be an array of Chrome DevTools tool names with numeric updatedAt\");\n }\n normalized.tools = toolSettings.tools;\n normalized.updatedAt = toolSettings.updatedAt;\n }\n\n if (document.browser !== undefined) {\n if (!isRecord(document.browser)) throw new Error(\"expected browser to be an object\");\n normalized.browser = await normalizeBrowserSection(document.browser, scope, filePath, cwd);\n }\n\n if (scope === \"user\" && document.webmcp !== undefined) {\n if (!isRecord(document.webmcp) || typeof document.webmcp.enabled !== \"boolean\") {\n throw new Error(\"expected webmcp.enabled to be a boolean\");\n }\n normalized.webmcp = { enabled: document.webmcp.enabled };\n }\n\n return normalized;\n}\n\nasync function normalizeBrowserSection(\n browser: Record<string, unknown>,\n scope: \"project\" | \"user\",\n _filePath: string,\n cwd?: string,\n): Promise<UserBrowserSettings> {\n const normalized: UserBrowserSettings = {};\n if (scope === \"user\" && browser.endpoint !== undefined) {\n if (typeof browser.endpoint !== \"string\") {\n throw new Error(\"expected browser.endpoint to be an HTTP URL with an explicit port\");\n }\n normalized.endpoint = parseBrowserEndpoint(browser.endpoint).endpoint;\n }\n if (scope === \"user\" && browser.autoLaunch !== undefined) {\n if (typeof browser.autoLaunch !== \"boolean\") {\n throw new Error(\"expected browser.autoLaunch to be a boolean\");\n }\n normalized.autoLaunch = browser.autoLaunch;\n }\n if (scope === \"user\" && browser.executablePath !== undefined) {\n if (typeof browser.executablePath !== \"string\" || browser.executablePath.length === 0) {\n throw new Error(\"expected browser.executablePath to be a non-empty absolute path\");\n }\n if (!isAbsolute(browser.executablePath)) {\n throw new Error(\"browser.executablePath in user settings must be absolute\");\n }\n normalized.executablePath = resolve(browser.executablePath);\n }\n\n if (browser.extensionPaths !== undefined) {\n if (\n !Array.isArray(browser.extensionPaths) ||\n !browser.extensionPaths.every((entry) => typeof entry === \"string\" && entry.length > 0)\n ) {\n throw new Error(`expected ${scope} browser.extensionPaths to be an array of non-empty paths`);\n }\n const resolvedPaths: string[] = [];\n for (const configuredPath of browser.extensionPaths as string[]) {\n if (scope === \"user\" && !isAbsolute(configuredPath)) {\n throw new Error(\"browser.extensionPaths in user settings must contain only absolute paths\");\n }\n const absolutePath = isAbsolute(configuredPath)\n ? resolve(configuredPath)\n : resolve(cwd ?? process.cwd(), configuredPath);\n resolvedPaths.push(await validateUnpackedExtensionPath(absolutePath));\n }\n normalized.extensionPaths = orderedUnique(resolvedPaths);\n }\n return normalized;\n}\n\nasync function validateUnpackedExtensionPath(extensionPath: string) {\n let canonicalPath: string;\n try {\n canonicalPath = await realpath(extensionPath);\n const extensionStat = await stat(canonicalPath);\n if (!extensionStat.isDirectory()) throw new Error(\"not a directory\");\n } catch (error) {\n throw new Error(`unpacked extension path ${extensionPath} is invalid: ${formatError(error)}`);\n }\n\n const manifestPath = join(canonicalPath, \"manifest.json\");\n let manifest: unknown;\n try {\n const manifestStat = await lstat(manifestPath);\n if (!manifestStat.isFile()) throw new Error(\"not a regular file\");\n manifest = JSON.parse(await readFile(manifestPath, \"utf8\")) as unknown;\n } catch (error) {\n throw new Error(`unpacked extension ${canonicalPath} has invalid manifest.json: ${formatError(error)}`);\n }\n if (canonicalPath.includes(\",\")) {\n throw new Error(\n `unpacked extension path ${canonicalPath} cannot contain a comma because Chrome separates multiple --load-extension paths with commas`,\n );\n }\n if (\n !isRecord(manifest) ||\n ![2, 3].includes(manifest.manifest_version as number) ||\n typeof manifest.name !== \"string\" ||\n typeof manifest.version !== \"string\"\n ) {\n throw new Error(\n `unpacked extension ${canonicalPath} has invalid manifest.json: expected manifest_version, name, and version`,\n );\n }\n return canonicalPath;\n}\n\nexport function parseBrowserEndpoint(value: string) {\n const trimmedValue = value.trim();\n const explicitPort = trimmedValue.match(/^http:\\/\\/(?:\\[[^\\]]+\\]|[^/:?#]+):(\\d+)\\/?$/i)?.[1];\n let endpoint: URL;\n try {\n endpoint = new URL(trimmedValue);\n } catch {\n throw new Error(\"browser.endpoint must be a valid HTTP URL with an explicit port\");\n }\n if (\n endpoint.protocol !== \"http:\" ||\n endpoint.username ||\n endpoint.password ||\n !endpoint.hostname ||\n !explicitPort ||\n (endpoint.pathname !== \"/\" && endpoint.pathname !== \"\") ||\n endpoint.search ||\n endpoint.hash\n ) {\n throw new Error(\n \"browser.endpoint must be an HTTP origin with an explicit port and no credentials, path, query, or fragment\",\n );\n }\n const port = parseConfiguredPort(explicitPort);\n if (port === undefined) {\n throw new Error(\"browser.endpoint must use a port from 1 through 65535\");\n }\n const host = endpoint.hostname;\n return { endpoint: formatBrowserEndpoint(host, port), host, port };\n}\n\nexport function parseConfiguredPort(value: string | undefined) {\n if (value === undefined) return undefined;\n const trimmedValue = value.trim();\n if (!/^\\d+$/.test(trimmedValue)) return undefined;\n const port = Number(trimmedValue);\n if (!Number.isInteger(port) || port < 1 || port > 65_535) return undefined;\n return port;\n}\n\nfunction formatBrowserEndpoint(host: string, port: number) {\n const formattedHost = host.startsWith(\"[\") && host.endsWith(\"]\") ? host : host.includes(\":\") ? `[${host}]` : host;\n return `http://${formattedHost}:${port}`;\n}\n\nexport function normalizeChromeDevtoolsSettings(value: unknown): ChromeDevToolsSettings | undefined {\n if (!isRecord(value)) return undefined;\n if (typeof value.updatedAt !== \"number\" || !Number.isFinite(value.updatedAt)) return undefined;\n\n if (value.tools === \"enabled\") {\n return { tools: [...CHROME_DEVTOOLS_TOOL_NAMES], updatedAt: value.updatedAt };\n }\n if (value.tools === \"disabled\") return { tools: [], updatedAt: value.updatedAt };\n if (!Array.isArray(value.tools) || !value.tools.every(isChromeDevtoolsToolName)) return undefined;\n return { tools: orderedUniqueChromeDevtoolsTools(value.tools), updatedAt: value.updatedAt };\n}\n\nfunction isChromeDevtoolsToolName(value: unknown): value is ChromeDevToolsToolName {\n return typeof value === \"string\" && CHROME_DEVTOOLS_TOOL_NAMES.includes(value as never);\n}\n\nfunction orderedUniqueChromeDevtoolsTools(tools: readonly ChromeDevToolsToolName[]) {\n const selectedTools = new Set(tools);\n return CHROME_DEVTOOLS_TOOL_NAMES.filter((toolName) => selectedTools.has(toolName));\n}\n\nfunction orderedUnique(values: readonly string[]) {\n return [...new Set(values)];\n}\n\nexport class ToolCatalogApplicationError extends Error {\n constructor(\n error: unknown,\n readonly rollbackError?: unknown,\n ) {\n super(\n rollbackError\n ? `${formatError(error)}; saved catalog rollback failed: ${formatError(rollbackError)}`\n : `${formatError(error)}; previous catalog restored`,\n { cause: error },\n );\n }\n}\n\nexport function saveSettings(\n settings: ChromeDevToolsSettings,\n operations: Partial<SettingsFileOperations> = {},\n applyAfterSave?: () => void,\n): Promise<void> {\n return queueSettingsMutation(\n (current) => ({\n ...current,\n tools: [...settings.tools],\n updatedAt: settings.updatedAt,\n }),\n operations,\n applyAfterSave,\n );\n}\n\nexport function saveToolMode(\n mode: ChromeDevToolsToolMode,\n operations: Partial<SettingsFileOperations> = {},\n): Promise<void> {\n if (!isChromeDevtoolsToolMode(mode)) return Promise.reject(new Error(\"Invalid tool mode\"));\n return queueSettingsMutation((current) => ({ ...current, toolMode: mode }), operations);\n}\n\nexport function saveWebMcpSettings(enabled: boolean, operations: Partial<SettingsFileOperations> = {}): Promise<void> {\n return queueSettingsMutation(\n (current) => ({\n ...current,\n webmcp: {\n ...(isRecord(current.webmcp) ? current.webmcp : {}),\n enabled,\n },\n }),\n operations,\n );\n}\n\nexport function saveBrowserSettings(\n patch: BrowserSettingsPatch,\n operations: Partial<SettingsFileOperations> = {},\n): Promise<void> {\n return queueSettingsMutation(async (current) => {\n const browser = isRecord(current.browser) ? { ...current.browser } : {};\n for (const field of [\"endpoint\", \"autoLaunch\", \"executablePath\"] as const) {\n const value = patch[field];\n if (value === undefined) continue;\n if (value === null) delete browser[field];\n else browser[field] = value;\n }\n await normalizeBrowserSection(browser, \"user\", settingsFilePath());\n return { ...current, browser };\n }, operations);\n}\n\nfunction queueSettingsMutation(\n mutate: (current: Record<string, unknown>) => Record<string, unknown> | Promise<Record<string, unknown>>,\n operations: Partial<SettingsFileOperations>,\n applyToolCatalog?: () => void,\n) {\n const operation = settingsSaveQueue.then(() => saveSettingsMutationNow(mutate, operations, applyToolCatalog));\n settingsSaveQueue = operation.catch(() => undefined);\n return operation;\n}\n\nasync function saveSettingsMutationNow(\n mutate: (current: Record<string, unknown>) => Record<string, unknown> | Promise<Record<string, unknown>>,\n operations: Partial<SettingsFileOperations>,\n applyToolCatalog?: () => void,\n): Promise<void> {\n const filePath = settingsFilePath();\n let current = await readSettingsDocument(filePath, \"user\");\n const replaceCanonical = current.kind !== \"missing\";\n if (!replaceCanonical) current = await readSettingsDocument(legacySettingsFilePath(), \"user\");\n if (current.kind === \"invalid\") {\n throw new Error(`Cannot save Chrome DevTools settings until you repair ${current.reason}`);\n }\n const nextDocument = await mutate(current.document ?? {});\n await mkdir(dirname(filePath), { recursive: true });\n const tempFile = `${filePath}.${process.pid}.${randomUUID()}.tmp`;\n try {\n await (operations.write ?? DEFAULT_FILE_OPERATIONS.write)(tempFile, `${JSON.stringify(nextDocument, null, 2)}\\n`);\n if (!replaceCanonical && (await pathEntryExists(filePath))) {\n throw new Error(`${NEW_SETTINGS_FILE_NAME} was created concurrently; reopen settings and retry.`);\n }\n await (operations.rename ?? DEFAULT_FILE_OPERATIONS.rename)(tempFile, filePath);\n } catch (error) {\n await rm(tempFile, { force: true }).catch(() => undefined);\n throw error;\n }\n if (!applyToolCatalog) return;\n try {\n // Synchronous runtime publication and its compensating write remain inside\n // this queue, so dependent reads/replacements cannot see a rejected catalog.\n applyToolCatalog();\n } catch (error) {\n let rollbackError: unknown;\n try {\n await saveSettingsMutationNow((latest) => {\n const restored = { ...latest };\n for (const field of [\"tools\", \"updatedAt\"] as const) {\n if (JSON.stringify(latest[field]) !== JSON.stringify(nextDocument[field]))\n throw new Error(\"Tool catalog changed after save; refusing to overwrite newer settings\");\n delete restored[field];\n if (current.document?.[field] !== undefined) restored[field] = current.document[field];\n }\n return restored;\n }, operations);\n } catch (caught) {\n rollbackError = caught;\n }\n throw new ToolCatalogApplicationError(error, rollbackError);\n }\n}\n\nexport function settingsFilePath() {\n return join(getAgentDir(), NEW_SETTINGS_FILE_NAME);\n}\n\nexport function projectSettingsFilePath(cwd: string) {\n return join(cwd, CONFIG_DIR_NAME, NEW_SETTINGS_FILE_NAME);\n}\n\nfunction legacySettingsFilePath() {\n return join(getAgentDir(), LEGACY_SETTINGS_FILE_NAME);\n}\n\nasync function fileExists(filePath: string) {\n try {\n await access(filePath, constants.F_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function pathEntryExists(filePath: string) {\n try {\n await lstat(filePath);\n return true;\n } catch (error) {\n if (isNodeError(error) && error.code === \"ENOENT\") return false;\n throw error;\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return Boolean(value) && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction isNodeError(error: unknown): error is NodeJS.ErrnoException {\n return error instanceof Error && \"code\" in error;\n}\n\nfunction formatError(error: unknown) {\n return error instanceof Error ? error.message : String(error);\n}\n", "import type { ChildProcess } from \"node:child_process\";\nimport {\n DEFAULT_BROWSER_HOST,\n DEFAULT_BROWSER_PORT,\n type EffectiveBrowserSettings,\n parseConfiguredPort,\n} from \"./settings.js\";\n\nexport const DEFAULT_HOST = DEFAULT_BROWSER_HOST;\nexport const DEFAULT_PORT = DEFAULT_BROWSER_PORT;\nexport const DEFAULT_TIMEOUT_MS = 10_000;\nexport const DEFAULT_HTTP_TIMEOUT_MS = 1_000;\nexport const DEFAULT_ENDPOINT_WAIT_MS = 5_000;\nexport const DEFAULT_ENDPOINT_RETRY_MS = 250;\nexport const MANAGED_BROWSER_PROFILE_PREFIX = \"pi-chrome-devtools-profile-\";\nexport const BROWSER_SHUTDOWN_WAIT_MS = 1_500;\n\nexport interface DevToolsPage {\n id: string;\n type: string;\n title: string;\n url: string;\n webSocketDebuggerUrl?: string;\n}\n\nexport interface ChromeDevToolsState {\n host: string;\n port: number;\n configuredPort: number;\n hostConfigured: boolean;\n portConfigured: boolean;\n autoLaunchEnabled: boolean;\n endpointSource: EffectiveBrowserSettings[\"endpointSource\"];\n autoLaunchSource: EffectiveBrowserSettings[\"autoLaunchSource\"];\n browserExecutable?: string;\n extensionPaths: string[];\n browserExecutableSource: EffectiveBrowserSettings[\"executablePathSource\"];\n extensionPathsSource: EffectiveBrowserSettings[\"extensionPathsSource\"];\n settingsFilePath?: string;\n projectSettingsFilePath?: string;\n projectSettingsTrusted: boolean;\n activePageId?: string;\n managedBrowser?: ManagedBrowser;\n launchPromise?: Promise<void>;\n latestLaunchPromise?: Promise<void>;\n lastLaunchAttempt?: BrowserLaunchAttempt;\n shuttingDown: boolean;\n sessionGeneration: number;\n sessionController: AbortController;\n settingsNotice?: string;\n}\n\nexport interface ManagedBrowser {\n process: ChildProcess;\n userDataDir: string;\n port?: number;\n exited: boolean;\n ready: boolean;\n ownerGeneration: number;\n sessionOwner?: object;\n cleanupPromise?: Promise<void>;\n}\n\nexport interface BrowserLaunchAttempt {\n candidateLabels: string[];\n mode: \"automatic-port\" | \"explicit-port\";\n selectedCandidate?: string;\n userDataDir?: string;\n lastError?: string;\n}\n\nexport interface BrowserCandidateDefinition {\n label: string;\n executable: string;\n source: \"env\" | \"path\" | \"wellKnownPath\";\n}\n\nexport interface BrowserCandidate extends BrowserCandidateDefinition {\n resolvedExecutable: string;\n}\n\nexport { parseConfiguredPort };\n\nexport const state: ChromeDevToolsState = {\n host: DEFAULT_HOST,\n port: DEFAULT_PORT,\n configuredPort: DEFAULT_PORT,\n hostConfigured: false,\n portConfigured: false,\n autoLaunchEnabled: true,\n endpointSource: \"default\",\n autoLaunchSource: \"default\",\n extensionPaths: [],\n browserExecutableSource: \"default\",\n extensionPathsSource: \"default\",\n projectSettingsTrusted: false,\n shuttingDown: false,\n sessionGeneration: 0,\n sessionController: new AbortController(),\n};\n\ninterface WebMcpSessionRuntime {\n controller: AbortController;\n enabled: boolean;\n controllers: Set<AbortController>;\n generation: number;\n sessionGeneration: number;\n}\n\nconst webMcpRuntimeByOwner = new WeakMap<object, WebMcpSessionRuntime>();\n\nexport function setWebMcpSessionOwner(owner: object) {\n const runtime = webMcpRuntime(owner);\n runtime.enabled = false;\n runtime.sessionGeneration += 1;\n}\n\nexport function beginWebMcpOperation(owner: object, toolSignal?: AbortSignal) {\n const runtime = webMcpRuntime(owner);\n const controller = new AbortController();\n runtime.controllers.add(controller);\n const signals = [controller.signal, runtime.controller.signal];\n if (toolSignal) signals.push(toolSignal);\n const signal = AbortSignal.any(signals);\n return {\n signal,\n owner,\n sessionGeneration: runtime.sessionGeneration,\n webMcpGeneration: runtime.generation,\n dispose() {\n runtime.controllers.delete(controller);\n },\n };\n}\n\nexport function invalidateWebMcpOperations(owner: object, reason: string) {\n const runtime = webMcpRuntime(owner);\n runtime.generation += 1;\n const controllers = [...runtime.controllers];\n runtime.controllers.clear();\n const error = new DOMException(reason, \"AbortError\");\n runtime.controller.abort(error);\n runtime.controller = new AbortController();\n for (const controller of controllers) controller.abort(error);\n}\n\nexport function currentWebMcpGeneration(owner: object) {\n return webMcpRuntime(owner).generation;\n}\n\nexport function webMcpSessionSignal(owner: object) {\n return webMcpRuntime(owner).controller.signal;\n}\n\nexport function applyRuntimeWebMcpSetting(enabled: boolean, owner: object) {\n const runtime = webMcpRuntime(owner);\n if (runtime.enabled !== enabled) {\n invalidateWebMcpOperations(owner, `WebMCP ${enabled ? \"enabled\" : \"disabled\"}`);\n }\n runtime.enabled = enabled;\n}\n\nexport function webMcpEnabled(owner: object) {\n return webMcpRuntime(owner).enabled;\n}\n\nexport function webMcpOperationIsCurrent(operation: {\n owner: object;\n sessionGeneration: number;\n webMcpGeneration: number;\n}) {\n const runtime = webMcpRuntime(operation.owner);\n return operation.sessionGeneration === runtime.sessionGeneration && operation.webMcpGeneration === runtime.generation;\n}\n\nfunction webMcpRuntime(owner: object) {\n const existing = webMcpRuntimeByOwner.get(owner);\n if (existing) return existing;\n const created: WebMcpSessionRuntime = {\n controller: new AbortController(),\n controllers: new Set(),\n enabled: false,\n generation: 0,\n sessionGeneration: 0,\n };\n webMcpRuntimeByOwner.set(owner, created);\n return created;\n}\n\nexport function applyRuntimeBrowserSettings(\n browser: EffectiveBrowserSettings,\n paths: { user: string; project?: string },\n projectTrusted: boolean,\n) {\n state.host = browser.host;\n state.port = browser.port;\n state.configuredPort = browser.port;\n state.hostConfigured = browser.hostConfigured;\n state.portConfigured = browser.portConfigured;\n state.autoLaunchEnabled = browser.autoLaunchEnabled;\n state.endpointSource = browser.endpointSource;\n state.autoLaunchSource = browser.autoLaunchSource;\n state.browserExecutable = browser.executablePath;\n state.extensionPaths = [...browser.extensionPaths];\n state.browserExecutableSource = browser.executablePathSource;\n state.extensionPathsSource = browser.extensionPathsSource;\n state.settingsFilePath = paths.user;\n state.projectSettingsFilePath = paths.project;\n state.projectSettingsTrusted = projectTrusted;\n}\n", "import { type ChildProcess, execFile, spawn } from \"node:child_process\";\nimport { access, mkdtemp, rm } from \"node:fs/promises\";\nimport { createServer } from \"node:net\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { browserCandidateDefinitions, resolveBrowserCandidates } from \"./browser-candidates.js\";\nimport { browserWebSocketIdentity, waitForBrowserStartup } from \"./browser-startup.js\";\nimport {\n BROWSER_SHUTDOWN_WAIT_MS,\n type BrowserCandidate,\n type BrowserCandidateDefinition,\n type BrowserLaunchAttempt,\n DEFAULT_ENDPOINT_RETRY_MS,\n DEFAULT_ENDPOINT_WAIT_MS,\n DEFAULT_HTTP_TIMEOUT_MS,\n type DevToolsPage,\n invalidateWebMcpOperations,\n MANAGED_BROWSER_PROFILE_PREFIX,\n type ManagedBrowser,\n state,\n} from \"./runtime.js\";\nimport type { EffectiveBrowserSettings } from \"./settings.js\";\n\n// Endpoint attachment, managed launch, selected-port publication, and shutdown intentionally remain\n// together because they form one ownership state machine behind the testable operations boundary.\ninterface BrowserSpawnOptions {\n shell: false;\n stdio: [\"ignore\", \"ignore\", \"pipe\"];\n}\n\nexport interface BrowserManagerOperations {\n access(path: string, mode: number): Promise<void>;\n mkdtemp(prefix: string): Promise<string>;\n allocatePort(host: string): Promise<number>;\n rm(path: string, options: { recursive: true; force: true }): Promise<void>;\n fetch(input: string, init?: RequestInit): Promise<Response>;\n spawn(executable: string, args: string[], options: BrowserSpawnOptions): ChildProcess;\n inspectBrowserVersion(executable: string, signal: AbortSignal): Promise<string>;\n isPortAvailable(host: string, port: number): Promise<boolean>;\n sleep(ms: number, signal?: AbortSignal): Promise<void>;\n}\n\nconst DEFAULT_BROWSER_MANAGER_OPERATIONS: BrowserManagerOperations = {\n access,\n mkdtemp,\n allocatePort: allocateBrowserPort,\n rm: (path, options) => rm(path, options),\n fetch: (input, init) => fetch(input, init),\n spawn,\n inspectBrowserVersion,\n isPortAvailable,\n sleep: abortableSleep,\n};\n\nlet browserManagerOperations = DEFAULT_BROWSER_MANAGER_OPERATIONS;\n\ninterface ManagedBrowserScope {\n browser: EffectiveBrowserSettings;\n controller: AbortController;\n generation: number;\n launchPromise?: Promise<void>;\n latestLaunchPromise?: Promise<void>;\n managedBrowser?: ManagedBrowser;\n port: number;\n lastLaunchAttempt?: BrowserLaunchAttempt;\n}\n\nconst managedBrowserScopes = new WeakMap<object, ManagedBrowserScope>();\n\nfunction cloneBrowserSettings(browser: EffectiveBrowserSettings): EffectiveBrowserSettings {\n return { ...browser, extensionPaths: [...browser.extensionPaths] };\n}\n\nfunction runtimeBrowserSettings(): EffectiveBrowserSettings {\n return {\n endpoint: `http://${formatHostForUrl(state.host)}:${state.configuredPort}`,\n host: state.host,\n port: state.configuredPort,\n hostConfigured: state.hostConfigured,\n portConfigured: state.portConfigured,\n autoLaunchEnabled: state.autoLaunchEnabled,\n ...(state.browserExecutable ? { executablePath: state.browserExecutable } : {}),\n extensionPaths: [...state.extensionPaths],\n endpointSource: state.endpointSource,\n autoLaunchSource: state.autoLaunchSource,\n executablePathSource: state.browserExecutableSource,\n extensionPathsSource: state.extensionPathsSource,\n };\n}\n\nfunction managedBrowserScope(owner: object) {\n const existing = managedBrowserScopes.get(owner);\n if (existing) return existing;\n const browser = runtimeBrowserSettings();\n const created: ManagedBrowserScope = {\n browser,\n controller: new AbortController(),\n generation: 0,\n port: browser.port,\n };\n managedBrowserScopes.set(owner, created);\n return created;\n}\n\nexport function startManagedBrowserSession(owner: object) {\n const scope = managedBrowserScope(owner);\n scope.controller.abort(new DOMException(\"Chrome DevTools session replaced\", \"AbortError\"));\n scope.controller = new AbortController();\n scope.generation += 1;\n scope.lastLaunchAttempt = undefined;\n}\n\nexport function syncManagedBrowserSettings(owner: object, browser: EffectiveBrowserSettings) {\n const scope = managedBrowserScope(owner);\n scope.browser = cloneBrowserSettings(browser);\n scope.port = browser.port;\n}\n\nexport function browserSettingsForOwner(owner?: object) {\n return owner ? managedBrowserScope(owner).browser : runtimeBrowserSettings();\n}\n\nexport function managedBrowserExtensionPaths(owner?: object) {\n return browserSettingsForOwner(owner).extensionPaths;\n}\n\nexport function managedBrowserExtensionPathsSource(owner?: object) {\n return browserSettingsForOwner(owner).extensionPathsSource;\n}\n\nexport function managedBrowserForOwner(owner?: object) {\n if (!owner) return state.managedBrowser;\n const scopedBrowser = managedBrowserScope(owner).managedBrowser;\n if (scopedBrowser) return scopedBrowser;\n return state.managedBrowser?.sessionOwner === owner ? state.managedBrowser : undefined;\n}\n\nfunction setManagedBrowser(owner: object | undefined, browser: ManagedBrowser | undefined) {\n if (owner) managedBrowserScope(owner).managedBrowser = browser;\n else state.managedBrowser = browser;\n}\n\nfunction launchPromiseForOwner(owner?: object) {\n return owner ? managedBrowserScope(owner).launchPromise : state.launchPromise;\n}\n\nfunction latestLaunchPromiseForOwner(owner?: object) {\n return owner ? managedBrowserScope(owner).latestLaunchPromise : state.latestLaunchPromise;\n}\n\nfunction setLaunchPromise(owner: object | undefined, launchPromise: Promise<void> | undefined) {\n const scope = owner ? managedBrowserScope(owner) : state;\n scope.launchPromise = launchPromise;\n // Retain one settled result so attach probes can observe a launch after cleanup.\n if (launchPromise) scope.latestLaunchPromise = launchPromise;\n}\n\nfunction managedBrowserPort(owner?: object) {\n return owner ? managedBrowserScope(owner).port : state.port;\n}\n\nfunction managedBrowserConfiguredPort(owner?: object) {\n return browserSettingsForOwner(owner).port;\n}\n\nfunction managedBrowserPortConfigured(owner?: object) {\n return browserSettingsForOwner(owner).portConfigured;\n}\n\nfunction setManagedBrowserPort(owner: object | undefined, port: number) {\n if (owner) managedBrowserScope(owner).port = port;\n else state.port = port;\n}\n\nfunction lastLaunchAttempt(owner?: object) {\n return owner ? managedBrowserScope(owner).lastLaunchAttempt : state.lastLaunchAttempt;\n}\n\nfunction setLastLaunchAttempt(owner: object | undefined, attempt: BrowserLaunchAttempt | undefined) {\n if (owner) managedBrowserScope(owner).lastLaunchAttempt = attempt;\n else state.lastLaunchAttempt = attempt;\n}\n\nexport function setBrowserManagerOperationsForTests(overrides: Partial<BrowserManagerOperations>) {\n const previous = browserManagerOperations;\n browserManagerOperations = { ...DEFAULT_BROWSER_MANAGER_OPERATIONS, ...overrides };\n return () => {\n browserManagerOperations = previous;\n };\n}\n\nfunction formatError(error: unknown) {\n return error instanceof Error ? error.message : String(error);\n}\n\nexport async function ensureDevToolsEndpoint(\n waitMs = DEFAULT_ENDPOINT_WAIT_MS,\n callerSignal?: AbortSignal,\n owner?: object,\n) {\n callerSignal?.throwIfAborted();\n if (extensionsConfigured(owner)) {\n validateExtensionLaunchMode(owner);\n await ensureManagedBrowserLaunched(waitMs, callerSignal, owner);\n return;\n }\n const pendingLaunch = launchPromiseForOwner(owner);\n if (pendingLaunch) {\n await waitForCaller(pendingLaunch, callerSignal);\n return;\n }\n if (canAutoLaunchBrowser(owner)) {\n const launchBeforeProbe = latestLaunchPromiseForOwner(owner);\n try {\n await withEndpointRetry(\n () => fetchDevToolsJson<unknown>(\"/json/version\", { signal: callerSignal }, owner),\n waitMs,\n callerSignal,\n );\n } catch (error) {\n if (shouldAutoLaunchAfterEndpointError(error, owner)) {\n await ensureManagedBrowserLaunched(waitMs, callerSignal, owner);\n return;\n }\n throw error;\n }\n // A retry can reach a managed port whose launch has already completed cleanup.\n // Observe its result even after the active launch promise has been cleared.\n let observedLaunch = launchBeforeProbe;\n while (true) {\n const concurrentLaunch = latestLaunchPromiseForOwner(owner);\n if (!concurrentLaunch || concurrentLaunch === observedLaunch) break;\n observedLaunch = concurrentLaunch;\n await waitForCaller(concurrentLaunch, callerSignal);\n }\n return;\n }\n\n try {\n await fetchDevToolsJson<unknown>(\"/json/version\", { signal: callerSignal }, owner);\n } catch (error) {\n if (isRetryableEndpointError(error)) return;\n throw error;\n }\n}\n\nfunction validateExtensionLaunchMode(owner?: object) {\n const browser = browserSettingsForOwner(owner);\n if (!isLocalDevToolsHost(browser.host)) {\n throw new DevToolsEndpointError(\n \"Unpacked extensions require a local extension-owned managed browser; remote CDP endpoints cannot be modified.\",\n );\n }\n if (!browser.autoLaunchEnabled) {\n throw new DevToolsEndpointError(\n \"Auto-launch is required for unpacked extensions so Pi can create an isolated managed browser.\",\n );\n }\n if (!browser.executablePath) {\n throw new DevToolsEndpointError(\n \"Unpacked extensions require browser.executablePath for Chrome for Testing or Chromium in pi-chrome-devtools.json.\",\n );\n }\n}\n\nasync function ensureManagedBrowserLaunched(waitMs: number, callerSignal?: AbortSignal, owner?: object) {\n const existingLaunch = launchPromiseForOwner(owner);\n if (existingLaunch) {\n await waitForCaller(existingLaunch, callerSignal);\n return;\n }\n const existingBrowser = managedBrowserForOwner(owner);\n if (existingBrowser && !existingBrowser.exited && existingBrowser.ready) return;\n const generation = owner ? managedBrowserScope(owner).generation : state.sessionGeneration;\n const signal = owner ? managedBrowserScope(owner).controller.signal : state.sessionController.signal;\n throwIfBrowserLaunchCancelled(generation, signal, owner);\n\n const launchPromise = prepareManagedBrowserLaunch(waitMs, generation, signal, owner);\n const wrappedPromise = launchPromise.finally(() => {\n if (launchPromiseForOwner(owner) === wrappedPromise) setLaunchPromise(owner, undefined);\n });\n setLaunchPromise(owner, wrappedPromise);\n await waitForCaller(wrappedPromise, callerSignal);\n}\n\nfunction waitForCaller<T>(operation: Promise<T>, signal?: AbortSignal) {\n if (!signal) return operation;\n signal.throwIfAborted();\n return new Promise<T>((resolve, reject) => {\n let settled = false;\n const onAbort = () => settle(() => reject(signal.reason));\n const settle = (callback: () => void) => {\n if (settled) return;\n settled = true;\n signal.removeEventListener(\"abort\", onAbort);\n callback();\n };\n signal.addEventListener(\"abort\", onAbort, { once: true });\n operation.then(\n (value) => settle(() => resolve(value)),\n (error) => settle(() => reject(error)),\n );\n });\n}\n\nasync function prepareManagedBrowserLaunch(waitMs: number, generation: number, signal: AbortSignal, owner?: object) {\n const existingBrowser = managedBrowserForOwner(owner);\n if (existingBrowser) {\n await shutdownManagedBrowser(existingBrowser, { awaitLaunch: false, owner });\n throwIfBrowserLaunchCancelled(generation, signal, owner);\n }\n if (managedBrowserPortConfigured(owner)) {\n const available = await browserManagerOperations.isPortAvailable(\n browserSettingsForOwner(owner).host,\n managedBrowserPort(owner),\n );\n throwIfBrowserLaunchCancelled(generation, signal, owner);\n if (!available) {\n throw new DevToolsEndpointError(\n `Cannot launch the extension-owned browser because explicit port ${managedBrowserPort(owner)} is already in use. Choose a free browser.endpoint port or reset the endpoint to use an automatically selected managed port.`,\n );\n }\n }\n return launchManagedBrowser(waitMs, generation, signal, owner);\n}\n\nasync function launchManagedBrowser(waitMs: number, generation: number, signal: AbortSignal, owner?: object) {\n throwIfBrowserLaunchCancelled(generation, signal, owner);\n const candidateDefinitions = browserCandidateDefinitions(browserSettingsForOwner(owner));\n const candidates = await resolveBrowserCandidates(candidateDefinitions, browserManagerOperations.access, () =>\n throwIfBrowserLaunchCancelled(generation, signal, owner),\n );\n throwIfBrowserLaunchCancelled(generation, signal, owner);\n setLastLaunchAttempt(owner, {\n candidateLabels: candidateDefinitions.map(formatBrowserCandidateDefinition),\n mode: managedBrowserPortConfigured(owner) ? \"explicit-port\" : \"automatic-port\",\n });\n\n if (candidates.length === 0) {\n throw new DevToolsEndpointError(noBrowserCandidateMessage(candidateDefinitions, owner));\n }\n\n let lastError: unknown;\n for (const candidate of candidates) {\n throwIfBrowserLaunchCancelled(generation, signal, owner);\n try {\n if (extensionsConfigured(owner)) await requireSupportedExtensionBrowser(candidate, generation, signal, owner);\n await launchBrowserCandidate(candidate, waitMs, generation, signal, owner);\n throwIfBrowserLaunchCancelled(generation, signal, owner);\n setLastLaunchAttempt(owner, {\n ...lastLaunchAttempt(owner),\n candidateLabels: candidateDefinitions.map(formatBrowserCandidateDefinition),\n mode: managedBrowserPortConfigured(owner) ? \"explicit-port\" : \"automatic-port\",\n selectedCandidate: formatBrowserCandidate(candidate),\n userDataDir: managedBrowserForOwner(owner)?.userDataDir,\n });\n return;\n } catch (error) {\n try {\n throwIfBrowserLaunchCancelled(generation, signal, owner);\n } catch (cancellation) {\n setLastLaunchAttempt(owner, {\n ...(lastLaunchAttempt(owner) ?? {\n candidateLabels: candidateDefinitions.map(formatBrowserCandidateDefinition),\n mode: managedBrowserPortConfigured(owner) ? \"explicit-port\" : \"automatic-port\",\n }),\n lastError: formatError(cancellation),\n });\n throw cancellation;\n }\n lastError = error;\n setLastLaunchAttempt(owner, {\n ...(lastLaunchAttempt(owner) ?? {\n candidateLabels: candidateDefinitions.map(formatBrowserCandidateDefinition),\n mode: managedBrowserPortConfigured(owner) ? \"explicit-port\" : \"automatic-port\",\n }),\n lastError: formatError(error),\n });\n }\n }\n\n if (lastError instanceof DevToolsEndpointError && extensionsConfigured(owner)) throw lastError;\n throw new DevToolsEndpointError(\n [\n \"Unable to auto-launch a Chromium-family browser for Chrome DevTools.\",\n `Tried: ${candidates.map(formatBrowserCandidate).join(\", \")}`,\n lastError ? `Last error: ${formatError(lastError)}` : undefined,\n launchHint(owner),\n endpointConfigHint(),\n ]\n .filter(Boolean)\n .join(\"\\n\"),\n );\n}\n\nasync function requireSupportedExtensionBrowser(\n candidate: BrowserCandidate,\n generation: number,\n signal: AbortSignal,\n owner?: object,\n) {\n let version: string;\n try {\n version = (await browserManagerOperations.inspectBrowserVersion(candidate.resolvedExecutable, signal)).trim();\n } catch (error) {\n throwIfBrowserLaunchCancelled(generation, signal, owner);\n throw new DevToolsEndpointError(\n `Unable to identify the configured extension browser ${candidate.resolvedExecutable}: ${formatError(error)}. Configure Chrome for Testing or Chromium.`,\n );\n }\n throwIfBrowserLaunchCancelled(generation, signal, owner);\n const classification = classifyExtensionBrowserVersion(version);\n if (!classification.supported) {\n throw new DevToolsEndpointError(\n `Unsupported browser for unpacked extensions: ${version || \"unknown product\"}. Configure Chrome for Testing or Chromium; branded Chrome may silently ignore extension startup flags.`,\n );\n }\n}\n\nexport function classifyExtensionBrowserVersion(version: string): {\n supported: boolean;\n product: string;\n} {\n if (/^(?:Google )?Chrome for Testing\\b/i.test(version)) {\n return { supported: true, product: \"Chrome for Testing\" };\n }\n if (/^Chromium\\b/i.test(version)) return { supported: true, product: \"Chromium\" };\n const product = version.trim().replace(/\\s+\\d+(?:\\.\\d+)*.*$/, \"\") || \"Unknown\";\n return { supported: false, product };\n}\n\nasync function launchBrowserCandidate(\n candidate: BrowserCandidate,\n waitMs: number,\n generation: number,\n signal: AbortSignal,\n owner?: object,\n) {\n throwIfBrowserLaunchCancelled(generation, signal, owner);\n const userDataDir = await browserManagerOperations.mkdtemp(join(tmpdir(), MANAGED_BROWSER_PROFILE_PREFIX));\n let managedBrowser: ManagedBrowser | undefined;\n try {\n throwIfBrowserLaunchCancelled(generation, signal, owner);\n const port = managedBrowserPortConfigured(owner)\n ? managedBrowserPort(owner)\n : await browserManagerOperations.allocatePort(browserSettingsForOwner(owner).host);\n throwIfBrowserLaunchCancelled(generation, signal, owner);\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n throw new DevToolsEndpointError(\"Cannot launch a browser without a valid nonzero DevTools port.\");\n }\n const args = buildManagedBrowserLaunchArguments(userDataDir, String(port), managedBrowserExtensionPaths(owner));\n const child = browserManagerOperations.spawn(candidate.resolvedExecutable, args, {\n shell: false,\n stdio: [\"ignore\", \"ignore\", \"pipe\"],\n });\n const launchedBrowser: ManagedBrowser = {\n process: child,\n userDataDir,\n port,\n exited: false,\n ready: false,\n ownerGeneration: generation,\n ...(owner ? { sessionOwner: owner } : {}),\n };\n managedBrowser = launchedBrowser;\n setManagedBrowser(owner, launchedBrowser);\n\n child.once(\"exit\", () => {\n if (managedBrowserForOwner(owner) === launchedBrowser && owner) {\n invalidateWebMcpOperations(owner, \"Chrome DevTools managed browser exited\");\n }\n launchedBrowser.exited = true;\n launchedBrowser.ready = false;\n if (!managedBrowserPortConfigured(owner) && launchedBrowser.port === managedBrowserPort(owner)) {\n setManagedBrowserPort(owner, managedBrowserConfiguredPort(owner));\n }\n });\n\n const browserIdentity = await waitForBrowserStartup(child, port, waitMs, signal);\n throwIfBrowserLaunchCancelled(generation, signal, owner);\n setManagedBrowserPort(owner, port);\n await waitForDevToolsEndpoint(waitMs, launchedBrowser, browserIdentity, generation, signal, owner);\n throwIfBrowserLaunchCancelled(generation, signal, owner);\n throwIfManagedBrowserExited(launchedBrowser);\n launchedBrowser.ready = true;\n } catch (error) {\n if (managedBrowser) await shutdownManagedBrowser(managedBrowser, { awaitLaunch: false, owner });\n else {\n await browserManagerOperations.rm(userDataDir, { recursive: true, force: true }).catch(() => undefined);\n }\n throw error;\n }\n}\n\nexport function buildManagedBrowserLaunchArguments(\n userDataDir: string,\n portArgument: string,\n extensionPaths: readonly string[],\n) {\n const extensionList = extensionPaths.join(\",\");\n return [\n `--remote-debugging-port=${portArgument}`,\n `--user-data-dir=${userDataDir}`,\n ...(extensionPaths.length > 0\n ? [`--disable-extensions-except=${extensionList}`, `--load-extension=${extensionList}`]\n : []),\n // Chrome 138+ de-elevates when launched from an elevated process on Windows: the\n // spawned process relaunches a de-elevated child and exits immediately, which the\n // exit watchdog misreads as a failed launch.\n ...(process.platform === \"win32\" ? [\"--do-not-de-elevate\"] : []),\n \"--no-first-run\",\n \"--no-default-browser-check\",\n \"about:blank\",\n ];\n}\n\nasync function waitForDevToolsEndpoint(\n waitMs: number,\n managedBrowser: ManagedBrowser,\n browserIdentity: string,\n generation: number,\n signal: AbortSignal,\n owner?: object,\n) {\n const deadline = Date.now() + waitMs;\n while (true) {\n throwIfManagedBrowserExited(managedBrowser);\n try {\n const version = await fetchDevToolsJson<{ webSocketDebuggerUrl?: unknown } | null>(\n \"/json/version\",\n { signal },\n owner,\n );\n throwIfBrowserLaunchCancelled(generation, signal, owner);\n throwIfManagedBrowserExited(managedBrowser);\n if (browserWebSocketIdentity(version?.webSocketDebuggerUrl, managedBrowser.port ?? 0) !== browserIdentity) {\n throw new DevToolsEndpointError(\"DevTools endpoint does not match the auto-launched browser.\");\n }\n return;\n } catch (error) {\n if (!isRetryableEndpointError(error)) throw error;\n }\n\n throwIfBrowserLaunchCancelled(generation, signal, owner);\n const remainingMs = deadline - Date.now();\n if (remainingMs <= 0) {\n throw new DevToolsEndpointError(\n [`Timed out waiting for auto-launched browser at ${devToolsEndpoint(owner)}.`, launchHint(owner)].join(\"\\n\"),\n );\n }\n await browserManagerOperations.sleep(Math.min(DEFAULT_ENDPOINT_RETRY_MS, remainingMs), signal);\n }\n}\n\nfunction throwIfManagedBrowserExited(managedBrowser: ManagedBrowser) {\n if (!managedBrowser.exited) return;\n throw new DevToolsEndpointError(\"Auto-launched browser exited before DevTools became available.\");\n}\n\nfunction throwIfBrowserLaunchCancelled(generation: number, signal: AbortSignal, owner?: object) {\n const currentGeneration = owner ? managedBrowserScope(owner).generation : state.sessionGeneration;\n const shuttingDown = owner ? signal.aborted : state.shuttingDown;\n if (!shuttingDown && generation === currentGeneration && !signal.aborted) return;\n throw new DevToolsEndpointError(\n generation === currentGeneration\n ? \"Chrome DevTools browser launch cancelled during shutdown.\"\n : \"Chrome DevTools browser launch cancelled because the session was replaced.\",\n );\n}\n\nexport async function shutdownManagedBrowser(\n managedBrowser?: ManagedBrowser,\n options: { awaitLaunch?: boolean; cancelLaunch?: boolean; owner?: object } = {},\n) {\n const owner = options.owner ?? managedBrowser?.sessionOwner;\n if (options.cancelLaunch) {\n if (owner) {\n const scope = managedBrowserScope(owner);\n scope.controller.abort(\n new DOMException(\"Chrome DevTools browser launch cancelled during shutdown\", \"AbortError\"),\n );\n scope.generation += 1;\n } else {\n state.shuttingDown = true;\n }\n }\n managedBrowser ??= managedBrowserForOwner(owner);\n if (options.awaitLaunch !== false) {\n await launchPromiseForOwner(owner)?.catch(() => undefined);\n managedBrowser ??= managedBrowserForOwner(owner);\n }\n if (!managedBrowser) return;\n if (managedBrowser.cleanupPromise) return managedBrowser.cleanupPromise;\n\n const cleanup = cleanupManagedBrowser(managedBrowser, owner);\n managedBrowser.cleanupPromise = cleanup;\n return cleanup;\n}\n\nasync function cleanupManagedBrowser(managedBrowser: ManagedBrowser, owner?: object) {\n if (managedBrowserForOwner(owner) === managedBrowser) {\n if (owner) invalidateWebMcpOperations(owner, \"Chrome DevTools managed browser closed\");\n if (state.managedBrowser === managedBrowser) state.managedBrowser = undefined;\n else setManagedBrowser(owner, undefined);\n }\n if (!managedBrowser.exited) {\n killManagedBrowserProcess(managedBrowser);\n await waitForManagedBrowserExit(managedBrowser, BROWSER_SHUTDOWN_WAIT_MS).catch(async () => {\n killManagedBrowserProcess(managedBrowser, \"SIGKILL\");\n await waitForManagedBrowserExit(managedBrowser, BROWSER_SHUTDOWN_WAIT_MS).catch(() => undefined);\n });\n }\n await browserManagerOperations\n .rm(managedBrowser.userDataDir, { recursive: true, force: true })\n .catch(() => undefined);\n if (!managedBrowserPortConfigured(owner) && managedBrowser.port === managedBrowserPort(owner)) {\n setManagedBrowserPort(owner, managedBrowserConfiguredPort(owner));\n }\n}\n\nfunction killManagedBrowserProcess(managedBrowser: ManagedBrowser, signal?: NodeJS.Signals) {\n try {\n managedBrowser.process.kill(signal);\n } catch {\n // Best-effort shutdown: the browser may have already exited or failed to spawn.\n }\n}\n\nfunction waitForManagedBrowserExit(managedBrowser: ManagedBrowser, waitMs: number) {\n if (managedBrowser.exited) return Promise.resolve();\n return new Promise<void>((resolve, reject) => {\n const settle = (callback: () => void) => {\n clearTimeout(timeout);\n managedBrowser.process.off(\"exit\", onExitOrClose);\n managedBrowser.process.off(\"close\", onExitOrClose);\n callback();\n };\n const onExitOrClose = () => {\n managedBrowser.exited = true;\n settle(resolve);\n };\n const timeout = setTimeout(\n () => settle(() => reject(new Error(\"Timed out waiting for browser shutdown.\"))),\n waitMs,\n );\n managedBrowser.process.once(\"exit\", onExitOrClose);\n managedBrowser.process.once(\"close\", onExitOrClose);\n });\n}\n\nexport async function fetchDevToolsJson<T>(path: string, init?: RequestInit, owner?: object) {\n const url = `${devToolsEndpoint(owner)}${path}`;\n let response: Response;\n try {\n const timeoutSignal = AbortSignal.timeout(DEFAULT_HTTP_TIMEOUT_MS);\n response = await browserManagerOperations.fetch(url, {\n ...init,\n signal: init?.signal ? AbortSignal.any([init.signal, timeoutSignal]) : timeoutSignal,\n });\n } catch (error) {\n throw new DevToolsEndpointError(endpointConnectionErrorMessage(error, owner), {\n launchable: true,\n retryable: true,\n });\n }\n\n if (!response.ok) {\n const body = (await response.text().catch(() => \"\")).trim();\n const suffix = body ? `: ${body.slice(0, 200)}` : \"\";\n throw new DevToolsEndpointError(\n [\n `Chrome DevTools endpoint ${url} returned ${response.status} ${response.statusText}${suffix}.`,\n endpointConfigHint(),\n ].join(\"\\n\"),\n { retryable: response.status === 429 || response.status >= 500 },\n );\n }\n\n try {\n return (await response.json()) as T;\n } catch (error) {\n throw new DevToolsEndpointError(\n [`Chrome DevTools endpoint ${url} returned invalid JSON: ${formatError(error)}.`, endpointConfigHint()].join(\n \"\\n\",\n ),\n );\n }\n}\n\nexport async function withEndpointRetry<T>(operation: () => Promise<T>, waitMs: number, signal?: AbortSignal) {\n const deadline = Date.now() + waitMs;\n while (true) {\n signal?.throwIfAborted();\n try {\n return await operation();\n } catch (error) {\n if (!isRetryableEndpointError(error)) throw error;\n\n const remainingMs = deadline - Date.now();\n if (remainingMs <= 0) throw error;\n\n await browserManagerOperations.sleep(Math.min(DEFAULT_ENDPOINT_RETRY_MS, remainingMs), signal);\n }\n }\n}\n\nfunction isRetryableEndpointError(error: unknown) {\n return error instanceof DevToolsEndpointError && error.retryable;\n}\n\nfunction isLaunchableEndpointError(error: unknown) {\n return error instanceof DevToolsEndpointError && error.launchable;\n}\n\nfunction shouldAutoLaunchAfterEndpointError(error: unknown, owner?: object) {\n if (!canAutoLaunchBrowser(owner)) return false;\n if (isLaunchableEndpointError(error)) return true;\n\n // After the attach-first attempt (including its retry window, when applicable) fails, treat any\n // DevTools endpoint error on an unpinned port as a conflict we can avoid with an automatically selected port.\n return !managedBrowserPortConfigured(owner) && error instanceof DevToolsEndpointError;\n}\n\nfunction canAutoLaunchBrowser(owner?: object) {\n const browser = browserSettingsForOwner(owner);\n return browser.autoLaunchEnabled && isLocalDevToolsHost(browser.host);\n}\n\nfunction extensionsConfigured(owner?: object) {\n return managedBrowserExtensionPaths(owner).length > 0;\n}\n\nfunction endpointConnectionErrorMessage(error: unknown, owner?: object) {\n const reason = isTimeoutError(error) ? \"request timed out\" : \"connection failed\";\n return [\n `Cannot connect to Chrome DevTools endpoint at ${devToolsEndpoint(owner)} (${reason}).`,\n launchHint(owner),\n endpointConfigHint(),\n ].join(\"\\n\");\n}\n\nfunction isTimeoutError(error: unknown) {\n return error instanceof Error && [\"AbortError\", \"TimeoutError\"].includes(error.name);\n}\n\nexport function devToolsEndpoint(owner?: object) {\n return `http://${formatHostForUrl(browserSettingsForOwner(owner).host)}:${managedBrowserPort(owner)}`;\n}\n\nexport function formatHostForUrl(host: string) {\n if (host.startsWith(\"[\") && host.endsWith(\"]\")) return host;\n return host.includes(\":\") ? `[${host}]` : host;\n}\n\nexport function endpointSourceLabel(owner?: object) {\n return browserSettingsForOwner(owner).endpointSource;\n}\n\nexport type BrowserLifecycleState = \"starting\" | \"running\" | \"exited\" | \"failed\" | \"unobserved\";\n\nexport function browserLifecycleState(owner?: object): BrowserLifecycleState {\n if (launchPromiseForOwner(owner)) return \"starting\";\n if (managedBrowserForOwner(owner)?.exited) return \"exited\";\n if (managedBrowserForOwner(owner)?.ready) return \"running\";\n if (lastLaunchAttempt(owner)?.lastError) return \"failed\";\n return \"unobserved\";\n}\n\nexport function launchModeLabel(owner?: object) {\n const browser = browserSettingsForOwner(owner);\n const managedBrowser = managedBrowserForOwner(owner);\n if (extensionsConfigured(owner)) {\n if (!isLocalDevToolsHost(browser.host)) return \"invalid; extensions require a local endpoint\";\n if (!browser.autoLaunchEnabled) return \"invalid; extensions require auto-launch\";\n if (managedBrowser && !managedBrowser.exited) {\n return managedBrowserPortConfigured(owner)\n ? \"extension-owned browser on explicit port\"\n : \"extension-owned browser on automatically selected port\";\n }\n return managedBrowserPortConfigured(owner)\n ? \"force extension-owned launch on explicit port\"\n : \"force extension-owned launch on automatically selected port\";\n }\n if (!isLocalDevToolsHost(browser.host)) return \"manual remote endpoint\";\n if (!browser.autoLaunchEnabled) return \"manual; auto-launch disabled\";\n if (managedBrowser && !managedBrowser.exited) {\n return managedBrowserPortConfigured(owner)\n ? \"auto-launched on explicit port\"\n : \"auto-launched on automatically selected port\";\n }\n return managedBrowserPortConfigured(owner)\n ? \"attach first; auto-launch explicit port\"\n : \"attach first; auto-launch on an automatically selected port\";\n}\n\nexport function launchAttemptLines(owner?: object) {\n const attempt = lastLaunchAttempt(owner);\n if (!attempt) return [];\n\n const lines = [`Last launch attempt: ${attempt.mode}`];\n if (attempt.selectedCandidate) {\n lines.push(`Launched browser: ${attempt.selectedCandidate}`);\n } else {\n lines.push(`Tried browser candidates: ${attempt.candidateLabels.join(\", \")}`);\n }\n if (attempt.userDataDir) lines.push(`Managed browser profile: ${attempt.userDataDir}`);\n if (attempt.lastError) lines.push(`Last launch error: ${attempt.lastError}`);\n return lines;\n}\n\nexport function launchHint(owner?: object) {\n const browser = browserSettingsForOwner(owner);\n if (extensionsConfigured(owner)) {\n return \"Configured unpacked extensions force an isolated extension-owned launch; existing CDP browsers are never reused, modified, or closed.\";\n }\n if (!isLocalDevToolsHost(browser.host)) {\n return `Remote/non-local endpoints are not auto-launched. Start a browser with CDP enabled at ${devToolsEndpoint(owner)}.`;\n }\n if (!browser.autoLaunchEnabled) {\n return `Auto-launch is disabled. Start a browser manually: ${chromeLaunchCommand(owner)}`;\n }\n const managedMode = managedBrowserPortConfigured(owner)\n ? `port ${managedBrowserPort(owner)}`\n : \"an automatically selected nonzero DevTools port\";\n return `If no endpoint is available, Pi will auto-launch a Chromium-family browser with ${managedMode} and an isolated temp profile. Manual command: ${chromeLaunchCommand(owner)}`;\n}\n\nexport function browserCandidateHint(owner?: object) {\n if (extensionsConfigured(owner)) {\n return \"Extension browser requirement: configure Chrome for Testing or Chromium with browser.executablePath; branded Chrome is rejected because it may ignore unpacked-extension flags.\";\n }\n return `Browser candidates: ${browserCandidateDefinitions(browserSettingsForOwner(owner))\n .map((candidate) => candidate.label)\n .join(\", \")}`;\n}\n\nexport function chromeLaunchCommand(owner?: object) {\n const executable = browserSettingsForOwner(owner).executablePath ?? defaultManualBrowserExecutable();\n const dataDir = process.platform === \"win32\" ? \"%TEMP%\\\\pi-chrome-devtools\" : \"/tmp/pi-chrome-devtools\";\n return `${quoteCommandPart(executable)} --remote-debugging-port=${managedBrowserPort(owner)} --user-data-dir=${dataDir}`;\n}\n\nfunction defaultManualBrowserExecutable() {\n return process.platform === \"darwin\"\n ? \"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome\"\n : process.platform === \"win32\"\n ? \"chrome.exe\"\n : \"google-chrome\";\n}\n\nexport function quoteCommandPart(value: string) {\n return /\\s/.test(value) ? `\"${value.replaceAll('\"', '\\\\\"')}\"` : value;\n}\n\nexport function endpointConfigHint() {\n return \"Configure browser.endpoint, browser.executablePath, and browser.autoLaunch in pi-chrome-devtools.json or the /chrome-devtools Settings flow.\";\n}\n\nexport function isLocalDevToolsHost(host: string) {\n const normalizedHost = host.toLowerCase().replace(/^\\[(.*)]$/, \"$1\");\n return [\"localhost\", \"127.0.0.1\", \"::1\", \"0:0:0:0:0:0:0:1\"].includes(normalizedHost);\n}\n\nfunction formatBrowserCandidate(candidate: BrowserCandidate) {\n return `${candidate.label} (${candidate.resolvedExecutable})`;\n}\n\nfunction formatBrowserCandidateDefinition(candidate: BrowserCandidateDefinition) {\n return `${candidate.label} (${candidate.executable})`;\n}\n\nfunction noBrowserCandidateMessage(candidateDefinitions: BrowserCandidateDefinition[], owner?: object) {\n if (extensionsConfigured(owner)) {\n return [\n \"Cannot launch unpacked extensions because the configured browser executable was not found or is not executable.\",\n `Tried: ${candidateDefinitions.map(formatBrowserCandidateDefinition).join(\", \")}`,\n \"Set browser.executablePath to an executable Chrome for Testing or Chromium binary.\",\n ].join(\"\\n\");\n }\n return [\n \"Cannot auto-launch Chrome DevTools because no Chromium-family browser executable was found.\",\n `Tried: ${candidateDefinitions.map(formatBrowserCandidateDefinition).join(\", \")}`,\n endpointConfigHint(),\n ].join(\"\\n\");\n}\n\nexport function formatPageListItem(page: DevToolsPage) {\n return `- ${page.id}: ${page.title || \"(untitled)\"} ${page.url}`;\n}\n\nfunction abortableSleep(ms: number, signal?: AbortSignal) {\n return new Promise<void>((resolveSleep, reject) => {\n if (signal?.aborted) {\n reject(signal.reason);\n return;\n }\n const timeout = setTimeout(settleResolve, ms);\n const onAbort = () => settleReject(signal?.reason);\n function cleanup() {\n clearTimeout(timeout);\n signal?.removeEventListener(\"abort\", onAbort);\n }\n function settleResolve() {\n cleanup();\n resolveSleep();\n }\n function settleReject(reason: unknown) {\n cleanup();\n reject(reason);\n }\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nfunction inspectBrowserVersion(executable: string, signal: AbortSignal) {\n return new Promise<string>((resolveVersion, reject) => {\n execFile(executable, [\"--version\"], { signal, timeout: 5_000 }, (error, stdout, stderr) => {\n if (error) {\n reject(error);\n return;\n }\n resolveVersion(`${stdout}${stderr}`.trim());\n });\n });\n}\n\nexport async function allocateBrowserPort(host: string) {\n const port = await probeBrowserPort(host, 0);\n if (port === undefined) throw new Error(\"Cannot allocate an available DevTools port.\");\n return port;\n}\n\nasync function isPortAvailable(host: string, port: number) {\n return (await probeBrowserPort(host, port)) !== undefined;\n}\n\n// The probe always closes before publication. Chrome's startup identity check handles the\n// unavoidable bind-close-spawn race without attaching to a competing CDP browser.\nfunction probeBrowserPort(host: string, port: number) {\n return new Promise<number | undefined>((resolvePort, reject) => {\n const server = createServer();\n const normalizedHost = host.replace(/^\\[(.*)]$/, \"$1\");\n server.unref();\n server.once(\"error\", (error: NodeJS.ErrnoException) => {\n if (error.code === \"EADDRINUSE\") resolvePort(undefined);\n else reject(error);\n });\n server.listen(port, normalizedHost, () => {\n const address = server.address();\n server.close((error) => {\n if (error) reject(error);\n else if (!address || typeof address === \"string\") reject(new Error(\"DevTools port probe has no address.\"));\n else resolvePort(address.port);\n });\n });\n });\n}\n\nclass DevToolsEndpointError extends Error {\n readonly retryable: boolean;\n readonly launchable: boolean;\n\n constructor(message: string, options: { retryable?: boolean; launchable?: boolean } = {}) {\n super(message);\n this.name = \"DevToolsEndpointError\";\n this.retryable = options.retryable ?? false;\n this.launchable = options.launchable ?? false;\n }\n}\n", "import { constants } from \"node:fs\";\nimport { delimiter, isAbsolute, join, resolve } from \"node:path\";\nimport type { BrowserCandidate, BrowserCandidateDefinition } from \"./runtime.js\";\nimport type { EffectiveBrowserSettings } from \"./settings.js\";\n\nfunction normalizePathForComparison(value: string) {\n return process.platform === \"win32\" ? value.toLowerCase() : value;\n}\n\nexport function browserCandidateDefinitions(browser: EffectiveBrowserSettings): BrowserCandidateDefinition[] {\n const explicitCandidate = explicitBrowserCandidateDefinition(browser);\n if (explicitCandidate.length > 0) return explicitCandidate;\n\n return uniqueBrowserCandidates(platformBrowserCandidateDefinitions());\n}\n\nfunction explicitBrowserCandidateDefinition(browser: EffectiveBrowserSettings): BrowserCandidateDefinition[] {\n if (!browser.executablePath) return [];\n return [\n {\n label: browser.executablePathSource === \"environment\" ? \"PI_CHROME_DEVTOOLS_BROWSER\" : \"browser.executablePath\",\n executable: browser.executablePath,\n source: \"env\",\n },\n ];\n}\n\nfunction platformBrowserCandidateDefinitions(): BrowserCandidateDefinition[] {\n if (process.platform === \"darwin\") {\n return [\n {\n label: \"Google Chrome\",\n executable: \"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome\",\n source: \"wellKnownPath\",\n },\n {\n label: \"Chromium\",\n executable: \"/Applications/Chromium.app/Contents/MacOS/Chromium\",\n source: \"wellKnownPath\",\n },\n {\n label: \"Brave Browser\",\n executable: \"/Applications/Brave Browser.app/Contents/MacOS/Brave Browser\",\n source: \"wellKnownPath\",\n },\n {\n label: \"Microsoft Edge\",\n executable: \"/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge\",\n source: \"wellKnownPath\",\n },\n ];\n }\n\n if (process.platform === \"win32\") {\n return windowsBrowserCandidateDefinitions();\n }\n\n return [\n { label: \"Google Chrome\", executable: \"google-chrome\", source: \"path\" },\n { label: \"Google Chrome Stable\", executable: \"google-chrome-stable\", source: \"path\" },\n { label: \"Chromium\", executable: \"chromium\", source: \"path\" },\n { label: \"Chromium Browser\", executable: \"chromium-browser\", source: \"path\" },\n { label: \"Brave Browser\", executable: \"brave-browser\", source: \"path\" },\n { label: \"Brave\", executable: \"brave\", source: \"path\" },\n { label: \"Microsoft Edge\", executable: \"microsoft-edge\", source: \"path\" },\n { label: \"Microsoft Edge Stable\", executable: \"microsoft-edge-stable\", source: \"path\" },\n ];\n}\n\nfunction windowsBrowserCandidateDefinitions(): BrowserCandidateDefinition[] {\n const programFiles = [process.env.PROGRAMFILES, process.env[\"PROGRAMFILES(X86)\"], process.env.LOCALAPPDATA].filter(\n (value): value is string => typeof value === \"string\" && value.length > 0,\n );\n const wellKnownPaths = programFiles.flatMap((root) => [\n join(root, \"Google\", \"Chrome\", \"Application\", \"chrome.exe\"),\n join(root, \"Chromium\", \"Application\", \"chrome.exe\"),\n join(root, \"BraveSoftware\", \"Brave-Browser\", \"Application\", \"brave.exe\"),\n join(root, \"Microsoft\", \"Edge\", \"Application\", \"msedge.exe\"),\n ]);\n return [\n ...wellKnownPaths.map((executable) => ({\n label: browserLabelFromExecutable(executable),\n executable,\n source: \"wellKnownPath\" as const,\n })),\n { label: \"Google Chrome\", executable: \"chrome.exe\", source: \"path\" },\n { label: \"Chromium\", executable: \"chromium.exe\", source: \"path\" },\n { label: \"Brave Browser\", executable: \"brave.exe\", source: \"path\" },\n { label: \"Microsoft Edge\", executable: \"msedge.exe\", source: \"path\" },\n ];\n}\n\nfunction browserLabelFromExecutable(executable: string) {\n const normalizedExecutable = normalizePathForComparison(executable);\n if (normalizedExecutable.includes(\"brave\")) return \"Brave Browser\";\n if (normalizedExecutable.includes(\"edge\") || normalizedExecutable.includes(\"msedge\")) {\n return \"Microsoft Edge\";\n }\n if (normalizedExecutable.includes(\"chromium\")) return \"Chromium\";\n return \"Google Chrome\";\n}\n\nfunction uniqueBrowserCandidates(candidates: BrowserCandidateDefinition[]) {\n const seen = new Set<string>();\n return candidates.filter((candidate) => {\n const key = normalizePathForComparison(candidate.executable);\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\nexport async function resolveBrowserCandidates(\n definitions: BrowserCandidateDefinition[],\n access: (path: string, mode: number) => Promise<void>,\n throwIfCancelled: () => void,\n) {\n const candidates: BrowserCandidate[] = [];\n for (const definition of definitions) {\n const resolvedExecutable = await resolveBrowserExecutable(definition.executable, access, throwIfCancelled);\n throwIfCancelled();\n if (!resolvedExecutable) continue;\n candidates.push({ ...definition, resolvedExecutable });\n }\n return uniqueBrowserCandidatesByResolvedPath(candidates);\n}\n\nfunction uniqueBrowserCandidatesByResolvedPath(candidates: BrowserCandidate[]) {\n const seen = new Set<string>();\n return candidates.filter((candidate) => {\n const key = normalizePathForComparison(resolve(candidate.resolvedExecutable));\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\nasync function resolveBrowserExecutable(\n executable: string,\n access: (path: string, mode: number) => Promise<void>,\n throwIfCancelled: () => void,\n) {\n if (hasPathSeparator(executable) || isAbsolute(executable)) {\n const resolvedExecutable = isAbsolute(executable) ? executable : resolve(executable);\n return (await canAccessExecutable(resolvedExecutable, access, throwIfCancelled)) ? resolvedExecutable : undefined;\n }\n\n for (const directory of executableSearchPath()) {\n for (const executableName of executableSearchNames(executable)) {\n const candidate = join(directory, executableName);\n if (await canAccessExecutable(candidate, access, throwIfCancelled)) return candidate;\n }\n }\n return undefined;\n}\n\nfunction hasPathSeparator(path: string) {\n return path.includes(\"/\") || path.includes(\"\\\\\");\n}\n\nfunction executableSearchPath() {\n return (process.env.PATH ?? \"\").split(delimiter).filter((part) => part.length > 0);\n}\n\nfunction executableSearchNames(executable: string) {\n if (process.platform !== \"win32\" || /\\.[a-z0-9]+$/i.test(executable)) return [executable];\n return [executable, `${executable}.exe`, `${executable}.cmd`, `${executable}.bat`];\n}\n\nasync function canAccessExecutable(\n path: string,\n access: (path: string, mode: number) => Promise<void>,\n throwIfCancelled: () => void,\n) {\n let accessible = false;\n try {\n await access(path, process.platform === \"win32\" ? constants.F_OK : constants.X_OK);\n accessible = true;\n } catch {\n // An absent or inaccessible executable is not a browser candidate.\n }\n throwIfCancelled();\n return accessible;\n}\n", "import type { ChildProcess } from \"node:child_process\";\nimport type { EventEmitter } from \"node:events\";\n\nconst MAX_STARTUP_STDERR_BYTES = 64 * 1024;\n\nfunction handleErrorsUntilClose(emitter: EventEmitter) {\n // Cancellation or readiness can settle before an already queued process/pipe error.\n // Keep the resource safe until close, then remove this lifetime-only handler.\n const ignoreError = () => undefined;\n emitter.on(\"error\", ignoreError);\n emitter.once(\"close\", () => emitter.off(\"error\", ignoreError));\n}\n\nexport function browserWebSocketIdentity(value: unknown, port: number): string | undefined {\n if (typeof value !== \"string\") return undefined;\n try {\n const url = new URL(value);\n if (\n url.protocol !== \"ws:\" ||\n ![\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(url.hostname) ||\n Number(url.port || \"80\") !== port ||\n url.username ||\n url.password ||\n url.search ||\n url.hash ||\n !/^\\/devtools\\/browser\\/[^/]+$/.test(url.pathname)\n ) {\n return undefined;\n }\n return url.pathname;\n } catch {\n return undefined;\n }\n}\n\n// A free-port probe cannot reserve the port through Chrome's startup. Use the owned child's\n// announcement, not an arbitrary responding HTTP server, as the browser identity authority.\nexport function waitForBrowserStartup(\n child: ChildProcess,\n port: number,\n waitMs: number,\n signal: AbortSignal,\n): Promise<string> {\n handleErrorsUntilClose(child);\n const stderr = child.stderr;\n if (stderr && !stderr.closed) handleErrorsUntilClose(stderr);\n signal.throwIfAborted();\n if (!stderr) return Promise.reject(new Error(\"Auto-launched browser has no startup stderr stream.\"));\n\n return new Promise<string>((resolve, reject) => {\n let spawned = false;\n let identity: string | undefined;\n let receivedBytes = 0;\n let pendingLine = \"\";\n let settled = false;\n let timeout: ReturnType<typeof setTimeout> | undefined;\n\n const settle = (error?: Error) => {\n if (settled) return;\n if (!error && (!spawned || !identity)) return;\n settled = true;\n clearTimeout(timeout);\n child.off(\"spawn\", onSpawn);\n child.off(\"error\", onError);\n child.off(\"exit\", onExit);\n child.off(\"close\", onExit);\n stderr.off(\"data\", onData);\n stderr.off(\"end\", onEnd);\n stderr.off(\"error\", onError);\n signal.removeEventListener(\"abort\", onAbort);\n // Keep the pipe drained after startup without retaining or displaying browser logs.\n stderr.resume();\n if (error) reject(error);\n else resolve(identity as string);\n };\n const onError = (error: Error) => settle(error);\n const onAbort = () => settle(new Error(\"Chrome DevTools browser startup cancelled.\", { cause: signal.reason }));\n const onExit = () => settle(new Error(\"Auto-launched browser exited before DevTools became available.\"));\n const onSpawn = () => {\n spawned = true;\n timeout = setTimeout(\n () => settle(new Error(\"Timed out waiting for auto-launched browser DevTools startup announcement.\")),\n waitMs,\n );\n settle();\n };\n const inspectLine = (line: string) => {\n const match = /^DevTools listening on (\\S+)$/.exec(line.trim());\n if (!match) return;\n identity = browserWebSocketIdentity(match[1], port);\n if (!identity) settle(new Error(\"Auto-launched browser announced an unexpected DevTools endpoint.\"));\n else settle();\n };\n const onData = (data: Buffer | string) => {\n receivedBytes += Buffer.byteLength(data);\n if (receivedBytes > MAX_STARTUP_STDERR_BYTES) {\n settle(new Error(\"Auto-launched browser startup stderr exceeded 64 KB before readiness.\"));\n return;\n }\n pendingLine += data.toString();\n const lines = pendingLine.split(\"\\n\");\n pendingLine = lines.pop() ?? \"\";\n for (const line of lines) {\n inspectLine(line);\n if (settled) break;\n }\n };\n const onEnd = () => {\n inspectLine(pendingLine);\n if (!identity) settle(new Error(\"Auto-launched browser closed stderr before its DevTools startup announcement.\"));\n };\n\n child.once(\"spawn\", onSpawn);\n child.once(\"error\", onError);\n child.once(\"exit\", onExit);\n child.once(\"close\", onExit);\n stderr.on(\"data\", onData);\n stderr.once(\"end\", onEnd);\n stderr.once(\"error\", onError);\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n"],
5
+ "mappings": ";;;;AAAO,IAAM,kCAAkC;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,oBAAoB,CAAC,qCAAqC,kCAAkC;AAElG,IAAM,6BAA6B,CAAC,GAAG,iCAAiC,GAAG,iBAAiB;AAK5F,SAAS,iBAAiB,OAAwC;AACvE,SAAO,kBAAkB,SAAS,KAAuB;AAC3D;;;ACjBA,SAAS,kBAAkB;AAC3B,SAAS,iBAAiB;AAC1B,SAAS,QAAQ,OAAO,OAAO,UAAU,UAAU,QAAQ,IAAI,MAAM,iBAAiB;AACtF,SAAS,SAAS,YAAY,MAAM,eAAe;AACnD,SAAS,iBAAiB,mBAAmB;AAG7C,IAAM,yBAAyB;AAC/B,IAAM,4BAA4B;AAI3B,SAAS,yBAAyB,OAAiD;AACxF,SAAO,UAAU,cAAc,UAAU,UAAU,UAAU;AAC/D;AAOO,IAAM,uBAAuB;AAC7B,IAAM,uBAAuB;AAC7B,IAAM,2BAA2B,UAAU,oBAAoB,IAAI,oBAAoB;AAkF9F,IAAM,0BAAkD;AAAA,EACtD,OAAO,CAAC,MAAM,SAAS,UAAU,MAAM,MAAM,MAAM,EAAE,KAAK,MAAM,MAAS;AAAA,EACzE;AACF;AAEA,IAAI,oBAAoB,QAAQ,QAAQ;AAExC,eAAsB,wBAAwB;AAC5C,QAAM;AACR;AAEA,eAAsB,aAAa,UAA+B,CAAC,GAAgC;AACjG,QAAM;AACN,QAAM,WAAW,iBAAiB;AAClC,QAAM,cAAc,QAAQ,MAAM,wBAAwB,QAAQ,GAAG,IAAI;AACzE,QAAM,QAAQ,EAAE,MAAM,UAAU,GAAI,cAAc,EAAE,SAAS,YAAY,IAAI,CAAC,EAAG;AACjF,QAAM,WAAqB,CAAC;AAE5B,MAAI,OAAO,MAAM,qBAAqB,UAAU,MAAM;AACtD,QAAM,eAAe,MAAM,WAAW,uBAAuB,CAAC;AAC9D,MAAI,KAAK,SAAS,aAAa,cAAc;AAC3C,aAAS;AAAA,MACP,4CAA4C,uBAAuB,CAAC,gBAAgB,QAAQ,6BAA6B,yBAAyB;AAAA,IACpJ;AAAA,EACF;AACA,MAAI,KAAK,SAAS,WAAW;AAC3B,UAAM,SAAS,MAAM,qBAAqB,uBAAuB,GAAG,MAAM;AAC1E,UAAM,sBAAsB,MAAM,qBAAqB,UAAU,MAAM;AACvE,QAAI,oBAAoB,SAAS,WAAW;AAC1C,aAAO;AACP,UAAI,OAAO,SAAS,WAAW;AAC7B,iBAAS;AAAA,UACP,4CAA4C,uBAAuB,CAAC,gBAAgB,QAAQ,6BAA6B,yBAAyB;AAAA,QACpJ;AAAA,MACF;AAAA,IACF,WAAW,OAAO,SAAS,WAAW;AACpC,aAAO;AACP,UAAI,OAAO,SAAS,SAAS;AAC3B,iBAAS;AAAA,UACP,gBAAgB,yBAAyB,kBAAkB,sBAAsB,wBAAwB,sBAAsB;AAAA,QACjI;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,WAAS,KAAK,GAAG,KAAK,QAAQ;AAE9B,MAAI,UAAkC,EAAE,MAAM,WAAW,UAAU,CAAC,EAAE;AACtE,MAAI,eAAe,QAAQ,gBAAgB;AACzC,cAAU,MAAM,qBAAqB,aAAa,WAAW,QAAQ,GAAG;AACxE,aAAS,KAAK,GAAG,QAAQ,QAAQ;AAAA,EACnC;AAEA,QAAM,qBAAqB,6BAA6B;AACxD,MAAI,mBAAoB,UAAS,KAAK,kBAAkB;AAExD,QAAM,cAAc,KAAK,YAAY,WAAW,CAAC;AACjD,QAAM,mBAAmB,wBAAwB,aAAa,QAAQ,YAAY,OAAO;AACzF,QAAM,WAAW,gBAAgB,KAAK,YAAY,QAAQ,YAAY,gBAAgB;AACtF,QAAM,aACJ,KAAK,YAAY,aAAa,UAC9B,SAAS,UAAU,UACnB,KAAK,YAAY,YAAY,UAC7B,QAAQ,YAAY,YAAY,UAChC,KAAK,YAAY,WAAW;AAC9B,QAAM,iBAAiB,CAAC,MAAM,OAAO,EAClC,OAAO,CAAC,WAAW,OAAO,SAAS,SAAS,EAC5C,IAAI,CAAC,WAAW,OAAO,MAAM,EAC7B,OAAO,CAAC,WAA6B,QAAQ,MAAM,CAAC;AACvD,QAAM,WACJ,KAAK,SAAS,YACV;AAAA,IACE,MAAM;AAAA,IACN,QAAQ,KAAK,UAAU,GAAG,QAAQ;AAAA,EACpC,IACA,EAAE,MAAM,KAAK,KAAK;AACxB,QAAM,OAAO;AAAA,IACX;AAAA,IACA,wBAAwB,SAAS,OAAO;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAI,SAAS,SAAS,IAAI,EAAE,QAAQ,SAAS,KAAK,IAAI,EAAE,IAAI,CAAC;AAAA,EAC/D;AAEA,MAAI,WAAY,QAAO,EAAE,GAAG,MAAM,MAAM,UAAU,SAAS;AAC3D,MAAI,eAAe,SAAS,GAAG;AAC7B,WAAO,EAAE,GAAG,MAAM,MAAM,WAAW,QAAQ,eAAe,KAAK,IAAI,EAAE;AAAA,EACvE;AACA,SAAO,EAAE,GAAG,MAAM,MAAM,UAAU;AACpC;AAEA,SAAS,gBACP,MACA,UACA,SACgC;AAChC,SAAO;AAAA,IACL,UAAU,MAAM,YAAY;AAAA,IAC5B,GAAI,MAAM,QAAQ,EAAE,OAAO,KAAK,OAAO,WAAW,KAAK,UAAU,IAAI,CAAC;AAAA,IACtE;AAAA,IACA,QAAQ,EAAE,SAAS,MAAM,QAAQ,WAAW,MAAM;AAAA,EACpD;AACF;AAEA,SAAS,wBACP,MACA,SAC0B;AAC1B,QAAM,qBAAqB,qBAAqB,KAAK,YAAY,wBAAwB;AACzF,QAAM,kBAAkB,QAAQ,IAAI;AACpC,QAAM,uBAAuB,QAAQ,IAAI;AACzC,QAAM,kBAAkB,oBAAoB,oBAAoB;AAChE,QAAM,gCAAgC,oBAAoB,UAAa,oBAAoB;AAC3F,QAAM,OAAO,mBAAmB,mBAAmB;AACnD,QAAM,OAAO,mBAAmB,mBAAmB;AACnD,QAAM,wBAAwB,QAAQ,IAAI;AAC1C,QAAM,wBAAwB,QAAQ,IAAI;AAC1C,QAAM,iBAAiB,yBAAyB,KAAK;AACrD,QAAM,iBAAiB,SAAS,kBAAkB,KAAK,kBAAkB,CAAC;AAC1E,QAAM,iBAAwC,gCAC1C,gBACA,KAAK,WACH,SACA;AACN,SAAO;AAAA,IACL,UAAU,sBAAsB,MAAM,IAAI;AAAA,IAC1C;AAAA,IACA;AAAA,IACA,gBAAgB,oBAAoB,UAAa,KAAK,aAAa;AAAA,IACnE,gBAAgB,oBAAoB,UAAa,KAAK,aAAa;AAAA,IACnE,mBAAmB,0BAA0B,SAAa,KAAK,cAAc,OAAQ,0BAA0B;AAAA,IAC/G,GAAI,iBAAiB,EAAE,eAAe,IAAI,CAAC;AAAA,IAC3C,gBAAgB,CAAC,GAAG,cAAc;AAAA,IAClC;AAAA,IACA,kBACE,0BAA0B,SAAY,gBAAgB,KAAK,eAAe,SAAY,SAAS;AAAA,IACjG,sBAAsB,wBAAwB,gBAAgB,KAAK,iBAAiB,SAAS;AAAA,IAC7F,sBAAsB,SAAS,iBAAiB,YAAY,KAAK,iBAAiB,SAAS;AAAA,EAC7F;AACF;AAEA,SAAS,+BAA+B;AACtC,QAAM,kBAAkB;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,OAAO,CAAC,SAAS,QAAQ,IAAI,IAAI,MAAM,MAAS;AAClD,MAAI,gBAAgB,WAAW,EAAG,QAAO;AACzC,SAAO,gGAAgG,gBAAgB,KAAK,IAAI,CAAC,sFAAsF,iBAAiB,CAAC;AAC3O;AAEA,eAAe,qBACb,UACA,OACA,KACiC;AACjC,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,SAAS,UAAU,MAAM;AAAA,EACxC,SAAS,OAAO;AACd,QAAI,YAAY,KAAK,KAAK,MAAM,SAAS,SAAU,QAAO,EAAE,MAAM,WAAW,UAAU,CAAC,EAAE;AAC1F,UAAM,SAAS,GAAG,QAAQ,KAAK,YAAY,KAAK,CAAC;AACjD,WAAO,EAAE,MAAM,WAAW,QAAQ,UAAU,CAAC,qCAAqC,MAAM,EAAE,EAAE;AAAA,EAC9F;AAEA,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,IAAI;AAAA,EAC1B,QAAQ;AACN,UAAM,SAAS,GAAG,QAAQ;AAC1B,WAAO,EAAE,MAAM,WAAW,QAAQ,UAAU,CAAC,qCAAqC,MAAM,EAAE,EAAE;AAAA,EAC9F;AACA,MAAI,CAAC,SAAS,MAAM,GAAG;AACrB,UAAM,SAAS,GAAG,QAAQ;AAC1B,WAAO,EAAE,MAAM,WAAW,QAAQ,UAAU,CAAC,qCAAqC,MAAM,EAAE,EAAE;AAAA,EAC9F;AAEA,QAAM,gBAAgB,6BAA6B,QAAQ,OAAO,QAAQ;AAC1E,MAAI;AACF,UAAM,aAAa,MAAM,0BAA0B,QAAQ,OAAO,UAAU,GAAG;AAC/E,WAAO,EAAE,MAAM,SAAS,UAAU,EAAE,GAAG,OAAO,GAAG,YAAY,UAAU,cAAc;AAAA,EACvF,SAAS,OAAO;AACd,UAAM,SAAS,GAAG,QAAQ,KAAK,YAAY,KAAK,CAAC;AACjD,WAAO;AAAA,MACL,MAAM;AAAA,MACN;AAAA,MACA,UAAU,CAAC,GAAG,eAAe,qCAAqC,MAAM,EAAE;AAAA,IAC5E;AAAA,EACF;AACF;AAEA,SAAS,6BAA6B,UAAmC,OAA2B,UAAkB;AACpH,MAAI,UAAU,UAAW,QAAO,CAAC;AACjC,QAAM,UAAU,SAAS,SAAS,OAAO,IAAI,SAAS,UAAU;AAChE,QAAM,WAAW,UACb,CAAC,YAAY,cAAc,gBAAgB,EACxC,OAAO,CAAC,UAAU,QAAQ,KAAK,MAAM,MAAS,EAC9C;AAAA,IACC,CAAC,UACC,mCAAmC,KAAK,eAAe,QAAQ,6CAA6C,iBAAiB,CAAC;AAAA,EAClI,IACF,CAAC;AACL,MAAI,SAAS,WAAW,QAAW;AACjC,aAAS;AAAA,MACP,sDAAsD,QAAQ;AAAA,IAChE;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAe,0BACb,UACA,OACA,UACA,KACqC;AACrC,QAAM,aAAyC,CAAC;AAChD,MAAI,UAAU,UAAU,SAAS,aAAa,QAAW;AACvD,QAAI,CAAC,yBAAyB,SAAS,QAAQ;AAC7C,YAAM,IAAI,MAAM,mDAAmD;AACrE,eAAW,WAAW,SAAS;AAAA,EACjC;AAEA,MAAI,UAAU,WAAW,SAAS,UAAU,UAAa,SAAS,cAAc,SAAY;AAC1F,UAAM,eAAe,gCAAgC,QAAQ;AAC7D,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI,MAAM,oFAAoF;AAAA,IACtG;AACA,eAAW,QAAQ,aAAa;AAChC,eAAW,YAAY,aAAa;AAAA,EACtC;AAEA,MAAI,SAAS,YAAY,QAAW;AAClC,QAAI,CAAC,SAAS,SAAS,OAAO,EAAG,OAAM,IAAI,MAAM,kCAAkC;AACnF,eAAW,UAAU,MAAM,wBAAwB,SAAS,SAAS,OAAO,UAAU,GAAG;AAAA,EAC3F;AAEA,MAAI,UAAU,UAAU,SAAS,WAAW,QAAW;AACrD,QAAI,CAAC,SAAS,SAAS,MAAM,KAAK,OAAO,SAAS,OAAO,YAAY,WAAW;AAC9E,YAAM,IAAI,MAAM,yCAAyC;AAAA,IAC3D;AACA,eAAW,SAAS,EAAE,SAAS,SAAS,OAAO,QAAQ;AAAA,EACzD;AAEA,SAAO;AACT;AAEA,eAAe,wBACb,SACA,OACA,WACA,KAC8B;AAC9B,QAAM,aAAkC,CAAC;AACzC,MAAI,UAAU,UAAU,QAAQ,aAAa,QAAW;AACtD,QAAI,OAAO,QAAQ,aAAa,UAAU;AACxC,YAAM,IAAI,MAAM,mEAAmE;AAAA,IACrF;AACA,eAAW,WAAW,qBAAqB,QAAQ,QAAQ,EAAE;AAAA,EAC/D;AACA,MAAI,UAAU,UAAU,QAAQ,eAAe,QAAW;AACxD,QAAI,OAAO,QAAQ,eAAe,WAAW;AAC3C,YAAM,IAAI,MAAM,6CAA6C;AAAA,IAC/D;AACA,eAAW,aAAa,QAAQ;AAAA,EAClC;AACA,MAAI,UAAU,UAAU,QAAQ,mBAAmB,QAAW;AAC5D,QAAI,OAAO,QAAQ,mBAAmB,YAAY,QAAQ,eAAe,WAAW,GAAG;AACrF,YAAM,IAAI,MAAM,iEAAiE;AAAA,IACnF;AACA,QAAI,CAAC,WAAW,QAAQ,cAAc,GAAG;AACvC,YAAM,IAAI,MAAM,0DAA0D;AAAA,IAC5E;AACA,eAAW,iBAAiB,QAAQ,QAAQ,cAAc;AAAA,EAC5D;AAEA,MAAI,QAAQ,mBAAmB,QAAW;AACxC,QACE,CAAC,MAAM,QAAQ,QAAQ,cAAc,KACrC,CAAC,QAAQ,eAAe,MAAM,CAAC,UAAU,OAAO,UAAU,YAAY,MAAM,SAAS,CAAC,GACtF;AACA,YAAM,IAAI,MAAM,YAAY,KAAK,2DAA2D;AAAA,IAC9F;AACA,UAAM,gBAA0B,CAAC;AACjC,eAAW,kBAAkB,QAAQ,gBAA4B;AAC/D,UAAI,UAAU,UAAU,CAAC,WAAW,cAAc,GAAG;AACnD,cAAM,IAAI,MAAM,0EAA0E;AAAA,MAC5F;AACA,YAAM,eAAe,WAAW,cAAc,IAC1C,QAAQ,cAAc,IACtB,QAAQ,OAAO,QAAQ,IAAI,GAAG,cAAc;AAChD,oBAAc,KAAK,MAAM,8BAA8B,YAAY,CAAC;AAAA,IACtE;AACA,eAAW,iBAAiB,cAAc,aAAa;AAAA,EACzD;AACA,SAAO;AACT;AAEA,eAAe,8BAA8B,eAAuB;AAClE,MAAI;AACJ,MAAI;AACF,oBAAgB,MAAM,SAAS,aAAa;AAC5C,UAAM,gBAAgB,MAAM,KAAK,aAAa;AAC9C,QAAI,CAAC,cAAc,YAAY,EAAG,OAAM,IAAI,MAAM,iBAAiB;AAAA,EACrE,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,2BAA2B,aAAa,gBAAgB,YAAY,KAAK,CAAC,EAAE;AAAA,EAC9F;AAEA,QAAM,eAAe,KAAK,eAAe,eAAe;AACxD,MAAI;AACJ,MAAI;AACF,UAAM,eAAe,MAAM,MAAM,YAAY;AAC7C,QAAI,CAAC,aAAa,OAAO,EAAG,OAAM,IAAI,MAAM,oBAAoB;AAChE,eAAW,KAAK,MAAM,MAAM,SAAS,cAAc,MAAM,CAAC;AAAA,EAC5D,SAAS,OAAO;AACd,UAAM,IAAI,MAAM,sBAAsB,aAAa,+BAA+B,YAAY,KAAK,CAAC,EAAE;AAAA,EACxG;AACA,MAAI,cAAc,SAAS,GAAG,GAAG;AAC/B,UAAM,IAAI;AAAA,MACR,2BAA2B,aAAa;AAAA,IAC1C;AAAA,EACF;AACA,MACE,CAAC,SAAS,QAAQ,KAClB,CAAC,CAAC,GAAG,CAAC,EAAE,SAAS,SAAS,gBAA0B,KACpD,OAAO,SAAS,SAAS,YACzB,OAAO,SAAS,YAAY,UAC5B;AACA,UAAM,IAAI;AAAA,MACR,sBAAsB,aAAa;AAAA,IACrC;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,qBAAqB,OAAe;AAClD,QAAM,eAAe,MAAM,KAAK;AAChC,QAAM,eAAe,aAAa,MAAM,8CAA8C,IAAI,CAAC;AAC3F,MAAI;AACJ,MAAI;AACF,eAAW,IAAI,IAAI,YAAY;AAAA,EACjC,QAAQ;AACN,UAAM,IAAI,MAAM,iEAAiE;AAAA,EACnF;AACA,MACE,SAAS,aAAa,WACtB,SAAS,YACT,SAAS,YACT,CAAC,SAAS,YACV,CAAC,gBACA,SAAS,aAAa,OAAO,SAAS,aAAa,MACpD,SAAS,UACT,SAAS,MACT;AACA,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,QAAM,OAAO,oBAAoB,YAAY;AAC7C,MAAI,SAAS,QAAW;AACtB,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AACA,QAAM,OAAO,SAAS;AACtB,SAAO,EAAE,UAAU,sBAAsB,MAAM,IAAI,GAAG,MAAM,KAAK;AACnE;AAEO,SAAS,oBAAoB,OAA2B;AAC7D,MAAI,UAAU,OAAW,QAAO;AAChC,QAAM,eAAe,MAAM,KAAK;AAChC,MAAI,CAAC,QAAQ,KAAK,YAAY,EAAG,QAAO;AACxC,QAAM,OAAO,OAAO,YAAY;AAChC,MAAI,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAAK,OAAO,MAAQ,QAAO;AACjE,SAAO;AACT;AAEA,SAAS,sBAAsB,MAAc,MAAc;AACzD,QAAM,gBAAgB,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,GAAG,IAAI,OAAO,KAAK,SAAS,GAAG,IAAI,IAAI,IAAI,MAAM;AAC7G,SAAO,UAAU,aAAa,IAAI,IAAI;AACxC;AAEO,SAAS,gCAAgC,OAAoD;AAClG,MAAI,CAAC,SAAS,KAAK,EAAG,QAAO;AAC7B,MAAI,OAAO,MAAM,cAAc,YAAY,CAAC,OAAO,SAAS,MAAM,SAAS,EAAG,QAAO;AAErF,MAAI,MAAM,UAAU,WAAW;AAC7B,WAAO,EAAE,OAAO,CAAC,GAAG,0BAA0B,GAAG,WAAW,MAAM,UAAU;AAAA,EAC9E;AACA,MAAI,MAAM,UAAU,WAAY,QAAO,EAAE,OAAO,CAAC,GAAG,WAAW,MAAM,UAAU;AAC/E,MAAI,CAAC,MAAM,QAAQ,MAAM,KAAK,KAAK,CAAC,MAAM,MAAM,MAAM,wBAAwB,EAAG,QAAO;AACxF,SAAO,EAAE,OAAO,iCAAiC,MAAM,KAAK,GAAG,WAAW,MAAM,UAAU;AAC5F;AAEA,SAAS,yBAAyB,OAAiD;AACjF,SAAO,OAAO,UAAU,YAAY,2BAA2B,SAAS,KAAc;AACxF;AAEA,SAAS,iCAAiC,OAA0C;AAClF,QAAM,gBAAgB,IAAI,IAAI,KAAK;AACnC,SAAO,2BAA2B,OAAO,CAAC,aAAa,cAAc,IAAI,QAAQ,CAAC;AACpF;AAEA,SAAS,cAAc,QAA2B;AAChD,SAAO,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC;AAC5B;AAEO,IAAM,8BAAN,cAA0C,MAAM;AAAA,EACrD,YACE,OACS,eACT;AACA;AAAA,MACE,gBACI,GAAG,YAAY,KAAK,CAAC,oCAAoC,YAAY,aAAa,CAAC,KACnF,GAAG,YAAY,KAAK,CAAC;AAAA,MACzB,EAAE,OAAO,MAAM;AAAA,IACjB;AAPS;AAAA,EAQX;AAAA,EARW;AASb;AAEO,SAAS,aACd,UACA,aAA8C,CAAC,GAC/C,gBACe;AACf,SAAO;AAAA,IACL,CAAC,aAAa;AAAA,MACZ,GAAG;AAAA,MACH,OAAO,CAAC,GAAG,SAAS,KAAK;AAAA,MACzB,WAAW,SAAS;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,aACd,MACA,aAA8C,CAAC,GAChC;AACf,MAAI,CAAC,yBAAyB,IAAI,EAAG,QAAO,QAAQ,OAAO,IAAI,MAAM,mBAAmB,CAAC;AACzF,SAAO,sBAAsB,CAAC,aAAa,EAAE,GAAG,SAAS,UAAU,KAAK,IAAI,UAAU;AACxF;AAEO,SAAS,mBAAmB,SAAkB,aAA8C,CAAC,GAAkB;AACpH,SAAO;AAAA,IACL,CAAC,aAAa;AAAA,MACZ,GAAG;AAAA,MACH,QAAQ;AAAA,QACN,GAAI,SAAS,QAAQ,MAAM,IAAI,QAAQ,SAAS,CAAC;AAAA,QACjD;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,oBACd,OACA,aAA8C,CAAC,GAChC;AACf,SAAO,sBAAsB,OAAO,YAAY;AAC9C,UAAM,UAAU,SAAS,QAAQ,OAAO,IAAI,EAAE,GAAG,QAAQ,QAAQ,IAAI,CAAC;AACtE,eAAW,SAAS,CAAC,YAAY,cAAc,gBAAgB,GAAY;AACzE,YAAM,QAAQ,MAAM,KAAK;AACzB,UAAI,UAAU,OAAW;AACzB,UAAI,UAAU,KAAM,QAAO,QAAQ,KAAK;AAAA,UACnC,SAAQ,KAAK,IAAI;AAAA,IACxB;AACA,UAAM,wBAAwB,SAAS,QAAQ,iBAAiB,CAAC;AACjE,WAAO,EAAE,GAAG,SAAS,QAAQ;AAAA,EAC/B,GAAG,UAAU;AACf;AAEA,SAAS,sBACP,QACA,YACA,kBACA;AACA,QAAM,YAAY,kBAAkB,KAAK,MAAM,wBAAwB,QAAQ,YAAY,gBAAgB,CAAC;AAC5G,sBAAoB,UAAU,MAAM,MAAM,MAAS;AACnD,SAAO;AACT;AAEA,eAAe,wBACb,QACA,YACA,kBACe;AACf,QAAM,WAAW,iBAAiB;AAClC,MAAI,UAAU,MAAM,qBAAqB,UAAU,MAAM;AACzD,QAAM,mBAAmB,QAAQ,SAAS;AAC1C,MAAI,CAAC,iBAAkB,WAAU,MAAM,qBAAqB,uBAAuB,GAAG,MAAM;AAC5F,MAAI,QAAQ,SAAS,WAAW;AAC9B,UAAM,IAAI,MAAM,yDAAyD,QAAQ,MAAM,EAAE;AAAA,EAC3F;AACA,QAAM,eAAe,MAAM,OAAO,QAAQ,YAAY,CAAC,CAAC;AACxD,QAAM,MAAM,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAClD,QAAM,WAAW,GAAG,QAAQ,IAAI,QAAQ,GAAG,IAAI,WAAW,CAAC;AAC3D,MAAI;AACF,WAAO,WAAW,SAAS,wBAAwB,OAAO,UAAU,GAAG,KAAK,UAAU,cAAc,MAAM,CAAC,CAAC;AAAA,CAAI;AAChH,QAAI,CAAC,oBAAqB,MAAM,gBAAgB,QAAQ,GAAI;AAC1D,YAAM,IAAI,MAAM,GAAG,sBAAsB,uDAAuD;AAAA,IAClG;AACA,WAAO,WAAW,UAAU,wBAAwB,QAAQ,UAAU,QAAQ;AAAA,EAChF,SAAS,OAAO;AACd,UAAM,GAAG,UAAU,EAAE,OAAO,KAAK,CAAC,EAAE,MAAM,MAAM,MAAS;AACzD,UAAM;AAAA,EACR;AACA,MAAI,CAAC,iBAAkB;AACvB,MAAI;AAGF,qBAAiB;AAAA,EACnB,SAAS,OAAO;AACd,QAAI;AACJ,QAAI;AACF,YAAM,wBAAwB,CAAC,WAAW;AACxC,cAAM,WAAW,EAAE,GAAG,OAAO;AAC7B,mBAAW,SAAS,CAAC,SAAS,WAAW,GAAY;AACnD,cAAI,KAAK,UAAU,OAAO,KAAK,CAAC,MAAM,KAAK,UAAU,aAAa,KAAK,CAAC;AACtE,kBAAM,IAAI,MAAM,uEAAuE;AACzF,iBAAO,SAAS,KAAK;AACrB,cAAI,QAAQ,WAAW,KAAK,MAAM,OAAW,UAAS,KAAK,IAAI,QAAQ,SAAS,KAAK;AAAA,QACvF;AACA,eAAO;AAAA,MACT,GAAG,UAAU;AAAA,IACf,SAAS,QAAQ;AACf,sBAAgB;AAAA,IAClB;AACA,UAAM,IAAI,4BAA4B,OAAO,aAAa;AAAA,EAC5D;AACF;AAEO,SAAS,mBAAmB;AACjC,SAAO,KAAK,YAAY,GAAG,sBAAsB;AACnD;AAEO,SAAS,wBAAwB,KAAa;AACnD,SAAO,KAAK,KAAK,iBAAiB,sBAAsB;AAC1D;AAEA,SAAS,yBAAyB;AAChC,SAAO,KAAK,YAAY,GAAG,yBAAyB;AACtD;AAEA,eAAe,WAAW,UAAkB;AAC1C,MAAI;AACF,UAAM,OAAO,UAAU,UAAU,IAAI;AACrC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAe,gBAAgB,UAAkB;AAC/C,MAAI;AACF,UAAM,MAAM,QAAQ;AACpB,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI,YAAY,KAAK,KAAK,MAAM,SAAS,SAAU,QAAO;AAC1D,UAAM;AAAA,EACR;AACF;AAEA,SAAS,SAAS,OAAkD;AAClE,SAAO,QAAQ,KAAK,KAAK,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAEA,SAAS,YAAY,OAAgD;AACnE,SAAO,iBAAiB,SAAS,UAAU;AAC7C;AAEA,SAAS,YAAY,OAAgB;AACnC,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;;;AChqBO,IAAM,eAAe;AACrB,IAAM,eAAe;AACrB,IAAM,qBAAqB;AAC3B,IAAM,0BAA0B;AAChC,IAAM,2BAA2B;AACjC,IAAM,4BAA4B;AAClC,IAAM,iCAAiC;AACvC,IAAM,2BAA2B;AAoEjC,IAAM,QAA6B;AAAA,EACxC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,gBAAgB,CAAC;AAAA,EACjB,yBAAyB;AAAA,EACzB,sBAAsB;AAAA,EACtB,wBAAwB;AAAA,EACxB,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,mBAAmB,IAAI,gBAAgB;AACzC;AAUA,IAAM,uBAAuB,oBAAI,QAAsC;AAEhE,SAAS,sBAAsB,OAAe;AACnD,QAAM,UAAU,cAAc,KAAK;AACnC,UAAQ,UAAU;AAClB,UAAQ,qBAAqB;AAC/B;AAEO,SAAS,qBAAqB,OAAe,YAA0B;AAC5E,QAAM,UAAU,cAAc,KAAK;AACnC,QAAM,aAAa,IAAI,gBAAgB;AACvC,UAAQ,YAAY,IAAI,UAAU;AAClC,QAAM,UAAU,CAAC,WAAW,QAAQ,QAAQ,WAAW,MAAM;AAC7D,MAAI,WAAY,SAAQ,KAAK,UAAU;AACvC,QAAM,SAAS,YAAY,IAAI,OAAO;AACtC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,mBAAmB,QAAQ;AAAA,IAC3B,kBAAkB,QAAQ;AAAA,IAC1B,UAAU;AACR,cAAQ,YAAY,OAAO,UAAU;AAAA,IACvC;AAAA,EACF;AACF;AAEO,SAAS,2BAA2B,OAAe,QAAgB;AACxE,QAAM,UAAU,cAAc,KAAK;AACnC,UAAQ,cAAc;AACtB,QAAM,cAAc,CAAC,GAAG,QAAQ,WAAW;AAC3C,UAAQ,YAAY,MAAM;AAC1B,QAAM,QAAQ,IAAI,aAAa,QAAQ,YAAY;AACnD,UAAQ,WAAW,MAAM,KAAK;AAC9B,UAAQ,aAAa,IAAI,gBAAgB;AACzC,aAAW,cAAc,YAAa,YAAW,MAAM,KAAK;AAC9D;AAEO,SAAS,wBAAwB,OAAe;AACrD,SAAO,cAAc,KAAK,EAAE;AAC9B;AAEO,SAAS,oBAAoB,OAAe;AACjD,SAAO,cAAc,KAAK,EAAE,WAAW;AACzC;AAEO,SAAS,0BAA0B,SAAkB,OAAe;AACzE,QAAM,UAAU,cAAc,KAAK;AACnC,MAAI,QAAQ,YAAY,SAAS;AAC/B,+BAA2B,OAAO,UAAU,UAAU,YAAY,UAAU,EAAE;AAAA,EAChF;AACA,UAAQ,UAAU;AACpB;AAEO,SAAS,cAAc,OAAe;AAC3C,SAAO,cAAc,KAAK,EAAE;AAC9B;AAEO,SAAS,yBAAyB,WAItC;AACD,QAAM,UAAU,cAAc,UAAU,KAAK;AAC7C,SAAO,UAAU,sBAAsB,QAAQ,qBAAqB,UAAU,qBAAqB,QAAQ;AAC7G;AAEA,SAAS,cAAc,OAAe;AACpC,QAAM,WAAW,qBAAqB,IAAI,KAAK;AAC/C,MAAI,SAAU,QAAO;AACrB,QAAM,UAAgC;AAAA,IACpC,YAAY,IAAI,gBAAgB;AAAA,IAChC,aAAa,oBAAI,IAAI;AAAA,IACrB,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,mBAAmB;AAAA,EACrB;AACA,uBAAqB,IAAI,OAAO,OAAO;AACvC,SAAO;AACT;AAEO,SAAS,4BACd,SACA,OACA,gBACA;AACA,QAAM,OAAO,QAAQ;AACrB,QAAM,OAAO,QAAQ;AACrB,QAAM,iBAAiB,QAAQ;AAC/B,QAAM,iBAAiB,QAAQ;AAC/B,QAAM,iBAAiB,QAAQ;AAC/B,QAAM,oBAAoB,QAAQ;AAClC,QAAM,iBAAiB,QAAQ;AAC/B,QAAM,mBAAmB,QAAQ;AACjC,QAAM,oBAAoB,QAAQ;AAClC,QAAM,iBAAiB,CAAC,GAAG,QAAQ,cAAc;AACjD,QAAM,0BAA0B,QAAQ;AACxC,QAAM,uBAAuB,QAAQ;AACrC,QAAM,mBAAmB,MAAM;AAC/B,QAAM,0BAA0B,MAAM;AACtC,QAAM,yBAAyB;AACjC;;;ACjNA,SAA4B,UAAU,aAAa;AACnD,SAAS,UAAAA,SAAQ,SAAS,MAAAC,WAAU;AACpC,SAAS,oBAAoB;AAC7B,SAAS,cAAc;AACvB,SAAS,QAAAC,aAAY;;;ACJrB,SAAS,aAAAC,kBAAiB;AAC1B,SAAS,WAAW,cAAAC,aAAY,QAAAC,OAAM,WAAAC,gBAAe;AAIrD,SAAS,2BAA2B,OAAe;AACjD,SAAO,QAAQ,aAAa,UAAU,MAAM,YAAY,IAAI;AAC9D;AAEO,SAAS,4BAA4B,SAAiE;AAC3G,QAAM,oBAAoB,mCAAmC,OAAO;AACpE,MAAI,kBAAkB,SAAS,EAAG,QAAO;AAEzC,SAAO,wBAAwB,oCAAoC,CAAC;AACtE;AAEA,SAAS,mCAAmC,SAAiE;AAC3G,MAAI,CAAC,QAAQ,eAAgB,QAAO,CAAC;AACrC,SAAO;AAAA,IACL;AAAA,MACE,OAAO,QAAQ,yBAAyB,gBAAgB,+BAA+B;AAAA,MACvF,YAAY,QAAQ;AAAA,MACpB,QAAQ;AAAA,IACV;AAAA,EACF;AACF;AAEA,SAAS,sCAAoE;AAC3E,MAAI,QAAQ,aAAa,UAAU;AACjC,WAAO;AAAA,MACL;AAAA,QACE,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,QAAQ;AAAA,MACV;AAAA,MACA;AAAA,QACE,OAAO;AAAA,QACP,YAAY;AAAA,QACZ,QAAQ;AAAA,MACV;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,aAAa,SAAS;AAChC,WAAO,mCAAmC;AAAA,EAC5C;AAEA,SAAO;AAAA,IACL,EAAE,OAAO,iBAAiB,YAAY,iBAAiB,QAAQ,OAAO;AAAA,IACtE,EAAE,OAAO,wBAAwB,YAAY,wBAAwB,QAAQ,OAAO;AAAA,IACpF,EAAE,OAAO,YAAY,YAAY,YAAY,QAAQ,OAAO;AAAA,IAC5D,EAAE,OAAO,oBAAoB,YAAY,oBAAoB,QAAQ,OAAO;AAAA,IAC5E,EAAE,OAAO,iBAAiB,YAAY,iBAAiB,QAAQ,OAAO;AAAA,IACtE,EAAE,OAAO,SAAS,YAAY,SAAS,QAAQ,OAAO;AAAA,IACtD,EAAE,OAAO,kBAAkB,YAAY,kBAAkB,QAAQ,OAAO;AAAA,IACxE,EAAE,OAAO,yBAAyB,YAAY,yBAAyB,QAAQ,OAAO;AAAA,EACxF;AACF;AAEA,SAAS,qCAAmE;AAC1E,QAAM,eAAe,CAAC,QAAQ,IAAI,cAAc,QAAQ,IAAI,mBAAmB,GAAG,QAAQ,IAAI,YAAY,EAAE;AAAA,IAC1G,CAAC,UAA2B,OAAO,UAAU,YAAY,MAAM,SAAS;AAAA,EAC1E;AACA,QAAM,iBAAiB,aAAa,QAAQ,CAAC,SAAS;AAAA,IACpDD,MAAK,MAAM,UAAU,UAAU,eAAe,YAAY;AAAA,IAC1DA,MAAK,MAAM,YAAY,eAAe,YAAY;AAAA,IAClDA,MAAK,MAAM,iBAAiB,iBAAiB,eAAe,WAAW;AAAA,IACvEA,MAAK,MAAM,aAAa,QAAQ,eAAe,YAAY;AAAA,EAC7D,CAAC;AACD,SAAO;AAAA,IACL,GAAG,eAAe,IAAI,CAAC,gBAAgB;AAAA,MACrC,OAAO,2BAA2B,UAAU;AAAA,MAC5C;AAAA,MACA,QAAQ;AAAA,IACV,EAAE;AAAA,IACF,EAAE,OAAO,iBAAiB,YAAY,cAAc,QAAQ,OAAO;AAAA,IACnE,EAAE,OAAO,YAAY,YAAY,gBAAgB,QAAQ,OAAO;AAAA,IAChE,EAAE,OAAO,iBAAiB,YAAY,aAAa,QAAQ,OAAO;AAAA,IAClE,EAAE,OAAO,kBAAkB,YAAY,cAAc,QAAQ,OAAO;AAAA,EACtE;AACF;AAEA,SAAS,2BAA2B,YAAoB;AACtD,QAAM,uBAAuB,2BAA2B,UAAU;AAClE,MAAI,qBAAqB,SAAS,OAAO,EAAG,QAAO;AACnD,MAAI,qBAAqB,SAAS,MAAM,KAAK,qBAAqB,SAAS,QAAQ,GAAG;AACpF,WAAO;AAAA,EACT;AACA,MAAI,qBAAqB,SAAS,UAAU,EAAG,QAAO;AACtD,SAAO;AACT;AAEA,SAAS,wBAAwB,YAA0C;AACzE,QAAM,OAAO,oBAAI,IAAY;AAC7B,SAAO,WAAW,OAAO,CAAC,cAAc;AACtC,UAAM,MAAM,2BAA2B,UAAU,UAAU;AAC3D,QAAI,KAAK,IAAI,GAAG,EAAG,QAAO;AAC1B,SAAK,IAAI,GAAG;AACZ,WAAO;AAAA,EACT,CAAC;AACH;AAEA,eAAsB,yBACpB,aACAE,SACA,kBACA;AACA,QAAM,aAAiC,CAAC;AACxC,aAAW,cAAc,aAAa;AACpC,UAAM,qBAAqB,MAAM,yBAAyB,WAAW,YAAYA,SAAQ,gBAAgB;AACzG,qBAAiB;AACjB,QAAI,CAAC,mBAAoB;AACzB,eAAW,KAAK,EAAE,GAAG,YAAY,mBAAmB,CAAC;AAAA,EACvD;AACA,SAAO,sCAAsC,UAAU;AACzD;AAEA,SAAS,sCAAsC,YAAgC;AAC7E,QAAM,OAAO,oBAAI,IAAY;AAC7B,SAAO,WAAW,OAAO,CAAC,cAAc;AACtC,UAAM,MAAM,2BAA2BD,SAAQ,UAAU,kBAAkB,CAAC;AAC5E,QAAI,KAAK,IAAI,GAAG,EAAG,QAAO;AAC1B,SAAK,IAAI,GAAG;AACZ,WAAO;AAAA,EACT,CAAC;AACH;AAEA,eAAe,yBACb,YACAC,SACA,kBACA;AACA,MAAI,iBAAiB,UAAU,KAAKH,YAAW,UAAU,GAAG;AAC1D,UAAM,qBAAqBA,YAAW,UAAU,IAAI,aAAaE,SAAQ,UAAU;AACnF,WAAQ,MAAM,oBAAoB,oBAAoBC,SAAQ,gBAAgB,IAAK,qBAAqB;AAAA,EAC1G;AAEA,aAAW,aAAa,qBAAqB,GAAG;AAC9C,eAAW,kBAAkB,sBAAsB,UAAU,GAAG;AAC9D,YAAM,YAAYF,MAAK,WAAW,cAAc;AAChD,UAAI,MAAM,oBAAoB,WAAWE,SAAQ,gBAAgB,EAAG,QAAO;AAAA,IAC7E;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,MAAc;AACtC,SAAO,KAAK,SAAS,GAAG,KAAK,KAAK,SAAS,IAAI;AACjD;AAEA,SAAS,uBAAuB;AAC9B,UAAQ,QAAQ,IAAI,QAAQ,IAAI,MAAM,SAAS,EAAE,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC;AACnF;AAEA,SAAS,sBAAsB,YAAoB;AACjD,MAAI,QAAQ,aAAa,WAAW,gBAAgB,KAAK,UAAU,EAAG,QAAO,CAAC,UAAU;AACxF,SAAO,CAAC,YAAY,GAAG,UAAU,QAAQ,GAAG,UAAU,QAAQ,GAAG,UAAU,MAAM;AACnF;AAEA,eAAe,oBACb,MACAA,SACA,kBACA;AACA,MAAI,aAAa;AACjB,MAAI;AACF,UAAMA,QAAO,MAAM,QAAQ,aAAa,UAAUJ,WAAU,OAAOA,WAAU,IAAI;AACjF,iBAAa;AAAA,EACf,QAAQ;AAAA,EAER;AACA,mBAAiB;AACjB,SAAO;AACT;;;ACpLA,IAAM,2BAA2B,KAAK;AAEtC,SAAS,uBAAuB,SAAuB;AAGrD,QAAM,cAAc,MAAM;AAC1B,UAAQ,GAAG,SAAS,WAAW;AAC/B,UAAQ,KAAK,SAAS,MAAM,QAAQ,IAAI,SAAS,WAAW,CAAC;AAC/D;AAEO,SAAS,yBAAyB,OAAgB,MAAkC;AACzF,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,KAAK;AACzB,QACE,IAAI,aAAa,SACjB,CAAC,CAAC,aAAa,aAAa,OAAO,EAAE,SAAS,IAAI,QAAQ,KAC1D,OAAO,IAAI,QAAQ,IAAI,MAAM,QAC7B,IAAI,YACJ,IAAI,YACJ,IAAI,UACJ,IAAI,QACJ,CAAC,+BAA+B,KAAK,IAAI,QAAQ,GACjD;AACA,aAAO;AAAA,IACT;AACA,WAAO,IAAI;AAAA,EACb,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAIO,SAAS,sBACd,OACA,MACA,QACA,QACiB;AACjB,yBAAuB,KAAK;AAC5B,QAAM,SAAS,MAAM;AACrB,MAAI,UAAU,CAAC,OAAO,OAAQ,wBAAuB,MAAM;AAC3D,SAAO,eAAe;AACtB,MAAI,CAAC,OAAQ,QAAO,QAAQ,OAAO,IAAI,MAAM,qDAAqD,CAAC;AAEnG,SAAO,IAAI,QAAgB,CAACK,UAAS,WAAW;AAC9C,QAAI,UAAU;AACd,QAAI;AACJ,QAAI,gBAAgB;AACpB,QAAI,cAAc;AAClB,QAAI,UAAU;AACd,QAAI;AAEJ,UAAM,SAAS,CAAC,UAAkB;AAChC,UAAI,QAAS;AACb,UAAI,CAAC,UAAU,CAAC,WAAW,CAAC,UAAW;AACvC,gBAAU;AACV,mBAAa,OAAO;AACpB,YAAM,IAAI,SAAS,OAAO;AAC1B,YAAM,IAAI,SAAS,OAAO;AAC1B,YAAM,IAAI,QAAQ,MAAM;AACxB,YAAM,IAAI,SAAS,MAAM;AACzB,aAAO,IAAI,QAAQ,MAAM;AACzB,aAAO,IAAI,OAAO,KAAK;AACvB,aAAO,IAAI,SAAS,OAAO;AAC3B,aAAO,oBAAoB,SAAS,OAAO;AAE3C,aAAO,OAAO;AACd,UAAI,MAAO,QAAO,KAAK;AAAA,UAClB,CAAAA,SAAQ,QAAkB;AAAA,IACjC;AACA,UAAM,UAAU,CAAC,UAAiB,OAAO,KAAK;AAC9C,UAAM,UAAU,MAAM,OAAO,IAAI,MAAM,8CAA8C,EAAE,OAAO,OAAO,OAAO,CAAC,CAAC;AAC9G,UAAM,SAAS,MAAM,OAAO,IAAI,MAAM,gEAAgE,CAAC;AACvG,UAAM,UAAU,MAAM;AACpB,gBAAU;AACV,gBAAU;AAAA,QACR,MAAM,OAAO,IAAI,MAAM,4EAA4E,CAAC;AAAA,QACpG;AAAA,MACF;AACA,aAAO;AAAA,IACT;AACA,UAAM,cAAc,CAAC,SAAiB;AACpC,YAAM,QAAQ,gCAAgC,KAAK,KAAK,KAAK,CAAC;AAC9D,UAAI,CAAC,MAAO;AACZ,iBAAW,yBAAyB,MAAM,CAAC,GAAG,IAAI;AAClD,UAAI,CAAC,SAAU,QAAO,IAAI,MAAM,kEAAkE,CAAC;AAAA,UAC9F,QAAO;AAAA,IACd;AACA,UAAM,SAAS,CAAC,SAA0B;AACxC,uBAAiB,OAAO,WAAW,IAAI;AACvC,UAAI,gBAAgB,0BAA0B;AAC5C,eAAO,IAAI,MAAM,uEAAuE,CAAC;AACzF;AAAA,MACF;AACA,qBAAe,KAAK,SAAS;AAC7B,YAAM,QAAQ,YAAY,MAAM,IAAI;AACpC,oBAAc,MAAM,IAAI,KAAK;AAC7B,iBAAW,QAAQ,OAAO;AACxB,oBAAY,IAAI;AAChB,YAAI,QAAS;AAAA,MACf;AAAA,IACF;AACA,UAAM,QAAQ,MAAM;AAClB,kBAAY,WAAW;AACvB,UAAI,CAAC,SAAU,QAAO,IAAI,MAAM,+EAA+E,CAAC;AAAA,IAClH;AAEA,UAAM,KAAK,SAAS,OAAO;AAC3B,UAAM,KAAK,SAAS,OAAO;AAC3B,UAAM,KAAK,QAAQ,MAAM;AACzB,UAAM,KAAK,SAAS,MAAM;AAC1B,WAAO,GAAG,QAAQ,MAAM;AACxB,WAAO,KAAK,OAAO,KAAK;AACxB,WAAO,KAAK,SAAS,OAAO;AAC5B,WAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,EAC1D,CAAC;AACH;;;AF/EA,IAAM,qCAA+D;AAAA,EACnE,QAAAC;AAAA,EACA;AAAA,EACA,cAAc;AAAA,EACd,IAAI,CAAC,MAAM,YAAYC,IAAG,MAAM,OAAO;AAAA,EACvC,OAAO,CAAC,OAAO,SAAS,MAAM,OAAO,IAAI;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AACT;AAEA,IAAI,2BAA2B;AAa/B,IAAM,uBAAuB,oBAAI,QAAqC;AAEtE,SAAS,qBAAqB,SAA6D;AACzF,SAAO,EAAE,GAAG,SAAS,gBAAgB,CAAC,GAAG,QAAQ,cAAc,EAAE;AACnE;AAEA,SAAS,yBAAmD;AAC1D,SAAO;AAAA,IACL,UAAU,UAAU,iBAAiB,MAAM,IAAI,CAAC,IAAI,MAAM,cAAc;AAAA,IACxE,MAAM,MAAM;AAAA,IACZ,MAAM,MAAM;AAAA,IACZ,gBAAgB,MAAM;AAAA,IACtB,gBAAgB,MAAM;AAAA,IACtB,mBAAmB,MAAM;AAAA,IACzB,GAAI,MAAM,oBAAoB,EAAE,gBAAgB,MAAM,kBAAkB,IAAI,CAAC;AAAA,IAC7E,gBAAgB,CAAC,GAAG,MAAM,cAAc;AAAA,IACxC,gBAAgB,MAAM;AAAA,IACtB,kBAAkB,MAAM;AAAA,IACxB,sBAAsB,MAAM;AAAA,IAC5B,sBAAsB,MAAM;AAAA,EAC9B;AACF;AAEA,SAAS,oBAAoB,OAAe;AAC1C,QAAM,WAAW,qBAAqB,IAAI,KAAK;AAC/C,MAAI,SAAU,QAAO;AACrB,QAAM,UAAU,uBAAuB;AACvC,QAAM,UAA+B;AAAA,IACnC;AAAA,IACA,YAAY,IAAI,gBAAgB;AAAA,IAChC,YAAY;AAAA,IACZ,MAAM,QAAQ;AAAA,EAChB;AACA,uBAAqB,IAAI,OAAO,OAAO;AACvC,SAAO;AACT;AAEO,SAAS,2BAA2B,OAAe;AACxD,QAAM,QAAQ,oBAAoB,KAAK;AACvC,QAAM,WAAW,MAAM,IAAI,aAAa,oCAAoC,YAAY,CAAC;AACzF,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,cAAc;AACpB,QAAM,oBAAoB;AAC5B;AAEO,SAAS,2BAA2B,OAAe,SAAmC;AAC3F,QAAM,QAAQ,oBAAoB,KAAK;AACvC,QAAM,UAAU,qBAAqB,OAAO;AAC5C,QAAM,OAAO,QAAQ;AACvB;AAEO,SAAS,wBAAwB,OAAgB;AACtD,SAAO,QAAQ,oBAAoB,KAAK,EAAE,UAAU,uBAAuB;AAC7E;AAEO,SAAS,6BAA6B,OAAgB;AAC3D,SAAO,wBAAwB,KAAK,EAAE;AACxC;AAMO,SAAS,uBAAuB,OAAgB;AACrD,MAAI,CAAC,MAAO,QAAO,MAAM;AACzB,QAAM,gBAAgB,oBAAoB,KAAK,EAAE;AACjD,MAAI,cAAe,QAAO;AAC1B,SAAO,MAAM,gBAAgB,iBAAiB,QAAQ,MAAM,iBAAiB;AAC/E;AAEA,SAAS,kBAAkB,OAA2B,SAAqC;AACzF,MAAI,MAAO,qBAAoB,KAAK,EAAE,iBAAiB;AAAA,MAClD,OAAM,iBAAiB;AAC9B;AAEA,SAAS,sBAAsB,OAAgB;AAC7C,SAAO,QAAQ,oBAAoB,KAAK,EAAE,gBAAgB,MAAM;AAClE;AAEA,SAAS,4BAA4B,OAAgB;AACnD,SAAO,QAAQ,oBAAoB,KAAK,EAAE,sBAAsB,MAAM;AACxE;AAEA,SAAS,iBAAiB,OAA2B,eAA0C;AAC7F,QAAM,QAAQ,QAAQ,oBAAoB,KAAK,IAAI;AACnD,QAAM,gBAAgB;AAEtB,MAAI,cAAe,OAAM,sBAAsB;AACjD;AAEA,SAAS,mBAAmB,OAAgB;AAC1C,SAAO,QAAQ,oBAAoB,KAAK,EAAE,OAAO,MAAM;AACzD;AAEA,SAAS,6BAA6B,OAAgB;AACpD,SAAO,wBAAwB,KAAK,EAAE;AACxC;AAEA,SAAS,6BAA6B,OAAgB;AACpD,SAAO,wBAAwB,KAAK,EAAE;AACxC;AAEA,SAAS,sBAAsB,OAA2B,MAAc;AACtE,MAAI,MAAO,qBAAoB,KAAK,EAAE,OAAO;AAAA,MACxC,OAAM,OAAO;AACpB;AAEA,SAAS,kBAAkB,OAAgB;AACzC,SAAO,QAAQ,oBAAoB,KAAK,EAAE,oBAAoB,MAAM;AACtE;AAEA,SAAS,qBAAqB,OAA2B,SAA2C;AAClG,MAAI,MAAO,qBAAoB,KAAK,EAAE,oBAAoB;AAAA,MACrD,OAAM,oBAAoB;AACjC;AAUA,SAASC,aAAY,OAAgB;AACnC,SAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D;AAEA,eAAsB,uBACpB,SAAS,0BACT,cACA,OACA;AACA,gBAAc,eAAe;AAC7B,MAAI,qBAAqB,KAAK,GAAG;AAC/B,gCAA4B,KAAK;AACjC,UAAM,6BAA6B,QAAQ,cAAc,KAAK;AAC9D;AAAA,EACF;AACA,QAAM,gBAAgB,sBAAsB,KAAK;AACjD,MAAI,eAAe;AACjB,UAAM,cAAc,eAAe,YAAY;AAC/C;AAAA,EACF;AACA,MAAI,qBAAqB,KAAK,GAAG;AAC/B,UAAM,oBAAoB,4BAA4B,KAAK;AAC3D,QAAI;AACF,YAAM;AAAA,QACJ,MAAM,kBAA2B,iBAAiB,EAAE,QAAQ,aAAa,GAAG,KAAK;AAAA,QACjF;AAAA,QACA;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AACd,UAAI,mCAAmC,OAAO,KAAK,GAAG;AACpD,cAAM,6BAA6B,QAAQ,cAAc,KAAK;AAC9D;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAGA,QAAI,iBAAiB;AACrB,WAAO,MAAM;AACX,YAAM,mBAAmB,4BAA4B,KAAK;AAC1D,UAAI,CAAC,oBAAoB,qBAAqB,eAAgB;AAC9D,uBAAiB;AACjB,YAAM,cAAc,kBAAkB,YAAY;AAAA,IACpD;AACA;AAAA,EACF;AAEA,MAAI;AACF,UAAM,kBAA2B,iBAAiB,EAAE,QAAQ,aAAa,GAAG,KAAK;AAAA,EACnF,SAAS,OAAO;AACd,QAAI,yBAAyB,KAAK,EAAG;AACrC,UAAM;AAAA,EACR;AACF;AAEA,SAAS,4BAA4B,OAAgB;AACnD,QAAM,UAAU,wBAAwB,KAAK;AAC7C,MAAI,CAAC,oBAAoB,QAAQ,IAAI,GAAG;AACtC,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,MAAI,CAAC,QAAQ,mBAAmB;AAC9B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,MAAI,CAAC,QAAQ,gBAAgB;AAC3B,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAe,6BAA6B,QAAgB,cAA4B,OAAgB;AACtG,QAAM,iBAAiB,sBAAsB,KAAK;AAClD,MAAI,gBAAgB;AAClB,UAAM,cAAc,gBAAgB,YAAY;AAChD;AAAA,EACF;AACA,QAAM,kBAAkB,uBAAuB,KAAK;AACpD,MAAI,mBAAmB,CAAC,gBAAgB,UAAU,gBAAgB,MAAO;AACzE,QAAM,aAAa,QAAQ,oBAAoB,KAAK,EAAE,aAAa,MAAM;AACzE,QAAM,SAAS,QAAQ,oBAAoB,KAAK,EAAE,WAAW,SAAS,MAAM,kBAAkB;AAC9F,gCAA8B,YAAY,QAAQ,KAAK;AAEvD,QAAM,gBAAgB,4BAA4B,QAAQ,YAAY,QAAQ,KAAK;AACnF,QAAM,iBAAiB,cAAc,QAAQ,MAAM;AACjD,QAAI,sBAAsB,KAAK,MAAM,eAAgB,kBAAiB,OAAO,MAAS;AAAA,EACxF,CAAC;AACD,mBAAiB,OAAO,cAAc;AACtC,QAAM,cAAc,gBAAgB,YAAY;AAClD;AAEA,SAAS,cAAiB,WAAuB,QAAsB;AACrE,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,eAAe;AACtB,SAAO,IAAI,QAAW,CAACC,UAAS,WAAW;AACzC,QAAI,UAAU;AACd,UAAM,UAAU,MAAM,OAAO,MAAM,OAAO,OAAO,MAAM,CAAC;AACxD,UAAM,SAAS,CAAC,aAAyB;AACvC,UAAI,QAAS;AACb,gBAAU;AACV,aAAO,oBAAoB,SAAS,OAAO;AAC3C,eAAS;AAAA,IACX;AACA,WAAO,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AACxD,cAAU;AAAA,MACR,CAAC,UAAU,OAAO,MAAMA,SAAQ,KAAK,CAAC;AAAA,MACtC,CAAC,UAAU,OAAO,MAAM,OAAO,KAAK,CAAC;AAAA,IACvC;AAAA,EACF,CAAC;AACH;AAEA,eAAe,4BAA4B,QAAgB,YAAoB,QAAqB,OAAgB;AAClH,QAAM,kBAAkB,uBAAuB,KAAK;AACpD,MAAI,iBAAiB;AACnB,UAAM,uBAAuB,iBAAiB,EAAE,aAAa,OAAO,MAAM,CAAC;AAC3E,kCAA8B,YAAY,QAAQ,KAAK;AAAA,EACzD;AACA,MAAI,6BAA6B,KAAK,GAAG;AACvC,UAAM,YAAY,MAAM,yBAAyB;AAAA,MAC/C,wBAAwB,KAAK,EAAE;AAAA,MAC/B,mBAAmB,KAAK;AAAA,IAC1B;AACA,kCAA8B,YAAY,QAAQ,KAAK;AACvD,QAAI,CAAC,WAAW;AACd,YAAM,IAAI;AAAA,QACR,mEAAmE,mBAAmB,KAAK,CAAC;AAAA,MAC9F;AAAA,IACF;AAAA,EACF;AACA,SAAO,qBAAqB,QAAQ,YAAY,QAAQ,KAAK;AAC/D;AAEA,eAAe,qBAAqB,QAAgB,YAAoB,QAAqB,OAAgB;AAC3G,gCAA8B,YAAY,QAAQ,KAAK;AACvD,QAAM,uBAAuB,4BAA4B,wBAAwB,KAAK,CAAC;AACvF,QAAM,aAAa,MAAM;AAAA,IAAyB;AAAA,IAAsB,yBAAyB;AAAA,IAAQ,MACvG,8BAA8B,YAAY,QAAQ,KAAK;AAAA,EACzD;AACA,gCAA8B,YAAY,QAAQ,KAAK;AACvD,uBAAqB,OAAO;AAAA,IAC1B,iBAAiB,qBAAqB,IAAI,gCAAgC;AAAA,IAC1E,MAAM,6BAA6B,KAAK,IAAI,kBAAkB;AAAA,EAChE,CAAC;AAED,MAAI,WAAW,WAAW,GAAG;AAC3B,UAAM,IAAI,sBAAsB,0BAA0B,sBAAsB,KAAK,CAAC;AAAA,EACxF;AAEA,MAAI;AACJ,aAAW,aAAa,YAAY;AAClC,kCAA8B,YAAY,QAAQ,KAAK;AACvD,QAAI;AACF,UAAI,qBAAqB,KAAK,EAAG,OAAM,iCAAiC,WAAW,YAAY,QAAQ,KAAK;AAC5G,YAAM,uBAAuB,WAAW,QAAQ,YAAY,QAAQ,KAAK;AACzE,oCAA8B,YAAY,QAAQ,KAAK;AACvD,2BAAqB,OAAO;AAAA,QAC1B,GAAG,kBAAkB,KAAK;AAAA,QAC1B,iBAAiB,qBAAqB,IAAI,gCAAgC;AAAA,QAC1E,MAAM,6BAA6B,KAAK,IAAI,kBAAkB;AAAA,QAC9D,mBAAmB,uBAAuB,SAAS;AAAA,QACnD,aAAa,uBAAuB,KAAK,GAAG;AAAA,MAC9C,CAAC;AACD;AAAA,IACF,SAAS,OAAO;AACd,UAAI;AACF,sCAA8B,YAAY,QAAQ,KAAK;AAAA,MACzD,SAAS,cAAc;AACrB,6BAAqB,OAAO;AAAA,UAC1B,GAAI,kBAAkB,KAAK,KAAK;AAAA,YAC9B,iBAAiB,qBAAqB,IAAI,gCAAgC;AAAA,YAC1E,MAAM,6BAA6B,KAAK,IAAI,kBAAkB;AAAA,UAChE;AAAA,UACA,WAAWD,aAAY,YAAY;AAAA,QACrC,CAAC;AACD,cAAM;AAAA,MACR;AACA,kBAAY;AACZ,2BAAqB,OAAO;AAAA,QAC1B,GAAI,kBAAkB,KAAK,KAAK;AAAA,UAC9B,iBAAiB,qBAAqB,IAAI,gCAAgC;AAAA,UAC1E,MAAM,6BAA6B,KAAK,IAAI,kBAAkB;AAAA,QAChE;AAAA,QACA,WAAWA,aAAY,KAAK;AAAA,MAC9B,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,qBAAqB,yBAAyB,qBAAqB,KAAK,EAAG,OAAM;AACrF,QAAM,IAAI;AAAA,IACR;AAAA,MACE;AAAA,MACA,UAAU,WAAW,IAAI,sBAAsB,EAAE,KAAK,IAAI,CAAC;AAAA,MAC3D,YAAY,eAAeA,aAAY,SAAS,CAAC,KAAK;AAAA,MACtD,WAAW,KAAK;AAAA,MAChB,mBAAmB;AAAA,IACrB,EACG,OAAO,OAAO,EACd,KAAK,IAAI;AAAA,EACd;AACF;AAEA,eAAe,iCACb,WACA,YACA,QACA,OACA;AACA,MAAI;AACJ,MAAI;AACF,eAAW,MAAM,yBAAyB,sBAAsB,UAAU,oBAAoB,MAAM,GAAG,KAAK;AAAA,EAC9G,SAAS,OAAO;AACd,kCAA8B,YAAY,QAAQ,KAAK;AACvD,UAAM,IAAI;AAAA,MACR,uDAAuD,UAAU,kBAAkB,KAAKA,aAAY,KAAK,CAAC;AAAA,IAC5G;AAAA,EACF;AACA,gCAA8B,YAAY,QAAQ,KAAK;AACvD,QAAM,iBAAiB,gCAAgC,OAAO;AAC9D,MAAI,CAAC,eAAe,WAAW;AAC7B,UAAM,IAAI;AAAA,MACR,gDAAgD,WAAW,iBAAiB;AAAA,IAC9E;AAAA,EACF;AACF;AAEO,SAAS,gCAAgC,SAG9C;AACA,MAAI,qCAAqC,KAAK,OAAO,GAAG;AACtD,WAAO,EAAE,WAAW,MAAM,SAAS,qBAAqB;AAAA,EAC1D;AACA,MAAI,eAAe,KAAK,OAAO,EAAG,QAAO,EAAE,WAAW,MAAM,SAAS,WAAW;AAChF,QAAM,UAAU,QAAQ,KAAK,EAAE,QAAQ,uBAAuB,EAAE,KAAK;AACrE,SAAO,EAAE,WAAW,OAAO,QAAQ;AACrC;AAEA,eAAe,uBACb,WACA,QACA,YACA,QACA,OACA;AACA,gCAA8B,YAAY,QAAQ,KAAK;AACvD,QAAM,cAAc,MAAM,yBAAyB,QAAQE,MAAK,OAAO,GAAG,8BAA8B,CAAC;AACzG,MAAI;AACJ,MAAI;AACF,kCAA8B,YAAY,QAAQ,KAAK;AACvD,UAAM,OAAO,6BAA6B,KAAK,IAC3C,mBAAmB,KAAK,IACxB,MAAM,yBAAyB,aAAa,wBAAwB,KAAK,EAAE,IAAI;AACnF,kCAA8B,YAAY,QAAQ,KAAK;AACvD,QAAI,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAAK,OAAO,OAAO;AACvD,YAAM,IAAI,sBAAsB,gEAAgE;AAAA,IAClG;AACA,UAAM,OAAO,mCAAmC,aAAa,OAAO,IAAI,GAAG,6BAA6B,KAAK,CAAC;AAC9G,UAAM,QAAQ,yBAAyB,MAAM,UAAU,oBAAoB,MAAM;AAAA,MAC/E,OAAO;AAAA,MACP,OAAO,CAAC,UAAU,UAAU,MAAM;AAAA,IACpC,CAAC;AACD,UAAM,kBAAkC;AAAA,MACtC,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,iBAAiB;AAAA,MACjB,GAAI,QAAQ,EAAE,cAAc,MAAM,IAAI,CAAC;AAAA,IACzC;AACA,qBAAiB;AACjB,sBAAkB,OAAO,eAAe;AAExC,UAAM,KAAK,QAAQ,MAAM;AACvB,UAAI,uBAAuB,KAAK,MAAM,mBAAmB,OAAO;AAC9D,mCAA2B,OAAO,wCAAwC;AAAA,MAC5E;AACA,sBAAgB,SAAS;AACzB,sBAAgB,QAAQ;AACxB,UAAI,CAAC,6BAA6B,KAAK,KAAK,gBAAgB,SAAS,mBAAmB,KAAK,GAAG;AAC9F,8BAAsB,OAAO,6BAA6B,KAAK,CAAC;AAAA,MAClE;AAAA,IACF,CAAC;AAED,UAAM,kBAAkB,MAAM,sBAAsB,OAAO,MAAM,QAAQ,MAAM;AAC/E,kCAA8B,YAAY,QAAQ,KAAK;AACvD,0BAAsB,OAAO,IAAI;AACjC,UAAM,wBAAwB,QAAQ,iBAAiB,iBAAiB,YAAY,QAAQ,KAAK;AACjG,kCAA8B,YAAY,QAAQ,KAAK;AACvD,gCAA4B,eAAe;AAC3C,oBAAgB,QAAQ;AAAA,EAC1B,SAAS,OAAO;AACd,QAAI,eAAgB,OAAM,uBAAuB,gBAAgB,EAAE,aAAa,OAAO,MAAM,CAAC;AAAA,SACzF;AACH,YAAM,yBAAyB,GAAG,aAAa,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC,EAAE,MAAM,MAAM,MAAS;AAAA,IACxG;AACA,UAAM;AAAA,EACR;AACF;AAEO,SAAS,mCACd,aACA,cACA,gBACA;AACA,QAAM,gBAAgB,eAAe,KAAK,GAAG;AAC7C,SAAO;AAAA,IACL,2BAA2B,YAAY;AAAA,IACvC,mBAAmB,WAAW;AAAA,IAC9B,GAAI,eAAe,SAAS,IACxB,CAAC,+BAA+B,aAAa,IAAI,oBAAoB,aAAa,EAAE,IACpF,CAAC;AAAA;AAAA;AAAA;AAAA,IAIL,GAAI,QAAQ,aAAa,UAAU,CAAC,qBAAqB,IAAI,CAAC;AAAA,IAC9D;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAe,wBACb,QACA,gBACA,iBACA,YACA,QACA,OACA;AACA,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,SAAO,MAAM;AACX,gCAA4B,cAAc;AAC1C,QAAI;AACF,YAAM,UAAU,MAAM;AAAA,QACpB;AAAA,QACA,EAAE,OAAO;AAAA,QACT;AAAA,MACF;AACA,oCAA8B,YAAY,QAAQ,KAAK;AACvD,kCAA4B,cAAc;AAC1C,UAAI,yBAAyB,SAAS,sBAAsB,eAAe,QAAQ,CAAC,MAAM,iBAAiB;AACzG,cAAM,IAAI,sBAAsB,6DAA6D;AAAA,MAC/F;AACA;AAAA,IACF,SAAS,OAAO;AACd,UAAI,CAAC,yBAAyB,KAAK,EAAG,OAAM;AAAA,IAC9C;AAEA,kCAA8B,YAAY,QAAQ,KAAK;AACvD,UAAM,cAAc,WAAW,KAAK,IAAI;AACxC,QAAI,eAAe,GAAG;AACpB,YAAM,IAAI;AAAA,QACR,CAAC,kDAAkD,iBAAiB,KAAK,CAAC,KAAK,WAAW,KAAK,CAAC,EAAE,KAAK,IAAI;AAAA,MAC7G;AAAA,IACF;AACA,UAAM,yBAAyB,MAAM,KAAK,IAAI,2BAA2B,WAAW,GAAG,MAAM;AAAA,EAC/F;AACF;AAEA,SAAS,4BAA4B,gBAAgC;AACnE,MAAI,CAAC,eAAe,OAAQ;AAC5B,QAAM,IAAI,sBAAsB,gEAAgE;AAClG;AAEA,SAAS,8BAA8B,YAAoB,QAAqB,OAAgB;AAC9F,QAAM,oBAAoB,QAAQ,oBAAoB,KAAK,EAAE,aAAa,MAAM;AAChF,QAAM,eAAe,QAAQ,OAAO,UAAU,MAAM;AACpD,MAAI,CAAC,gBAAgB,eAAe,qBAAqB,CAAC,OAAO,QAAS;AAC1E,QAAM,IAAI;AAAA,IACR,eAAe,oBACX,8DACA;AAAA,EACN;AACF;AAEA,eAAsB,uBACpB,gBACA,UAA6E,CAAC,GAC9E;AACA,QAAM,QAAQ,QAAQ,SAAS,gBAAgB;AAC/C,MAAI,QAAQ,cAAc;AACxB,QAAI,OAAO;AACT,YAAM,QAAQ,oBAAoB,KAAK;AACvC,YAAM,WAAW;AAAA,QACf,IAAI,aAAa,4DAA4D,YAAY;AAAA,MAC3F;AACA,YAAM,cAAc;AAAA,IACtB,OAAO;AACL,YAAM,eAAe;AAAA,IACvB;AAAA,EACF;AACA,qBAAmB,uBAAuB,KAAK;AAC/C,MAAI,QAAQ,gBAAgB,OAAO;AACjC,UAAM,sBAAsB,KAAK,GAAG,MAAM,MAAM,MAAS;AACzD,uBAAmB,uBAAuB,KAAK;AAAA,EACjD;AACA,MAAI,CAAC,eAAgB;AACrB,MAAI,eAAe,eAAgB,QAAO,eAAe;AAEzD,QAAM,UAAU,sBAAsB,gBAAgB,KAAK;AAC3D,iBAAe,iBAAiB;AAChC,SAAO;AACT;AAEA,eAAe,sBAAsB,gBAAgC,OAAgB;AACnF,MAAI,uBAAuB,KAAK,MAAM,gBAAgB;AACpD,QAAI,MAAO,4BAA2B,OAAO,wCAAwC;AACrF,QAAI,MAAM,mBAAmB,eAAgB,OAAM,iBAAiB;AAAA,QAC/D,mBAAkB,OAAO,MAAS;AAAA,EACzC;AACA,MAAI,CAAC,eAAe,QAAQ;AAC1B,8BAA0B,cAAc;AACxC,UAAM,0BAA0B,gBAAgB,wBAAwB,EAAE,MAAM,YAAY;AAC1F,gCAA0B,gBAAgB,SAAS;AACnD,YAAM,0BAA0B,gBAAgB,wBAAwB,EAAE,MAAM,MAAM,MAAS;AAAA,IACjG,CAAC;AAAA,EACH;AACA,QAAM,yBACH,GAAG,eAAe,aAAa,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC,EAC/D,MAAM,MAAM,MAAS;AACxB,MAAI,CAAC,6BAA6B,KAAK,KAAK,eAAe,SAAS,mBAAmB,KAAK,GAAG;AAC7F,0BAAsB,OAAO,6BAA6B,KAAK,CAAC;AAAA,EAClE;AACF;AAEA,SAAS,0BAA0B,gBAAgC,QAAyB;AAC1F,MAAI;AACF,mBAAe,QAAQ,KAAK,MAAM;AAAA,EACpC,QAAQ;AAAA,EAER;AACF;AAEA,SAAS,0BAA0B,gBAAgC,QAAgB;AACjF,MAAI,eAAe,OAAQ,QAAO,QAAQ,QAAQ;AAClD,SAAO,IAAI,QAAc,CAACD,UAAS,WAAW;AAC5C,UAAM,SAAS,CAAC,aAAyB;AACvC,mBAAa,OAAO;AACpB,qBAAe,QAAQ,IAAI,QAAQ,aAAa;AAChD,qBAAe,QAAQ,IAAI,SAAS,aAAa;AACjD,eAAS;AAAA,IACX;AACA,UAAM,gBAAgB,MAAM;AAC1B,qBAAe,SAAS;AACxB,aAAOA,QAAO;AAAA,IAChB;AACA,UAAM,UAAU;AAAA,MACd,MAAM,OAAO,MAAM,OAAO,IAAI,MAAM,yCAAyC,CAAC,CAAC;AAAA,MAC/E;AAAA,IACF;AACA,mBAAe,QAAQ,KAAK,QAAQ,aAAa;AACjD,mBAAe,QAAQ,KAAK,SAAS,aAAa;AAAA,EACpD,CAAC;AACH;AAEA,eAAsB,kBAAqB,MAAc,MAAoB,OAAgB;AAC3F,QAAM,MAAM,GAAG,iBAAiB,KAAK,CAAC,GAAG,IAAI;AAC7C,MAAI;AACJ,MAAI;AACF,UAAM,gBAAgB,YAAY,QAAQ,uBAAuB;AACjE,eAAW,MAAM,yBAAyB,MAAM,KAAK;AAAA,MACnD,GAAG;AAAA,MACH,QAAQ,MAAM,SAAS,YAAY,IAAI,CAAC,KAAK,QAAQ,aAAa,CAAC,IAAI;AAAA,IACzE,CAAC;AAAA,EACH,SAAS,OAAO;AACd,UAAM,IAAI,sBAAsB,+BAA+B,OAAO,KAAK,GAAG;AAAA,MAC5E,YAAY;AAAA,MACZ,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAEA,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,QAAQ,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,EAAE,GAAG,KAAK;AAC1D,UAAM,SAAS,OAAO,KAAK,KAAK,MAAM,GAAG,GAAG,CAAC,KAAK;AAClD,UAAM,IAAI;AAAA,MACR;AAAA,QACE,4BAA4B,GAAG,aAAa,SAAS,MAAM,IAAI,SAAS,UAAU,GAAG,MAAM;AAAA,QAC3F,mBAAmB;AAAA,MACrB,EAAE,KAAK,IAAI;AAAA,MACX,EAAE,WAAW,SAAS,WAAW,OAAO,SAAS,UAAU,IAAI;AAAA,IACjE;AAAA,EACF;AAEA,MAAI;AACF,WAAQ,MAAM,SAAS,KAAK;AAAA,EAC9B,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR,CAAC,4BAA4B,GAAG,2BAA2BD,aAAY,KAAK,CAAC,KAAK,mBAAmB,CAAC,EAAE;AAAA,QACtG;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,kBAAqB,WAA6B,QAAgB,QAAsB;AAC5G,QAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,SAAO,MAAM;AACX,YAAQ,eAAe;AACvB,QAAI;AACF,aAAO,MAAM,UAAU;AAAA,IACzB,SAAS,OAAO;AACd,UAAI,CAAC,yBAAyB,KAAK,EAAG,OAAM;AAE5C,YAAM,cAAc,WAAW,KAAK,IAAI;AACxC,UAAI,eAAe,EAAG,OAAM;AAE5B,YAAM,yBAAyB,MAAM,KAAK,IAAI,2BAA2B,WAAW,GAAG,MAAM;AAAA,IAC/F;AAAA,EACF;AACF;AAEA,SAAS,yBAAyB,OAAgB;AAChD,SAAO,iBAAiB,yBAAyB,MAAM;AACzD;AAEA,SAAS,0BAA0B,OAAgB;AACjD,SAAO,iBAAiB,yBAAyB,MAAM;AACzD;AAEA,SAAS,mCAAmC,OAAgB,OAAgB;AAC1E,MAAI,CAAC,qBAAqB,KAAK,EAAG,QAAO;AACzC,MAAI,0BAA0B,KAAK,EAAG,QAAO;AAI7C,SAAO,CAAC,6BAA6B,KAAK,KAAK,iBAAiB;AAClE;AAEA,SAAS,qBAAqB,OAAgB;AAC5C,QAAM,UAAU,wBAAwB,KAAK;AAC7C,SAAO,QAAQ,qBAAqB,oBAAoB,QAAQ,IAAI;AACtE;AAEA,SAAS,qBAAqB,OAAgB;AAC5C,SAAO,6BAA6B,KAAK,EAAE,SAAS;AACtD;AAEA,SAAS,+BAA+B,OAAgB,OAAgB;AACtE,QAAM,SAAS,eAAe,KAAK,IAAI,sBAAsB;AAC7D,SAAO;AAAA,IACL,iDAAiD,iBAAiB,KAAK,CAAC,KAAK,MAAM;AAAA,IACnF,WAAW,KAAK;AAAA,IAChB,mBAAmB;AAAA,EACrB,EAAE,KAAK,IAAI;AACb;AAEA,SAAS,eAAe,OAAgB;AACtC,SAAO,iBAAiB,SAAS,CAAC,cAAc,cAAc,EAAE,SAAS,MAAM,IAAI;AACrF;AAEO,SAAS,iBAAiB,OAAgB;AAC/C,SAAO,UAAU,iBAAiB,wBAAwB,KAAK,EAAE,IAAI,CAAC,IAAI,mBAAmB,KAAK,CAAC;AACrG;AAEO,SAAS,iBAAiB,MAAc;AAC7C,MAAI,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,GAAG,EAAG,QAAO;AACvD,SAAO,KAAK,SAAS,GAAG,IAAI,IAAI,IAAI,MAAM;AAC5C;AAEO,SAAS,oBAAoB,OAAgB;AAClD,SAAO,wBAAwB,KAAK,EAAE;AACxC;AAIO,SAAS,sBAAsB,OAAuC;AAC3E,MAAI,sBAAsB,KAAK,EAAG,QAAO;AACzC,MAAI,uBAAuB,KAAK,GAAG,OAAQ,QAAO;AAClD,MAAI,uBAAuB,KAAK,GAAG,MAAO,QAAO;AACjD,MAAI,kBAAkB,KAAK,GAAG,UAAW,QAAO;AAChD,SAAO;AACT;AAEO,SAAS,gBAAgB,OAAgB;AAC9C,QAAM,UAAU,wBAAwB,KAAK;AAC7C,QAAM,iBAAiB,uBAAuB,KAAK;AACnD,MAAI,qBAAqB,KAAK,GAAG;AAC/B,QAAI,CAAC,oBAAoB,QAAQ,IAAI,EAAG,QAAO;AAC/C,QAAI,CAAC,QAAQ,kBAAmB,QAAO;AACvC,QAAI,kBAAkB,CAAC,eAAe,QAAQ;AAC5C,aAAO,6BAA6B,KAAK,IACrC,6CACA;AAAA,IACN;AACA,WAAO,6BAA6B,KAAK,IACrC,kDACA;AAAA,EACN;AACA,MAAI,CAAC,oBAAoB,QAAQ,IAAI,EAAG,QAAO;AAC/C,MAAI,CAAC,QAAQ,kBAAmB,QAAO;AACvC,MAAI,kBAAkB,CAAC,eAAe,QAAQ;AAC5C,WAAO,6BAA6B,KAAK,IACrC,mCACA;AAAA,EACN;AACA,SAAO,6BAA6B,KAAK,IACrC,4CACA;AACN;AAEO,SAAS,mBAAmB,OAAgB;AACjD,QAAM,UAAU,kBAAkB,KAAK;AACvC,MAAI,CAAC,QAAS,QAAO,CAAC;AAEtB,QAAM,QAAQ,CAAC,wBAAwB,QAAQ,IAAI,EAAE;AACrD,MAAI,QAAQ,mBAAmB;AAC7B,UAAM,KAAK,qBAAqB,QAAQ,iBAAiB,EAAE;AAAA,EAC7D,OAAO;AACL,UAAM,KAAK,6BAA6B,QAAQ,gBAAgB,KAAK,IAAI,CAAC,EAAE;AAAA,EAC9E;AACA,MAAI,QAAQ,YAAa,OAAM,KAAK,4BAA4B,QAAQ,WAAW,EAAE;AACrF,MAAI,QAAQ,UAAW,OAAM,KAAK,sBAAsB,QAAQ,SAAS,EAAE;AAC3E,SAAO;AACT;AAEO,SAAS,WAAW,OAAgB;AACzC,QAAM,UAAU,wBAAwB,KAAK;AAC7C,MAAI,qBAAqB,KAAK,GAAG;AAC/B,WAAO;AAAA,EACT;AACA,MAAI,CAAC,oBAAoB,QAAQ,IAAI,GAAG;AACtC,WAAO,yFAAyF,iBAAiB,KAAK,CAAC;AAAA,EACzH;AACA,MAAI,CAAC,QAAQ,mBAAmB;AAC9B,WAAO,sDAAsD,oBAAoB,KAAK,CAAC;AAAA,EACzF;AACA,QAAM,cAAc,6BAA6B,KAAK,IAClD,QAAQ,mBAAmB,KAAK,CAAC,KACjC;AACJ,SAAO,mFAAmF,WAAW,kDAAkD,oBAAoB,KAAK,CAAC;AACnL;AAEO,SAAS,qBAAqB,OAAgB;AACnD,MAAI,qBAAqB,KAAK,GAAG;AAC/B,WAAO;AAAA,EACT;AACA,SAAO,uBAAuB,4BAA4B,wBAAwB,KAAK,CAAC,EACrF,IAAI,CAAC,cAAc,UAAU,KAAK,EAClC,KAAK,IAAI,CAAC;AACf;AAEO,SAAS,oBAAoB,OAAgB;AAClD,QAAM,aAAa,wBAAwB,KAAK,EAAE,kBAAkB,+BAA+B;AACnG,QAAM,UAAU,QAAQ,aAAa,UAAU,+BAA+B;AAC9E,SAAO,GAAG,iBAAiB,UAAU,CAAC,4BAA4B,mBAAmB,KAAK,CAAC,oBAAoB,OAAO;AACxH;AAEA,SAAS,iCAAiC;AACxC,SAAO,QAAQ,aAAa,WACxB,iEACA,QAAQ,aAAa,UACnB,eACA;AACR;AAEO,SAAS,iBAAiB,OAAe;AAC9C,SAAO,KAAK,KAAK,KAAK,IAAI,IAAI,MAAM,WAAW,KAAK,KAAK,CAAC,MAAM;AAClE;AAEO,SAAS,qBAAqB;AACnC,SAAO;AACT;AAEO,SAAS,oBAAoB,MAAc;AAChD,QAAM,iBAAiB,KAAK,YAAY,EAAE,QAAQ,aAAa,IAAI;AACnE,SAAO,CAAC,aAAa,aAAa,OAAO,iBAAiB,EAAE,SAAS,cAAc;AACrF;AAEA,SAAS,uBAAuB,WAA6B;AAC3D,SAAO,GAAG,UAAU,KAAK,KAAK,UAAU,kBAAkB;AAC5D;AAEA,SAAS,iCAAiC,WAAuC;AAC/E,SAAO,GAAG,UAAU,KAAK,KAAK,UAAU,UAAU;AACpD;AAEA,SAAS,0BAA0B,sBAAoD,OAAgB;AACrG,MAAI,qBAAqB,KAAK,GAAG;AAC/B,WAAO;AAAA,MACL;AAAA,MACA,UAAU,qBAAqB,IAAI,gCAAgC,EAAE,KAAK,IAAI,CAAC;AAAA,MAC/E;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AACA,SAAO;AAAA,IACL;AAAA,IACA,UAAU,qBAAqB,IAAI,gCAAgC,EAAE,KAAK,IAAI,CAAC;AAAA,IAC/E,mBAAmB;AAAA,EACrB,EAAE,KAAK,IAAI;AACb;AAEO,SAAS,mBAAmB,MAAoB;AACrD,SAAO,KAAK,KAAK,EAAE,KAAK,KAAK,SAAS,YAAY,IAAI,KAAK,GAAG;AAChE;AAEA,SAAS,eAAe,IAAY,QAAsB;AACxD,SAAO,IAAI,QAAc,CAAC,cAAc,WAAW;AACjD,QAAI,QAAQ,SAAS;AACnB,aAAO,OAAO,MAAM;AACpB;AAAA,IACF;AACA,UAAM,UAAU,WAAW,eAAe,EAAE;AAC5C,UAAM,UAAU,MAAM,aAAa,QAAQ,MAAM;AACjD,aAAS,UAAU;AACjB,mBAAa,OAAO;AACpB,cAAQ,oBAAoB,SAAS,OAAO;AAAA,IAC9C;AACA,aAAS,gBAAgB;AACvB,cAAQ;AACR,mBAAa;AAAA,IACf;AACA,aAAS,aAAa,QAAiB;AACrC,cAAQ;AACR,aAAO,MAAM;AAAA,IACf;AACA,YAAQ,iBAAiB,SAAS,SAAS,EAAE,MAAM,KAAK,CAAC;AAAA,EAC3D,CAAC;AACH;AAEA,SAAS,sBAAsB,YAAoB,QAAqB;AACtE,SAAO,IAAI,QAAgB,CAAC,gBAAgB,WAAW;AACrD,aAAS,YAAY,CAAC,WAAW,GAAG,EAAE,QAAQ,SAAS,IAAM,GAAG,CAAC,OAAO,QAAQ,WAAW;AACzF,UAAI,OAAO;AACT,eAAO,KAAK;AACZ;AAAA,MACF;AACA,qBAAe,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;AAAA,IAC5C,CAAC;AAAA,EACH,CAAC;AACH;AAEA,eAAsB,oBAAoB,MAAc;AACtD,QAAM,OAAO,MAAM,iBAAiB,MAAM,CAAC;AAC3C,MAAI,SAAS,OAAW,OAAM,IAAI,MAAM,6CAA6C;AACrF,SAAO;AACT;AAEA,eAAe,gBAAgB,MAAc,MAAc;AACzD,SAAQ,MAAM,iBAAiB,MAAM,IAAI,MAAO;AAClD;AAIA,SAAS,iBAAiB,MAAc,MAAc;AACpD,SAAO,IAAI,QAA4B,CAAC,aAAa,WAAW;AAC9D,UAAM,SAAS,aAAa;AAC5B,UAAM,iBAAiB,KAAK,QAAQ,aAAa,IAAI;AACrD,WAAO,MAAM;AACb,WAAO,KAAK,SAAS,CAAC,UAAiC;AACrD,UAAI,MAAM,SAAS,aAAc,aAAY,MAAS;AAAA,UACjD,QAAO,KAAK;AAAA,IACnB,CAAC;AACD,WAAO,OAAO,MAAM,gBAAgB,MAAM;AACxC,YAAM,UAAU,OAAO,QAAQ;AAC/B,aAAO,MAAM,CAAC,UAAU;AACtB,YAAI,MAAO,QAAO,KAAK;AAAA,iBACd,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO,IAAI,MAAM,qCAAqC,CAAC;AAAA,YACpG,aAAY,QAAQ,IAAI;AAAA,MAC/B,CAAC;AAAA,IACH,CAAC;AAAA,EACH,CAAC;AACH;AAEA,IAAM,wBAAN,cAAoC,MAAM;AAAA,EAC/B;AAAA,EACA;AAAA,EAET,YAAY,SAAiB,UAAyD,CAAC,GAAG;AACxF,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,YAAY,QAAQ,aAAa;AACtC,SAAK,aAAa,QAAQ,cAAc;AAAA,EAC1C;AACF;",
6
+ "names": ["access", "rm", "join", "constants", "isAbsolute", "join", "resolve", "access", "resolve", "access", "rm", "formatError", "resolve", "join"]
7
+ }
@@ -6,7 +6,7 @@ import {
6
6
  buildCommandGuide,
7
7
  sanitizeChromeDevtoolsDisplay,
8
8
  setSelectedChromeDevtoolsTools
9
- } from "./chunk-WOFI2A72.ts";
9
+ } from "./chunk-JKPJYUVG.ts";
10
10
  import {
11
11
  CHROME_DEVTOOLS_TOOL_NAMES,
12
12
  CORE_CHROME_DEVTOOLS_TOOL_NAMES,
@@ -17,7 +17,7 @@ import {
17
17
  loadSettings,
18
18
  state,
19
19
  webMcpEnabled
20
- } from "./chunk-TVVYQ5KM.ts";
20
+ } from "./chunk-WTMZID3G.ts";
21
21
 
22
22
  // src/menu.ts
23
23
  import { defineMenu, runMenu, runTask } from "@narumitw/pi-tui-kit";
@@ -137,7 +137,7 @@ async function showChromeDevtoolsMenu(pi, ctx, generation) {
137
137
  return result?.closeParent ? { kind: "close" } : { kind: "stay" };
138
138
  },
139
139
  settings: async ({ state: current }) => {
140
- const { showChromeDevtoolsBrowserSettings } = await import("./browser-settings-menu-GQAXLWZ7.ts");
140
+ const { showChromeDevtoolsBrowserSettings } = await import("./browser-settings-menu-7M3VM7QN.ts");
141
141
  if (!isCurrent()) return { kind: "stay" };
142
142
  const result = await showChromeDevtoolsBrowserSettings(pi, ctx, generation);
143
143
  if (!isCurrent()) return { kind: "stay" };
@@ -415,4 +415,4 @@ export {
415
415
  showChromeDevtoolsMenu,
416
416
  showChromeDevtoolsToolWorkflow
417
417
  };
418
- //# sourceMappingURL=menu-Z26D6XSI.ts.map
418
+ //# sourceMappingURL=menu-HGG26E3X.ts.map
@@ -5,7 +5,7 @@ import {
5
5
  getPage,
6
6
  resolvePage,
7
7
  textResult
8
- } from "./chunk-5T2WEIYN.ts";
8
+ } from "./chunk-JLEJ6WFO.ts";
9
9
  import {
10
10
  DEFAULT_TIMEOUT_MS,
11
11
  beginWebMcpOperation,
@@ -15,7 +15,7 @@ import {
15
15
  webMcpEnabled,
16
16
  webMcpOperationIsCurrent,
17
17
  webMcpSessionSignal
18
- } from "./chunk-TVVYQ5KM.ts";
18
+ } from "./chunk-WTMZID3G.ts";
19
19
 
20
20
  // src/webmcp/policy.ts
21
21
  import { createHash } from "node:crypto";
@@ -919,4 +919,4 @@ export {
919
919
  executeWebMcpCallTool,
920
920
  executeWebMcpListTool
921
921
  };
922
- //# sourceMappingURL=tools-DSYQPFF3.ts.map
922
+ //# sourceMappingURL=tools-O5N4KIAK.ts.map
package/dist/index.ts CHANGED
@@ -9,7 +9,7 @@ import {
9
9
  setActivePageId,
10
10
  textResult,
11
11
  withCdp
12
- } from "./chunks/chunk-5T2WEIYN.ts";
12
+ } from "./chunks/chunk-JLEJ6WFO.ts";
13
13
  import {
14
14
  allChromeDevtoolsTools,
15
15
  availableChromeDevtoolsTools,
@@ -27,7 +27,7 @@ import {
27
27
  supportsNativeDeferredToolLoading,
28
28
  updateChromeDevtoolsTools,
29
29
  waitForChromeDevtoolsSettings
30
- } from "./chunks/chunk-WOFI2A72.ts";
30
+ } from "./chunks/chunk-JKPJYUVG.ts";
31
31
  import {
32
32
  CHROME_DEVTOOLS_TOOL_NAMES,
33
33
  WEBMCP_TOOL_NAMES,
@@ -42,7 +42,7 @@ import {
42
42
  syncManagedBrowserSettings,
43
43
  waitForSettingsWrites,
44
44
  webMcpEnabled
45
- } from "./chunks/chunk-TVVYQ5KM.ts";
45
+ } from "./chunks/chunk-WTMZID3G.ts";
46
46
 
47
47
  // src/tools.ts
48
48
  import { defineTool } from "@earendil-works/pi-coding-agent";
@@ -415,7 +415,7 @@ var webMcpListToolsTool = defineTool({
415
415
  renderResult: renderTextResult,
416
416
  async execute(_toolCallId, params, signal, _onUpdate, ctx) {
417
417
  return withStatus(ctx, "list WebMCP tools", async () => {
418
- const implementation = await import("./chunks/tools-DSYQPFF3.ts");
418
+ const implementation = await import("./chunks/tools-O5N4KIAK.ts");
419
419
  return implementation.executeWebMcpListTool(params, signal, ctx);
420
420
  });
421
421
  }
@@ -457,7 +457,7 @@ var webMcpCallTool = defineTool({
457
457
  renderResult: renderTextResult,
458
458
  async execute(_toolCallId, params, signal, _onUpdate, ctx) {
459
459
  return withStatus(ctx, "call WebMCP tool", async () => {
460
- const implementation = await import("./chunks/tools-DSYQPFF3.ts");
460
+ const implementation = await import("./chunks/tools-O5N4KIAK.ts");
461
461
  return implementation.executeWebMcpCallTool(params, signal, ctx);
462
462
  });
463
463
  }
@@ -663,7 +663,7 @@ async function handleChromeDevtoolsCommand(pi, args, ctx, generation) {
663
663
  if (!ctx.hasUI || ctx.mode !== "tui" && ctx.mode !== "rpc") {
664
664
  throw new Error("/chrome-devtools settings requires TUI or RPC mode");
665
665
  }
666
- const { showChromeDevtoolsBrowserSettings } = await import("./chunks/browser-settings-menu-GQAXLWZ7.ts");
666
+ const { showChromeDevtoolsBrowserSettings } = await import("./chunks/browser-settings-menu-7M3VM7QN.ts");
667
667
  if (generation !== state.sessionGeneration) return;
668
668
  await showChromeDevtoolsBrowserSettings(pi, ctx, generation);
669
669
  return;
@@ -672,7 +672,7 @@ async function handleChromeDevtoolsCommand(pi, args, ctx, generation) {
672
672
  if (!ctx.hasUI || ctx.mode !== "tui" && ctx.mode !== "rpc") {
673
673
  throw new Error("/chrome-devtools tools requires TUI or RPC mode");
674
674
  }
675
- const { showChromeDevtoolsToolWorkflow } = await import("./chunks/menu-Z26D6XSI.ts");
675
+ const { showChromeDevtoolsToolWorkflow } = await import("./chunks/menu-HGG26E3X.ts");
676
676
  if (generation !== state.sessionGeneration) return;
677
677
  await showChromeDevtoolsToolWorkflow(pi, ctx, generation);
678
678
  return;
@@ -703,7 +703,7 @@ async function showMenu(pi, ctx, generation) {
703
703
  if (!ctx.hasUI || ctx.mode !== "tui" && ctx.mode !== "rpc") {
704
704
  throw new Error("/chrome-devtools menu requires TUI or RPC mode; use a direct subcommand");
705
705
  }
706
- const { showChromeDevtoolsMenu } = await import("./chunks/menu-Z26D6XSI.ts");
706
+ const { showChromeDevtoolsMenu } = await import("./chunks/menu-HGG26E3X.ts");
707
707
  if (generation !== state.sessionGeneration) return;
708
708
  await showChromeDevtoolsMenu(pi, ctx, generation);
709
709
  }
@@ -26,8 +26,14 @@ Configure the canonical user file at `${PI_CODING_AGENT_DIR:-~/.pi/agent}/pi-chr
26
26
  ```
27
27
 
28
28
  `browser.endpoint` must be an HTTP origin with an explicit port and no credentials, path, query, or fragment.
29
- Omitting it keeps attach-first behavior on `127.0.0.1:9222` and lets a managed launch use Chrome's dynamic DevTools port mode (`--remote-debugging-port=0`).
29
+ Omitting it keeps attach-first behavior on `127.0.0.1:9222`; a managed launch selects an available local port and passes that nonzero number to Chrome.
30
30
  Saving an explicit endpoint pins managed launches to that port.
31
+ Chrome's port-`0` mode enables `navigator.webdriver`; automatic managed launches avoid that mode without overriding browser properties.
32
+ This does not guarantee access to bot-protected sites, which can use other signals and policies.
33
+
34
+ A selected port can become occupied before Chrome binds it.
35
+ Startup checks the owned browser's DevTools announcement and browser identity instead of accepting a competing CDP endpoint.
36
+ If startup fails because of a port conflict, retry the operation or configure another explicit endpoint.
31
37
  `browser.autoLaunch` defaults to `true`.
32
38
  `browser.executablePath` is optional and must be an absolute path; when absent, normal browser discovery applies.
33
39
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@narumitw/pi-chrome-devtools",
3
- "version": "0.54.0",
3
+ "version": "0.54.1",
4
4
  "description": "Pi extension that exposes Chrome DevTools Protocol tools.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -19,6 +19,7 @@
19
19
  "dist",
20
20
  "docs",
21
21
  "README.md",
22
+ "CHANGELOG.md",
22
23
  "LICENSE"
23
24
  ],
24
25
  "pi": {
@@ -39,14 +40,14 @@
39
40
  "typebox": "*"
40
41
  },
41
42
  "devDependencies": {
42
- "@earendil-works/pi-coding-agent": "1.0.2",
43
- "@earendil-works/pi-tui": "1.0.2",
43
+ "@earendil-works/pi-coding-agent": "1.5.0",
44
+ "@earendil-works/pi-tui": "1.5.0",
44
45
  "esbuild": "0.28.2",
45
- "typebox": "1.3.34",
46
+ "typebox": "1.4.4",
46
47
  "typescript": "7.0.2"
47
48
  },
48
49
  "dependencies": {
49
- "@narumitw/pi-tui-kit": "^0.59.0"
50
+ "@narumitw/pi-tui-kit": "^0.70.0"
50
51
  },
51
52
  "repository": {
52
53
  "type": "git",