@orkestrel/browser 0.0.26 → 0.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["BrowserError","isInstance","parseInteger","isError","parseJSON","isRecord","isNumber","isString","isBrowserError","pathWin32","pathPosix","mkdtemp","join","tmpdir","resolve","dirname","basename","BrowserError","rm","existsSync","spawnSync","globSync","spawn","BrowserConnectionError","isArray","BrowserTransition","Emitter","BROWSER_DEFAULT_TIMEOUT_MS","WEBSOCKET_READY_OPEN","BrowserConnectionError","attempt","randomBytes","WEBSOCKET_VERSION","httpsRequest","httpRequest","WEBSOCKET_READY_CLOSED","isString","computeWebSocketAccept","createNodeWebSocket","mkdir","dirname","writeFile","isInteger","BrowserError","createPool","resolve","createToolManager","BROWSER_TOOL_NAMES","BROWSER_JOURNEY_TOOL_NAMES","createTool","BROWSER_TOOL_COPY","createMCPServer","createStdioServer","createMCPLegacy","mkdir","join","isBrowserError","isPoolError","readFile","isError","rm","isString","randomUUID","addAbortListener","isRecord","MCPError","JSONRPC_SERVER_ERROR","createBrowserToolset","isCDPConnectionError","isCDPTimeoutError","writeFile","rename","readdir","createCDPClient","toolToDefinition","BrowserError","realpathSync","BROWSER_JOURNEY_NAME_PATTERN","BROWSER_RUN_ID_PATTERN","resolve","sep","relative","lstat","dirname","mkdir","readFile","randomUUID","open","rename","unlink","readdir","rmdir","parseJSON","isRecord","BrowserError","normalizeBrowserJourneyReason","BROWSER_JOURNEY_NAME_PATTERN","generateBrowserRunId","writeFile","parseJSON","isRecord","BrowserError","BROWSER_JOURNEY_FORMAT_VERSION","rm","readdir","lstat","BrowserTransition","Emitter","BrowserContext","isRecord","isString","BrowserConnectionError","isBrowserConnectionError","isError","addAbortListener","BROWSER_DEFAULT_TIMEOUT_MS","CDPClient","isArray","isInteger","once"],"sources":["../../../src/server/constants.ts","../../../src/server/errors.ts","../../../src/server/helpers.ts","../../../src/server/transports/WebSocketCDPTransport.ts","../../../src/server/writers/FileBrowserWriter.ts","../../../package.json","../../../src/server/BrowserMCPServer.ts","../../../src/server/stores/FileBrowserStore.ts","../../../src/server/stores/FileBrowserJourneyStore.ts","../../../src/server/stores/FileBrowserRunStore.ts","../../../src/server/factories.ts","../../../src/server/Browser.ts"],"sourcesContent":["import type { ToolDefinition } from '@orkestrel/tool'\nimport type { BrowserEngine, BrowserServerToolName } from './types.js'\n\n// === CDP discovery\n\n/**\n * Sets the default CDP port probed for an existing browser and used for launches, `9222`.\n */\nexport const BROWSER_DEFAULT_CDP_PORT = 9222\n\n/**\n * Sets the default host probed for an existing browser and used for launches, `'127.0.0.1'`,\n * which avoids `localhost` resolving to `::1` when Chromium binds `127.0.0.1`.\n */\nexport const BROWSER_DEFAULT_HOST = '127.0.0.1'\n\n/** Names the protocol prefix for CDP discovery requests, `'http'`. */\nexport const BROWSER_CDP_PROTOCOL = 'http'\n\n/**\n * Names the path appended to the CDP host to fetch version metadata, `'/json/version'`, which\n * is where endpoint discovery reads.\n */\nexport const BROWSER_CDP_VERSION_PATH = '/json/version'\n\n/**\n * Names the path appended to the CDP host to list open targets — pages, workers, and every\n * other target category Chromium reports — `'/json/list'`.\n */\nexport const BROWSER_CDP_LIST_PATH = '/json/list'\n\n// === Browser launch\n\n/**\n * Lists the flags always passed to a launched browser process, alongside the caller's own.\n *\n * @remarks\n * Disables account sync so extension installs cannot reset URL loader factories during page imports.\n * Disables Edge's implicit sign-in so fresh automation profiles carry no Microsoft account.\n * Chromium ignores the unknown Edge feature name on Chrome and Chromium.\n * The launcher merges disabled features with the caller's into one switch.\n */\nexport const BROWSER_LAUNCH_ARGS: readonly string[] = Object.freeze([\n\t'--no-first-run',\n\t'--no-default-browser-check',\n\t'--disable-sync',\n\t'--disable-features=msImplicitSignin',\n])\n\n/**\n * Names the flag that enables headless mode on a launched browser process, `'--headless=new'`.\n */\nexport const BROWSER_HEADLESS_ARG = '--headless=new'\n\n/**\n * Names the prefix for isolated browser profiles created beneath the operating-system temp\n * directory, `'orkestrel-browser-'`.\n */\nexport const BROWSER_PROFILE_PREFIX = 'orkestrel-browser-'\n\n/**\n * Bounds each launched-process exit window during TERM-to-KILL teardown at `3_000`\n * milliseconds.\n */\nexport const BROWSER_KILL_GRACE_MS = 3_000\n\n/**\n * Bounds the `discover: false` port-occupancy probe before launching at `200` milliseconds,\n * which is short because the probe only needs to detect an already-listening CDP endpoint\n * rather than perform full discovery.\n */\nexport const BROWSER_PORT_PROBE_TIMEOUT_MS = 200\n\n/**\n * Matches the stderr line Chromium prints when its CDP endpoint accepts connections, and\n * captures the `ws://` endpoint the line names.\n *\n * @remarks\n * Chromium prints the line only when launched with `--remote-debugging-port`, which is why an\n * owned launch always passes that flag.\n */\nexport const BROWSER_DEVTOOLS_PATTERN = /DevTools listening on (ws:\\/\\/\\S+)/\n\n/**\n * Sets the interval in milliseconds between liveness probes of a terminated browser process\n * group.\n *\n * @remarks\n * Node raises an exit event for the direct child only. Neither the rest of a POSIX process\n * group nor a process a launcher handed the endpoint to raises one, so the bounded drain in\n * `Browser` probes on this interval until the group is gone or the grace period ends.\n */\nexport const BROWSER_DRAIN_INTERVAL_MS = 100\n\n/**\n * Defers once for `50` milliseconds when a transport loss is observed on an owned process,\n * so a near-simultaneous process-exit event, which libuv might reap slightly later than the\n * socket close, decides the diagnosis first.\n */\nexport const BROWSER_TRANSPORT_LOSS_DEFER_MS = 50\n\n/**\n * Names the machine-readable error-context cause for an owned browser process exiting,\n * `'process-exit'`.\n */\nexport const BROWSER_PROCESS_EXIT_CAUSE = 'process-exit'\n\n/**\n * Names the machine-readable error-context cause for a CDP transport disconnecting while its\n * browser remains alive, `'transport-loss'`.\n */\nexport const BROWSER_TRANSPORT_LOSS_CAUSE = 'transport-loss'\n\n/**\n * Lists the environment variables checked, in order, for an explicit browser executable path\n * override: `PLAYWRIGHT_EXECUTABLE_PATH`, then `CHROME_PATH`.\n */\nexport const BROWSER_ENV_PATH_KEYS: readonly string[] = Object.freeze([\n\t'PLAYWRIGHT_EXECUTABLE_PATH',\n\t'CHROME_PATH',\n])\n\n/**\n * Lists the well-known Chrome/Chromium/Edge executable paths with no platform-specific root,\n * keyed by `process.platform`, leaving `win32` empty because its roots come from\n * `BROWSER_WINDOWS_SUFFIXES`.\n */\nexport const BROWSER_EXECUTABLE_PATHS: Readonly<Record<string, readonly string[]>> = Object.freeze({\n\tlinux: Object.freeze([\n\t\t'/usr/bin/google-chrome',\n\t\t'/usr/bin/google-chrome-stable',\n\t\t'/usr/bin/microsoft-edge',\n\t\t'/usr/bin/microsoft-edge-stable',\n\t\t'/usr/bin/chromium',\n\t\t'/usr/bin/chromium-browser',\n\t\t'/snap/bin/chromium',\n\t\t'/opt/google/chrome/chrome',\n\t\t'/opt/microsoft/msedge/msedge',\n\t]),\n\tdarwin: Object.freeze([\n\t\t'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',\n\t\t'/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',\n\t\t'/Applications/Chromium.app/Contents/MacOS/Chromium',\n\t]),\n\twin32: Object.freeze([]),\n})\n\n/** Lists the Windows install-root-relative suffixes for Chrome/Edge/Chromium, joined against each candidate root (`PROGRAMFILES`, `PROGRAMFILES(X86)`, `LOCALAPPDATA`). */\nexport const BROWSER_WINDOWS_SUFFIXES: readonly string[] = Object.freeze([\n\t'Google\\\\Chrome\\\\Application\\\\chrome.exe',\n\t'Microsoft\\\\Edge\\\\Application\\\\msedge.exe',\n\t'Chromium\\\\Application\\\\chrome.exe',\n])\n\n/**\n * Lists the fallback Windows install roots used when `PROGRAMFILES`, `PROGRAMFILES(X86)`, or\n * `LOCALAPPDATA` is absent.\n */\nexport const BROWSER_WINDOWS_ROOT_FALLBACKS: Readonly<Record<string, string>> = Object.freeze({\n\tPROGRAMFILES: 'C:\\\\Program Files',\n\t'PROGRAMFILES(X86)': 'C:\\\\Program Files (x86)',\n})\n\n/** Lists the command names probed on PATH when no well-known executable path exists. */\nexport const BROWSER_EXECUTABLE_NAMES: readonly string[] = Object.freeze([\n\t'google-chrome',\n\t'google-chrome-stable',\n\t'msedge',\n\t'microsoft-edge',\n\t'chromium',\n\t'chromium-browser',\n\t'chrome',\n])\n\n/**\n * Names the environment variable that carries an additional Playwright browser store base\n * directory, `'PLAYWRIGHT_BROWSERS_PATH'`.\n */\nexport const BROWSER_STORE_ENV_KEY = 'PLAYWRIGHT_BROWSERS_PATH'\n\n/**\n * Lists the well-known Playwright browser store base directories checked in addition to\n * `PLAYWRIGHT_BROWSERS_PATH`, starting with `/opt/pw-browsers`.\n */\nexport const BROWSER_STORE_DEFAULT_DIRS: readonly string[] = Object.freeze(['/opt/pw-browsers'])\n\n/** Names the per-OS default Playwright browser cache directory, relative to the home directory (win32 uses `LOCALAPPDATA` directly). */\nexport const BROWSER_STORE_CACHE_DIRS: Readonly<Record<string, string>> = Object.freeze({\n\tlinux: '.cache/ms-playwright',\n\tdarwin: 'Library/Caches/ms-playwright',\n})\n\n/**\n * Names the top-level Chromium symlink or binary Playwright maintains inside a browser store\n * base, `'chromium'`.\n */\nexport const BROWSER_STORE_LINK_NAME = 'chromium'\n\n/**\n * Lists the case-insensitive substrings identifying an executable path/name's browser\n * engine, checked by `parseBrowserEngine` in the order `edge` → `chromium` → `chrome`.\n */\nexport const BROWSER_ENGINE_HINTS: Readonly<Record<BrowserEngine, readonly string[]>> =\n\tObject.freeze({\n\t\tedge: Object.freeze(['msedge', 'microsoft-edge', 'edge']),\n\t\tchromium: Object.freeze([\n\t\t\t'chromium',\n\t\t\t'pw-browsers',\n\t\t\t'chrome-linux',\n\t\t\t'chrome-win',\n\t\t\t'chrome-mac',\n\t\t\t'chrome_headless',\n\t\t]),\n\t\tchrome: Object.freeze(['google-chrome', 'google/chrome', 'google\\\\chrome', 'chrome']),\n\t})\n\n/** Names the glob pattern (relative to a store base) matching a versioned Chromium binary, keyed by `process.platform`. */\nexport const BROWSER_STORE_GLOBS: Readonly<Record<string, string>> = Object.freeze({\n\tlinux: 'chromium-*/chrome-linux*/chrome',\n\tdarwin: 'chromium-*/chrome-mac*/Chromium.app/Contents/MacOS/Chromium',\n\twin32: 'chromium-*/chrome-win*/chrome.exe',\n})\n\n/** Names the persisted journey snapshot. */\nexport const BROWSER_JOURNEY_SNAPSHOT_FILE = 'journey.json'\n/** Names the retained journey revision counter. */\nexport const BROWSER_JOURNEY_REVISION_FILE = 'revision'\n/** Names the exclusive journey write lock directory. */\nexport const BROWSER_JOURNEY_LOCK_DIRECTORY = 'journey.lock'\n/** Bounds attempts to acquire a journey lock after concurrent recovery. */\nexport const BROWSER_JOURNEY_LOCK_ATTEMPTS = 8\n/** Names the persisted run snapshot. */\nexport const BROWSER_RUN_FILE = 'run.json'\n/** Names the journey directory holding its runs. */\nexport const BROWSER_RUN_DIRECTORY = 'runs'\n/** Bounds a file-store listing page by default. */\nexport const BROWSER_FILE_STORE_LIMIT = 100\n\n/** Names the refusal when no browser can serve a call. */\nexport const BROWSER_SERVER_UNAVAILABLE = 'BROWSER_SERVER_UNAVAILABLE'\n/** Names a failed attempt to warm a browser. */\nexport const BROWSER_SERVER_LAUNCH = 'BROWSER_SERVER_LAUNCH'\n/** Sets the default number of warm browsers to 1. */\nexport const BROWSER_SERVER_POOL_SIZE = 1\n/** Sets the default context capacity per browser, including the shared holder. */\nexport const BROWSER_SERVER_CONTEXTS = 2\n/** Limits context capacity to the largest measured per-browser count. */\nexport const BROWSER_SERVER_CONTEXTS_LIMIT = 4\n/** Limits the number of warm browsers to 3. */\nexport const BROWSER_SERVER_POOL_LIMIT = 3\n/** Permits one failed refill before the next failure spends the bound. */\nexport const BROWSER_SERVER_RESTARTS = 1\n/** Names the browser process record in each profile. */\nexport const BROWSER_SERVER_RECORD = 'browse.json'\n/** Names the diagnostic when the warm floor spends its restart bound. */\nexport const BROWSER_SERVER_EXHAUSTED = 'BROWSER_SERVER_EXHAUSTED'\n/** Names a failed browser server teardown. */\nexport const BROWSER_SERVER_TEARDOWN = 'BROWSER_SERVER_TEARDOWN'\n/** Names a failed profile sweep. */\nexport const BROWSER_SERVER_SWEEP = 'BROWSER_SERVER_SWEEP'\n/** Names a refused browser server option. */\nexport const BROWSER_SERVER_OPTIONS = 'BROWSER_SERVER_OPTIONS'\n/** Names the notice that a browser and its session state were lost. */\nexport const BROWSER_SERVER_CRASH = 'BROWSER_SERVER_CRASH'\n/** Names an interrupted call whose outcome is unknown. */\nexport const BROWSER_SERVER_UNRESOLVED = 'BROWSER_SERVER_UNRESOLVED'\n\n/** Names the refusal when every browser is admitted to a holder. */\nexport const BROWSER_SERVER_BUSY = 'BROWSER_SERVER_BUSY'\n/** Names the refusal for an unknown or ended holder. */\nexport const BROWSER_SERVER_HOLDER = 'BROWSER_SERVER_HOLDER'\n\n/** Defines the holder tools independently of the shared browser's vocabulary. */\nexport const BROWSER_SERVER_COPY: Readonly<Record<BrowserServerToolName, ToolDefinition>> =\n\tObject.freeze({\n\t\tacquire: Object.freeze({\n\t\t\tname: 'acquire',\n\t\t\tdescription:\n\t\t\t\t'Acquires an independent browser and returns its holder id and tool catalog. Destroy the holder when its work ends.',\n\t\t\tparameters: Object.freeze({\n\t\t\t\ttype: 'object',\n\t\t\t\tproperties: Object.freeze({\n\t\t\t\t\tpurpose: Object.freeze({\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: 'The work this browser will serve.',\n\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t\t\trequired: Object.freeze(['purpose']),\n\t\t\t}),\n\t\t}),\n\t\texecute: Object.freeze({\n\t\t\tname: 'execute',\n\t\t\tdescription:\n\t\t\t\t'Runs a tool on the selected holder, with that tool’s arguments inside arguments. Get its available tools with tools.',\n\t\t\tparameters: Object.freeze({\n\t\t\t\ttype: 'object',\n\t\t\t\tproperties: Object.freeze({\n\t\t\t\t\tholder: Object.freeze({\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: 'The holder id returned by acquire.',\n\t\t\t\t\t}),\n\t\t\t\t\tname: Object.freeze({\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: 'The tool name from this holder’s catalog.',\n\t\t\t\t\t}),\n\t\t\t\t\targuments: Object.freeze({\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tdescription: 'The arguments for the selected tool.',\n\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t\t\trequired: Object.freeze(['holder', 'name', 'arguments']),\n\t\t\t}),\n\t\t\tannotations: Object.freeze({ pure: false, untrusted: true }),\n\t\t}),\n\t\ttools: Object.freeze({\n\t\t\tname: 'tools',\n\t\t\tdescription: 'Lists the selected holder’s tools, including tools supplied by its page.',\n\t\t\tparameters: Object.freeze({\n\t\t\t\ttype: 'object',\n\t\t\t\tproperties: Object.freeze({\n\t\t\t\t\tholder: Object.freeze({\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: 'The holder id returned by acquire.',\n\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t\t\trequired: Object.freeze(['holder']),\n\t\t\t}),\n\t\t\tannotations: Object.freeze({ pure: true, untrusted: true }),\n\t\t}),\n\t\tdestroy: Object.freeze({\n\t\t\tname: 'destroy',\n\t\t\tdescription:\n\t\t\t\t'Ends the selected holder and destroys its browser. Calls still running on that holder report an unresolved outcome.',\n\t\t\tparameters: Object.freeze({\n\t\t\t\ttype: 'object',\n\t\t\t\tproperties: Object.freeze({\n\t\t\t\t\tholder: Object.freeze({\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: 'The holder id returned by acquire.',\n\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t\t\trequired: Object.freeze(['holder']),\n\t\t\t}),\n\t\t\tannotations: Object.freeze({ pure: false }),\n\t\t}),\n\t})\n","import { BrowserError } from '@src/core'\nimport { isInstance } from '@orkestrel/contract'\n\n// === Server browser errors\n\n/**\n * Reports that an operation requiring an active connection was attempted while disconnected,\n * under the code `BROWSER_NOT_CONNECTED_ERROR`.\n */\nexport class BrowserNotConnectedError extends BrowserError {\n\tconstructor(context?: Readonly<Record<string, unknown>>) {\n\t\tsuper('Browser is not connected', 'BROWSER_NOT_CONNECTED_ERROR', context)\n\t\tthis.name = 'BrowserNotConnectedError'\n\t}\n}\n\n/**\n * Reports that an operation was attempted after the browser wrapper was destroyed, under the\n * code `BROWSER_DESTROYED_ERROR`.\n */\nexport class BrowserDestroyedError extends BrowserError {\n\tconstructor(context?: Readonly<Record<string, unknown>>) {\n\t\tsuper('Browser has been destroyed', 'BROWSER_DESTROYED_ERROR', context)\n\t\tthis.name = 'BrowserDestroyedError'\n\t}\n}\n\n// === Server browser type guards\n\n/**\n * Narrows an unknown value to a `BrowserNotConnectedError`.\n *\n * @param value - Value to check\n * @returns True if value is a BrowserNotConnectedError instance; false otherwise\n */\nexport function isBrowserNotConnectedError(value: unknown): value is BrowserNotConnectedError {\n\treturn isInstance(value, BrowserNotConnectedError)\n}\n\n/**\n * Narrows an unknown value to a `BrowserDestroyedError`.\n *\n * @param value - Value to check\n * @returns True if value is a BrowserDestroyedError instance; false otherwise\n */\nexport function isBrowserDestroyedError(value: unknown): value is BrowserDestroyedError {\n\treturn isInstance(value, BrowserDestroyedError)\n}\n","import type { ChildProcess } from 'node:child_process'\nimport type { Readable } from 'node:stream'\nimport type { BrowserViewport, CDPTarget } from '@src/core'\nimport type { Result } from '@orkestrel/contract'\nimport type {\n\tBrowserEngine,\n\tBrowserProfileRecord,\n\tBrowserProfileResult,\n\tSystemBrowser,\n\tSystemBrowserOptions,\n} from './types.js'\nimport { existsSync, globSync } from 'node:fs'\nimport { mkdtemp, rm } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { basename, dirname, join, resolve, win32 as pathWin32, posix as pathPosix } from 'node:path'\nimport { spawn, spawnSync } from 'node:child_process'\nimport {\n\tisArray,\n\tisError,\n\tisNumber,\n\tisRecord,\n\tisString,\n\tparseInteger,\n\tparseJSON,\n} from '@orkestrel/contract'\nimport { BrowserConnectionError, BrowserError, isBrowserError } from '@src/core'\nimport {\n\tBROWSER_CDP_PROTOCOL,\n\tBROWSER_CDP_LIST_PATH,\n\tBROWSER_DEVTOOLS_PATTERN,\n\tBROWSER_ENV_PATH_KEYS,\n\tBROWSER_EXECUTABLE_PATHS,\n\tBROWSER_EXECUTABLE_NAMES,\n\tBROWSER_WINDOWS_SUFFIXES,\n\tBROWSER_WINDOWS_ROOT_FALLBACKS,\n\tBROWSER_STORE_ENV_KEY,\n\tBROWSER_STORE_DEFAULT_DIRS,\n\tBROWSER_STORE_CACHE_DIRS,\n\tBROWSER_STORE_LINK_NAME,\n\tBROWSER_STORE_GLOBS,\n\tBROWSER_ENGINE_HINTS,\n\tBROWSER_LAUNCH_ARGS,\n\tBROWSER_HEADLESS_ARG,\n\tBROWSER_DEFAULT_HOST,\n\tBROWSER_PROFILE_PREFIX,\n\tBROWSER_SERVER_CRASH,\n\tBROWSER_SERVER_UNRESOLVED,\n\tBROWSER_SERVER_UNAVAILABLE,\n} from './constants.js'\n\n/**\n * Parses positive integer viewport dimensions in WIDTHxHEIGHT form.\n * @param value - The viewport environment variable, or undefined when unset\n * @returns The viewport, or undefined when absent or malformed\n * @example\n * parseBrowserViewport('1280x720') // { width: 1280, height: 720 }\n */\nexport function parseBrowserViewport(value: string | undefined): BrowserViewport | undefined {\n\tif (value === undefined) return undefined\n\tconst match = /^([0-9]+)x([0-9]+)$/u.exec(value)\n\tif (match === null || match[0] !== value) return undefined\n\tconst width = parseInteger(match[1])\n\tconst height = parseInteger(match[2])\n\tif (\n\t\twidth === undefined ||\n\t\theight === undefined ||\n\t\t!Number.isSafeInteger(width) ||\n\t\t!Number.isSafeInteger(height) ||\n\t\twidth <= 0 ||\n\t\theight <= 0\n\t)\n\t\treturn undefined\n\treturn { width, height }\n}\n\n/**\n * Probes whether a process has not been confirmed absent.\n * @param pid - Process identifier to probe with signal zero\n * @returns True if the host has not confirmed absence with ESRCH; false otherwise\n * @example\n * probeProcess(process.pid) // true\n */\nexport function probeProcess(pid: number): boolean {\n\ttry {\n\t\tprocess.kill(pid, 0)\n\t\treturn true\n\t} catch (error) {\n\t\treturn !(isError(error) && 'code' in error && error.code === 'ESRCH')\n\t}\n}\n\n/**\n * Parses a profile record naming a positive process identifier and a loopback DevTools endpoint.\n * @param text - JSON record read from a browse profile\n * @returns The record, or undefined when its shape or endpoint is refused\n * @example\n * parseBrowserProfileRecord('{\"pid\":123,\"endpoint\":\"ws://127.0.0.1:9222/devtools/browser/session\"}')\n */\nexport function parseBrowserProfileRecord(text: string): BrowserProfileRecord | undefined {\n\tconst record = parseJSON(text)\n\tif (!isRecord(record)) return undefined\n\tconst pid = record['pid']\n\tconst endpoint = record['endpoint']\n\tif (!isNumber(pid) || !Number.isSafeInteger(pid) || pid <= 0 || !isString(endpoint))\n\t\treturn undefined\n\tconst match = /^ws:\\/\\/127\\.0\\.0\\.1:([1-9]\\d*)\\/devtools\\/browser\\/[^/?#\\s\\\\]+$/.exec(endpoint)\n\tif (match === null || Number(match[1]) > 65535) return undefined\n\treturn { pid, endpoint }\n}\n\n/**\n * Describes a browser loss with its code, cause, and the session state it invalidates.\n * @param code - Browser server diagnostic code\n * @param cause - The loss or refusal, including its process context when present\n * @param url - The lost page's last URL, when known\n * @returns The coded diagnostic and any operation-lifecycle guidance\n * @example\n * describeBrowserServerLoss('BROWSER_SERVER_UNAVAILABLE', new Error('Browser exited'))\n */\nexport function describeBrowserServerLoss(code: string, cause: unknown, url?: string): string {\n\tconst pid = isBrowserError(cause) ? cause.context?.['pid'] : undefined\n\tconst detail =\n\t\tcause === undefined ? 'Browser session lost' : isError(cause) ? cause.message : String(cause)\n\tconst message = `${code}: ${detail.replace(/\\.+$/u, '')}${isNumber(pid) ? ` (pid ${pid})` : ''}.`\n\tif (code !== BROWSER_SERVER_CRASH && code !== BROWSER_SERVER_UNRESOLVED) return message\n\tconst lost = `Lost the page${url === undefined ? '' : ` at ${url}`}, its tabs, every element reference, the retained reading, dialogs, holds, an unsaved recording, the active replay, and the isolated context's cookies.`\n\tconst next = `The next call acquires a browser that starts at about:blank, or answers ${BROWSER_SERVER_UNAVAILABLE} when none can serve.`\n\treturn code === BROWSER_SERVER_UNRESOLVED\n\t\t? `${message} The outcome is unknown. ${lost} Browse did not repeat the call. ${next}`\n\t\t: `${message} ${lost}`\n}\n\n/**\n * Formats a process identifier and UUID token as a lock entry name.\n * @param pid - Positive safe integer identifying the holder process\n * @param token - Lowercase UUID token identifying this acquisition\n * @returns The entry name\n * @example\n * formatBrowserLockEntry(123, '11111111-1111-4111-8111-111111111111')\n */\nexport function formatBrowserLockEntry(pid: number, token: string): string {\n\treturn `${pid}-${token}`\n}\n\n/**\n * Parses the holder process identifier from a lock entry name.\n * @remarks Requires a positive safe integer followed by a lowercase UUID token.\n * @param name - Directory entry name\n * @returns The process identifier, or undefined when the entry is malformed\n * @example\n * parseBrowserLockEntry('123-11111111-1111-4111-8111-111111111111') // 123\n */\nexport function parseBrowserLockEntry(name: string): number | undefined {\n\tconst match = /^([1-9]\\d*)-[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.exec(\n\t\tname,\n\t)\n\tconst pid = Number(match?.[1])\n\treturn Number.isSafeInteger(pid) && pid > 0 ? pid : undefined\n}\n\n// === Discovery helpers\n\n/**\n * Enumerates every Chrome/Chromium/Edge executable discoverable on this\n * machine, deduplicated by normalized absolute path.\n *\n * @remarks\n * Resolution precedence (candidates appended in this order):\n * 1. `PLAYWRIGHT_EXECUTABLE_PATH`, then `CHROME_PATH` — explicit environment\n * overrides that exist on disk\n * 2. Well-known platform install locations (Chrome, Edge, Chromium); Windows\n * roots are derived from `PROGRAMFILES` / `PROGRAMFILES(X86)` / `LOCALAPPDATA`\n * 3. PATH probe for known command names (`which` on POSIX, `where` on Windows)\n * 4. Playwright-managed browser stores (`PLAYWRIGHT_BROWSERS_PATH`, `/opt/pw-browsers`,\n * and the per-OS Playwright cache directory) — the top-level `chromium`\n * link/binary, then the highest-revision `chromium-*` install found\n *\n * Each candidate is classified into a {@link BrowserEngine} through\n * `parseBrowserEngine` (unclassifiable candidates default to `'chromium'`),\n * and `options.engine` (when given) narrows the result to that engine.\n *\n * @param options - Overrides for the candidate sources; see {@link SystemBrowserOptions}\n * @returns Every discovered browser, in resolution-precedence order\n */\nexport function findSystemBrowsers(options?: SystemBrowserOptions): readonly SystemBrowser[] {\n\tconst platform = process.platform\n\tconst env = options?.env ?? process.env\n\n\tconst candidates: string[] = []\n\n\tcandidates.push(...findEnvOverrides(env))\n\n\tconst paths = options?.paths ?? buildInstallPaths(platform, env)\n\tcandidates.push(...findInstallPaths(paths))\n\n\tconst names = options?.names ?? BROWSER_EXECUTABLE_NAMES\n\tcandidates.push(...probePathNames(names, platform))\n\n\tconst stores = options?.stores ?? buildStoreBases(env, platform)\n\tfor (const store of stores) {\n\t\tcandidates.push(...findStorePaths(store, platform))\n\t}\n\n\tconst seen = new Set<string>()\n\tconst browsers: SystemBrowser[] = []\n\n\tfor (const executable of candidates) {\n\t\tconst key = normalizeExecutablePath(executable, platform)\n\t\tif (seen.has(key)) continue\n\t\tseen.add(key)\n\n\t\tconst engine = parseBrowserEngine(executable) ?? 'chromium'\n\t\tif (options?.engine !== undefined && engine !== options.engine) continue\n\n\t\tbrowsers.push({ executable, engine })\n\t}\n\n\treturn browsers\n}\n\n/**\n * Locates a Chrome/Chromium/Edge executable on this machine — the first entry\n * of {@link findSystemBrowsers}.\n *\n * @param options - Overrides for the candidate sources; see {@link SystemBrowserOptions}\n * @returns The first discovered browser, or undefined\n */\nexport function findSystemBrowser(options?: SystemBrowserOptions): SystemBrowser | undefined {\n\treturn findSystemBrowsers(options)[0]\n}\n\n/**\n * Classifies an executable path/name into a {@link BrowserEngine} by\n * case-insensitive hint, checked in the order edge → chromium → chrome.\n *\n * @param executable - Executable path or command name to classify\n * @returns The classified engine, or undefined when no hint matches\n */\nexport function parseBrowserEngine(executable: string): BrowserEngine | undefined {\n\tconst lower = executable.toLowerCase()\n\tconst order: readonly BrowserEngine[] = ['edge', 'chromium', 'chrome']\n\tfor (const engine of order) {\n\t\tconst hints = BROWSER_ENGINE_HINTS[engine]\n\t\tif (hints.some((hint) => lower.includes(hint))) return engine\n\t}\n\treturn undefined\n}\n\n/** Normalizes an executable path for cross-source deduplication (case-insensitive on Windows). */\nexport function normalizeExecutablePath(path: string, platform: string): string {\n\tconst normalized = platform === 'win32' ? pathWin32.normalize(path) : pathPosix.normalize(path)\n\treturn platform === 'win32' ? normalized.toLowerCase() : normalized\n}\n\n/** Classifies a `/json/version` `Browser` string into a {@link BrowserEngine} (`Edg/` → edge, `Chrome/` → chrome, else chromium). */\nexport function browserToEngine(browser?: string): BrowserEngine {\n\tif (browser?.includes('Edg/') === true) return 'edge'\n\tif (browser?.includes('Chrome/') === true) return 'chrome'\n\treturn 'chromium'\n}\n\n/**\n * Resolves a persistent caller profile or creates an isolated temporary one.\n *\n * @param path - Optional caller-owned persistent user-data directory\n * @returns The resolved profile and whether the library owns its lifecycle\n */\nexport async function createBrowserProfile(path?: string): Promise<BrowserProfileResult> {\n\tif (path !== undefined) return { path, temporary: false }\n\tconst directory = await mkdtemp(join(tmpdir(), BROWSER_PROFILE_PREFIX))\n\treturn { path: directory, temporary: true }\n}\n\n/**\n * Removes a library-owned isolated browser profile.\n *\n * @remarks\n * The path must remain a direct child of the operating-system temp directory\n * with {@link BROWSER_PROFILE_PREFIX}; this defensive check prevents a\n * malformed profile value from widening recursive deletion.\n *\n * @param profile - Resolved profile lifecycle result\n */\nexport async function removeBrowserProfile(profile: BrowserProfileResult): Promise<void> {\n\tif (!profile.temporary) return\n\tconst path = resolve(profile.path)\n\tconst temporary = resolve(tmpdir())\n\tif (dirname(path) !== temporary || !basename(path).startsWith(BROWSER_PROFILE_PREFIX)) {\n\t\tthrow new BrowserError('Refusing to remove an unsafe browser profile path', undefined, {\n\t\t\tpath,\n\t\t})\n\t}\n\tawait rm(path, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 })\n}\n\n/** Checks the env-override keys (`PLAYWRIGHT_EXECUTABLE_PATH`, `CHROME_PATH`) in order and returns every one that exists. */\nexport function findEnvOverrides(\n\tenv: Readonly<Record<string, string | undefined>>,\n): readonly string[] {\n\tconst found: string[] = []\n\tfor (const key of BROWSER_ENV_PATH_KEYS) {\n\t\tconst value = env[key]\n\t\tif (value !== undefined && value.length > 0 && existsSync(value)) found.push(value)\n\t}\n\treturn found\n}\n\n/** Builds the default well-known install-path candidates for a platform, deriving Windows roots from env vars. */\nexport function buildInstallPaths(\n\tplatform: string,\n\tenv: Readonly<Record<string, string | undefined>>,\n): readonly string[] {\n\tif (platform !== 'win32') return BROWSER_EXECUTABLE_PATHS[platform] ?? []\n\n\tconst roots = buildWindowsRoots(env)\n\tconst paths: string[] = []\n\tfor (const root of roots) {\n\t\tfor (const suffix of BROWSER_WINDOWS_SUFFIXES) {\n\t\t\tpaths.push(pathWin32.join(root, suffix))\n\t\t}\n\t}\n\treturn paths\n}\n\n/** Derives Windows install roots from env vars, falling back to well-known literals when absent. */\nexport function buildWindowsRoots(\n\tenv: Readonly<Record<string, string | undefined>>,\n): readonly string[] {\n\tconst programFiles = env['PROGRAMFILES'] ?? BROWSER_WINDOWS_ROOT_FALLBACKS['PROGRAMFILES']\n\tconst programFilesX86 =\n\t\tenv['PROGRAMFILES(X86)'] ?? BROWSER_WINDOWS_ROOT_FALLBACKS['PROGRAMFILES(X86)']\n\tconst localAppData = env['LOCALAPPDATA']\n\n\tconst roots = [programFiles, programFilesX86, localAppData]\n\treturn roots.filter((root): root is string => root !== undefined)\n}\n\n/** Returns every candidate path that exists on disk, in the given order. */\nexport function findInstallPaths(paths: readonly string[]): readonly string[] {\n\treturn paths.filter((path) => existsSync(path))\n}\n\n/** Probes PATH (`which`/`where`) for every resolvable command name, in the given order. */\nexport function probePathNames(names: readonly string[], platform: string): readonly string[] {\n\tconst finder = platform === 'win32' ? 'where' : 'which'\n\tconst found: string[] = []\n\tfor (const name of names) {\n\t\tconst result = spawnSync(finder, [name], { stdio: 'pipe' })\n\t\tif (result.status === 0) {\n\t\t\tconst executable = readFirstLine(result.stdout.toString('utf-8'))\n\t\t\tif (executable !== undefined) found.push(executable)\n\t\t}\n\t}\n\treturn found\n}\n\n/**\n * Returns the first non-empty line of a command's output, without its\n * surrounding whitespace.\n *\n * @remarks\n * `where` reports every PATH match on its own CRLF-terminated line, so a\n * carriage return left on the first line would travel into `existsSync` and\n * `spawn` as part of the executable path.\n *\n * @param output - Raw decoded standard output of a command\n * @returns The first line carrying text, or undefined when the output has none\n *\n * @example\n * ```ts\n * readFirstLine('C:\\\\bin\\\\chrome.exe\\r\\nC:\\\\other\\\\chrome.exe\\r\\n') // 'C:\\\\bin\\\\chrome.exe'\n * ```\n */\nexport function readFirstLine(output: string): string | undefined {\n\tfor (const line of output.split(/\\r?\\n/)) {\n\t\tconst text = line.trim()\n\t\tif (text.length > 0) return text\n\t}\n\treturn undefined\n}\n\n/** Builds the default Playwright browser store base directories to search for a managed Chromium. */\nexport function buildStoreBases(\n\tenv: Readonly<Record<string, string | undefined>>,\n\tplatform: string,\n): readonly string[] {\n\tconst bases: string[] = []\n\n\tconst envBase = env[BROWSER_STORE_ENV_KEY]\n\tif (envBase !== undefined && envBase.length > 0) bases.push(envBase)\n\n\tbases.push(...BROWSER_STORE_DEFAULT_DIRS)\n\n\tif (platform === 'win32') {\n\t\tconst localAppData = env['LOCALAPPDATA']\n\t\tif (localAppData !== undefined) bases.push(pathWin32.join(localAppData, 'ms-playwright'))\n\t} else {\n\t\tconst cacheDir = BROWSER_STORE_CACHE_DIRS[platform]\n\t\tconst home = env['HOME']\n\t\tif (cacheDir !== undefined && home !== undefined) bases.push(pathPosix.join(home, cacheDir))\n\t}\n\n\treturn bases\n}\n\n/** Searches one store base for the top-level `chromium` link and every `chromium-*` install, highest revision first. */\nexport function findStorePaths(base: string, platform: string): readonly string[] {\n\tconst joiner = platform === 'win32' ? pathWin32.join : pathPosix.join\n\tconst found: string[] = []\n\n\tconst linkPath = joiner(base, BROWSER_STORE_LINK_NAME)\n\tif (existsSync(linkPath)) found.push(linkPath)\n\n\tconst glob = BROWSER_STORE_GLOBS[platform]\n\tif (glob === undefined) return found\n\n\tconst pattern = `${base.replaceAll('\\\\', '/')}/${glob}`\n\tconst matches = globSync(pattern).filter((match) => existsSync(match))\n\tmatches.sort((a, b) => b.localeCompare(a, undefined, { numeric: true }))\n\tfound.push(...matches)\n\n\treturn found\n}\n\n/**\n * Launches a browser process with raw-CDP debugging flags.\n *\n * @remarks\n * Merges every caller and library `--disable-features` value into one switch because Chromium\n * reads only the last occurrence. Keeps `msImplicitSignin` disabled alongside caller features;\n * Chrome and Chromium ignore this Edge feature name. Preserves the caller's other arguments.\n *\n * POSIX launches own an isolated process group so lifecycle teardown can\n * signal and await every Chromium subprocess without affecting the caller.\n * Windows launches are not detached and own no group, so teardown there\n * signals one process by identifier: the spawned process, or the process the\n * launcher handed the endpoint to when that spawned process re-executed the\n * browser and exited. Terminating a Chromium browser process takes its own\n * subprocesses with it, so that single signal drains the tree.\n *\n * @param executable - Absolute path to the browser executable\n * @param port - Port the browser exposes its CDP endpoint on, or undefined for a port the operating system picks\n * @param headless - Whether to launch in headless mode\n * @param profile - Optional user-data-dir for a persistent profile\n * @param extra - Additional command-line flags\n * @returns The spawned ChildProcess, whose standard error carries the endpoint line `readBrowserEndpoint` reads\n */\nexport function launchBrowserProcess(\n\texecutable: string,\n\tport: number | undefined,\n\theadless: boolean,\n\tprofile?: string,\n\textra?: readonly string[],\n): ChildProcess {\n\t// Caller-supplied args come first so a script path (for example `node <script>`,\n\t// used to spawn a Node stand-in executable cross-platform in tests) lands\n\t// as an early positional argv entry ahead of the CDP flags that follow —\n\t// Chromium itself accepts flags in any order, so production is unaffected.\n\tconst args: string[] = []\n\tconst features = new Set<string>()\n\tfor (const arg of [\n\t\t...(extra ?? []),\n\t\t`--remote-debugging-port=${port ?? 0}`,\n\t\t...BROWSER_LAUNCH_ARGS,\n\t]) {\n\t\tif (arg === '--disable-features') continue\n\t\tif (arg.startsWith('--disable-features=')) {\n\t\t\tfor (const feature of arg.slice('--disable-features='.length).split(',')) {\n\t\t\t\tif (feature.trim() !== '') features.add(feature.trim())\n\t\t\t}\n\t\t} else args.push(arg)\n\t}\n\targs.push(`--disable-features=${[...features].join(',')}`)\n\n\tif (headless) args.push(BROWSER_HEADLESS_ARG)\n\tif (profile !== undefined) args.push(`--user-data-dir=${profile}`)\n\n\treturn spawn(executable, args, {\n\t\tstdio: ['ignore', 'ignore', 'pipe'],\n\t\tdetached: process.platform !== 'win32',\n\t})\n}\n\n/**\n * Reads the CDP endpoint a launched browser announces on its standard error.\n *\n * @remarks\n * Chromium prints `DevTools listening on ws://HOST:PORT/devtools/browser/ID` after it binds the\n * debugging port. The read splits arriving text on line breaks across chunks, so a line split\n * between two chunks and a line ending `\\r\\n` both resolve. After resolving, the stream keeps\n * draining until it closes so the browser's logging never fills the pipe.\n *\n * @param stream - The browser's standard error\n * @param signal - Abort that rejects the read with its reason\n * @returns The `ws://` endpoint the browser announced\n *\n * @throws When the stream closes without the line, or the signal aborts first\n */\nexport function readBrowserEndpoint(stream: Readable, signal: AbortSignal): Promise<string> {\n\tconst read = Promise.withResolvers<string>()\n\tlet pending = ''\n\tlet found = false\n\n\tif (signal.aborted) read.reject(signal.reason)\n\tsignal.addEventListener('abort', () => read.reject(signal.reason), { once: true })\n\tstream.on('error', read.reject)\n\tstream.setEncoding('utf8')\n\tstream.on('data', (chunk) => {\n\t\tif (found || !isString(chunk)) return\n\t\tconst lines = (pending + chunk).split(/\\r\\n|\\n/)\n\t\tpending = lines.pop() ?? ''\n\t\tfor (const line of lines) {\n\t\t\tconst endpoint = BROWSER_DEVTOOLS_PATTERN.exec(line)?.[1]\n\t\t\tif (endpoint === undefined) continue\n\t\t\tfound = true\n\t\t\tpending = ''\n\t\t\tread.resolve(endpoint)\n\t\t\treturn\n\t\t}\n\t})\n\tstream.on('close', () => {\n\t\tconst endpoint = found ? undefined : BROWSER_DEVTOOLS_PATTERN.exec(pending)?.[1]\n\t\tif (endpoint !== undefined) read.resolve(endpoint)\n\t\telse {\n\t\t\tread.reject(\n\t\t\t\tnew BrowserConnectionError(\n\t\t\t\t\t'Browser closed its standard error before reporting a CDP endpoint',\n\t\t\t\t),\n\t\t\t)\n\t\t}\n\t})\n\n\treturn read.promise\n}\n\n/**\n * Fetches the current CDP target list from a browser's `/json/list` endpoint, as a `Result`\n * carrying either the targets or a coded `BrowserConnectionError`.\n *\n * @remarks\n * The endpoint is a network boundary, so an unreachable host, a non-2xx\n * response, and a body that is not a JSON array each come back as a failed\n * `Result` carrying a coded `BrowserConnectionError`. An entry missing a\n * required string field is skipped rather than failing the whole list.\n *\n * @param port - Port the browser exposes its CDP endpoint on\n * @param timeout - Request timeout in milliseconds\n * @param host - Host the browser exposes its CDP endpoint on (default `127.0.0.1`)\n * @returns The normalized CDP targets, or the fault that stopped the request\n *\n * @example\n * ```ts\n * import { fetchCDPTargets } from '@orkestrel/browser/server'\n *\n * const result = await fetchCDPTargets(9222, 2000)\n * if (result.success) log(result.value.length)\n * else log(result.error.code)\n * ```\n */\nexport async function fetchCDPTargets(\n\tport: number,\n\ttimeout: number,\n\thost: string = BROWSER_DEFAULT_HOST,\n): Promise<Result<readonly CDPTarget[], BrowserError>> {\n\tconst url = `${BROWSER_CDP_PROTOCOL}://${host}:${port}${BROWSER_CDP_LIST_PATH}`\n\tconst controller = new AbortController()\n\tconst timer = setTimeout(() => controller.abort(), timeout)\n\n\ttry {\n\t\tconst response = await fetch(url, { signal: controller.signal })\n\n\t\tif (!response.ok) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: new BrowserConnectionError('CDP target list request was refused', {\n\t\t\t\t\turl,\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t}),\n\t\t\t}\n\t\t}\n\n\t\tconst list: unknown = await response.json()\n\t\tif (!isArray(list)) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: new BrowserConnectionError('CDP target list is not a JSON array', { url }),\n\t\t\t}\n\t\t}\n\n\t\tconst targets: CDPTarget[] = []\n\t\tfor (const entry of list) {\n\t\t\tif (!isRecord(entry)) continue\n\t\t\tif (\n\t\t\t\t!isString(entry['id']) ||\n\t\t\t\t!isString(entry['type']) ||\n\t\t\t\t!isString(entry['title']) ||\n\t\t\t\t!isString(entry['url'])\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\ttargets.push({\n\t\t\t\tid: entry['id'],\n\t\t\t\tcategory: entry['type'],\n\t\t\t\ttitle: entry['title'],\n\t\t\t\turl: entry['url'],\n\t\t\t})\n\t\t}\n\n\t\treturn { success: true, value: targets }\n\t} catch (error) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: new BrowserConnectionError('CDP target list is unreachable', { url, error }),\n\t\t}\n\t} finally {\n\t\tclearTimeout(timer)\n\t}\n}\n","import type { CDPTransportEventMap, CDPTransportInterface } from '@src/core'\nimport type { EmitterInterface } from '@orkestrel/emitter'\nimport type { NodeWebSocketInterface } from '@orkestrel/websocket'\nimport type { WebSocketCDPTransportOptions } from '../types.js'\nimport type { ClientRequest, IncomingMessage, RequestOptions } from 'node:http'\nimport type { Duplex } from 'node:stream'\nimport { randomBytes } from 'node:crypto'\nimport { request as httpRequest } from 'node:http'\nimport { request as httpsRequest } from 'node:https'\nimport { attempt, isString } from '@orkestrel/contract'\nimport { Emitter } from '@orkestrel/emitter'\nimport {\n\tcomputeWebSocketAccept,\n\tcreateNodeWebSocket,\n\tWEBSOCKET_READY_CLOSED,\n\tWEBSOCKET_READY_OPEN,\n\tWEBSOCKET_VERSION,\n} from '@orkestrel/websocket'\nimport { BROWSER_DEFAULT_TIMEOUT_MS, BrowserConnectionError, BrowserTransition } from '@src/core'\n\n// === WebSocketCDPTransport\n\n/**\n * Provides a raw CDP text transport backed by `@orkestrel/websocket`.\n *\n * @remarks\n * Performs and validates the RFC 6455 HTTP upgrade, then delegates frame\n * handling to `@orkestrel/websocket`. Concurrent and repeated `start()` /\n * `close()` calls share their active transition, and a later `start()` opens a\n * fresh socket after the prior one closes.\n *\n * @example\n * ```ts\n * import { WebSocketCDPTransport } from '@orkestrel/browser/server'\n *\n * const transport = new WebSocketCDPTransport({ url: 'ws://127.0.0.1:9222/devtools/browser/abc' })\n * await transport.start()\n * await transport.close()\n * ```\n */\nexport class WebSocketCDPTransport implements CDPTransportInterface {\n\treadonly #emitter: Emitter<CDPTransportEventMap>\n\treadonly #url: string\n\treadonly #timeout: number\n\t#socket: NodeWebSocketInterface | undefined\n\treadonly #starting: BrowserTransition = new BrowserTransition()\n\treadonly #closing: BrowserTransition = new BrowserTransition()\n\t#request: ClientRequest | undefined\n\t#resolve: ((socket: NodeWebSocketInterface) => void) | undefined\n\t#reject: ((error: unknown) => void) | undefined\n\t#timer: ReturnType<typeof setTimeout> | undefined\n\t#closeResolve: (() => void) | undefined\n\treadonly #socketCloseHandler = this.#handleSocketClose.bind(this)\n\n\tconstructor(options: WebSocketCDPTransportOptions) {\n\t\tthis.#emitter = new Emitter({\n\t\t\t...(options.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t\tthis.#url = options.url\n\t\tthis.#timeout = options.timeout ?? BROWSER_DEFAULT_TIMEOUT_MS\n\t}\n\n\tget emitter(): EmitterInterface<CDPTransportEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tasync start(): Promise<void> {\n\t\tconst closing = this.#closing.pending\n\t\tif (closing !== undefined) await closing\n\t\tif (this.#socket?.readyState === WEBSOCKET_READY_OPEN) return\n\n\t\tconst active = this.#starting.pending\n\t\tif (active !== undefined) {\n\t\t\tawait active\n\t\t\treturn\n\t\t}\n\n\t\tthis.#socket?.destroy()\n\t\tthis.#socket = undefined\n\t\tawait this.#starting.execute(() => this.#start())\n\t}\n\n\tasync send(data: string): Promise<void> {\n\t\tconst socket = this.#socket\n\t\tif (socket === undefined || socket.readyState !== WEBSOCKET_READY_OPEN) {\n\t\t\tthrow new BrowserConnectionError('WebSocket CDP transport is not open', { url: this.#url })\n\t\t}\n\t\tsocket.send(data)\n\t}\n\n\tasync close(): Promise<void> {\n\t\tawait this.#closing.execute(() => this.#close())\n\t}\n\n\t// === Private helpers\n\n\tasync #start(): Promise<void> {\n\t\tconst parsed = attempt(() => new URL(this.#url))\n\t\tif (!parsed.success) {\n\t\t\tthrow new BrowserConnectionError(`WebSocket CDP URL is invalid: ${this.#url}`, {\n\t\t\t\turl: this.#url,\n\t\t\t\terror: parsed.error,\n\t\t\t})\n\t\t}\n\t\tconst url = parsed.value\n\t\tif (url.protocol !== 'ws:' && url.protocol !== 'wss:') {\n\t\t\tthrow new BrowserConnectionError(\n\t\t\t\t`WebSocket CDP connection requires a ws: or wss: URL: ${this.#url}`,\n\t\t\t\t{ url: this.#url },\n\t\t\t)\n\t\t}\n\t\tconst key = randomBytes(16).toString('base64')\n\t\tconst deferred = Promise.withResolvers<NodeWebSocketInterface>()\n\t\tconst options: RequestOptions = {\n\t\t\thostname: url.hostname,\n\t\t\tport: url.port.length > 0 ? Number(url.port) : url.protocol === 'wss:' ? 443 : 80,\n\t\t\tpath: `${url.pathname}${url.search}`,\n\t\t\theaders: {\n\t\t\t\tConnection: 'Upgrade',\n\t\t\t\tUpgrade: 'websocket',\n\t\t\t\t'Sec-WebSocket-Key': key,\n\t\t\t\t'Sec-WebSocket-Version': WEBSOCKET_VERSION,\n\t\t\t},\n\t\t}\n\t\tconst request = url.protocol === 'wss:' ? httpsRequest(options) : httpRequest(options)\n\n\t\tthis.#request = request\n\t\tthis.#resolve = deferred.resolve\n\t\tthis.#reject = deferred.reject\n\t\tthis.#timer = setTimeout(() => this.#expire(request), this.#timeout)\n\n\t\trequest.on('upgrade', (response: IncomingMessage, socket: Duplex, head: Buffer) => {\n\t\t\tthis.#upgrade(request, key, response, socket, head)\n\t\t})\n\t\trequest.on('response', (response) => this.#decline(request, response))\n\t\trequest.on('error', (error) => this.#fail(request, error))\n\t\trequest.end()\n\n\t\tconst socket = await deferred.promise\n\t\tthis.#socket = socket\n\t\tthis.#bind(socket)\n\t}\n\n\tasync #close(): Promise<void> {\n\t\tconst request = this.#request\n\t\tif (request !== undefined) {\n\t\t\tthis.#rejectRequest(\n\t\t\t\trequest,\n\t\t\t\tnew BrowserConnectionError(\n\t\t\t\t\t`WebSocket CDP connection to ${this.#url} was closed before it finished connecting`,\n\t\t\t\t\t{ url: this.#url },\n\t\t\t\t),\n\t\t\t)\n\t\t\trequest.destroy()\n\t\t}\n\t\tawait this.#starting.pending?.catch(() => undefined)\n\n\t\tconst socket = this.#socket\n\t\tthis.#socket = undefined\n\t\tif (socket === undefined || socket.readyState === WEBSOCKET_READY_CLOSED) return\n\n\t\tconst closed = Promise.withResolvers<void>()\n\t\tthis.#closeResolve = closed.resolve\n\t\tsocket.emitter.on('close', this.#socketCloseHandler)\n\t\ttry {\n\t\t\tsocket.close()\n\t\t\tif (socket.readyState !== WEBSOCKET_READY_CLOSED) await closed.promise\n\t\t} catch {\n\t\t\tsocket.destroy()\n\t\t\tif (socket.readyState !== WEBSOCKET_READY_CLOSED) await closed.promise\n\t\t} finally {\n\t\t\tsocket.emitter.off('close', this.#socketCloseHandler)\n\t\t\tthis.#closeResolve = undefined\n\t\t}\n\t}\n\n\t#upgrade(\n\t\trequest: ClientRequest,\n\t\tkey: string,\n\t\tresponse: IncomingMessage,\n\t\tsocket: Duplex,\n\t\thead: Buffer,\n\t): void {\n\t\tif (this.#request !== request) {\n\t\t\tsocket.destroy()\n\t\t\treturn\n\t\t}\n\n\t\tconst accept = response.headers['sec-websocket-accept']\n\t\tif (!isString(accept) || accept !== computeWebSocketAccept(key)) {\n\t\t\tsocket.destroy()\n\t\t\tthis.#rejectRequest(\n\t\t\t\trequest,\n\t\t\t\tnew BrowserConnectionError(\n\t\t\t\t\t`WebSocket CDP connection to ${this.#url} failed: Sec-WebSocket-Accept mismatch`,\n\t\t\t\t\t{ url: this.#url },\n\t\t\t\t),\n\t\t\t)\n\t\t\treturn\n\t\t}\n\n\t\ttry {\n\t\t\tthis.#resolveRequest(request, createNodeWebSocket({ socket, head }))\n\t\t} catch (error) {\n\t\t\tsocket.destroy()\n\t\t\tthis.#rejectRequest(request, error)\n\t\t}\n\t}\n\n\t#decline(request: ClientRequest, response: IncomingMessage): void {\n\t\tresponse.resume()\n\t\tconst reason =\n\t\t\tresponse.statusCode === undefined\n\t\t\t\t? 'upgrade was declined without a status code'\n\t\t\t\t: `upgrade declined with status ${response.statusCode}`\n\t\tthis.#rejectRequest(\n\t\t\trequest,\n\t\t\tnew BrowserConnectionError(`WebSocket CDP connection to ${this.#url} failed: ${reason}`, {\n\t\t\t\turl: this.#url,\n\t\t\t}),\n\t\t)\n\t}\n\n\t#fail(request: ClientRequest, error: Error): void {\n\t\tthis.#rejectRequest(\n\t\t\trequest,\n\t\t\tnew BrowserConnectionError(\n\t\t\t\t`WebSocket CDP connection to ${this.#url} failed: ${error.message}`,\n\t\t\t\t{ url: this.#url },\n\t\t\t),\n\t\t)\n\t}\n\n\t#expire(request: ClientRequest): void {\n\t\tthis.#rejectRequest(\n\t\t\trequest,\n\t\t\tnew BrowserConnectionError(\n\t\t\t\t`WebSocket CDP connection to ${this.#url} timed out after ${this.#timeout}ms`,\n\t\t\t\t{ url: this.#url, timeout: this.#timeout },\n\t\t\t),\n\t\t)\n\t\trequest.destroy()\n\t}\n\n\t#resolveRequest(request: ClientRequest, socket: NodeWebSocketInterface): void {\n\t\tif (this.#request !== request) {\n\t\t\tsocket.destroy()\n\t\t\treturn\n\t\t}\n\n\t\tconst resolve = this.#resolve\n\t\tthis.#clearRequest()\n\t\tresolve?.(socket)\n\t}\n\n\t#rejectRequest(request: ClientRequest, error: unknown): void {\n\t\tif (this.#request !== request) return\n\n\t\tconst reject = this.#reject\n\t\tthis.#clearRequest()\n\t\treject?.(error)\n\t}\n\n\t#clearRequest(): void {\n\t\tif (this.#timer !== undefined) clearTimeout(this.#timer)\n\t\tthis.#timer = undefined\n\t\tthis.#request = undefined\n\t\tthis.#resolve = undefined\n\t\tthis.#reject = undefined\n\t}\n\n\t#bind(socket: NodeWebSocketInterface): void {\n\t\tsocket.emitter.on('message', (data) => this.#emitter.emit('message', data))\n\t\tsocket.emitter.on('close', () => {\n\t\t\tif (this.#socket === socket) this.#socket = undefined\n\t\t\tthis.#emitter.emit('close')\n\t\t})\n\t\tsocket.emitter.on('error', (error) => this.#emitter.emit('error', error))\n\t}\n\n\t#handleSocketClose(): void {\n\t\tthis.#closeResolve?.()\n\t}\n}\n","import type { BrowserWriterInterface } from '@src/core'\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport { dirname } from 'node:path'\n\n// === FileBrowserWriter\n\n/**\n * Persists captured browser bytes to the filesystem through `node:fs/promises`.\n *\n * @remarks\n * Creates every missing parent directory of the target path before writing, so\n * a caller may name a nested destination that does not exist yet.\n *\n * @example\n * ```ts\n * import { FileBrowserWriter } from '@orkestrel/browser/server'\n *\n * const writer = new FileBrowserWriter()\n * await writer.write('shots/hero.png', new Uint8Array([137, 80, 78, 71]))\n * ```\n */\nexport class FileBrowserWriter implements BrowserWriterInterface {\n\t/**\n\t * Writes the captured bytes to a path, creating its parent directories.\n\t *\n\t * @param path - Destination file path\n\t * @param data - Captured bytes to persist\n\t * @returns A promise resolving once the bytes are on disk\n\t */\n\tasync write(path: string, data: Uint8Array): Promise<void> {\n\t\tawait mkdir(dirname(path), { recursive: true })\n\t\tawait writeFile(path, data)\n\t}\n}\n","{\n\t\"name\": \"@orkestrel/browser\",\n\t\"version\": \"0.0.26\",\n\t\"description\": \"Chrome DevTools Protocol browser automation with an environment-agnostic core. Part of the @orkestrel line.\",\n\t\"keywords\": [\n\t\t\"automation\",\n\t\t\"browser\",\n\t\t\"cdp\",\n\t\t\"chrome\",\n\t\t\"chromium\",\n\t\t\"devtools\",\n\t\t\"orkestrel\",\n\t\t\"screenshot\",\n\t\t\"typescript\"\n\t],\n\t\"homepage\": \"https://github.com/orkestrel/browser#readme\",\n\t\"bugs\": \"https://github.com/orkestrel/browser/issues\",\n\t\"license\": \"MIT\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"git+https://github.com/orkestrel/browser.git\"\n\t},\n\t\"bin\": {\n\t\t\"browse\": \"dist/bin/main.js\"\n\t},\n\t\"files\": [\n\t\t\"dist/src\",\n\t\t\"dist/bin\",\n\t\t\"README.md\"\n\t],\n\t\"type\": \"module\",\n\t\"sideEffects\": false,\n\t\"main\": \"./dist/src/core/index.cjs\",\n\t\"module\": \"./dist/src/core/index.js\",\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"import\": {\n\t\t\t\t\"types\": \"./dist/src/core/index.d.ts\",\n\t\t\t\t\"default\": \"./dist/src/core/index.js\"\n\t\t\t},\n\t\t\t\"require\": {\n\t\t\t\t\"types\": \"./dist/src/core/index.d.cts\",\n\t\t\t\t\"default\": \"./dist/src/core/index.cjs\"\n\t\t\t}\n\t\t},\n\t\t\"./server\": {\n\t\t\t\"import\": {\n\t\t\t\t\"types\": \"./dist/src/server/index.d.ts\",\n\t\t\t\t\"default\": \"./dist/src/server/index.js\"\n\t\t\t},\n\t\t\t\"require\": {\n\t\t\t\t\"types\": \"./dist/src/server/index.d.cts\",\n\t\t\t\t\"default\": \"./dist/src/server/index.cjs\"\n\t\t\t}\n\t\t},\n\t\t\"./browser\": {\n\t\t\t\"types\": \"./dist/src/browser/index.d.ts\",\n\t\t\t\"default\": \"./dist/src/browser/index.js\"\n\t\t},\n\t\t\"./package.json\": \"./package.json\"\n\t},\n\t\"publishConfig\": {\n\t\t\"access\": \"public\"\n\t},\n\t\"scripts\": {\n\t\t\"clean\": \"node -e \\\"require('node:fs').rmSync('dist',{recursive:true,force:true})\\\"\",\n\t\t\"copy\": \"node -e \\\"const fs=require('node:fs'),p=require('node:path'),a=process.argv[1],b=process.argv[2];fs.mkdirSync(p.dirname(b),{recursive:true});fs.cpSync(a,b,{force:true});console.log('Copied: '+a+' to '+b)\\\"\",\n\t\t\"scaffold\": \"scaffold\",\n\t\t\"lint\": \"oxlint --config .oxlintrc.json --fix .\",\n\t\t\"check\": \"tsc --noEmit --project tsconfig.json && npm run check:src\",\n\t\t\"check:src\": \"npm run check:src:core && npm run check:src:server && npm run check:src:browser && npm run check:src:bin\",\n\t\t\"check:src:core\": \"tsc --noEmit -p configs/src/tsconfig.core.json\",\n\t\t\"check:src:server\": \"tsc --noEmit -p configs/src/tsconfig.server.json\",\n\t\t\"check:src:browser\": \"tsc --noEmit -p configs/src/tsconfig.browser.json\",\n\t\t\"check:src:bin\": \"tsc --noEmit -p configs/src/tsconfig.bin.json\",\n\t\t\"format\": \"oxfmt --config .oxfmtrc.json --write .\",\n\t\t\"format:check\": \"oxfmt --config .oxfmtrc.json --check .\",\n\t\t\"lint:check\": \"oxlint --config .oxlintrc.json --deny-warnings .\",\n\t\t\"test\": \"npm run test:src && npm run test:src:bin && npm run test:policy && npm run test:config && npm run test:setup && npm run test:setup:browser && npm run test:guides && npm run test:conformance\",\n\t\t\"test:conformance\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project conformance\",\n\t\t\"test:src\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project src:core --project src:server --project src:browser\",\n\t\t\"test:src:core\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project src:core\",\n\t\t\"test:src:server\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project src:server\",\n\t\t\"test:src:browser\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project src:browser\",\n\t\t\"test:src:bin\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project src:bin\",\n\t\t\"test:policy\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project policy\",\n\t\t\"test:config\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project config\",\n\t\t\"test:guides\": \"node --experimental-strip-types tests/guides.test.ts\",\n\t\t\"build\": \"npm run clean && npm run build:src\",\n\t\t\"build:src\": \"npm run build:src:core && npm run build:src:server && npm run build:src:browser && npm run build:src:bin\",\n\t\t\"build:src:core\": \"vite build --config configs/src/vite.core.config.ts && npm run copy dist/src/core/index.d.ts dist/src/core/index.d.cts\",\n\t\t\"build:src:server\": \"vite build --config configs/src/vite.server.config.ts && npm run copy dist/src/server/index.d.ts dist/src/server/index.d.cts\",\n\t\t\"build:src:browser\": \"vite build --config configs/src/vite.browser.config.ts\",\n\t\t\"build:src:bin\": \"vite build --config configs/src/vite.bin.config.ts\",\n\t\t\"prepack\": \"npm run build\",\n\t\t\"prepublishOnly\": \"npm run format:check && npm run lint:check && npm run check && npm run build && npm test && npm run test:distribution -- --mode release && npm run test:service\",\n\t\t\"test:distribution\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project distribution\",\n\t\t\"test:service\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project service\",\n\t\t\"test:probe\": \"vitest run --config vite.config.ts --no-cache --reporter=verbose --project probe\",\n\t\t\"test:bench\": \"vitest bench --config vite.config.ts --no-cache --project probe\",\n\t\t\"test:setup\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project setup\",\n\t\t\"test:setup:browser\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project setup:browser\"\n\t},\n\t\"dependencies\": {\n\t\t\"@orkestrel/contract\": \"^0.0.19\",\n\t\t\"@orkestrel/emitter\": \"^0.0.11\",\n\t\t\"@orkestrel/html\": \"^0.0.12\",\n\t\t\"@orkestrel/markdown\": \"^0.0.17\",\n\t\t\"@orkestrel/mcp\": \"^0.0.36\",\n\t\t\"@orkestrel/pool\": \"^0.0.16\",\n\t\t\"@orkestrel/router\": \"^0.0.16\",\n\t\t\"@orkestrel/server\": \"^0.0.22\",\n\t\t\"@orkestrel/tool\": \"^0.0.18\",\n\t\t\"@orkestrel/websocket\": \"^0.0.14\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@microsoft/api-extractor\": \"^7.59.4\",\n\t\t\"@orkestrel/guide\": \"^0.0.24\",\n\t\t\"@orkestrel/probe\": \"^0.0.20\",\n\t\t\"@orkestrel/scaffold\": \"^0.0.92\",\n\t\t\"@orkestrel/test\": \"^0.0.24\",\n\t\t\"@types/node\": \"^26.6.4\",\n\t\t\"@vitest/browser-playwright\": \"^4.1.11\",\n\t\t\"oxfmt\": \"^0.72.0\",\n\t\t\"oxlint\": \"^1.87.0\",\n\t\t\"playwright\": \"^1.63.0\",\n\t\t\"typescript\": \"^6.0.3\",\n\t\t\"vite\": \"^8.3.2\",\n\t\t\"vitest\": \"^4.1.11\"\n\t},\n\t\"engines\": {\n\t\t\"node\": \">=22.12.0\"\n\t}\n}\n","import type {\n\tBrowserContextInterface,\n\tBrowserPageInterface,\n\tBrowserToolsetInterface,\n\tBrowserViewport,\n} from '@src/core'\nimport type { MCPCallResult, MCPExecutionContext, MCPMethodOptions } from '@orkestrel/mcp'\nimport type { PoolInterface, PoolToken } from '@orkestrel/pool'\nimport type { StdioServerInterface } from '@orkestrel/mcp/server'\nimport type { ToolContext, ToolInterface, ToolManagerInterface, ToolResult } from '@orkestrel/tool'\nimport type {\n\tBrowserInterface,\n\tBrowserLaunchFunction,\n\tBrowserMCPServerInterface,\n\tBrowserMCPServerOptions,\n\tBrowserServerHolder,\n\tBrowserServerCatalog,\n\tBrowserServerMirror,\n\tBrowserSlot,\n\tBrowserSlotWatch,\n\tBrowserServerContext,\n\tBrowserServerLease,\n\tBrowserServerLoss,\n\tBrowserServerWatch,\n} from './types.js'\nimport { randomUUID } from 'node:crypto'\nimport { addAbortListener } from 'node:events'\nimport { mkdir, readFile, readdir, rename, rm, writeFile } from 'node:fs/promises'\nimport { join, resolve } from 'node:path'\nimport { isError, isInteger, isRecord, isString } from '@orkestrel/contract'\nimport { createMCPLegacy, createMCPServer, JSONRPC_SERVER_ERROR, MCPError } from '@orkestrel/mcp'\nimport { createPool, isPoolError } from '@orkestrel/pool'\nimport { createStdioServer } from '@orkestrel/mcp/server'\nimport { createTool, createToolManager, toolToDefinition } from '@orkestrel/tool'\nimport {\n\tBROWSER_JOURNEY_TOOL_NAMES,\n\tBROWSER_TOOL_COPY,\n\tBROWSER_TOOL_NAMES,\n\tBrowserError,\n\tcreateBrowserToolset,\n\tcreateCDPClient,\n\tisBrowserError,\n\tisCDPConnectionError,\n\tisCDPTimeoutError,\n} from '@src/core'\nimport { version } from '../../package.json' with { type: 'json' }\nimport {\n\tcreateBrowser,\n\tcreateCDPTransport,\n\tcreateFileBrowserJourneyStore,\n\tcreateFileBrowserRunStore,\n} from './factories.js'\nimport {\n\tBROWSER_SERVER_EXHAUSTED,\n\tBROWSER_SERVER_BUSY,\n\tBROWSER_SERVER_HOLDER,\n\tBROWSER_SERVER_COPY,\n\tBROWSER_SERVER_LAUNCH,\n\tBROWSER_SERVER_OPTIONS,\n\tBROWSER_SERVER_POOL_LIMIT,\n\tBROWSER_SERVER_POOL_SIZE,\n\tBROWSER_SERVER_CONTEXTS,\n\tBROWSER_SERVER_CONTEXTS_LIMIT,\n\tBROWSER_SERVER_RECORD,\n\tBROWSER_SERVER_RESTARTS,\n\tBROWSER_SERVER_SWEEP,\n\tBROWSER_SERVER_TEARDOWN,\n\tBROWSER_SERVER_UNAVAILABLE,\n\tBROWSER_SERVER_CRASH,\n\tBROWSER_SERVER_UNRESOLVED,\n} from './constants.js'\nimport {\n\tdescribeBrowserServerLoss,\n\tformatBrowserLockEntry,\n\tparseBrowserLockEntry,\n\tparseBrowserProfileRecord,\n\tprobeProcess,\n} from './helpers.js'\n\n/**\n * Implements `BrowserMCPServerInterface`: serves the browser vocabulary and the journey tools over\n * the Model Context Protocol on stdio, and warms Chromium at server start.\n *\n * @remarks\n * The server's own manager holds one dispatcher per name of the vocabulary — `look`, `read`, `plain`,\n * `click`, `type`, `press`, `navigate`, `wait`, `dialog`, `tabs`, `switch`, `record`, `save`,\n * `journeys`, `edit`, `replay`, and `forget` — each carrying the description, parameters, and annotations\n * `BROWSER_TOOL_COPY` gives, so `tools/list` answers before Chromium starts and with Chromium\n * absent. After the launch, a tool the toolset's manager adds under another name, such as a page\n * tool it adopts, is mirrored as a dispatcher with that tool's definition, and the mirror is\n * removed when the toolset withdraws the tool, so the server's tool list changes and a subscribed\n * client is notified. The server also advertises `acquire`, `execute`, `tools`, and `destroy` with\n * `BROWSER_SERVER_COPY`. Startup warms the pool and assigns a prepared context to the shared holder. The legacy\n * handshake and browser calls await that setup. Named holders each own a lease, a pending grant,\n * and loss notices; concurrent calls on a holder share its replacement grant. Ending a holder\n * closes its context and releases its lease, and admission counts that holder until disposal settles.\n * A launch creates `ROOT/.profiles/PID-UUID/` exclusively, connects a browser that never attaches to an\n * existing endpoint, opens one page in an isolated context, and constructs the page toolset with\n * that context and the file journey and run stores under the root, on a manager the toolset owns.\n * A dispatcher forwards its arguments and the call's context, signal included, to the toolset's\n * manager and returns that manager's value, or rejects with its failure message; a text value\n * reaches the client as one text block rather than as its JSON text.\n * A disconnect retires its browser and every hosted generation. A current-page crash retires only\n * that holder's context. A failed call receives a liveness ping;\n * loss makes its outcome unresolved, while a known success remains successful. Pending losses\n * prefix the next outcome on a successor, or a refusal, and calls are never repeated.\n * Concurrent checks share one ping per slot. Cancelling a call ends only its wait; the ping keeps\n * its deadline and records loss for the next call.\n *\n * `start()` serves stdio and destroys the server at the end of its input, on `SIGINT`, and on\n * `SIGTERM`. `destroy()` stops reading requests and removes every dispatcher, then destroys every\n * slot through the pool — each toolset, which aborts its active replay, then its context and downloads,\n * then its browser and its\n * profile — and rechecks the profile folders this server made or kept.\n *\n * Chromium on Linux refuses to start as the root user unless its sandbox is disabled, so a server\n * running as root on Linux launches Chromium with `--no-sandbox`; a launch that could run\n * sandboxed is never changed.\n *\n * @example\n * ```ts\n * import { BrowserMCPServer } from '@orkestrel/browser/server'\n *\n * const server = new BrowserMCPServer({ root: 'tmp/browsers', readonly: true })\n * await server.start()\n * await server.destroy()\n * ```\n */\nexport class BrowserMCPServer implements BrowserMCPServerInterface {\n\treadonly #root: string\n\treadonly #headless: boolean\n\treadonly #executable: string | undefined\n\treadonly #viewport: BrowserViewport | undefined\n\treadonly #readonly: boolean\n\treadonly #launcher: BrowserLaunchFunction\n\treadonly #input: NodeJS.ReadableStream\n\treadonly #tools: ToolManagerInterface\n\treadonly #transport: StdioServerInterface\n\treadonly #abort = new AbortController()\n\treadonly #signal: () => void\n\treadonly #vocabulary: ReadonlySet<string>\n\t#mirrored: BrowserServerMirror | undefined\n\treadonly #pool: PoolInterface<BrowserSlot>\n\treadonly #log: NodeJS.WritableStream\n\treadonly #folders = new Set<string>()\n\treadonly #faults = new Set<unknown>()\n\treadonly #losses = new WeakMap<BrowserSlot, { readonly cause: unknown }>()\n\treadonly #departures = new WeakMap<BrowserServerLease, BrowserServerLoss>()\n\treadonly #pings = new WeakMap<BrowserSlot, Promise<void>>()\n\treadonly #watches = new Map<BrowserSlot, BrowserSlotWatch>()\n\treadonly #observed = new Map<BrowserServerContext, BrowserServerWatch>()\n\treadonly #prepared = new Map<BrowserSlot, BrowserServerContext>()\n\treadonly #owned = new Map<BrowserSlot, Set<BrowserServerContext>>()\n\treadonly #building = new Map<BrowserSlot, Set<Promise<BrowserServerContext>>>()\n\treadonly #cleaning = new WeakMap<BrowserServerContext, Promise<boolean>>()\n\treadonly #endings = new WeakMap<BrowserSlot, PromiseWithResolvers<void>>()\n\treadonly #retentions = new Map<BrowserServerHolder, unknown>()\n\treadonly #shared: BrowserServerHolder = {\n\t\tid: 'shared',\n\t\tpurpose: 'Shared browser',\n\t\tabort: this.#abort,\n\t}\n\treadonly #holders = new Map<string, BrowserServerHolder>([[this.#shared.id, this.#shared]])\n\treadonly #leases = new Map<BrowserServerHolder, BrowserServerLease>()\n\treadonly #grants = new Map<BrowserServerHolder, Promise<BrowserServerLease>>()\n\treadonly #notices = new Map<BrowserServerHolder, Set<BrowserServerLease>>()\n\treadonly #disposals = new Map<string, Promise<void>>()\n\treadonly #drains = new Map<BrowserServerHolder, Set<Promise<void>>>()\n\treadonly #readers = new Map<string, Set<symbol>>()\n\treadonly #writers = new Set<string>()\n\treadonly #admission: number\n\treadonly #reference: () => string\n\t#references = 0\n\t#failure: unknown\n\t#stranded: unknown\n\t#starting: Promise<void> | undefined\n\t#sweeping: Promise<void> | undefined\n\t#closing: Promise<void> | undefined\n\n\t/**\n\t * Registers the dispatchers and binds the protocol to the stdio streams without reading them.\n\t *\n\t * @param options - The root, the launch, the journeys' read-only switch, and the streams\n\t */\n\tconstructor(options?: BrowserMCPServerOptions) {\n\t\tconst size = options?.pool?.size ?? BROWSER_SERVER_POOL_SIZE\n\t\tconst contexts = options?.pool?.contexts ?? BROWSER_SERVER_CONTEXTS\n\t\tif (!isInteger(size) || size < 1 || size > BROWSER_SERVER_POOL_LIMIT)\n\t\t\tthrow new BrowserError(\n\t\t\t\t`pool.size must be an integer from 1 through ${BROWSER_SERVER_POOL_LIMIT}`,\n\t\t\t\tBROWSER_SERVER_OPTIONS,\n\t\t\t)\n\t\tif (!isInteger(contexts) || contexts < 1 || contexts > BROWSER_SERVER_CONTEXTS_LIMIT)\n\t\t\tthrow new BrowserError(\n\t\t\t\t`pool.contexts must be an integer from 1 through ${BROWSER_SERVER_CONTEXTS_LIMIT}`,\n\t\t\t\tBROWSER_SERVER_OPTIONS,\n\t\t\t)\n\t\tthis.#admission = size * contexts\n\t\tthis.#log = options?.log ?? process.stderr\n\t\tthis.#reference = this.#issue.bind(this)\n\t\tthis.#pool = createPool<BrowserSlot>({\n\t\t\tcreate: this.#warm.bind(this),\n\t\t\tdestroy: this.#destroyRecord.bind(this),\n\t\t\tvalidate: this.#validate.bind(this),\n\t\t\twatch: this.#watch.bind(this),\n\t\t\terror: this.#fault.bind(this),\n\t\t\tmin: size,\n\t\t\tcapacity: contexts,\n\t\t\trestarts: BROWSER_SERVER_RESTARTS,\n\t\t})\n\t\tthis.#root = resolve(options?.root ?? 'tmp/browsers')\n\t\tthis.#headless = options?.headless ?? true\n\t\tthis.#executable = options?.executable\n\t\tthis.#viewport = options?.viewport\n\t\tthis.#readonly = options?.readonly ?? false\n\t\tthis.#launcher = options?.launch ?? createBrowser\n\t\tthis.#input = options?.stdio?.input ?? process.stdin\n\t\tthis.#tools = createToolManager()\n\t\tconst names = [...BROWSER_TOOL_NAMES, ...BROWSER_JOURNEY_TOOL_NAMES]\n\t\tthis.#vocabulary = new Set([...names, ...Object.keys(BROWSER_SERVER_COPY)])\n\t\tfor (const name of names) {\n\t\t\tthis.#tools.add(\n\t\t\t\tcreateTool({\n\t\t\t\t\t...BROWSER_TOOL_COPY[name],\n\t\t\t\t\texecute: this.#forward.bind(this, this.#shared, name),\n\t\t\t\t}),\n\t\t\t)\n\t\t}\n\t\tthis.#tools.add(\n\t\t\tcreateTool({ ...BROWSER_SERVER_COPY.acquire, execute: this.#acquire.bind(this) }),\n\t\t)\n\t\tthis.#tools.add(\n\t\t\tcreateTool({ ...BROWSER_SERVER_COPY.execute, execute: this.#dispatch.bind(this) }),\n\t\t)\n\t\tthis.#tools.add(createTool({ ...BROWSER_SERVER_COPY.tools, execute: this.#catalog.bind(this) }))\n\t\tthis.#tools.add(\n\t\t\tcreateTool({ ...BROWSER_SERVER_COPY.destroy, execute: this.#dispose.bind(this) }),\n\t\t)\n\t\tconst server = createMCPServer({\n\t\t\tidentity: { name: 'browse', version },\n\t\t\ttools: this.#tools,\n\t\t\texecution: this.#execute.bind(this),\n\t\t\thandshake: this.#handshake.bind(this),\n\t\t})\n\t\tthis.#transport = createStdioServer(createMCPLegacy(server), {\n\t\t\tinput: this.#input,\n\t\t\t...(options?.stdio?.output === undefined ? {} : { output: options.stdio.output }),\n\t\t})\n\t\t// One reference serves the end of input and both signals, because a listener is removed by\n\t\t// identity.\n\t\tthis.#signal = this.#end.bind(this)\n\t}\n\n\tasync start(): Promise<void> {\n\t\tif (this.#closing !== undefined) throw this.#ended()\n\t\tthis.#starting ??= this.#setup()\n\t\treturn this.#starting\n\t}\n\n\tdestroy(): Promise<void> {\n\t\tthis.#closing ??= Promise.resolve().then(this.#destroy.bind(this))\n\t\treturn this.#closing\n\t}\n\n\tasync #setup(): Promise<void> {\n\t\tthis.#input.on('end', this.#signal)\n\t\tprocess.on('SIGINT', this.#signal)\n\t\tprocess.on('SIGTERM', this.#signal)\n\t\tthis.#transport.start()\n\t\ttry {\n\t\t\tawait mkdir(join(this.#root, '.profiles'), { recursive: true })\n\t\t\tif (this.#closing !== undefined) return\n\t\t\tthis.#sweeping = this.#sweep()\n\t\t\tconst warming = this.#pool.start().then(undefined, (error: unknown) => error)\n\t\t\tawait this.#grant(this.#shared, this.#abort.signal)\n\t\t\tif (this.#closing !== undefined) return\n\t\t\tvoid warming.then(this.#exhaust.bind(this))\n\t\t} catch (error) {\n\t\t\tif (this.#closing !== undefined) return\n\t\t\tif (isBrowserError(error) && error.code === BROWSER_SERVER_UNAVAILABLE) throw error\n\t\t\tthrow this.#unavailable(isPoolError(error) ? (error.cause ?? this.#failure) : error)\n\t\t}\n\t}\n\n\tasync #destroy(): Promise<void> {\n\t\t// The handlers go first: a second signal during a slow teardown asks for the process.\n\t\tprocess.removeListener('SIGINT', this.#signal)\n\t\tprocess.removeListener('SIGTERM', this.#signal)\n\t\tthis.#input.removeListener('end', this.#signal)\n\t\tthis.#transport.stop()\n\t\tfor (const tool of this.#tools.tools()) this.#tools.remove(tool.name)\n\t\tthis.#unmirror()\n\t\tfor (const generation of this.#observed.keys()) this.#untrack(generation)\n\t\tthis.#leases.clear()\n\t\tfor (const holder of this.#holders.values()) holder.abort.abort()\n\t\tthis.#abort.abort()\n\t\tconst barrier = this.#pool.destroy().catch((error: unknown) => {\n\t\t\tfor (const failure of isPoolError(error) ? (error.context?.failures ?? [error]) : [error])\n\t\t\t\tthis.#faults.add(failure)\n\t\t})\n\t\tawait this.#starting?.catch(() => undefined)\n\t\tawait barrier\n\t\tawait Promise.allSettled(this.#grants.values())\n\t\tawait Promise.allSettled(this.#disposals.values())\n\t\tthis.#holders.clear()\n\t\tawait this.#sweeping\n\t\tif (this.#stranded !== undefined) this.#faults.add(this.#stranded)\n\t\tfor (const folder of this.#folders) {\n\t\t\ttry {\n\t\t\t\tconst record = parseBrowserProfileRecord(\n\t\t\t\t\tawait readFile(join(folder, BROWSER_SERVER_RECORD), 'utf8'),\n\t\t\t\t)\n\t\t\t\tif (record === undefined || probeProcess(record.pid)) continue\n\t\t\t} catch (error) {\n\t\t\t\tif (!isError(error) || !('code' in error) || error.code !== 'ENOENT') continue\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait rm(folder, { recursive: true, force: true, maxRetries: 5 })\n\t\t\t\tthis.#folders.delete(folder)\n\t\t\t} catch (error) {\n\t\t\t\tthis.#faults.add(error)\n\t\t\t}\n\t\t}\n\t\tif (this.#faults.size > 0)\n\t\t\tthrow new AggregateError([...this.#faults], 'The browse server teardown failed')\n\t}\n\n\t// Runs the dispatcher and answers a text result as one text block, because the protocol's own\n\t// rendering of a value is its JSON text, which escapes every quote and line break of a receipt.\n\tasync #execute(context: MCPExecutionContext): Promise<ToolResult | MCPCallResult> {\n\t\tconst result = await context.tools.execute(context.call, {\n\t\t\tsignal: context.signal,\n\t\t\t...(context.caller === undefined ? {} : { caller: context.caller }),\n\t\t})\n\t\tif (!result.success || typeof result.value !== 'string') return result\n\t\treturn { resultType: 'complete', content: [{ type: 'text', text: result.value }] }\n\t}\n\n\t// Answers the end of input and a termination signal.\n\t#end(): void {\n\t\tif (this.#closing !== undefined) return\n\t\tvoid this.destroy().catch(this.#endFailure.bind(this))\n\t}\n\n\t#endFailure(error: unknown): void {\n\t\tprocess.exitCode = 1\n\t\tthis.#write(`browse: ${describeBrowserServerLoss(BROWSER_SERVER_TEARDOWN, error)}`)\n\t}\n\n\tasync #acquire(args: Readonly<Record<string, unknown>>, context: ToolContext): Promise<string> {\n\t\tcontext.signal.throwIfAborted()\n\t\tif (this.#closing !== undefined) throw this.#ended()\n\t\tconst purpose = args['purpose']\n\t\tif (!isString(purpose) || purpose.trim().length === 0)\n\t\t\tthrow new BrowserError('purpose must describe the work', 'BROWSER_TOOLSET_ARGUMENT')\n\t\tif (this.#holders.size >= this.#admission)\n\t\t\tthrow new BrowserError(\n\t\t\t\t`${BROWSER_SERVER_BUSY}: ${[...this.#holders.values()].map((holder) => `${holder.id} (${holder.purpose})`).join(', ')}. Call destroy for a holder no longer needed or call the named tools to share the shared browser.`,\n\t\t\t\tBROWSER_SERVER_BUSY,\n\t\t\t)\n\t\tconst holder: BrowserServerHolder = { id: randomUUID(), purpose, abort: new AbortController() }\n\t\tthis.#holders.set(holder.id, holder)\n\t\tconst listener = addAbortListener(context.signal, () =>\n\t\t\tholder.abort.abort(context.signal.reason),\n\t\t)\n\t\ttry {\n\t\t\tconst lease = await this.#serve(holder, context.signal)\n\t\t\tcontext.signal.throwIfAborted()\n\t\t\tif (holder.abort.signal.aborted || this.#holders.get(holder.id) !== holder)\n\t\t\t\tthrow this.#ended()\n\t\t\tif (this.#leases.get(holder) !== lease)\n\t\t\t\tthrow this.#unavailable(this.#departures.get(lease)?.cause)\n\t\t\tconst catalog: BrowserServerCatalog = {\n\t\t\t\tholder: holder.id,\n\t\t\t\ttools: lease.generation.toolset.tools.definitions(),\n\t\t\t}\n\t\t\treturn JSON.stringify(catalog)\n\t\t} catch (error) {\n\t\t\tawait this.#retire(holder).catch(this.#fault.bind(this))\n\t\t\tthrow error\n\t\t} finally {\n\t\t\tlistener[Symbol.dispose]()\n\t\t}\n\t}\n\n\t#holder(value: unknown): BrowserServerHolder {\n\t\tconst holder = isString(value) ? this.#holders.get(value) : undefined\n\t\tif (holder === undefined || holder === this.#shared || holder.abort.signal.aborted)\n\t\t\tthrow new BrowserError(\n\t\t\t\t`${BROWSER_SERVER_HOLDER}: unknown or ended holder`,\n\t\t\t\tBROWSER_SERVER_HOLDER,\n\t\t\t)\n\t\treturn holder\n\t}\n\n\tasync #dispatch(args: Readonly<Record<string, unknown>>, context: ToolContext): Promise<unknown> {\n\t\tconst holder = this.#holder(args['holder'])\n\t\tconst name = args['name']\n\t\tconst parameters = args['arguments']\n\t\tif (!isString(name) || !isRecord(parameters))\n\t\t\tthrow new BrowserError('execute requires name and arguments', 'BROWSER_TOOLSET_ARGUMENT')\n\t\treturn this.#forward(holder, name, parameters, context)\n\t}\n\n\tasync #catalog(args: Readonly<Record<string, unknown>>, context: ToolContext): Promise<string> {\n\t\tconst holder = this.#holder(args['holder'])\n\t\tconst signal = AbortSignal.any([context.signal, holder.abort.signal])\n\t\ttry {\n\t\t\tconst lease = await this.#serve(holder, signal)\n\t\t\tsignal.throwIfAborted()\n\t\t\tif (this.#leases.get(holder) !== lease)\n\t\t\t\tthrow this.#unavailable(this.#departures.get(lease)?.cause)\n\t\t\tconst catalog: BrowserServerCatalog = {\n\t\t\t\tholder: holder.id,\n\t\t\t\ttools: lease.generation.toolset.tools.definitions(),\n\t\t\t}\n\t\t\treturn this.#annotate(holder, JSON.stringify(catalog))\n\t\t} catch (error) {\n\t\t\tcontext.signal.throwIfAborted()\n\t\t\tif (holder.abort.signal.aborted)\n\t\t\t\tthrow new BrowserError(\n\t\t\t\t\t`${BROWSER_SERVER_UNRESOLVED}: the holder ended during the call`,\n\t\t\t\t\tBROWSER_SERVER_UNRESOLVED,\n\t\t\t\t)\n\t\t\tif (isBrowserError(error))\n\t\t\t\tthrow new BrowserError(\n\t\t\t\t\tthis.#annotate(holder, `${error.code}: ${error.message}`),\n\t\t\t\t\terror.code,\n\t\t\t\t)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync #dispose(args: Readonly<Record<string, unknown>>): Promise<string> {\n\t\tconst id = args['holder']\n\t\tconst disposal = isString(id) ? this.#disposals.get(id) : undefined\n\t\tawait (disposal ?? this.#retire(this.#holder(id)))\n\t\treturn 'Holder destroyed.'\n\t}\n\n\t#retire(holder: BrowserServerHolder): Promise<void> {\n\t\tconst pending = this.#disposals.get(holder.id)\n\t\tif (pending !== undefined) return pending\n\t\tholder.abort.abort()\n\t\tconst lease = this.#leases.get(holder)\n\t\tthis.#leases.delete(holder)\n\t\tif (lease !== undefined) this.#untrack(lease.generation)\n\t\tconst disposal = Promise.resolve().then(async () => {\n\t\t\ttry {\n\t\t\t\tawait this.#grants.get(holder)?.catch(() => undefined)\n\t\t\t\tif (lease !== undefined) await this.#release(holder, lease)\n\t\t\t\tawait Promise.all(this.#drains.get(holder) ?? [])\n\t\t\t\tawait Promise.all(\n\t\t\t\t\t[...(this.#notices.get(holder) ?? [])]\n\t\t\t\t\t\t.filter((lost) => this.#losses.has(lost.token.value))\n\t\t\t\t\t\t.map((lost) => this.#endings.get(lost.token.value)?.promise),\n\t\t\t\t)\n\t\t\t} catch (error) {\n\t\t\t\tthis.#faults.add(error)\n\t\t\t} finally {\n\t\t\t\tif (this.#holders.get(holder.id) === holder && !this.#retentions.has(holder))\n\t\t\t\t\tthis.#holders.delete(holder.id)\n\t\t\t\tthis.#notices.delete(holder)\n\t\t\t\tthis.#drains.delete(holder)\n\t\t\t}\n\t\t})\n\t\tthis.#disposals.set(holder.id, disposal)\n\t\treturn disposal\n\t}\n\n\tasync #forward(\n\t\tholder: BrowserServerHolder,\n\t\tname: string,\n\t\targs: Readonly<Record<string, unknown>>,\n\t\tcontext: ToolContext,\n\t): Promise<unknown> {\n\t\tcontext.signal.throwIfAborted()\n\t\tconst journey = args['journey']\n\t\tif ((name !== 'replay' && name !== 'forget') || !isString(journey))\n\t\t\treturn this.#perform(holder, name, args, context)\n\t\tif (this.#writers.has(journey) || (name === 'forget' && this.#readers.has(journey)))\n\t\t\tthrow new BrowserError(\n\t\t\t\t`BROWSER_JOURNEY_LOCKED: Journey ${journey} is locked; call ${name} again.`,\n\t\t\t\t'BROWSER_JOURNEY_LOCKED',\n\t\t\t\t{ name: journey },\n\t\t\t)\n\t\tconst reader = Symbol(journey)\n\t\tif (name === 'forget') this.#writers.add(journey)\n\t\telse {\n\t\t\tconst readers = this.#readers.get(journey) ?? new Set<symbol>()\n\t\t\treaders.add(reader)\n\t\t\tthis.#readers.set(journey, readers)\n\t\t}\n\t\ttry {\n\t\t\treturn await this.#perform(holder, name, args, context)\n\t\t} finally {\n\t\t\tif (name === 'forget') this.#writers.delete(journey)\n\t\t\telse {\n\t\t\t\tconst readers = this.#readers.get(journey)\n\t\t\t\treaders?.delete(reader)\n\t\t\t\tif (readers?.size === 0) this.#readers.delete(journey)\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #perform(\n\t\tholder: BrowserServerHolder,\n\t\tname: string,\n\t\targs: Readonly<Record<string, unknown>>,\n\t\tcontext: ToolContext,\n\t): Promise<unknown> {\n\t\tconst signal =\n\t\t\tholder === this.#shared\n\t\t\t\t? context.signal\n\t\t\t\t: AbortSignal.any([context.signal, holder.abort.signal])\n\t\tlet lease: BrowserServerLease\n\t\ttry {\n\t\t\tlease = await this.#serve(holder, signal)\n\t\t} catch (error) {\n\t\t\tcontext.signal.throwIfAborted()\n\t\t\tif (holder !== this.#shared && holder.abort.signal.aborted)\n\t\t\t\tthrow new BrowserError(\n\t\t\t\t\t`${BROWSER_SERVER_UNRESOLVED}: the holder ended during the call`,\n\t\t\t\t\tBROWSER_SERVER_UNRESOLVED,\n\t\t\t\t)\n\t\t\tif (isBrowserError(error))\n\t\t\t\tthrow new BrowserError(\n\t\t\t\t\tthis.#annotate(holder, `${error.code}: ${error.message}`),\n\t\t\t\t\terror.code,\n\t\t\t\t)\n\t\t\tthrow error\n\t\t}\n\t\tlet result: ToolResult\n\t\ttry {\n\t\t\tconst execution = lease.generation.toolset.tools.execute(\n\t\t\t\t{ id: name, name, arguments: args },\n\t\t\t\t{ ...context, signal },\n\t\t\t)\n\t\t\t// A cancelled replay still persists its run before surrendering admission.\n\t\t\tconst outcome = await (name === 'replay' || name === 'forget'\n\t\t\t\t? execution\n\t\t\t\t: this.#race(execution, signal))\n\t\t\tif (outcome === undefined) throw this.#ended()\n\t\t\tresult = outcome\n\t\t} catch (error) {\n\t\t\tresult = {\n\t\t\t\tid: name,\n\t\t\t\tname,\n\t\t\t\tsuccess: false,\n\t\t\t\terror: isError(error) ? error.message : String(error),\n\t\t\t}\n\t\t}\n\t\tcontext.signal.throwIfAborted()\n\t\tif (holder !== this.#shared && holder.abort.signal.aborted)\n\t\t\tthrow new BrowserError(\n\t\t\t\tBROWSER_SERVER_UNRESOLVED + ': the holder ended during the call',\n\t\t\t\tBROWSER_SERVER_UNRESOLVED,\n\t\t\t)\n\t\tif (!result.success) {\n\t\t\tif (this.#leases.get(holder) === lease && !context.signal.aborted) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.#race(this.#ping(lease.token.value), context.signal)\n\t\t\t\t} catch {\n\t\t\t\t\t// The shared ping records loss even when this caller stops waiting.\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontext.signal.throwIfAborted()\n\t\t\tif (this.#leases.get(holder) !== lease) {\n\t\t\t\tconst loss = this.#departures.get(lease)\n\t\t\t\tthrow new BrowserError(\n\t\t\t\t\tthis.#annotate(\n\t\t\t\t\t\tholder,\n\t\t\t\t\t\tdescribeBrowserServerLoss(BROWSER_SERVER_UNRESOLVED, loss?.cause, loss?.url),\n\t\t\t\t\t\tlease,\n\t\t\t\t\t),\n\t\t\t\t\tBROWSER_SERVER_UNRESOLVED,\n\t\t\t\t)\n\t\t\t}\n\t\t\tthrow new BrowserError(this.#annotate(holder, result.error, lease))\n\t\t}\n\t\treturn typeof result.value === 'string'\n\t\t\t? this.#annotate(holder, result.value, lease)\n\t\t\t: result.value\n\t}\n\n\t#annotate(holder: BrowserServerHolder, value: string, lease?: BrowserServerLease): string {\n\t\tconst notes: string[] = []\n\t\tfor (const lost of this.#notices.get(holder) ?? []) {\n\t\t\tif (lost === lease) continue\n\t\t\tconst loss = this.#departures.get(lost)\n\t\t\tnotes.push(describeBrowserServerLoss(BROWSER_SERVER_CRASH, loss?.cause, loss?.url))\n\t\t\tthis.#notices.get(holder)?.delete(lost)\n\t\t}\n\t\treturn [...notes, value].join('\\n')\n\t}\n\n\tasync #handshake(options: MCPMethodOptions): Promise<void> {\n\t\ttry {\n\t\t\tawait this.#race(this.#starting, options.signal)\n\t\t\tif (this.#closing !== undefined) throw this.#ended()\n\t\t} catch (error) {\n\t\t\toptions.signal.throwIfAborted()\n\t\t\tif (isBrowserError(error))\n\t\t\t\tthrow new MCPError(`${error.code}: ${error.message}`, JSONRPC_SERVER_ERROR, {\n\t\t\t\t\tcode: error.code,\n\t\t\t\t})\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync #race<T>(promise: Promise<T> | undefined, signal: AbortSignal): Promise<T | undefined> {\n\t\tsignal.throwIfAborted()\n\t\tconst aborted = Promise.withResolvers<never>()\n\t\tconst listener = addAbortListener(signal, () => aborted.reject(signal.reason))\n\t\ttry {\n\t\t\treturn await Promise.race([promise, aborted.promise])\n\t\t} finally {\n\t\t\tlistener[Symbol.dispose]()\n\t\t}\n\t}\n\n\tasync #grant(holder: BrowserServerHolder, signal: AbortSignal): Promise<BrowserServerLease> {\n\t\tconst held = this.#leases.get(holder)\n\t\tif (held !== undefined) return held\n\t\tlet granting = this.#grants.get(holder)\n\t\tif (granting === undefined) {\n\t\t\tgranting = Promise.resolve().then(async () => {\n\t\t\t\tawait Promise.allSettled(this.#drains.get(holder) ?? [])\n\t\t\t\tif (this.#retentions.has(holder)) throw this.#unavailable(this.#retentions.get(holder))\n\t\t\t\tconst token = await this.#pool.acquire(holder.abort.signal)\n\t\t\t\treturn this.#hold(holder, token)\n\t\t\t})\n\t\t\tthis.#grants.set(holder, granting)\n\t\t\tvoid granting\n\t\t\t\t.finally(() => {\n\t\t\t\t\tif (this.#grants.get(holder) === granting) this.#grants.delete(holder)\n\t\t\t\t})\n\t\t\t\t.catch(() => undefined)\n\t\t}\n\t\tconst lease = await this.#race(granting, signal)\n\t\tif (lease === undefined) throw this.#ended()\n\t\treturn lease\n\t}\n\n\tasync #hold(\n\t\tholder: BrowserServerHolder,\n\t\ttoken: PoolToken<BrowserSlot>,\n\t): Promise<BrowserServerLease> {\n\t\tconst slot = token.value\n\t\tif (\n\t\t\tthis.#closing !== undefined ||\n\t\t\tthis.#holders.get(holder.id) !== holder ||\n\t\t\tholder.abort.signal.aborted\n\t\t) {\n\t\t\ttoken.release()\n\t\t\tthrow this.#ended()\n\t\t}\n\t\tif (!this.#prepared.has(slot)) await this.#ping(slot)\n\t\tif (this.#closing !== undefined || holder.abort.signal.aborted) {\n\t\t\ttoken.release()\n\t\t\tthrow this.#ended()\n\t\t}\n\t\tif (this.#losses.has(slot)) {\n\t\t\ttoken.release()\n\t\t\tthrow this.#unavailable(this.#losses.get(slot)?.cause)\n\t\t}\n\t\tlet generation = this.#prepared.get(slot)\n\t\tthis.#prepared.delete(slot)\n\t\ttry {\n\t\t\tgeneration ??= await this.#build(slot, token)\n\t\t} catch (error) {\n\t\t\tif (this.#losses.has(slot)) await this.#endings.get(slot)?.promise\n\t\t\telse token.release()\n\t\t\tthrow this.#unavailable(error)\n\t\t}\n\t\tconst lease: BrowserServerLease = { token, generation }\n\t\tif (\n\t\t\tthis.#closing !== undefined ||\n\t\t\tthis.#holders.get(holder.id) !== holder ||\n\t\t\tholder.abort.signal.aborted ||\n\t\t\tthis.#losses.has(slot)\n\t\t) {\n\t\t\tawait this.#release(holder, lease)\n\t\t\tthrow this.#ended()\n\t\t}\n\t\tthis.#leases.set(holder, lease)\n\t\tthis.#observe(slot, generation)\n\t\tif (holder === this.#shared) {\n\t\t\tconst tools = generation.toolset.tools\n\t\t\tconst mirrored: BrowserServerMirror = {\n\t\t\t\tlease,\n\t\t\t\tadded: this.#mirror.bind(this, lease),\n\t\t\t\tremoved: this.#withdraw.bind(this, lease),\n\t\t\t\tcleared: this.#clear.bind(this, lease),\n\t\t\t}\n\t\t\tthis.#mirrored = mirrored\n\t\t\tfor (const tool of tools.tools()) this.#mirror(lease, tool)\n\t\t\ttools.emitter.on('add', mirrored.added)\n\t\t\ttools.emitter.on('remove', mirrored.removed)\n\t\t\ttools.emitter.on('clear', mirrored.cleared)\n\t\t}\n\t\treturn lease\n\t}\n\n\tasync #serve(holder: BrowserServerHolder, signal: AbortSignal): Promise<BrowserServerLease> {\n\t\tif (this.#closing !== undefined || holder.abort.signal.aborted) throw this.#ended()\n\t\tawait this.#race(this.#starting, signal)\n\t\tif (this.#closing !== undefined || holder.abort.signal.aborted) throw this.#ended()\n\t\tconst held = this.#leases.get(holder)\n\t\tif (held !== undefined) {\n\t\t\ttry {\n\t\t\t\tawait this.#race(this.#ping(held.token.value), signal)\n\t\t\t\tif (this.#leases.get(holder) === held) return held\n\t\t\t} catch {\n\t\t\t\tsignal.throwIfAborted()\n\t\t\t\tif (holder.abort.signal.aborted) throw this.#ended()\n\t\t\t}\n\t\t}\n\t\ttry {\n\t\t\tconst lease = await this.#grant(holder, signal)\n\t\t\tif (this.#leases.get(holder) !== lease)\n\t\t\t\tthrow this.#unavailable(this.#departures.get(lease)?.cause)\n\t\t\treturn lease\n\t\t} catch (error) {\n\t\t\tsignal.throwIfAborted()\n\t\t\tif (holder.abort.signal.aborted || (isPoolError(error) && error.code === 'destroyed'))\n\t\t\t\tthrow this.#ended()\n\t\t\tif (isPoolError(error) && (error.code === 'create' || error.code === 'cleanup')) {\n\t\t\t\tthis.#exhaust(error)\n\t\t\t\tthrow this.#unavailable(error.cause ?? this.#failure)\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t#ping(slot: BrowserSlot): Promise<void> {\n\t\tconst pending = this.#pings.get(slot)\n\t\tif (pending !== undefined) return pending\n\t\tconst ping = slot.browser\n\t\t\t.ping({ signal: this.#abort.signal })\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (!this.#abort.signal.aborted) this.#lose(slot, error)\n\t\t\t})\n\t\t\t.finally(() => this.#pings.delete(slot))\n\t\tthis.#pings.set(slot, ping)\n\t\treturn ping\n\t}\n\n\tasync #validate(slot: BrowserSlot): Promise<boolean> {\n\t\ttry {\n\t\t\tawait slot.browser.ping({ signal: this.#abort.signal })\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\tif (!this.#abort.signal.aborted) this.#lose(slot, error)\n\t\t\treturn false\n\t\t}\n\t}\n\n\t#lose(slot: BrowserSlot, cause: unknown): void {\n\t\tif (this.#closing !== undefined || this.#losses.has(slot)) return\n\t\tthis.#losses.set(slot, { cause })\n\t\tthis.#failure = cause\n\t\tfor (const [holder, lease] of this.#leases) {\n\t\t\tif (lease.token.value !== slot) continue\n\t\t\tthis.#detach(holder, lease, cause)\n\t\t}\n\t\tconst watch = this.#watches.get(slot)\n\t\tthis.#unwatch(slot)\n\t\twatch?.resolve(cause)\n\t}\n\n\t#detach(holder: BrowserServerHolder, lease: BrowserServerLease, cause: unknown): void {\n\t\tif (this.#leases.get(holder) !== lease || this.#holders.get(holder.id) !== holder) return\n\t\tthis.#departures.set(lease, { cause, url: lease.generation.toolset.view.url })\n\t\tif (holder === this.#shared) this.#unmirror()\n\t\tthis.#leases.delete(holder)\n\t\tthis.#untrack(lease.generation)\n\t\tconst notices = this.#notices.get(holder) ?? new Set<BrowserServerLease>()\n\t\tnotices.add(lease)\n\t\tthis.#notices.set(holder, notices)\n\t}\n\n\t#watch(slot: BrowserSlot, signal: AbortSignal): Promise<unknown> {\n\t\tconst loss = Promise.withResolvers<unknown>()\n\t\tconst disconnect = this.#disconnect.bind(this, slot)\n\t\tconst subscription = addAbortListener(signal, this.#unwatch.bind(this, slot))\n\t\tthis.#watches.set(slot, { resolve: loss.resolve, disconnect, subscription })\n\t\tslot.browser.emitter.on('disconnect', disconnect)\n\t\tif (signal.aborted) this.#unwatch(slot)\n\t\telse if (slot.browser.status !== 'connected') this.#disconnect(slot)\n\t\treturn loss.promise\n\t}\n\n\t#observe(slot: BrowserSlot, generation: BrowserServerContext): void {\n\t\tif (this.#observed.has(generation)) return\n\t\tconst page = this.#track.bind(this, slot, generation)\n\t\tthis.#observed.set(generation, { page, crashes: new Map() })\n\t\tgeneration.context.emitter.on('page', page)\n\t\tfor (const current of generation.context.pages()) this.#track(slot, generation, current)\n\t}\n\n\t#track(slot: BrowserSlot, generation: BrowserServerContext, page: BrowserPageInterface): void {\n\t\tconst watch = this.#observed.get(generation)\n\t\tif (watch === undefined || watch.crashes.has(page)) return\n\t\tconst crash = this.#crash.bind(this, slot, generation, page)\n\t\tpage.emitter.on('crash', crash)\n\t\tthis.#observed.set(generation, {\n\t\t\t...watch,\n\t\t\tcrashes: new Map([...watch.crashes, [page, crash]]),\n\t\t})\n\t}\n\n\t#crash(slot: BrowserSlot, generation: BrowserServerContext, page: BrowserPageInterface): void {\n\t\tif (this.#prepared.get(slot) === generation) {\n\t\t\tthis.#prepared.delete(slot)\n\t\t\tthis.#untrack(generation)\n\t\t\tvoid this.#clean(slot, generation).catch(this.#fault.bind(this))\n\t\t\treturn\n\t\t}\n\t\tconst held = [...this.#leases].find(([, lease]) => lease.generation === generation)\n\t\tif (held === undefined || page !== generation.toolset.view) return\n\t\tconst [holder, lease] = held\n\t\tthis.#detach(holder, lease, new Error('The current page renderer crashed'))\n\t\tconst drain = this.#release(holder, lease)\n\t\tconst drains = this.#drains.get(holder) ?? new Set<Promise<void>>()\n\t\tdrains.add(drain)\n\t\tthis.#drains.set(holder, drains)\n\t\tvoid drain.finally(() => drains.delete(drain)).catch(this.#fault.bind(this))\n\t}\n\n\t#untrack(generation: BrowserServerContext): void {\n\t\tconst watch = this.#observed.get(generation)\n\t\tif (watch === undefined) return\n\t\tthis.#observed.delete(generation)\n\t\tgeneration.context.emitter.off('page', watch.page)\n\t\tfor (const [page, crash] of watch.crashes) page.emitter.off('crash', crash)\n\t}\n\n\t#disconnect(slot: BrowserSlot): void {\n\t\tthis.#lose(\n\t\t\tslot,\n\t\t\tnew Error(\n\t\t\t\tslot.browser.pid === undefined\n\t\t\t\t\t? 'The browser process exited'\n\t\t\t\t\t: 'The browser transport disconnected',\n\t\t\t),\n\t\t)\n\t}\n\n\t#unwatch(slot: BrowserSlot): void {\n\t\tconst watch = this.#watches.get(slot)\n\t\tif (watch === undefined) return\n\t\tthis.#watches.delete(slot)\n\t\tslot.browser.emitter.off('disconnect', watch.disconnect)\n\t\twatch.subscription[Symbol.dispose]()\n\t}\n\n\tasync #release(holder: BrowserServerHolder, lease: BrowserServerLease): Promise<void> {\n\t\tconst slot = lease.token.value\n\t\tconst removed = await this.#clean(slot, lease.generation)\n\t\tconst disposal = lease.generation.context.disposal\n\t\tif (!removed)\n\t\t\tthis.#retentions.set(holder, new Error('The context downloads directory remains owned'))\n\t\tif (disposal?.confirmed !== true && !this.#losses.has(slot) && this.#closing === undefined) {\n\t\t\t// Releasing into a FIFO waiter would publish capacity on the dying browser.\n\t\t\tif (\n\t\t\t\t![...this.#leases.values()].some((held) => held.token.value === slot && held !== lease) &&\n\t\t\t\t(this.#building.get(slot)?.size ?? 0) === 0\n\t\t\t)\n\t\t\t\tlease.token.release()\n\t\t\tthis.#lose(slot, disposal?.error ?? new Error('The context disposal is unconfirmed'))\n\t\t\tawait this.#endings.get(slot)?.promise\n\t\t} else if (removed) lease.token.release()\n\t}\n\n\t#clean(slot: BrowserSlot, generation: BrowserServerContext): Promise<boolean> {\n\t\tlet cleaning = this.#cleaning.get(generation)\n\t\tif (cleaning !== undefined) return cleaning\n\t\tcleaning = Promise.resolve().then(async () => {\n\t\t\tawait generation.toolset.destroy().catch(this.#fault.bind(this))\n\t\t\tawait generation.context.close().catch((error: unknown) => {\n\t\t\t\tif (!this.#losses.has(slot) && slot.browser.status === 'connected') this.#fault(error)\n\t\t\t})\n\t\t\ttry {\n\t\t\t\tawait rm(generation.directory, { recursive: true, force: true })\n\t\t\t\tthis.#owned.get(slot)?.delete(generation)\n\t\t\t\treturn true\n\t\t\t} catch (error) {\n\t\t\t\tthis.#fault(error)\n\t\t\t\treturn false\n\t\t\t}\n\t\t})\n\t\tthis.#cleaning.set(generation, cleaning)\n\t\treturn cleaning\n\t}\n\n\t#build(slot: BrowserSlot, token?: PoolToken<BrowserSlot>): Promise<BrowserServerContext> {\n\t\tconst construction = this.#construct(slot, token)\n\t\tconst building = this.#building.get(slot) ?? new Set<Promise<BrowserServerContext>>()\n\t\tbuilding.add(construction)\n\t\tthis.#building.set(slot, building)\n\t\tvoid construction.finally(() => building.delete(construction)).catch(() => undefined)\n\t\treturn construction\n\t}\n\n\tasync #construct(\n\t\tslot: BrowserSlot,\n\t\ttoken?: PoolToken<BrowserSlot>,\n\t): Promise<BrowserServerContext> {\n\t\tconst directory = join(slot.profile, 'contexts', randomUUID(), 'downloads')\n\t\tlet context: BrowserContextInterface | undefined\n\t\tlet toolset: BrowserToolsetInterface | undefined\n\t\ttry {\n\t\t\tawait mkdir(directory, { recursive: true })\n\t\t\tlet page: BrowserPageInterface\n\t\t\ttry {\n\t\t\t\tcontext = await slot.browser.isolate({\n\t\t\t\t\treference: this.#reference,\n\t\t\t\t\tdownloads: { path: directory },\n\t\t\t\t\t...(this.#viewport === undefined ? {} : { emulation: { viewport: this.#viewport } }),\n\t\t\t\t})\n\t\t\t\tpage = await context.create()\n\t\t\t} catch (error) {\n\t\t\t\tif (token !== undefined) {\n\t\t\t\t\t// This construction still occupies one entry until its rejection settles.\n\t\t\t\t\tif (\n\t\t\t\t\t\t![...this.#leases.values()].some((lease) => lease.token.value === slot) &&\n\t\t\t\t\t\t(this.#building.get(slot)?.size ?? 0) === 1\n\t\t\t\t\t)\n\t\t\t\t\t\ttoken.release()\n\t\t\t\t\tthis.#lose(slot, error)\n\t\t\t\t}\n\t\t\t\tthrow error\n\t\t\t}\n\t\t\ttoolset = createBrowserToolset(page, {\n\t\t\t\tcontext,\n\t\t\t\tjourneys: {\n\t\t\t\t\tstore: createFileBrowserJourneyStore({ root: this.#root }),\n\t\t\t\t\truns: createFileBrowserRunStore({ root: this.#root }),\n\t\t\t\t\treadonly: this.#readonly,\n\t\t\t\t},\n\t\t\t})\n\t\t\tawait toolset.start()\n\t\t\tconst generation: BrowserServerContext = { context, toolset, directory }\n\t\t\tconst owned = this.#owned.get(slot) ?? new Set<BrowserServerContext>()\n\t\t\towned.add(generation)\n\t\t\tthis.#owned.set(slot, owned)\n\t\t\treturn generation\n\t\t} catch (error) {\n\t\t\tawait toolset?.destroy().catch(this.#fault.bind(this))\n\t\t\tawait context?.close().catch((failure: unknown) => {\n\t\t\t\t// A launched browser defers its loss event; CDP can already report the disconnection.\n\t\t\t\tif (\n\t\t\t\t\t!this.#losses.has(slot) &&\n\t\t\t\t\tslot.browser.status === 'connected' &&\n\t\t\t\t\tthis.#closing === undefined &&\n\t\t\t\t\t!isCDPConnectionError(failure)\n\t\t\t\t)\n\t\t\t\t\tthis.#fault(failure)\n\t\t\t})\n\t\t\tawait rm(directory, { recursive: true, force: true }).catch(this.#fault.bind(this))\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync #destroyRecord(slot: BrowserSlot): Promise<void> {\n\t\t// A timed-out browser cannot answer context cleanup; kill before awaiting that cleanup.\n\t\tif (isCDPTimeoutError(this.#losses.get(slot)?.cause) && slot.browser.pid !== undefined) {\n\t\t\ttry {\n\t\t\t\tprocess.kill(slot.browser.pid, 'SIGKILL')\n\t\t\t} catch (error) {\n\t\t\t\tif (!isError(error) || !('code' in error) || error.code !== 'ESRCH') this.#faults.add(error)\n\t\t\t}\n\t\t}\n\t\ttry {\n\t\t\tawait Promise.allSettled(this.#building.get(slot) ?? [])\n\t\t\tconst prepared = this.#prepared.get(slot)\n\t\t\tif (prepared !== undefined) this.#untrack(prepared)\n\t\t\tthis.#prepared.delete(slot)\n\t\t\tawait Promise.all(\n\t\t\t\t[...(this.#owned.get(slot) ?? [])].map((generation) => this.#clean(slot, generation)),\n\t\t\t)\n\t\t\tawait this.#destroySlot(slot.profile, slot.browser)\n\t\t\tthis.#owned.delete(slot)\n\t\t\tthis.#building.delete(slot)\n\t\t\tthis.#endings.get(slot)?.resolve()\n\t\t} catch (error) {\n\t\t\tthis.#endings.get(slot)?.reject(error)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t#fault(error: unknown): void {\n\t\tthis.#faults.add(error)\n\t}\n\n\tasync #warm(): Promise<BrowserSlot> {\n\t\tif (this.#closing !== undefined) throw this.#ended()\n\t\tif (this.#stranded !== undefined)\n\t\t\tthrow new BrowserError(\n\t\t\t\tisError(this.#stranded) ? this.#stranded.message : String(this.#stranded),\n\t\t\t\tBROWSER_SERVER_TEARDOWN,\n\t\t\t\tisBrowserError(this.#stranded) ? this.#stranded.context : undefined,\n\t\t\t)\n\t\tconst profile = join(this.#root, '.profiles', formatBrowserLockEntry(process.pid, randomUUID()))\n\t\t// Without `recursive`, an existing directory refuses with `EEXIST`, so no two launches share one.\n\t\tlet browser: BrowserInterface | undefined\n\t\tlet slot: BrowserSlot | undefined\n\t\ttry {\n\t\t\tawait mkdir(profile)\n\t\t\tthis.#folders.add(profile)\n\t\t\tbrowser = this.#launcher({\n\t\t\t\theadless: this.#headless,\n\t\t\t\tprofile,\n\t\t\t\tcdp: { discover: false },\n\t\t\t\tsignal: this.#abort.signal,\n\t\t\t\t...(this.#executable === undefined ? {} : { executable: this.#executable }),\n\t\t\t\t...(this.#viewport === undefined ? {} : { viewport: this.#viewport }),\n\t\t\t\t...(process.platform === 'linux' && process.getuid?.() === 0\n\t\t\t\t\t? { args: ['--no-sandbox'] }\n\t\t\t\t\t: {}),\n\t\t\t})\n\t\t\tawait browser.connect()\n\t\t\tif (browser.pid !== undefined && browser.endpoint !== undefined) {\n\t\t\t\tconst record = join(profile, BROWSER_SERVER_RECORD)\n\t\t\t\tawait writeFile(\n\t\t\t\t\t`${record}.tmp`,\n\t\t\t\t\tJSON.stringify({ pid: browser.pid, endpoint: browser.endpoint }),\n\t\t\t\t)\n\t\t\t\tawait rename(`${record}.tmp`, record)\n\t\t\t}\n\t\t\tslot = { browser, profile }\n\t\t\tconst ending = Promise.withResolvers<void>()\n\t\t\tvoid ending.promise.catch(() => undefined)\n\t\t\tthis.#endings.set(slot, ending)\n\t\t\tconst generation = await this.#build(slot)\n\t\t\tthis.#prepared.set(slot, generation)\n\t\t\tthis.#observe(slot, generation)\n\t\t\treturn slot\n\t\t} catch (error) {\n\t\t\tif (this.#folders.has(profile))\n\t\t\t\tawait (\n\t\t\t\t\tslot === undefined ? this.#destroySlot(profile, browser) : this.#destroyRecord(slot)\n\t\t\t\t).catch((failure: unknown) => {\n\t\t\t\t\tthis.#stranded = failure\n\t\t\t\t})\n\t\t\tif (this.#closing === undefined)\n\t\t\t\tthis.#write(`browse: ${describeBrowserServerLoss(BROWSER_SERVER_LAUNCH, error)}`)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync #destroySlot(profile: string, browser?: BrowserInterface): Promise<void> {\n\t\ttry {\n\t\t\tawait browser?.destroy()\n\t\t} catch (error) {\n\t\t\tif (this.#closing === undefined)\n\t\t\t\tthis.#write(`browse: ${describeBrowserServerLoss(BROWSER_SERVER_TEARDOWN, error)}`)\n\t\t\tthrow error\n\t\t}\n\t\ttry {\n\t\t\tawait rm(profile, { recursive: true, force: true, maxRetries: 5 })\n\t\t\tthis.#folders.delete(profile)\n\t\t} catch {\n\t\t\t// The shutdown recheck retries this folder; only its persistent failure reaches destroy.\n\t\t}\n\t}\n\n\tasync #sweep(): Promise<void> {\n\t\tconst profiles = join(this.#root, '.profiles')\n\t\ttry {\n\t\t\tfor (const entry of await readdir(profiles)) {\n\t\t\t\tif (this.#closing !== undefined) return\n\t\t\t\tconst pid = parseBrowserLockEntry(entry)\n\t\t\t\tif (pid === undefined || pid === process.pid || probeProcess(pid)) continue\n\t\t\t\tconst folder = join(profiles, entry)\n\t\t\t\tthis.#folders.add(folder)\n\t\t\t\ttry {\n\t\t\t\t\tconst record = parseBrowserProfileRecord(\n\t\t\t\t\t\tawait readFile(join(folder, BROWSER_SERVER_RECORD), 'utf8'),\n\t\t\t\t\t)\n\t\t\t\t\tif (record === undefined) continue\n\t\t\t\t\tif (probeProcess(record.pid)) {\n\t\t\t\t\t\tconst transport = createCDPTransport({ url: record.endpoint })\n\t\t\t\t\t\tconst client = createCDPClient({ transport })\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// A file read can finish after shutdown; do not start an unobserved connection.\n\t\t\t\t\t\t\tthis.#abort.signal.throwIfAborted()\n\t\t\t\t\t\t\tawait this.#race(client.connect(), this.#abort.signal)\n\t\t\t\t\t\t\tawait client.send('Browser.close', undefined, { signal: this.#abort.signal })\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// A dead peer can close without acknowledging, and a live peer can refuse.\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t// Client close waits for connect; close the owned transport to end a held upgrade.\n\t\t\t\t\t\t\tawait transport.close()\n\t\t\t\t\t\t\tawait client.close()\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (probeProcess(record.pid)) continue\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isError(error) || !('code' in error) || error.code !== 'ENOENT') continue\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tawait rm(folder, { recursive: true, force: true, maxRetries: 5 })\n\t\t\t\t\tthis.#folders.delete(folder)\n\t\t\t\t} catch {\n\t\t\t\t\t/* The shutdown recheck owns a later removal attempt. */\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.#write(`browse: ${describeBrowserServerLoss(BROWSER_SERVER_SWEEP, error)}`)\n\t\t}\n\t}\n\n\t#write(line: string): void {\n\t\ttry {\n\t\t\tthis.#log.write(`${line}\\n`, (error?: Error | null) => {\n\t\t\t\tif (error !== undefined && error !== null) this.#faults.add(error)\n\t\t\t})\n\t\t} catch (error) {\n\t\t\tthis.#faults.add(error)\n\t\t}\n\t}\n\n\t#exhaust(error: unknown): void {\n\t\tif (isPoolError(error) && error.code === 'create')\n\t\t\tthis.#write(\n\t\t\t\t`browse: ${describeBrowserServerLoss(BROWSER_SERVER_EXHAUSTED, error.cause ?? this.#failure)}`,\n\t\t\t)\n\t}\n\n\t#unavailable(cause: unknown): BrowserError {\n\t\tconst message = describeBrowserServerLoss(BROWSER_SERVER_UNAVAILABLE, cause)\n\t\treturn new BrowserError(\n\t\t\tmessage.slice(BROWSER_SERVER_UNAVAILABLE.length + 2),\n\t\t\tBROWSER_SERVER_UNAVAILABLE,\n\t\t)\n\t}\n\n\t#issue(): string {\n\t\treturn `e${++this.#references}`\n\t}\n\n\t// Adds a dispatcher for a tool the toolset's manager added under a name outside the vocabulary.\n\t#mirror(lease: BrowserServerLease, tool: ToolInterface): void {\n\t\tif (this.#leases.get(this.#shared) !== lease || this.#vocabulary.has(tool.name)) return\n\t\tthis.#tools.add(\n\t\t\tcreateTool({\n\t\t\t\t...toolToDefinition(tool),\n\t\t\t\texecute: this.#forward.bind(this, this.#shared, tool.name),\n\t\t\t}),\n\t\t)\n\t}\n\n\t// Removes the dispatcher of a withdrawn tool; a replacement publishes `remove` while it is\n\t// installed, so the mirror follows the manager's current tool rather than the event.\n\t#withdraw(lease: BrowserServerLease, tool: ToolInterface): void {\n\t\tif (this.#leases.get(this.#shared) !== lease || this.#vocabulary.has(tool.name)) return\n\t\tconst current = lease.generation.toolset.tools.tool(tool.name)\n\t\tif (current === undefined) this.#tools.remove(tool.name)\n\t\telse this.#mirror(lease, current)\n\t}\n\n\t#clear(lease: BrowserServerLease, tools: readonly ToolInterface[]): void {\n\t\tfor (const tool of tools) this.#withdraw(lease, tool)\n\t}\n\n\t#unmirror(): void {\n\t\tconst mirrored = this.#mirrored\n\t\tif (mirrored === undefined) return\n\t\tthis.#mirrored = undefined\n\t\tconst tools = mirrored.lease.generation.toolset.tools\n\t\tfor (const tool of tools.tools())\n\t\t\tif (!this.#vocabulary.has(tool.name)) this.#tools.remove(tool.name)\n\t\ttools.emitter.off('add', mirrored.added)\n\t\ttools.emitter.off('remove', mirrored.removed)\n\t\ttools.emitter.off('clear', mirrored.cleared)\n\t}\n\n\t#ended(): BrowserError {\n\t\treturn new BrowserError('the browser session ended', 'BROWSER_TOOLSET_ENDED')\n\t}\n}\n","import type { BrowserStoreOptions, BrowserStorePage, BrowserStoreFault } from '@src/core'\nimport type { FileBrowserStoreOptions } from '../types.js'\nimport { realpathSync } from 'node:fs'\nimport { lstat, mkdir, open, readFile, readdir, rename, rmdir, unlink } from 'node:fs/promises'\nimport { dirname, relative, resolve, sep } from 'node:path'\nimport { randomUUID } from 'node:crypto'\nimport {\n\tBrowserError,\n\tBROWSER_JOURNEY_NAME_PATTERN,\n\tBROWSER_RUN_ID_PATTERN,\n\tvalidateBrowserStorePage,\n} from '@src/core'\nimport { BROWSER_FILE_STORE_LIMIT, BROWSER_JOURNEY_LOCK_ATTEMPTS } from '../constants.js'\nimport { formatBrowserLockEntry, parseBrowserLockEntry, probeProcess } from '../helpers.js'\n\n/**\n * Shares confined filesystem operations between the journey and run stores.\n * @remarks Requires an existing root directory. Links present during a component check are refused;\n * replacement between a check and its use by another filesystem writer is outside this boundary.\n * @example\n * const files = new FileBrowserStore({ root: directory })\n * files.validateName('check-ready')\n */\nexport class FileBrowserStore {\n\treadonly #root: string\n\treadonly #limit: number\n\n\tconstructor(options: FileBrowserStoreOptions) {\n\t\tthis.#limit = options.limit ?? BROWSER_FILE_STORE_LIMIT\n\t\tif (!Number.isSafeInteger(this.#limit) || this.#limit < 1)\n\t\t\tthrow new BrowserError(\n\t\t\t\t'The listing cap must be a positive integer',\n\t\t\t\t'BROWSER_JOURNEY_ARGUMENT',\n\t\t\t)\n\t\ttry {\n\t\t\tthis.#root = realpathSync(options.root)\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && 'code' in error && error.code === 'ENOENT')\n\t\t\t\tthrow new BrowserError(`Missing root: ${options.root}`, 'BROWSER_JOURNEY_PATH', {\n\t\t\t\t\tpath: options.root,\n\t\t\t\t})\n\t\t\tthrow this.translateError(options.root, error)\n\t\t}\n\t}\n\n\t/** Checks a journey name before filesystem access. @param name - Journey name */\n\tvalidateName(name: string): void {\n\t\tif (!BROWSER_JOURNEY_NAME_PATTERN.test(name))\n\t\t\tthrow new BrowserError(`Refused journey name: ${name}`, 'BROWSER_JOURNEY_PATH')\n\t}\n\n\t/** Checks a run id before filesystem access. @param id - Producer id */\n\tvalidateId(id: string): void {\n\t\tif (!BROWSER_RUN_ID_PATTERN.test(id))\n\t\t\tthrow new BrowserError(`Refused run id: ${id}`, 'BROWSER_JOURNEY_PATH')\n\t}\n\n\t/** Resolves a confined target. @param parts - Relative components @returns Absolute target */\n\tresolvePath(...parts: readonly string[]): string {\n\t\tconst path = resolve(this.#root, ...parts)\n\t\tif (\n\t\t\tpath !== this.#root &&\n\t\t\t!path.startsWith(this.#root.endsWith(sep) ? this.#root : this.#root + sep)\n\t\t)\n\t\t\tthrow new BrowserError(`Refused path: ${path}`, 'BROWSER_JOURNEY_PATH')\n\t\treturn path\n\t}\n\n\t/**\n\t * Checks every existing component including the root and target.\n\t * @param path - Absolute target\n\t * @param options - Cancellation options\n\t * @returns True if the target exists; false if a component is missing\n\t */\n\tasync check(path: string, options?: BrowserStoreOptions): Promise<boolean> {\n\t\tthis.resolvePath(path)\n\t\tlet current = this.#root\n\t\tconst parts = relative(this.#root, path).split(sep).filter(Boolean)\n\t\tfor (let index = 0; index <= parts.length; index += 1) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\ttry {\n\t\t\t\tconst status = await lstat(current)\n\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\tif (status.isSymbolicLink())\n\t\t\t\t\tthrow new BrowserError(`Refused symbolic link: ${current}`, 'BROWSER_JOURNEY_PATH')\n\t\t\t\tif (index < parts.length && !status.isDirectory())\n\t\t\t\t\tthrow new BrowserError(`Not a directory: ${current}`, 'BROWSER_JOURNEY_PATH')\n\t\t\t} catch (error) {\n\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\tif (error instanceof Error && 'code' in error && error.code === 'ENOENT') return false\n\t\t\t\tthrow this.translateError(current, error)\n\t\t\t}\n\t\t\tconst part = parts[index]\n\t\t\tif (part !== undefined) current = this.resolvePath(current, part)\n\t\t}\n\t\treturn true\n\t}\n\n\t/** Creates checked directories one component at a time. @param path - Directory @param options - Cancellation options */\n\tasync createDirectory(path: string, options?: BrowserStoreOptions): Promise<void> {\n\t\tif (await this.check(path, options)) return\n\t\tif (path === this.#root) throw new BrowserError(`Missing root: ${path}`, 'BROWSER_JOURNEY_PATH')\n\t\tawait this.createDirectory(dirname(path), options)\n\t\toptions?.signal?.throwIfAborted()\n\t\ttry {\n\t\t\tawait mkdir(path)\n\t\t} catch (error) {\n\t\t\tif (!(error instanceof Error && 'code' in error && error.code === 'EEXIST'))\n\t\t\t\tthrow this.translateError(path, error)\n\t\t}\n\t\tawait this.check(path, options)\n\t}\n\n\t/** Reads an existing file without collapsing a fault to absence. @param path - File @param options - Cancellation options @returns Bytes as UTF-8, or absence */\n\tasync read(path: string, options?: BrowserStoreOptions): Promise<string | undefined> {\n\t\tif (!(await this.check(path, options))) return undefined\n\t\ttry {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tconst value = await readFile(path, { encoding: 'utf8', signal: options?.signal })\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\treturn value\n\t\t} catch (error) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tif (error instanceof Error && 'code' in error && error.code === 'ENOENT') return undefined\n\t\t\tthrow this.translateError(path, error)\n\t\t}\n\t}\n\n\t/** Atomically replaces a file and cleans its owned temporary file on failure. @param path - Destination @param value - Bytes or UTF-8 @param options - Cancellation options */\n\tasync write(\n\t\tpath: string,\n\t\tvalue: string | Uint8Array,\n\t\toptions?: BrowserStoreOptions,\n\t): Promise<void> {\n\t\tconst temporary = this.resolvePath(dirname(path), `.${randomUUID()}.tmp`)\n\t\tlet owned = false\n\t\ttry {\n\t\t\tawait this.check(path, options)\n\t\t\tawait this.check(temporary, options)\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tconst file = await open(temporary, 'wx')\n\t\t\towned = true\n\t\t\ttry {\n\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\tawait file.writeFile(value, { signal: options?.signal })\n\t\t\t} finally {\n\t\t\t\tawait file.close()\n\t\t\t}\n\t\t\tawait this.check(path, options)\n\t\t\tawait this.check(temporary, options)\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\ttry {\n\t\t\t\tawait rename(temporary, path)\n\t\t\t} catch (error) {\n\t\t\t\t// A file cannot replace a directory: hosts report EISDIR or EPERM.\n\t\t\t\tconst target = await lstat(path).catch(() => undefined)\n\t\t\t\tif (\n\t\t\t\t\terror instanceof Error &&\n\t\t\t\t\t'code' in error &&\n\t\t\t\t\t(error.code === 'EISDIR' || error.code === 'EPERM') &&\n\t\t\t\t\ttarget?.isDirectory()\n\t\t\t\t)\n\t\t\t\t\tthrow new BrowserError(`Cannot replace directory: ${path}`, 'BROWSER_JOURNEY_FILE', {\n\t\t\t\t\t\tpath,\n\t\t\t\t\t})\n\t\t\t\tthrow error\n\t\t\t}\n\t\t\towned = false\n\t\t} catch (error) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tthrow this.translateError(path, error)\n\t\t} finally {\n\t\t\tif (owned) await this.remove(temporary)\n\t\t}\n\t}\n\n\t/** Removes a checked file, accepting absence. @param path - File @param options - Cancellation options */\n\tasync remove(path: string, options?: BrowserStoreOptions): Promise<void> {\n\t\tif (!(await this.check(path, options))) return\n\t\ttry {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tawait unlink(path)\n\t\t} catch (error) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tif (!(error instanceof Error && 'code' in error && error.code === 'ENOENT'))\n\t\t\t\tthrow this.translateError(path, error)\n\t\t}\n\t}\n\n\t/**\n\t * Holds a directory lock through a mutation and releases only its named entry.\n\t * @remarks Reclaims dead or empty locks within a bounded attempt count; a live or unknown holder refuses.\n\t * @param path - Lock directory\n\t * @param action - Mutation inside the lock\n\t * @param options - Cancellation options\n\t * @returns The mutation result\n\t */\n\tasync lock<T>(path: string, action: () => Promise<T>, options?: BrowserStoreOptions): Promise<T> {\n\t\tawait this.createDirectory(dirname(path), options)\n\t\tconst name = formatBrowserLockEntry(process.pid, randomUUID())\n\t\tconst entry = this.resolvePath(path, name)\n\t\tfor (let attempt = 0; attempt < BROWSER_JOURNEY_LOCK_ATTEMPTS; attempt += 1) {\n\t\t\tawait this.check(path, options)\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\ttry {\n\t\t\t\tawait mkdir(path)\n\t\t\t} catch (error) {\n\t\t\t\tif (!(error instanceof Error && 'code' in error && error.code === 'EEXIST'))\n\t\t\t\t\tthrow this.translateError(path, error)\n\t\t\t\tconst entries = await this.#readLock(path, options)\n\t\t\t\tif (entries === undefined) continue\n\t\t\t\tif (entries.length > 1) break\n\t\t\t\tconst holder = entries[0]\n\t\t\t\tif (holder !== undefined) {\n\t\t\t\t\tconst pid = parseBrowserLockEntry(holder)\n\t\t\t\t\tif (pid === undefined || probeProcess(pid)) break\n\t\t\t\t\tif (!(await this.#unlinkLock(this.resolvePath(path, holder)))) continue\n\t\t\t\t}\n\t\t\t\tawait this.#removeLock(path)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tlet owned = false\n\t\t\ttry {\n\t\t\t\tawait this.check(entry, options)\n\t\t\t\ttry {\n\t\t\t\t\tconst file = await open(entry, 'wx')\n\t\t\t\t\towned = true\n\t\t\t\t\tawait file.close()\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (error instanceof Error && 'code' in error && error.code === 'ENOENT') continue\n\t\t\t\t\tthrow this.translateError(entry, error)\n\t\t\t\t}\n\t\t\t\t// An empty directory can be replaced between mkdir and entry creation.\n\t\t\t\tconst entries = await this.#readLock(path, options)\n\t\t\t\tif (entries?.length !== 1 || entries[0] !== name) break\n\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\treturn await action()\n\t\t\t} finally {\n\t\t\t\tif (owned) await this.#unlinkLock(entry)\n\t\t\t\tawait this.#removeLock(path)\n\t\t\t}\n\t\t}\n\t\tthrow new BrowserError(`Journey is locked: ${path}`, 'BROWSER_JOURNEY_LOCKED')\n\t}\n\n\t/**\n\t * Lists readable entries in sorted order with a bounded page and one extra readable probe.\n\t * @param path - Parent directory\n\t * @param reader - Entry reader\n\t * @param options - Paging and cancellation\n\t * @returns Page and observed entry faults\n\t */\n\tasync list<T>(\n\t\tpath: string,\n\t\treader: (name: string) => Promise<T | undefined>,\n\t\toptions?: BrowserStoreOptions & { readonly offset?: number; readonly limit?: number },\n\t): Promise<BrowserStorePage<T>> {\n\t\tconst offset = options?.offset ?? 0\n\t\tconst requested = options?.limit ?? this.#limit\n\t\tvalidateBrowserStorePage(offset, requested)\n\t\tconst limit = Math.min(requested, this.#limit)\n\t\tconst entries: T[] = []\n\t\tconst faults: BrowserStoreFault[] = []\n\t\tif (!(await this.check(path, options))) return { entries, faults, truncated: false }\n\t\tlet names: string[]\n\t\ttry {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tnames = (await readdir(path)).sort()\n\t\t} catch (error) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tthrow this.translateError(path, error)\n\t\t}\n\t\tlet count = 0\n\t\tfor (const name of names) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\ttry {\n\t\t\t\tconst entry = await reader(name)\n\t\t\t\tif (entry === undefined) continue\n\t\t\t\tif (count++ < offset) continue\n\t\t\t\tif (entries.length === limit) return { entries, faults, truncated: true }\n\t\t\t\tentries.push(entry)\n\t\t\t} catch (error) {\n\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\tconst reason = error instanceof BrowserError ? error.context?.['reason'] : undefined\n\t\t\t\tfaults.push({\n\t\t\t\t\tname,\n\t\t\t\t\treason:\n\t\t\t\t\t\ttypeof reason === 'string'\n\t\t\t\t\t\t\t? reason\n\t\t\t\t\t\t\t: error instanceof BrowserError && error.code === 'BROWSER_JOURNEY_PATH'\n\t\t\t\t\t\t\t\t? 'The entry path is refused'\n\t\t\t\t\t\t\t\t: error instanceof BrowserError && error.code === 'BROWSER_JOURNEY_ACCESS'\n\t\t\t\t\t\t\t\t\t? 'Permission denied'\n\t\t\t\t\t\t\t\t\t: error instanceof BrowserError && error.code === 'BROWSER_JOURNEY_FORMAT'\n\t\t\t\t\t\t\t\t\t\t? 'Unknown file format'\n\t\t\t\t\t\t\t\t\t\t: 'The stored entry is malformed or unreadable',\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\treturn { entries, faults, truncated: false }\n\t}\n\n\t/**\n\t * Allocates a run directory exclusively, retrying colliding producer candidates.\n\t * @param parent - Checked parent directory\n\t * @param candidate - Producer id source\n\t * @param options - Cancellation options\n\t * @returns Allocated id and absolute directory\n\t */\n\tasync allocate(\n\t\tparent: string,\n\t\tcandidate: () => string,\n\t\toptions?: BrowserStoreOptions,\n\t): Promise<{ readonly id: string; readonly path: string }> {\n\t\tawait this.createDirectory(parent, options)\n\t\tfor (;;) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tconst id = candidate()\n\t\t\tthis.validateId(id)\n\t\t\tconst path = this.resolvePath(parent, id)\n\t\t\tawait this.check(path, options)\n\t\t\ttry {\n\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\tawait mkdir(path)\n\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\treturn { id, path }\n\t\t\t} catch (error) {\n\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\tif (error instanceof Error && 'code' in error && error.code === 'EEXIST') continue\n\t\t\t\tthrow this.translateError(path, error)\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Translates filesystem and validation failures with their path. @param path - Failed path @param error - Cause @returns Coded error */\n\ttranslateError(path: string, error: unknown): BrowserError {\n\t\tconst code = error instanceof Error && 'code' in error ? error.code : undefined\n\t\treturn new BrowserError(\n\t\t\t`${path}: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\tcode === 'EACCES' || code === 'EPERM'\n\t\t\t\t? 'BROWSER_JOURNEY_ACCESS'\n\t\t\t\t: error instanceof BrowserError && code !== 'BROWSER_JOURNEY_INVALID'\n\t\t\t\t\t? error.code\n\t\t\t\t\t: 'BROWSER_JOURNEY_FILE',\n\t\t\t{ path },\n\t\t)\n\t}\n\tasync #readLock(\n\t\tpath: string,\n\t\toptions?: BrowserStoreOptions,\n\t): Promise<readonly string[] | undefined> {\n\t\tawait this.check(path, options)\n\t\ttry {\n\t\t\tconst entries = await readdir(path, { withFileTypes: true })\n\t\t\tfor (const entry of entries) {\n\t\t\t\tawait this.check(this.resolvePath(path, entry.name), options)\n\t\t\t\tif (!entry.isFile())\n\t\t\t\t\tthrow new BrowserError(`Journey is locked: ${path}`, 'BROWSER_JOURNEY_LOCKED')\n\t\t\t}\n\t\t\treturn entries.map((entry) => entry.name)\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && 'code' in error) {\n\t\t\t\tif (error.code === 'ENOENT') return undefined\n\t\t\t\tif (error.code === 'ENOTDIR')\n\t\t\t\t\tthrow new BrowserError(`Journey is locked: ${path}`, 'BROWSER_JOURNEY_LOCKED')\n\t\t\t}\n\t\t\tthrow this.translateError(path, error)\n\t\t}\n\t}\n\n\tasync #unlinkLock(path: string): Promise<boolean> {\n\t\tawait this.check(path)\n\t\ttry {\n\t\t\tawait unlink(path)\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\tif (\n\t\t\t\terror instanceof Error &&\n\t\t\t\t'code' in error &&\n\t\t\t\t(error.code === 'ENOENT' || error.code === 'ENOTEMPTY')\n\t\t\t)\n\t\t\t\treturn false\n\t\t\tthrow new BrowserError(`Cannot remove lock entry: ${path}`, 'BROWSER_JOURNEY_ACCESS', {\n\t\t\t\tpath,\n\t\t\t})\n\t\t}\n\t}\n\n\tasync #removeLock(path: string): Promise<void> {\n\t\tawait this.check(path)\n\t\ttry {\n\t\t\tawait rmdir(path)\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && 'code' in error) {\n\t\t\t\tif (error.code === 'ENOTEMPTY') return\n\t\t\t\tif (error.code === 'ENOENT' || error.code === 'EPERM') {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ((await lstat(path)).isDirectory()) return\n\t\t\t\t\t} catch (cause) {\n\t\t\t\t\t\tif (cause instanceof Error && 'code' in cause && cause.code === 'ENOENT') return\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new BrowserError(`Cannot remove lock directory: ${path}`, 'BROWSER_JOURNEY_ACCESS', {\n\t\t\t\tpath,\n\t\t\t})\n\t\t}\n\t}\n}\n","import type {\n\tBrowserJourney,\n\tBrowserJourneyRevision,\n\tBrowserJourneyStoreInterface,\n\tBrowserStoreOptions,\n\tBrowserStorePage,\n} from '@src/core'\nimport type { FileBrowserStoreOptions } from '../types.js'\nimport { isRecord, parseJSON } from '@orkestrel/contract'\nimport {\n\tBROWSER_JOURNEY_NAME_PATTERN,\n\tBrowserError,\n\tvalidateBrowserJourney,\n\tnormalizeBrowserJourneyReason,\n} from '@src/core'\nimport {\n\tBROWSER_JOURNEY_SNAPSHOT_FILE,\n\tBROWSER_JOURNEY_REVISION_FILE,\n\tBROWSER_JOURNEY_LOCK_DIRECTORY,\n} from '../constants.js'\nimport { FileBrowserStore } from './FileBrowserStore.js'\n\n/**\n * Persists journeys with exclusive writes and revision counters retained across deletion.\n * @remarks Requires an existing root. A live holder refuses immediately; dead or empty locks are reclaimed within a bounded attempt count.\n * @example\n * const store = new FileBrowserJourneyStore({ root: directory })\n * await store.set(journey)\n */\nexport class FileBrowserJourneyStore implements BrowserJourneyStoreInterface {\n\treadonly #files: FileBrowserStore\n\n\tconstructor(options: FileBrowserStoreOptions) {\n\t\tthis.#files = new FileBrowserStore(options)\n\t}\n\n\tasync get(\n\t\tname: string,\n\t\toptions?: BrowserStoreOptions,\n\t): Promise<BrowserJourneyRevision | undefined> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tthis.#files.validateName(name)\n\t\tconst path = this.#files.resolvePath(name, BROWSER_JOURNEY_SNAPSHOT_FILE)\n\t\tconst source = await this.#files.read(path, options)\n\t\tif (source === undefined) return undefined\n\t\ttry {\n\t\t\tconst value = parseJSON(source)\n\t\t\tif (\n\t\t\t\t!isRecord(value) ||\n\t\t\t\ttypeof value['revision'] !== 'number' ||\n\t\t\t\t!Number.isSafeInteger(value['revision']) ||\n\t\t\t\tvalue['revision'] < 1\n\t\t\t)\n\t\t\t\tthrow new BrowserError('Malformed journey revision', 'BROWSER_JOURNEY_FILE')\n\t\t\tif (!isRecord(value['journey']) || !('format' in value['journey']))\n\t\t\t\tthrow new BrowserError('Missing journey format', 'BROWSER_JOURNEY_FILE')\n\t\t\tvalidateBrowserJourney(value['journey'])\n\t\t\tif (value['journey'].name !== name)\n\t\t\t\tthrow new BrowserError('Journey name differs from its directory', 'BROWSER_JOURNEY_FILE')\n\t\t\treturn { journey: value['journey'], revision: value['revision'] }\n\t\t} catch (error) {\n\t\t\tconst translated = this.#files.translateError(path, error)\n\t\t\tthrow new BrowserError(translated.message, translated.code, {\n\t\t\t\t...translated.context,\n\t\t\t\treason: normalizeBrowserJourneyReason(error),\n\t\t\t})\n\t\t}\n\t}\n\n\tasync set(\n\t\tjourney: BrowserJourney,\n\t\texpected?: number,\n\t\toptions?: BrowserStoreOptions,\n\t): Promise<BrowserJourneyRevision> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tthis.#files.validateName(journey.name)\n\t\tvalidateBrowserJourney(journey)\n\t\tconst owned = structuredClone(journey)\n\t\tconst path = this.#files.resolvePath(owned.name, BROWSER_JOURNEY_SNAPSHOT_FILE)\n\t\tconst counter = this.#files.resolvePath(owned.name, BROWSER_JOURNEY_REVISION_FILE)\n\t\treturn this.#files.lock(\n\t\t\tthis.#files.resolvePath(owned.name, BROWSER_JOURNEY_LOCK_DIRECTORY),\n\t\t\tasync () => {\n\t\t\t\tconst current = await this.get(owned.name, options)\n\t\t\t\tif (expected !== undefined && expected !== (current?.revision ?? 0))\n\t\t\t\t\tthrow new BrowserError(\n\t\t\t\t\t\t`Journey ${owned.name} changed since you read it`,\n\t\t\t\t\t\t'BROWSER_JOURNEY_STALE',\n\t\t\t\t\t)\n\t\t\t\tconst source = await this.#files.read(counter, options)\n\t\t\t\tconst previous = source === undefined ? 0 : Number(source)\n\t\t\t\tif (!Number.isSafeInteger(previous) || previous < 0 || source?.trim() === '')\n\t\t\t\t\tthrow new BrowserError(`Malformed revision: ${counter}`, 'BROWSER_JOURNEY_FILE')\n\t\t\t\tconst revision = Math.max(previous, current?.revision ?? 0) + 1\n\t\t\t\tif (!Number.isSafeInteger(revision))\n\t\t\t\t\tthrow new BrowserError(`Exhausted revision: ${counter}`, 'BROWSER_JOURNEY_FILE')\n\t\t\t\tconst saved = { journey: owned, revision }\n\t\t\t\tawait this.#files.write(path, JSON.stringify(saved), options)\n\t\t\t\ttry {\n\t\t\t\t\tawait this.#files.write(counter, String(revision), options)\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Rollback and lock cleanup must finish even when the caller aborts.\n\t\t\t\t\tif (current === undefined) await this.#files.remove(path)\n\t\t\t\t\telse await this.#files.write(path, JSON.stringify(current))\n\t\t\t\t\tthrow error\n\t\t\t\t}\n\t\t\t\treturn saved\n\t\t\t},\n\t\t\toptions,\n\t\t)\n\t}\n\n\tasync delete(name: string, options?: BrowserStoreOptions): Promise<void> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tthis.#files.validateName(name)\n\t\tawait this.#files.lock(\n\t\t\tthis.#files.resolvePath(name, BROWSER_JOURNEY_LOCK_DIRECTORY),\n\t\t\tasync () => {\n\t\t\t\tconst current = await this.get(name, options)\n\t\t\t\tif (current === undefined) return\n\t\t\t\tconst counter = this.#files.resolvePath(name, BROWSER_JOURNEY_REVISION_FILE)\n\t\t\t\tconst source = await this.#files.read(counter, options)\n\t\t\t\tconst previous = source === undefined ? 0 : Number(source)\n\t\t\t\tif (!Number.isSafeInteger(previous) || previous < 0 || source?.trim() === '')\n\t\t\t\t\tthrow new BrowserError(`Malformed revision: ${counter}`, 'BROWSER_JOURNEY_FILE')\n\t\t\t\t// Preserve the committed revision even if a process exited before updating its counter.\n\t\t\t\tawait this.#files.write(counter, String(Math.max(previous, current.revision ?? 0)), options)\n\t\t\t\tawait this.#files.remove(\n\t\t\t\t\tthis.#files.resolvePath(name, BROWSER_JOURNEY_SNAPSHOT_FILE),\n\t\t\t\t\toptions,\n\t\t\t\t)\n\t\t\t},\n\t\t\toptions,\n\t\t)\n\t}\n\n\tasync list(\n\t\toptions?: BrowserStoreOptions & { readonly offset?: number; readonly limit?: number },\n\t): Promise<BrowserStorePage<BrowserJourneyRevision>> {\n\t\toptions?.signal?.throwIfAborted()\n\t\treturn this.#files.list(\n\t\t\tthis.#files.resolvePath(),\n\t\t\tasync (name) => {\n\t\t\t\tif (!BROWSER_JOURNEY_NAME_PATTERN.test(name)) return undefined\n\t\t\t\treturn this.get(name, options)\n\t\t\t},\n\t\t\toptions,\n\t\t)\n\t}\n}\n","import type {\n\tBrowserRun,\n\tBrowserRunSlot,\n\tBrowserRunStoreInterface,\n\tBrowserStoreOptions,\n\tBrowserStorePage,\n} from '@src/core'\nimport type { FileBrowserStoreOptions } from '../types.js'\nimport { lstat, readdir, rm, writeFile } from 'node:fs/promises'\nimport { isRecord, parseJSON } from '@orkestrel/contract'\nimport {\n\tBROWSER_JOURNEY_FORMAT_VERSION,\n\tBrowserError,\n\tgenerateBrowserRunId,\n\tvalidateBrowserRun,\n} from '@src/core'\nimport {\n\tBROWSER_RUN_FILE,\n\tBROWSER_RUN_DIRECTORY,\n\tBROWSER_JOURNEY_LOCK_DIRECTORY,\n} from '../constants.js'\nimport { FileBrowserStore } from './FileBrowserStore.js'\n\n/**\n * Persists runs and captures only in directories allocated by this instance.\n * @remarks Requires an existing root. Reopened stores can read and delete saved runs.\n * Allocations of one journey share a process-local queue across instances; the filesystem lock\n * still refuses conflicting mutations and allocations from another process.\n * @example\n * const store = new FileBrowserRunStore({ root: directory })\n * const slot = await store.open('check-ready')\n */\nexport class FileBrowserRunStore implements BrowserRunStoreInterface {\n\tstatic readonly #allocations = new Map<string, Promise<void>>()\n\treadonly #files: FileBrowserStore\n\treadonly #slots = new WeakMap<BrowserRunSlot, string>()\n\treadonly #directories = new Set<string>()\n\n\tconstructor(options: FileBrowserStoreOptions) {\n\t\tthis.#files = new FileBrowserStore(options)\n\t}\n\n\tasync snapshot(bytes: Uint8Array, options?: BrowserStoreOptions): Promise<string> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tconst owned = new Uint8Array(bytes)\n\t\tconst directory = await this.#files.allocate(\n\t\t\tthis.#files.resolvePath(BROWSER_RUN_DIRECTORY),\n\t\t\tgenerateBrowserRunId,\n\t\t\toptions,\n\t\t)\n\t\tconst path = this.#files.resolvePath(directory.path, 'view.png')\n\t\ttry {\n\t\t\tawait this.#files.check(path, options)\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tawait writeFile(path, owned, { flag: 'wx', signal: options?.signal })\n\t\t\treturn path\n\t\t} catch (error) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tthrow this.#files.translateError(path, error)\n\t\t}\n\t}\n\n\tasync open(name: string, options?: BrowserStoreOptions): Promise<BrowserRunSlot> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tthis.#files.validateName(name)\n\t\tconst path = this.#files.resolvePath(name, BROWSER_JOURNEY_LOCK_DIRECTORY)\n\t\tconst previous = FileBrowserRunStore.#allocations.get(path)\n\t\tconst allocation = Promise.withResolvers<void>()\n\t\tFileBrowserRunStore.#allocations.set(path, allocation.promise)\n\t\ttry {\n\t\t\tawait previous\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\treturn await this.#files.lock(\n\t\t\t\tpath,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst directory = await this.#files.allocate(\n\t\t\t\t\t\tthis.#files.resolvePath(name, BROWSER_RUN_DIRECTORY),\n\t\t\t\t\t\tgenerateBrowserRunId,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t)\n\t\t\t\t\tconst slot = Object.freeze({ id: directory.id, directory: directory.path })\n\t\t\t\t\tthis.#directories.add(directory.path)\n\t\t\t\t\tthis.#slots.set(slot, directory.path)\n\t\t\t\t\treturn slot\n\t\t\t\t},\n\t\t\t\toptions,\n\t\t\t)\n\t\t} finally {\n\t\t\tallocation.resolve()\n\t\t\tif (FileBrowserRunStore.#allocations.get(path) === allocation.promise)\n\t\t\t\tFileBrowserRunStore.#allocations.delete(path)\n\t\t}\n\t}\n\n\tasync get(\n\t\tname: string,\n\t\tid: string,\n\t\toptions?: BrowserStoreOptions,\n\t): Promise<BrowserRun | undefined> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tthis.#files.validateName(name)\n\t\tthis.#files.validateId(id)\n\t\tconst path = this.#files.resolvePath(name, BROWSER_RUN_DIRECTORY, id, BROWSER_RUN_FILE)\n\t\tconst source = await this.#files.read(path, options)\n\t\tif (source === undefined) return undefined\n\t\ttry {\n\t\t\tconst value = parseJSON(source)\n\t\t\tif (!isRecord(value) || !('format' in value))\n\t\t\t\tthrow new BrowserError('Missing run format', 'BROWSER_JOURNEY_FILE')\n\t\t\tif (\n\t\t\t\tvalue['format'] === BROWSER_JOURNEY_FORMAT_VERSION &&\n\t\t\t\t(!isRecord(value['journey']) || !('format' in value['journey']))\n\t\t\t)\n\t\t\t\tthrow new BrowserError('Missing run journey format', 'BROWSER_JOURNEY_FILE')\n\t\t\tvalidateBrowserRun(value)\n\t\t\tif (value.id !== id || value.journey.name !== name)\n\t\t\t\tthrow new BrowserError('Run identity differs from its directory', 'BROWSER_JOURNEY_FILE')\n\t\t\treturn value\n\t\t} catch (error) {\n\t\t\tthrow this.#files.translateError(path, error)\n\t\t}\n\t}\n\n\tasync set(run: BrowserRun, options?: BrowserStoreOptions): Promise<void> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tthis.#files.validateName(run.journey.name)\n\t\tthis.#files.validateId(run.id)\n\t\tvalidateBrowserRun(run)\n\t\tconst source = JSON.stringify(run)\n\t\tconst directory = this.#files.resolvePath(run.journey.name, BROWSER_RUN_DIRECTORY, run.id)\n\t\tawait this.#requireDirectory(directory, options)\n\t\tawait this.#files.write(this.#files.resolvePath(directory, BROWSER_RUN_FILE), source, options)\n\t}\n\n\tasync capture(\n\t\tslot: BrowserRunSlot,\n\t\tname: string,\n\t\tbytes: Uint8Array,\n\t\toptions?: BrowserStoreOptions,\n\t): Promise<string> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tconst directory = this.#slots.get(slot)\n\t\tif (directory === undefined || !/^s[1-9]\\d*\\.png$/.test(name))\n\t\t\tthrow new BrowserError(\n\t\t\t\t'Capture requires an opened slot and an sN.png name',\n\t\t\t\t'BROWSER_JOURNEY_PATH',\n\t\t\t)\n\t\tconst owned = new Uint8Array(bytes)\n\t\tawait this.#requireDirectory(directory, options)\n\t\tawait this.#files.write(this.#files.resolvePath(directory, name), owned, options)\n\t\treturn name\n\t}\n\n\tasync delete(name: string, id: string, options?: BrowserStoreOptions): Promise<void> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tthis.#files.validateName(name)\n\t\tthis.#files.validateId(id)\n\t\tconst directory = this.#files.resolvePath(name, BROWSER_RUN_DIRECTORY, id)\n\t\tawait this.#files.check(this.#files.resolvePath(directory, BROWSER_RUN_FILE), options)\n\t\ttry {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tawait rm(directory, { recursive: true, force: true, maxRetries: 3 })\n\t\t\tthis.#directories.delete(directory)\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t} catch (error) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tthrow this.#files.translateError(directory, error)\n\t\t}\n\t}\n\n\tasync clear(name: string, options?: BrowserStoreOptions): Promise<number> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tthis.#files.validateName(name)\n\t\tconst parent = this.#files.resolvePath(name, BROWSER_RUN_DIRECTORY)\n\t\tif (!(await this.#files.check(parent, options))) return 0\n\t\treturn this.#files.lock(\n\t\t\tthis.#files.resolvePath(name, BROWSER_JOURNEY_LOCK_DIRECTORY),\n\t\t\tasync () => {\n\t\t\t\ttry {\n\t\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\t\tconst ids = await readdir(parent)\n\t\t\t\t\t// Check the whole removal before deleting any run, including unsaved slots.\n\t\t\t\t\tfor (const id of ids) {\n\t\t\t\t\t\tthis.#files.validateId(id)\n\t\t\t\t\t\tawait this.#files.check(this.#files.resolvePath(parent, id, BROWSER_RUN_FILE), options)\n\t\t\t\t\t}\n\t\t\t\t\tfor (const id of ids) await this.delete(name, id, options)\n\t\t\t\t\treturn ids.length\n\t\t\t\t} catch (error) {\n\t\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\t\tthrow this.#files.translateError(parent, error)\n\t\t\t\t}\n\t\t\t},\n\t\t\toptions,\n\t\t)\n\t}\n\n\tasync list(\n\t\tname: string,\n\t\toptions?: BrowserStoreOptions & { readonly offset?: number; readonly limit?: number },\n\t): Promise<BrowserStorePage<BrowserRun>> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tthis.#files.validateName(name)\n\t\treturn this.#files.list(\n\t\t\tthis.#files.resolvePath(name, BROWSER_RUN_DIRECTORY),\n\t\t\t(id) => this.get(name, id, options),\n\t\t\toptions,\n\t\t)\n\t}\n\n\tasync #requireDirectory(directory: string, options?: BrowserStoreOptions): Promise<void> {\n\t\tif (!this.#directories.has(directory) || !(await this.#files.check(directory, options)))\n\t\t\tthrow new BrowserError(\n\t\t\t\t`Run directory was not opened or is missing: ${directory}`,\n\t\t\t\t'BROWSER_JOURNEY_PATH',\n\t\t\t)\n\t\ttry {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tconst status = await lstat(directory)\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tif (!status.isDirectory())\n\t\t\t\tthrow new BrowserError(\n\t\t\t\t\t`Run directory is not a directory: ${directory}`,\n\t\t\t\t\t'BROWSER_JOURNEY_PATH',\n\t\t\t\t)\n\t\t} catch (error) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tthrow this.#files.translateError(directory, error)\n\t\t}\n\t}\n}\n","import type {\n\tBrowserJourneyStoreInterface,\n\tBrowserRunStoreInterface,\n\tCDPTransportInterface,\n\tBrowserWriterInterface,\n} from '@src/core'\nimport type {\n\tFileBrowserStoreOptions,\n\tBrowserInterface,\n\tBrowserMCPServerInterface,\n\tBrowserMCPServerOptions,\n\tBrowserOptions,\n\tWebSocketCDPTransportOptions,\n} from './types.js'\nimport { BrowserMCPServer } from './BrowserMCPServer.js'\nimport { FileBrowserJourneyStore } from './stores/FileBrowserJourneyStore.js'\nimport { FileBrowserRunStore } from './stores/FileBrowserRunStore.js'\nimport { Browser } from './Browser.js'\nimport { WebSocketCDPTransport } from './transports/WebSocketCDPTransport.js'\nimport { FileBrowserWriter } from './writers/FileBrowserWriter.js'\n\n/**\n * Creates a raw-CDP `BrowserInterface` façade with discovery, connection, and lifecycle\n * management.\n *\n * @param options - Connection, launch, and viewport configuration\n * @returns A {@link BrowserInterface}\n *\n * @example Connect to a browser and drive a page\n * ```ts\n * import { createBrowser } from '@orkestrel/browser/server'\n *\n * const browser = createBrowser({ headless: true })\n * await browser.connect() // CDP endpoint discovery → connect, else launch\n * const page = await browser.create({ url: 'https://example.com' })\n * await (await page.elements.find({ css: '#accept' }))[0]?.click()\n * const shot = await page.screenshot({ path: './out.png' })\n * await browser.destroy()\n * ```\n */\nexport function createBrowser(options?: BrowserOptions): BrowserInterface {\n\treturn new Browser(options)\n}\n\n/**\n * Creates a Node `WebSocket`-backed `CDPTransportInterface` for the given CDP debugger URL.\n *\n * @param options - The CDP WebSocket debugger URL (and optional timeout)\n * @returns A {@link CDPTransportInterface}\n */\nexport function createCDPTransport(options: WebSocketCDPTransportOptions): CDPTransportInterface {\n\treturn new WebSocketCDPTransport(options)\n}\n\n/**\n * Creates a filesystem-backed `BrowserWriterInterface` that persists bytes through\n * `node:fs/promises`.\n *\n * @returns A {@link BrowserWriterInterface} that persists bytes through `node:fs/promises`\n */\nexport function createBrowserWriter(): BrowserWriterInterface {\n\treturn new FileBrowserWriter()\n}\n\n/**\n * Creates a journey store over an existing filesystem root.\n * @param options - Root and listing cap\n * @returns A durable journey store\n * @example\n * const store = createFileBrowserJourneyStore({ root: directory })\n */\nexport function createFileBrowserJourneyStore(\n\toptions: FileBrowserStoreOptions,\n): BrowserJourneyStoreInterface {\n\treturn new FileBrowserJourneyStore(options)\n}\n\n/**\n * Creates a run store over an existing filesystem root.\n * @param options - Root and listing cap\n * @returns A durable run and capture store\n * @example\n * const store = createFileBrowserRunStore({ root: directory })\n */\nexport function createFileBrowserRunStore(\n\toptions: FileBrowserStoreOptions,\n): BrowserRunStoreInterface {\n\treturn new FileBrowserRunStore(options)\n}\n\n/**\n * Creates the browse server, which serves the browser vocabulary and the journey tools over the\n * Model Context Protocol on stdio and warms Chromium at server start.\n *\n * @param options - The root, the launch, the journeys' read-only switch, and the streams\n * @returns A {@link BrowserMCPServerInterface} that reads nothing until `start()`\n *\n * @example\n * ```ts\n * import { createBrowserMCPServer } from '@orkestrel/browser/server'\n *\n * const server = createBrowserMCPServer({ root: 'tmp/browsers', headless: true })\n * await server.start() // resolves after leasing a connected browser\n * await server.destroy()\n * ```\n */\nexport function createBrowserMCPServer(\n\toptions?: BrowserMCPServerOptions,\n): BrowserMCPServerInterface {\n\treturn new BrowserMCPServer(options)\n}\n","import type { ChildProcess } from 'node:child_process'\nimport type {\n\tBrowserConnection,\n\tBrowserDiscoveryResult,\n\tBrowserEngine,\n\tBrowserEventMap,\n\tBrowserInterface,\n\tBrowserOptions,\n\tBrowserProfileResult,\n\tBrowserStatus,\n} from './types.js'\nimport type {\n\tBrowserCallOptions,\n\tBrowserContextInterface,\n\tBrowserContextOptions,\n\tBrowserPageInterface,\n\tBrowserPageOptions,\n\tCDPTarget,\n\tCDPTransportInterface,\n} from '@src/core'\nimport type { EmitterInterface } from '@orkestrel/emitter'\nimport { addAbortListener, once } from 'node:events'\nimport { isArray, isError, isInteger, isRecord, isString } from '@orkestrel/contract'\nimport { Emitter } from '@orkestrel/emitter'\nimport {\n\tBrowserConnectionError,\n\tBrowserContext,\n\tBrowserTransition,\n\tBROWSER_DEFAULT_TIMEOUT_MS,\n\tCDPClient,\n\tisBrowserConnectionError,\n\tvalidateBrowserContextOptions,\n} from '@src/core'\nimport { BrowserDestroyedError, BrowserNotConnectedError } from './errors.js'\nimport {\n\tBROWSER_CDP_PROTOCOL,\n\tBROWSER_CDP_VERSION_PATH,\n\tBROWSER_DEFAULT_CDP_PORT,\n\tBROWSER_DEFAULT_HOST,\n\tBROWSER_DRAIN_INTERVAL_MS,\n\tBROWSER_KILL_GRACE_MS,\n\tBROWSER_PORT_PROBE_TIMEOUT_MS,\n\tBROWSER_PROCESS_EXIT_CAUSE,\n\tBROWSER_TRANSPORT_LOSS_CAUSE,\n\tBROWSER_TRANSPORT_LOSS_DEFER_MS,\n} from './constants.js'\nimport {\n\tbrowserToEngine,\n\tcreateBrowserProfile,\n\tfindSystemBrowser,\n\tlaunchBrowserProcess,\n\tparseBrowserEngine,\n\treadBrowserEndpoint,\n\tremoveBrowserProfile,\n} from './helpers.js'\nimport { createCDPTransport, createBrowserWriter } from './factories.js'\n\n// === Browser\n\n/**\n * Discovers, launches, connects to, and owns Chromium-family browser sessions.\n *\n * @example\n * ```ts\n * import { Browser } from '@orkestrel/browser/server'\n *\n * const browser = new Browser({ headless: true })\n * await browser.connect()\n * const page = await browser.create({ url: 'https://example.com' })\n * await browser.destroy()\n * ```\n */\nexport class Browser implements BrowserInterface {\n\treadonly #emitter: Emitter<BrowserEventMap>\n\treadonly #options: BrowserOptions\n\treadonly #abort = new AbortController()\n\treadonly #cdpPort: number\n\treadonly #cdpHost: string\n\t#engine: BrowserEngine\n\t#status: BrowserStatus = 'idle'\n\t#connection: BrowserConnection | undefined\n\t#owned: boolean | undefined\n\t#endpoint: string | undefined\n\t#client: CDPClient | undefined\n\t#process: ChildProcess | undefined\n\t// Identifier the launcher handed the endpoint to when it re-executed the\n\t// browser and exited before CDP became ready. Undefined whenever the\n\t// spawned child is itself the process serving the endpoint.\n\t#servingPid: number | undefined\n\t#profile: BrowserProfileResult | undefined\n\t#contexts: BrowserContext[] = []\n\treadonly #isolating = new Set<Promise<BrowserContextInterface>>()\n\t#destroyed = false\n\treadonly #connecting: BrowserTransition = new BrowserTransition()\n\treadonly #disconnecting: BrowserTransition = new BrowserTransition()\n\t#exitCleanup: Promise<void> | undefined\n\t#shutdown: Promise<void> | undefined\n\t#transport: CDPTransportInterface | undefined\n\treadonly #transportCloseHandler = this.#handleTransportLoss.bind(this)\n\treadonly #transportErrorHandler = this.#handleTransportLoss.bind(this)\n\treadonly #processExitHandler = this.#handleProcessExit.bind(this)\n\n\tconstructor(options?: BrowserOptions) {\n\t\tthis.#emitter = new Emitter({\n\t\t\t...(options?.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options?.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t\tthis.#options = options ?? {}\n\t\tthis.#engine =\n\t\t\tthis.#options.engine ??\n\t\t\t(this.#options.executable !== undefined\n\t\t\t\t? (parseBrowserEngine(this.#options.executable) ?? 'chromium')\n\t\t\t\t: 'chromium')\n\t\tthis.#cdpPort = this.#options.cdp?.port ?? BROWSER_DEFAULT_CDP_PORT\n\t\tthis.#cdpHost = this.#options.cdp?.host ?? BROWSER_DEFAULT_HOST\n\n\t\tqueueMicrotask(() => this.#emitter.emit('idle'))\n\t}\n\n\tget emitter(): EmitterInterface<BrowserEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget engine(): BrowserEngine {\n\t\treturn this.#engine\n\t}\n\n\tget status(): BrowserStatus {\n\t\treturn this.#status\n\t}\n\n\tget connection(): BrowserConnection | undefined {\n\t\treturn this.#connection\n\t}\n\n\tget owned(): boolean | undefined {\n\t\treturn this.#owned\n\t}\n\n\tget pid(): number | undefined {\n\t\treturn this.#servingPid ?? this.#process?.pid\n\t}\n\n\tget endpoint(): string | undefined {\n\t\treturn this.#endpoint\n\t}\n\n\tasync ping(options?: BrowserCallOptions): Promise<void> {\n\t\tif (this.#destroyed) throw new BrowserDestroyedError()\n\t\tconst client = this.#client\n\t\tif (this.#status !== 'connected' || client === undefined) {\n\t\t\tthrow new BrowserNotConnectedError()\n\t\t}\n\t\tawait client.send('Browser.getVersion', undefined, options)\n\t}\n\n\tasync discover(): Promise<BrowserDiscoveryResult> {\n\t\tconst result = await this.#discoverCDP()\n\t\tthis.#emitter.emit('discover', result)\n\t\treturn result\n\t}\n\n\tasync connect(): Promise<void> {\n\t\tif (this.#destroyed) throw new BrowserDestroyedError()\n\n\t\tconst active = this.#connecting.pending\n\t\tif (active !== undefined) {\n\t\t\tawait active\n\t\t\treturn\n\t\t}\n\t\tif (this.#status === 'connected') return\n\n\t\tawait this.#connecting.execute(() => this.#establish())\n\t}\n\n\tadopt(): void {\n\t\tif (this.#destroyed) throw new BrowserDestroyedError()\n\t\tif (\n\t\t\tthis.#status !== 'connected' ||\n\t\t\tthis.#client === undefined ||\n\t\t\tthis.#endpoint === undefined\n\t\t) {\n\t\t\tthrow new BrowserNotConnectedError()\n\t\t}\n\t\tthis.#owned = true\n\t}\n\n\tasync disconnect(): Promise<void> {\n\t\tif (this.#destroyed) return\n\n\t\tconst disconnecting = this.#disconnecting.pending\n\t\tconst connecting = this.#connecting.pending\n\t\tif (disconnecting !== undefined) await disconnecting\n\t\tif (connecting !== undefined) await connecting.catch(() => undefined)\n\t\tif (this.#destroyed) return\n\t\tif (this.#status !== 'connected' || this.#client === undefined) return\n\n\t\tawait this.#disconnecting.execute(() => this.#detach())\n\t}\n\n\tcontext(index?: number): BrowserContextInterface | undefined {\n\t\tconst i = index ?? 0\n\t\tif (i < 0 || i >= this.#contexts.length) return undefined\n\t\treturn this.#contexts[i]\n\t}\n\n\tcontexts(): readonly BrowserContextInterface[] {\n\t\treturn [...this.#contexts]\n\t}\n\n\tasync isolate(options?: BrowserContextOptions): Promise<BrowserContextInterface> {\n\t\tconst attempt = this.#isolate(options)\n\t\tthis.#isolating.add(attempt)\n\t\ttry {\n\t\t\treturn await attempt\n\t\t} finally {\n\t\t\tthis.#isolating.delete(attempt)\n\t\t}\n\t}\n\n\tasync create(options?: BrowserPageOptions): Promise<BrowserPageInterface> {\n\t\tif (this.#destroyed) throw new BrowserDestroyedError()\n\t\tconst client = this.#client\n\t\tif (this.#status !== 'connected' || client === undefined) {\n\t\t\tthrow new BrowserNotConnectedError()\n\t\t}\n\n\t\tlet context = this.#contexts[0]\n\t\tif (context === undefined) {\n\t\t\tcontext = new BrowserContext(client, undefined, this.#options.viewport, createBrowserWriter())\n\t\t\tthis.#registerContext(context)\n\t\t}\n\n\t\tconst page = await context.create(options)\n\t\tthis.#emitter.emit('page', page)\n\t\treturn page\n\t}\n\n\tdestroy(): Promise<void> {\n\t\tconst active = this.#shutdown\n\t\tif (active !== undefined) return active\n\t\tif (this.#destroyed) return Promise.resolve()\n\n\t\tthis.#destroyed = true\n\t\tthis.#abort.abort()\n\t\tconst shutdown = this.#destroyResources()\n\t\tthis.#shutdown = shutdown\n\t\treturn shutdown\n\t}\n\n\tclose(): Promise<void> {\n\t\tconst active = this.#shutdown\n\t\tif (active !== undefined) return active\n\t\tif (this.#destroyed) return Promise.resolve()\n\n\t\tthis.#destroyed = true\n\t\tthis.#abort.abort()\n\t\tconst shutdown = this.#closeResources()\n\t\tthis.#shutdown = shutdown\n\t\treturn shutdown\n\t}\n\n\t// === Private helpers\n\n\tasync #isolate(options?: BrowserContextOptions): Promise<BrowserContextInterface> {\n\t\tif (this.#destroyed) throw new BrowserDestroyedError()\n\t\tconst client = this.#client\n\t\tif (this.#status !== 'connected' || client === undefined) {\n\t\t\tthrow new BrowserNotConnectedError()\n\t\t}\n\t\tvalidateBrowserContextOptions(options)\n\t\tconst params: Record<string, unknown> = { disposeOnDetach: false }\n\t\tif (options?.proxy !== undefined) {\n\t\t\tparams['proxyServer'] = options.proxy.server\n\t\t\tif (options.proxy.bypass !== undefined) {\n\t\t\t\tparams['proxyBypassList'] = options.proxy.bypass.join(',')\n\t\t\t}\n\t\t}\n\t\tif (options?.origins !== undefined) {\n\t\t\tparams['originsWithUniversalNetworkAccess'] = [...options.origins]\n\t\t}\n\t\tconst result = await client.send('Target.createBrowserContext', params)\n\t\tif (!isRecord(result) || !isString(result['browserContextId'])) {\n\t\t\tthrow new BrowserConnectionError('Failed to create isolated browser context')\n\t\t}\n\t\tconst id = result['browserContextId']\n\t\tconst context = new BrowserContext(\n\t\t\tclient,\n\t\t\tid,\n\t\t\toptions?.emulation?.viewport ?? this.#options.viewport,\n\t\t\tcreateBrowserWriter(),\n\t\t\toptions?.emulation,\n\t\t\toptions?.downloads,\n\t\t\toptions,\n\t\t)\n\n\t\ttry {\n\t\t\tif (this.#destroyed || this.#client !== client) throw new BrowserDestroyedError()\n\t\t\tif (options?.downloads !== undefined) {\n\t\t\t\tawait client.send('Browser.setDownloadBehavior', {\n\t\t\t\t\tbehavior: options.downloads.named === true ? 'allowAndName' : 'allow',\n\t\t\t\t\tbrowserContextId: id,\n\t\t\t\t\tdownloadPath: options.downloads.path,\n\t\t\t\t\teventsEnabled: true,\n\t\t\t\t})\n\t\t\t}\n\t\t\tif (this.#destroyed || this.#client !== client) throw new BrowserDestroyedError()\n\t\t} catch (error) {\n\t\t\tawait context.close().catch(() => undefined)\n\t\t\tthrow error\n\t\t}\n\n\t\tthis.#registerContext(context)\n\t\treturn context\n\t}\n\n\tasync #establish(): Promise<void> {\n\t\tconst disconnecting = this.#disconnecting.pending\n\t\tif (disconnecting !== undefined) await disconnecting\n\t\tawait this.#settleExit()\n\t\tif (this.#destroyed) throw new BrowserDestroyedError()\n\t\tif (this.#status === 'connected') return\n\n\t\tthis.#assertNotAborted()\n\t\tthis.#status = 'connecting'\n\n\t\ttry {\n\t\t\tif (this.#owned === true && this.#endpoint !== undefined) {\n\t\t\t\tawait this.#connectCDP(this.#endpoint)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst endpoint = this.#options.cdp?.endpoint\n\t\t\tif (endpoint !== undefined) {\n\t\t\t\tawait this.#connectCDP(endpoint)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst discover = this.#options.cdp?.discover ?? true\n\t\t\tif (discover) {\n\t\t\t\tconst discovery = await this.#raceAbort(this.#discoverCDP(this.#signal()))\n\t\t\t\tif (discovery.endpoint !== undefined) {\n\t\t\t\t\tthis.#engine = browserToEngine(discovery.browser)\n\t\t\t\t\tawait this.#connectCDP(discovery.endpoint)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t} else if (this.#options.cdp?.port !== undefined) {\n\t\t\t\tawait this.#raceAbort(this.#assertPortFree())\n\t\t\t}\n\n\t\t\tthis.#assertNotAborted()\n\t\t\tawait this.#launch()\n\t\t} catch (error) {\n\t\t\tif (this.#destroyed) throw new BrowserDestroyedError()\n\n\t\t\tthis.#status = 'error'\n\t\t\tthis.#emitter.emit('error', error)\n\t\t\tif (isBrowserConnectionError(error)) throw error\n\n\t\t\tconst message = isError(error) ? error.message : String(error)\n\t\t\tthrow new BrowserConnectionError(message, { executable: this.#options.executable })\n\t\t}\n\t}\n\n\tasync #detach(): Promise<void> {\n\t\tthis.#status = 'disconnected'\n\t\tthis.#connection = undefined\n\t\tthis.#unbindTransport()\n\n\t\tconst client = this.#client\n\t\tthis.#client = undefined\n\t\tawait this.#destroyContexts()\n\t\tthis.#contexts = []\n\n\t\tif (this.#owned !== true) {\n\t\t\tthis.#owned = undefined\n\t\t\tthis.#endpoint = undefined\n\t\t}\n\n\t\tawait this.#closeClient(client)\n\t\tif (this.#destroyed) return\n\n\t\tthis.#emitter.emit('disconnect')\n\t\tthis.#emitter.emit('idle')\n\t}\n\n\t#assertNotAborted(): void {\n\t\tif (this.#signal().aborted) throw new BrowserConnectionError('Connection aborted')\n\t}\n\n\t#signal(): AbortSignal {\n\t\tconst external = this.#options.signal\n\t\treturn external === undefined\n\t\t\t? this.#abort.signal\n\t\t\t: AbortSignal.any([this.#abort.signal, external])\n\t}\n\n\tasync #raceAbort<T>(promise: Promise<T>): Promise<T> {\n\t\tconst signal = this.#signal()\n\t\tif (signal.aborted) throw new BrowserConnectionError('Connection aborted')\n\n\t\tconst aborted = Promise.withResolvers<never>()\n\t\tconst listener = addAbortListener(signal, () => {\n\t\t\taborted.reject(new BrowserConnectionError('Connection aborted'))\n\t\t})\n\n\t\ttry {\n\t\t\treturn await Promise.race([promise, aborted.promise])\n\t\t} finally {\n\t\t\tlistener[Symbol.dispose]()\n\t\t\tvoid promise.catch(() => undefined)\n\t\t}\n\t}\n\n\t#handleProcessExit(): void {\n\t\tif (this.#destroyed) return\n\n\t\tconst connected = this.#status === 'connected'\n\t\tconst client = this.#client\n\t\tconst contexts = this.#contexts\n\t\tconst process = this.#process\n\t\tthis.#unbindTransport()\n\t\tthis.#unbindProcess()\n\t\tthis.#process = undefined\n\t\tthis.#servingPid = undefined\n\t\tconst cleanup = this.#cleanupExitedProcess(process, contexts, client)\n\t\tthis.#exitCleanup = cleanup\n\t\tvoid cleanup.catch((error: unknown) => this.#emitter.emit('error', error))\n\t\tthis.#client = undefined\n\t\tthis.#contexts = []\n\t\tthis.#connection = undefined\n\t\tthis.#owned = undefined\n\t\tthis.#endpoint = undefined\n\t\tif (connected) this.#status = 'disconnected'\n\n\t\tthis.#emitter.emit(\n\t\t\t'error',\n\t\t\tnew BrowserConnectionError('The browser process exited unexpectedly', {\n\t\t\t\tcause: BROWSER_PROCESS_EXIT_CAUSE,\n\t\t\t}),\n\t\t)\n\n\t\tif (connected) {\n\t\t\tthis.#emitter.emit('disconnect')\n\t\t\tthis.#emitter.emit('idle')\n\t\t}\n\t}\n\n\t#handleTransportLoss(): void {\n\t\tif (this.#destroyed || this.#status !== 'connected') return\n\n\t\tif (this.#process === undefined) {\n\t\t\tthis.#confirmTransportLoss()\n\t\t\treturn\n\t\t}\n\n\t\tif (!this.#alive()) {\n\t\t\tthis.#handleProcessExit()\n\t\t\treturn\n\t\t}\n\n\t\t// A spawned child that is already dead is diagnosed by its own `exit`\n\t\t// event, never by a probe here: Node sets `exitCode` in the same callback\n\t\t// that emits `exit`, and reports ESRCH from `ChildProcess.kill(0)` as a\n\t\t// `false` return rather than a throw, so no reading of the handle can see\n\t\t// the death before the event does. The defer only has to outlast the loop\n\t\t// turn that delivers it.\n\t\tsetTimeout(() => this.#confirmTransportLoss(), BROWSER_TRANSPORT_LOSS_DEFER_MS)\n\t}\n\n\t#confirmTransportLoss(): void {\n\t\tif (this.#destroyed || this.#status !== 'connected') return\n\n\t\tif (this.#process !== undefined && !this.#alive()) {\n\t\t\tthis.#handleProcessExit()\n\t\t\treturn\n\t\t}\n\n\t\tconst client = this.#client\n\t\tconst owned = this.#owned === true\n\t\tconst contexts = this.#contexts\n\t\tthis.#unbindTransport()\n\t\tthis.#client = undefined\n\t\tthis.#contexts = []\n\t\tthis.#connection = undefined\n\t\tthis.#status = 'disconnected'\n\n\t\tif (!owned) {\n\t\t\tthis.#owned = undefined\n\t\t\tthis.#endpoint = undefined\n\t\t}\n\n\t\tvoid this.#destroyContextList(contexts)\n\t\tvoid this.#closeClient(client)\n\t\tthis.#emitter.emit(\n\t\t\t'error',\n\t\t\tnew BrowserConnectionError('The CDP transport connection was lost', {\n\t\t\t\tcause: BROWSER_TRANSPORT_LOSS_CAUSE,\n\t\t\t}),\n\t\t)\n\t\tthis.#emitter.emit('disconnect')\n\t\tthis.#emitter.emit('idle')\n\t}\n\n\t#bindTransport(transport: CDPTransportInterface): void {\n\t\tthis.#unbindTransport()\n\t\tthis.#transport = transport\n\t\ttransport.emitter.on('close', this.#transportCloseHandler)\n\t\ttransport.emitter.on('error', this.#transportErrorHandler)\n\t}\n\n\t#unbindTransport(): void {\n\t\tconst transport = this.#transport\n\t\tif (transport === undefined) return\n\t\ttransport.emitter.off('close', this.#transportCloseHandler)\n\t\ttransport.emitter.off('error', this.#transportErrorHandler)\n\t\tthis.#transport = undefined\n\t}\n\n\t#bindProcess(process: ChildProcess): void {\n\t\tthis.#unbindProcess()\n\t\t// A launcher that handed the endpoint on has already exited, and its exit\n\t\t// says nothing about the browser now serving CDP. That browser has no\n\t\t// child handle, so the transport reports its death.\n\t\tif (this.#servingPid !== undefined) return\n\t\tprocess.once('exit', this.#processExitHandler)\n\t\tif (process.exitCode !== null || process.signalCode !== null) {\n\t\t\tqueueMicrotask(this.#processExitHandler)\n\t\t}\n\t}\n\n\t#unbindProcess(): void {\n\t\tthis.#process?.off('exit', this.#processExitHandler)\n\t}\n\n\t#timeout(): number {\n\t\treturn this.#options.timeout ?? BROWSER_DEFAULT_TIMEOUT_MS\n\t}\n\n\tasync #discoverCDP(signal?: AbortSignal): Promise<BrowserDiscoveryResult> {\n\t\tconst url = `${BROWSER_CDP_PROTOCOL}://${this.#cdpHost}:${this.#cdpPort}${BROWSER_CDP_VERSION_PATH}`\n\t\tconst requestSignal =\n\t\t\tsignal === undefined\n\t\t\t\t? AbortSignal.timeout(this.#timeout())\n\t\t\t\t: AbortSignal.any([signal, AbortSignal.timeout(this.#timeout())])\n\n\t\ttry {\n\t\t\tconst response = await fetch(url, { signal: requestSignal })\n\t\t\tif (!response.ok) return this.#notFound()\n\n\t\t\tconst info: unknown = await response.json()\n\t\t\tif (!isRecord(info)) return this.#notFound()\n\n\t\t\tconst endpoint = isString(info['webSocketDebuggerUrl'])\n\t\t\t\t? info['webSocketDebuggerUrl']\n\t\t\t\t: undefined\n\t\t\tconst browser = isString(info['Browser']) ? info['Browser'] : undefined\n\n\t\t\treturn { endpoint, browser }\n\t\t} catch (error) {\n\t\t\tif (signal?.aborted === true) throw error\n\t\t\treturn this.#notFound()\n\t\t}\n\t}\n\n\t#notFound(): BrowserDiscoveryResult {\n\t\treturn { endpoint: undefined, browser: undefined }\n\t}\n\n\tasync #assertPortFree(): Promise<void> {\n\t\tif (await this.#probePort()) {\n\t\t\tthrow new BrowserConnectionError(\n\t\t\t\t`Port ${this.#cdpPort} on ${this.#cdpHost} is already occupied by another CDP endpoint`,\n\t\t\t\t{ port: this.#cdpPort, host: this.#cdpHost },\n\t\t\t)\n\t\t}\n\t}\n\n\tasync #probePort(): Promise<boolean> {\n\t\tconst url = `${BROWSER_CDP_PROTOCOL}://${this.#cdpHost}:${this.#cdpPort}${BROWSER_CDP_VERSION_PATH}`\n\n\t\ttry {\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tsignal: AbortSignal.timeout(BROWSER_PORT_PROBE_TIMEOUT_MS),\n\t\t\t})\n\t\t\treturn response.ok\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tasync #connectCDP(endpoint: string): Promise<void> {\n\t\tconst transport = createCDPTransport({ url: endpoint, timeout: this.#timeout() })\n\t\tconst client = new CDPClient({ transport, timeout: this.#timeout() })\n\t\tconst retained = this.#owned === true && this.#endpoint === endpoint\n\n\t\ttry {\n\t\t\tawait this.#raceAbort(client.connect())\n\n\t\t\tthis.#client = client\n\t\t\tthis.#endpoint = endpoint\n\t\t\tthis.#connection = retained ? this.#retainedConnection() : 'cdp'\n\t\t\tthis.#owned = retained\n\t\t\tthis.#status = 'connected'\n\t\t\tthis.#bindTransport(transport)\n\n\t\t\tawait this.#syncContexts()\n\t\t\tthis.#emitter.emit('connect', this.#connection)\n\t\t} catch (error) {\n\t\t\tthis.#unbindTransport()\n\t\t\tif (this.#client === client) this.#client = undefined\n\t\t\tthis.#contexts = []\n\t\t\tthis.#connection = undefined\n\t\t\tif (!retained) {\n\t\t\t\tthis.#owned = undefined\n\t\t\t\tthis.#endpoint = undefined\n\t\t\t}\n\t\t\tawait this.#closeClient(client)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync #launch(): Promise<void> {\n\t\tif (this.#process !== undefined) {\n\t\t\tthrow new BrowserConnectionError('A browser process is already active on this instance')\n\t\t}\n\n\t\tconst requestedEngine = this.#options.engine ?? this.#options.browsers?.engine\n\t\tlet executable = this.#options.executable\n\t\tlet resolvedEngine: BrowserEngine | undefined\n\n\t\tif (executable !== undefined) {\n\t\t\tresolvedEngine = parseBrowserEngine(executable) ?? 'chromium'\n\t\t} else {\n\t\t\tconst found = findSystemBrowser({\n\t\t\t\t...this.#options.browsers,\n\t\t\t\t...(requestedEngine !== undefined ? { engine: requestedEngine } : {}),\n\t\t\t})\n\t\t\texecutable = found?.executable\n\t\t\tresolvedEngine = found?.engine\n\t\t}\n\n\t\tif (executable === undefined) {\n\t\t\tthrow new BrowserConnectionError(\n\t\t\t\t'No Chromium browser found. Install Chrome, Edge, or Chromium.',\n\t\t\t\trequestedEngine === undefined ? undefined : { engine: requestedEngine },\n\t\t\t)\n\t\t}\n\n\t\tthis.#engine = resolvedEngine ?? 'chromium'\n\t\tawait this.#releaseProfile()\n\t\tconst profile = await createBrowserProfile(this.#options.profile)\n\t\tthis.#profile = profile\n\t\tlet process: ChildProcess\n\t\ttry {\n\t\t\tprocess = launchBrowserProcess(\n\t\t\t\texecutable,\n\t\t\t\tthis.#options.cdp?.port,\n\t\t\t\tthis.#options.headless ?? true,\n\t\t\t\tprofile.path,\n\t\t\t\tthis.#options.args,\n\t\t\t)\n\t\t} catch (error) {\n\t\t\tawait this.#releaseProfile()\n\t\t\tthrow error\n\t\t}\n\t\tthis.#process = process\n\n\t\tlet client: CDPClient | undefined\n\n\t\ttry {\n\t\t\tconst endpoint = await this.#waitForLaunch(process, executable, this.#options.args)\n\t\t\tconst transport = createCDPTransport({ url: endpoint, timeout: this.#timeout() })\n\t\t\tclient = new CDPClient({ transport, timeout: this.#timeout() })\n\t\t\tawait this.#raceAbort(client.connect())\n\t\t\tawait this.#takeEndpointOwner(process, client)\n\n\t\t\tconst connection = this.#options.profile === undefined ? 'launch' : 'persistent'\n\t\t\tthis.#client = client\n\t\t\tthis.#endpoint = endpoint\n\t\t\tthis.#connection = connection\n\t\t\tthis.#owned = true\n\t\t\tthis.#status = 'connected'\n\t\t\tthis.#bindTransport(transport)\n\t\t\tthis.#bindProcess(process)\n\n\t\t\tawait this.#syncContexts()\n\t\t\tthis.#emitter.emit('launch', this.#engine)\n\t\t\tthis.#emitter.emit('connect', connection)\n\t\t} catch (error) {\n\t\t\tthis.#unbindTransport()\n\t\t\tthis.#unbindProcess()\n\t\t\tawait this.#closeClient(client)\n\t\t\tawait this.#terminate(process)\n\t\t\tawait this.#releaseProfile()\n\t\t\tthis.#process = undefined\n\t\t\tthis.#servingPid = undefined\n\t\t\tthis.#client = undefined\n\t\t\tthis.#endpoint = undefined\n\t\t\tthis.#owned = undefined\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Takes over the process serving the CDP endpoint when the spawned child is\n\t * no longer it.\n\t *\n\t * @remarks\n\t * A Windows launcher — Microsoft Edge — re-executes the browser with the\n\t * same `--remote-debugging-port` and exits 0 before the endpoint answers, so\n\t * the child this instance spawned parents the real tree without being part\n\t * of it. Chromium names the process behind the endpoint as the `browser`\n\t * entry of `SystemInfo.getProcessInfo`, which identifies it without a\n\t * platform branch. An endpoint that names no such process cannot be owned,\n\t * so the launch closes it and fails rather than leaking it.\n\t */\n\tasync #takeEndpointOwner(process: ChildProcess, client: CDPClient): Promise<void> {\n\t\tif (process.exitCode === null && process.signalCode === null) return\n\n\t\tlet result: unknown\n\t\ttry {\n\t\t\tresult = await client.send('SystemInfo.getProcessInfo')\n\t\t} catch {\n\t\t\tresult = undefined\n\t\t}\n\n\t\tlet pid: number | undefined\n\t\tif (isRecord(result) && isArray(result['processInfo'])) {\n\t\t\tfor (const entry of result['processInfo']) {\n\t\t\t\tif (!isRecord(entry) || entry['type'] !== 'browser' || !isInteger(entry['id'])) continue\n\t\t\t\tpid = entry['id']\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif (pid === undefined) {\n\t\t\tawait this.#closeRemote(client)\n\t\t\tthrow new BrowserConnectionError(\n\t\t\t\t'The browser launcher exited without naming the process serving its CDP endpoint',\n\t\t\t\t{ executable: this.#options.executable, pid: process.pid },\n\t\t\t)\n\t\t}\n\n\t\tthis.#servingPid = pid\n\t}\n\n\tasync #waitForLaunch(\n\t\tprocess: ChildProcess,\n\t\texecutable: string,\n\t\targs?: readonly string[],\n\t): Promise<string> {\n\t\tconst context = { executable, args }\n\t\tconst timeout = this.#timeout()\n\t\tconst controller = new AbortController()\n\t\tconst deadline = AbortSignal.timeout(timeout)\n\t\tconst signal = AbortSignal.any([controller.signal, this.#signal(), deadline])\n\t\tconst stderr = process.stderr\n\t\tif (stderr === null) {\n\t\t\tthrow new BrowserConnectionError('The browser process has no standard error to read', context)\n\t\t}\n\t\tconst exit = once(process, 'exit', { signal })\n\t\tvoid exit.catch(() => undefined)\n\t\tconst ready = readBrowserEndpoint(stderr, signal).catch(async (error: unknown) => {\n\t\t\t// A stream that closes without the line ends the launch, and the exit\n\t\t\t// that closed it names the cause: a nonzero exit is the launch-exit\n\t\t\t// fault, while a clean exit leaves the readiness failure standing.\n\t\t\tif (signal.aborted) throw error\n\t\t\tconst values = await exit\n\t\t\tif (values[0] === 0 && values[1] === null) throw error\n\t\t\tthrow new BrowserConnectionError(\n\t\t\t\tthis.#formatLaunchExit(\n\t\t\t\t\tisInteger(values[0]) ? values[0] : null,\n\t\t\t\t\tisString(values[1]) ? values[1] : null,\n\t\t\t\t),\n\t\t\t\tcontext,\n\t\t\t)\n\t\t})\n\t\tconst exited = exit.then((values) => {\n\t\t\tconst code = isInteger(values[0]) ? values[0] : null\n\t\t\tconst exitSignal = isString(values[1]) ? values[1] : null\n\t\t\t// A launcher that re-executes the browser exits cleanly and hands the\n\t\t\t// inherited standard error to the process it spawned, so a clean exit\n\t\t\t// ends the child rather than the launch. Keep reading the same pipe on\n\t\t\t// the same readiness budget, which still fails when the line never\n\t\t\t// arrives.\n\t\t\tif (code === 0 && exitSignal === null) return ready\n\t\t\tthrow new BrowserConnectionError(this.#formatLaunchExit(code, exitSignal), context)\n\t\t})\n\n\t\ttry {\n\t\t\treturn await Promise.race([ready, exited])\n\t\t} catch (error) {\n\t\t\tif (isBrowserConnectionError(error)) throw error\n\t\t\tif (this.#signal().aborted) throw new BrowserConnectionError('Connection aborted', context)\n\t\t\tif (deadline.aborted) {\n\t\t\t\tthrow new BrowserConnectionError(\n\t\t\t\t\t`Browser did not report a CDP endpoint within ${timeout}ms`,\n\t\t\t\t\t{ ...context, timeout },\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tconst message = isError(error) ? error.message : String(error)\n\t\t\tthrow new BrowserConnectionError(message, context)\n\t\t} finally {\n\t\t\tcontroller.abort()\n\t\t\tvoid ready.catch(() => undefined)\n\t\t\tvoid exited.catch(() => undefined)\n\t\t}\n\t}\n\n\t#formatLaunchExit(code: number | null, signal: string | null): string {\n\t\tif (signal !== null) {\n\t\t\treturn `Browser process exited before CDP became ready (signal: ${signal})`\n\t\t}\n\t\tif (code !== null) return `Browser process exited before CDP became ready (code: ${code})`\n\t\treturn 'Browser process exited before CDP became ready'\n\t}\n\n\t#retainedConnection(): BrowserConnection {\n\t\tif (this.#process === undefined) return 'cdp'\n\t\treturn this.#options.profile === undefined ? 'launch' : 'persistent'\n\t}\n\n\tasync #syncContexts(): Promise<void> {\n\t\tconst client = this.#client\n\t\tif (client === undefined) return\n\n\t\tlet result: unknown\n\t\ttry {\n\t\t\tresult = await client.send('Target.getTargets')\n\t\t} catch {\n\t\t\treturn\n\t\t}\n\t\tif (!isRecord(result) || !isArray(result['targetInfos'])) return\n\n\t\tconst pages: CDPTarget[] = []\n\t\tfor (const target of result['targetInfos']) {\n\t\t\tif (\n\t\t\t\t!isRecord(target) ||\n\t\t\t\t!isString(target['targetId']) ||\n\t\t\t\ttarget['type'] !== 'page' ||\n\t\t\t\t!isString(target['title']) ||\n\t\t\t\t!isString(target['url'])\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpages.push({\n\t\t\t\tid: target['targetId'],\n\t\t\t\tcategory: target['type'],\n\t\t\t\ttitle: target['title'],\n\t\t\t\turl: target['url'],\n\t\t\t})\n\t\t}\n\t\tif (pages.length === 0 || this.#contexts.length > 0) return\n\n\t\tconst context = new BrowserContext(\n\t\t\tclient,\n\t\t\tundefined,\n\t\t\tthis.#options.viewport,\n\t\t\tcreateBrowserWriter(),\n\t\t)\n\t\tawait context.sync(pages)\n\t\tthis.#registerContext(context)\n\t}\n\n\tasync #destroyResources(): Promise<void> {\n\t\tlet terminated = false\n\t\ttry {\n\t\t\tawait this.#settle()\n\t\t\tthis.#unbindTransport()\n\t\t\tthis.#unbindProcess()\n\n\t\t\tconst client = this.#client\n\t\t\tif (this.#owned === true) {\n\t\t\t\tawait this.#closeContexts()\n\t\t\t\tif (this.#process === undefined) await this.#closeRemote(client)\n\t\t\t} else {\n\t\t\t\tawait this.#destroyContexts()\n\t\t\t}\n\t\t\tthis.#contexts = []\n\n\t\t\tawait this.#terminate(this.#process)\n\t\t\tthis.#process = undefined\n\t\t\tthis.#servingPid = undefined\n\t\t\tterminated = true\n\t\t} finally {\n\t\t\tconst contexts = this.#contexts\n\t\t\tthis.#contexts = []\n\t\t\tconst client = this.#client\n\t\t\tthis.#client = undefined\n\t\t\ttry {\n\t\t\t\tawait this.#cleanupLocal(contexts, client)\n\t\t\t\tif (terminated) await this.#releaseProfile()\n\t\t\t} finally {\n\t\t\t\tthis.#finish()\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #closeResources(): Promise<void> {\n\t\tlet terminated = false\n\t\ttry {\n\t\t\tawait this.#settle()\n\t\t\tthis.#unbindTransport()\n\t\t\tthis.#unbindProcess()\n\n\t\t\tconst client = this.#client\n\t\t\tawait this.#closeContexts()\n\t\t\tthis.#contexts = []\n\t\t\tawait this.#closeRemote(client)\n\n\t\t\tconst process = this.#process\n\t\t\tif (process !== undefined) {\n\t\t\t\tconst exited = await this.#waitForTerminationWithin(process, BROWSER_KILL_GRACE_MS)\n\t\t\t\tif (!exited) await this.#terminate(process)\n\t\t\t\tawait this.#closeProcessPipe(process)\n\t\t\t}\n\t\t\tthis.#process = undefined\n\t\t\tthis.#servingPid = undefined\n\t\t\tterminated = true\n\t\t} finally {\n\t\t\tconst contexts = this.#contexts\n\t\t\tthis.#contexts = []\n\t\t\tconst client = this.#client\n\t\t\tthis.#client = undefined\n\t\t\ttry {\n\t\t\t\tawait this.#cleanupLocal(contexts, client)\n\t\t\t\tif (terminated) await this.#releaseProfile()\n\t\t\t} finally {\n\t\t\t\tthis.#finish()\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #settle(): Promise<void> {\n\t\tawait Promise.allSettled(this.#isolating)\n\t\tawait this.#connecting.pending?.catch(() => undefined)\n\t\tawait this.#disconnecting.pending?.catch(() => undefined)\n\t\tawait this.#settleExit()\n\t}\n\n\tasync #settleExit(): Promise<void> {\n\t\tconst cleanup = this.#exitCleanup\n\t\tif (cleanup === undefined) return\n\t\tawait cleanup\n\t\tif (this.#exitCleanup === cleanup) this.#exitCleanup = undefined\n\t}\n\n\tasync #closeRemote(client: CDPClient | undefined): Promise<void> {\n\t\tlet remote = client\n\t\tlet temporary = false\n\n\t\tif (remote === undefined && this.#owned === true && this.#endpoint !== undefined) {\n\t\t\tconst transport = createCDPTransport({\n\t\t\t\turl: this.#endpoint,\n\t\t\t\ttimeout: this.#timeout(),\n\t\t\t})\n\t\t\tremote = new CDPClient({ transport, timeout: this.#timeout() })\n\t\t\ttry {\n\t\t\t\tawait remote.connect()\n\t\t\t\ttemporary = true\n\t\t\t} catch {\n\t\t\t\tawait this.#closeClient(remote)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tif (remote !== undefined) {\n\t\t\ttry {\n\t\t\t\tawait remote.send('Browser.close')\n\t\t\t} catch {\n\t\t\t\t// The remote may already be gone or close before acknowledging.\n\t\t\t}\n\t\t}\n\n\t\tif (temporary) await this.#closeClient(remote)\n\t}\n\n\tasync #closeContexts(): Promise<void> {\n\t\tfor (const context of [...this.#contexts]) {\n\t\t\ttry {\n\t\t\t\tawait context.close()\n\t\t\t} catch {\n\t\t\t\t// Teardown is best-effort after the browser begins shutting down.\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #destroyContexts(): Promise<void> {\n\t\tawait this.#destroyContextList([...this.#contexts])\n\t}\n\n\t#registerContext(context: BrowserContext): void {\n\t\tthis.#contexts.push(context)\n\t\tcontext.emitter.on('close', () => {\n\t\t\tconst index = this.#contexts.indexOf(context)\n\t\t\tif (index >= 0) this.#contexts.splice(index, 1)\n\t\t})\n\t\tthis.#emitter.emit('context', context)\n\t}\n\n\tasync #destroyContextList(contexts: readonly BrowserContext[]): Promise<void> {\n\t\tfor (const context of contexts) {\n\t\t\ttry {\n\t\t\t\tawait context.destroy()\n\t\t\t} catch {\n\t\t\t\t// The transport may already be unavailable.\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #closeClient(client: CDPClient | undefined): Promise<void> {\n\t\tif (client === undefined) return\n\t\ttry {\n\t\t\tawait client.close()\n\t\t} catch {\n\t\t\t// Teardown is best-effort after a connection fault.\n\t\t}\n\t}\n\n\tasync #releaseProfile(): Promise<void> {\n\t\tconst profile = this.#profile\n\t\tthis.#profile = undefined\n\t\tif (profile !== undefined) await removeBrowserProfile(profile)\n\t}\n\n\tasync #cleanupExitedProcess(\n\t\tprocess: ChildProcess | undefined,\n\t\tcontexts: readonly BrowserContext[],\n\t\tclient: CDPClient | undefined,\n\t): Promise<void> {\n\t\tlet terminated = false\n\t\ttry {\n\t\t\tawait this.#terminate(process)\n\t\t\tterminated = true\n\t\t} finally {\n\t\t\tawait this.#cleanupLocal(contexts, client)\n\t\t}\n\t\tif (terminated) await this.#releaseProfile()\n\t}\n\n\tasync #cleanupLocal(\n\t\tcontexts: readonly BrowserContext[],\n\t\tclient: CDPClient | undefined,\n\t): Promise<void> {\n\t\tawait this.#destroyContextList(contexts)\n\t\tawait this.#closeClient(client)\n\t}\n\n\tasync #waitForProcessWithin(process: ChildProcess, timeout: number): Promise<boolean> {\n\t\tif (process.exitCode !== null || process.signalCode !== null) return true\n\n\t\tconst signal = AbortSignal.timeout(timeout)\n\t\ttry {\n\t\t\tawait once(process, 'exit', { signal })\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\tif (signal.aborted) {\n\t\t\t\treturn process.exitCode !== null || process.signalCode !== null\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t#hasProcessGroup(process: ChildProcess): boolean {\n\t\tconst pid = process.pid\n\t\treturn globalThis.process.platform !== 'win32' && pid !== undefined && pid > 0\n\t}\n\n\t// Whether the process serving the CDP endpoint is still running. The spawned\n\t// child reports through its own handle; a process the launcher handed the\n\t// endpoint to has none, so it is probed by identifier.\n\t#alive(): boolean {\n\t\tconst process = this.#process\n\t\tif (process === undefined) return false\n\t\tif (this.#servingPid !== undefined) return this.#signalProcess(process, 0) !== false\n\t\treturn process.exitCode === null && process.signalCode === null\n\t}\n\n\t// Whether the launch retains a process the reaped child does not account\n\t// for: the POSIX process group, or the process the launcher handed the\n\t// endpoint to.\n\t#inspectRemainder(process: ChildProcess): boolean | undefined {\n\t\tif (!this.#hasProcessGroup(process) && this.#servingPid === undefined) return false\n\t\treturn this.#signalProcess(process, 0)\n\t}\n\n\t#signalProcess(process: ChildProcess, signal: NodeJS.Signals | 0): boolean | undefined {\n\t\tconst pid = process.pid\n\t\tconst serving = this.#servingPid\n\t\ttry {\n\t\t\tif (this.#hasProcessGroup(process) && pid !== undefined) {\n\t\t\t\treturn globalThis.process.kill(-pid, signal)\n\t\t\t}\n\t\t\t// Terminating the Chromium browser process takes its whole tree with\n\t\t\t// it, so Windows needs no separate tree walk to reach the renderers,\n\t\t\t// GPU, and utility children the serving process parents.\n\t\t\tif (serving !== undefined) return globalThis.process.kill(serving, signal)\n\t\t\treturn process.kill(signal)\n\t\t} catch (error) {\n\t\t\tconst code =\n\t\t\t\tisError(error) && 'code' in error && isString(error.code) ? error.code : undefined\n\t\t\tif (code === 'ESRCH') return false\n\t\t\tif (signal === 0) return code === 'EPERM' ? true : undefined\n\t\t\tthrow new BrowserConnectionError('Failed to signal the browser process', {\n\t\t\t\tpid: serving ?? pid,\n\t\t\t\tsignal,\n\t\t\t\tcause: error,\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Waits within a bound for the rest of a terminated process group, or the process a\n\t * launcher handed the endpoint to, to disappear.\n\t *\n\t * @remarks\n\t * This is the one interval loop in the server. Node raises an exit event for the direct\n\t * child only, so no event source reports the remainder of a POSIX process group or a\n\t * handed-off process, and the drain probes on `BROWSER_DRAIN_INTERVAL_MS` until the\n\t * remainder is gone or `timeout` elapses.\n\t */\n\tasync #waitForRemainderWithin(\n\t\tprocess: ChildProcess,\n\t\ttimeout: number,\n\t): Promise<boolean | undefined> {\n\t\tconst deadline = performance.now() + timeout\n\t\tlet confirmed = false\n\t\twhile (true) {\n\t\t\tconst alive = this.#inspectRemainder(process)\n\t\t\tif (alive === false) return true\n\t\t\tif (alive === true) confirmed = true\n\t\t\tconst remaining = deadline - performance.now()\n\t\t\tif (remaining <= 0) return confirmed ? false : undefined\n\t\t\tawait new Promise<void>((resolve) =>\n\t\t\t\tsetTimeout(resolve, Math.min(BROWSER_DRAIN_INTERVAL_MS, remaining)),\n\t\t\t)\n\t\t}\n\t}\n\n\tasync #waitForTerminationWithin(\n\t\tprocess: ChildProcess,\n\t\ttimeout: number,\n\t\tfinal = false,\n\t): Promise<boolean> {\n\t\tconst exited = this.#waitForProcessWithin(process, timeout)\n\t\tconst drained = this.#waitForRemainderWithin(process, timeout)\n\t\tconst results = await Promise.all([exited, drained])\n\t\treturn results[0] && (results[1] === true || (final && results[1] === undefined))\n\t}\n\n\tasync #terminate(process: ChildProcess | undefined): Promise<void> {\n\t\ttry {\n\t\t\tif (\n\t\t\t\tprocess === undefined ||\n\t\t\t\t((process.exitCode !== null || process.signalCode !== null) &&\n\t\t\t\t\tthis.#inspectRemainder(process) === false)\n\t\t\t) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (this.#signalProcess(process, 'SIGTERM') === false) return\n\t\t\tif (await this.#waitForTerminationWithin(process, BROWSER_KILL_GRACE_MS)) return\n\n\t\t\tif (this.#signalProcess(process, 'SIGKILL') === false) return\n\t\t\tif (await this.#waitForTerminationWithin(process, BROWSER_KILL_GRACE_MS, true)) return\n\n\t\t\tthrow new BrowserConnectionError('Browser process did not exit after SIGKILL', {\n\t\t\t\tpid: this.#servingPid ?? process.pid,\n\t\t\t})\n\t\t} finally {\n\t\t\tawait this.#closeProcessPipe(process)\n\t\t}\n\t}\n\n\tasync #closeProcessPipe(process: ChildProcess | undefined): Promise<void> {\n\t\tconst stream = process?.stderr\n\t\tif (stream === undefined || stream === null || stream.closed) return\n\t\t// A descendant can inherit the writer after the browser exits, especially on Windows.\n\t\t// Release our read end explicitly and await its close before teardown settles.\n\t\tconst closed = once(stream, 'close')\n\t\tstream.destroy()\n\t\tawait closed\n\t}\n\n\t#finish(): void {\n\t\tthis.#unbindTransport()\n\t\tthis.#unbindProcess()\n\t\tthis.#status = 'disconnected'\n\t\tthis.#connection = undefined\n\t\tthis.#owned = undefined\n\t\tthis.#endpoint = undefined\n\t\tthis.#client = undefined\n\t\tthis.#process = undefined\n\t\tthis.#servingPid = undefined\n\t\tthis.#exitCleanup = undefined\n\t\tthis.#contexts = []\n\t\tthis.#emitter.emit('destroy')\n\t\tthis.#emitter.destroy()\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["parseInteger","isError","parseJSON","isRecord","isNumber","isString","isBrowserError","pathWin32","pathPosix","mkdtemp","join","tmpdir","resolve","dirname","basename","BrowserError","rm","existsSync","spawnSync","globSync","spawn","isArray","isJSONValue","BrowserTransition","Emitter","BROWSER_DEFAULT_TIMEOUT_MS","WEBSOCKET_READY_OPEN","BrowserError","attempt","isJSONValue","randomBytes","WEBSOCKET_VERSION","httpsRequest","httpRequest","WEBSOCKET_READY_CLOSED","isString","computeWebSocketAccept","createNodeWebSocket","mkdir","dirname","writeFile","isInteger","BrowserError","createPool","resolve","createToolManager","BROWSER_TOOL_NAMES","BROWSER_JOURNEY_TOOL_NAMES","createTool","BROWSER_TOOL_COPY","createMCPServer","createStdioServer","createMCPLegacy","mkdir","join","isBrowserError","isPoolError","readFile","isError","rm","boundBrowserText","BROWSER_TOOL_LIMIT","BROWSER_TOOL_CUT_FOOTER","isString","randomUUID","addAbortListener","isRecord","MCPError","JSONRPC_SERVER_ERROR","createBrowserToolset","writeFile","rename","readdir","createCDPClient","toolToDefinition","BrowserError","realpathSync","BROWSER_JOURNEY_NAME_PATTERN","BROWSER_RUN_ID_PATTERN","resolve","sep","relative","lstat","dirname","mkdir","readFile","randomUUID","open","rename","unlink","readdir","rmdir","parseJSON","isRecord","BrowserError","normalizeBrowserJourneyReason","BROWSER_JOURNEY_NAME_PATTERN","generateBrowserRunId","writeFile","parseJSON","isRecord","BrowserError","BROWSER_JOURNEY_FORMAT_VERSION","rm","readdir","lstat","BrowserTransition","Emitter","BrowserError","BrowserContext","isRecord","isString","isBrowserError","isError","addAbortListener","BROWSER_DEFAULT_TIMEOUT_MS","CDPClient","isArray","isInteger","once","isJSONValue"],"sources":["../../../src/server/constants.ts","../../../src/server/helpers.ts","../../../src/server/transports/WebSocketCDPTransport.ts","../../../src/server/writers/FileBrowserWriter.ts","../../../package.json","../../../src/server/BrowserMCPServer.ts","../../../src/server/stores/FileBrowserStore.ts","../../../src/server/stores/FileBrowserJourneyStore.ts","../../../src/server/stores/FileBrowserRunStore.ts","../../../src/server/factories.ts","../../../src/server/Browser.ts"],"sourcesContent":["import type { ToolDefinition } from '@orkestrel/tool'\nimport type { BrowserEngine, BrowserServerToolName } from './types.js'\n\n// === CDP discovery\n\n/**\n * Sets the default CDP port probed for an existing browser and used for launches, `9222`.\n */\nexport const BROWSER_DEFAULT_CDP_PORT = 9222\n\n/**\n * Sets the default host probed for an existing browser and used for launches, `'127.0.0.1'`,\n * which avoids `localhost` resolving to `::1` when Chromium binds `127.0.0.1`.\n */\nexport const BROWSER_DEFAULT_HOST = '127.0.0.1'\n\n/** Names the protocol prefix for CDP discovery requests, `'http'`. */\nexport const BROWSER_CDP_PROTOCOL = 'http'\n\n/**\n * Names the path appended to the CDP host to fetch version metadata, `'/json/version'`, which\n * is where endpoint discovery reads.\n */\nexport const BROWSER_CDP_VERSION_PATH = '/json/version'\n\n/**\n * Names the path appended to the CDP host to list open targets — pages, workers, and every\n * other target category Chromium reports — `'/json/list'`.\n */\nexport const BROWSER_CDP_LIST_PATH = '/json/list'\n\n// === Browser launch\n\n/**\n * Lists the flags always passed to a launched browser process, alongside the caller's own.\n *\n * @remarks\n * Disables account sync so extension installs cannot reset URL loader factories during page imports.\n * Disables Edge's implicit sign-in so fresh automation profiles carry no Microsoft account.\n * Chromium ignores the unknown Edge feature name on Chrome and Chromium.\n * The launcher merges disabled features with the caller's into one switch.\n */\nexport const BROWSER_LAUNCH_ARGS: readonly string[] = Object.freeze([\n\t'--no-first-run',\n\t'--no-default-browser-check',\n\t'--disable-sync',\n\t'--disable-features=msImplicitSignin',\n])\n\n/**\n * Names the flag that enables headless mode on a launched browser process, `'--headless=new'`.\n */\nexport const BROWSER_HEADLESS_ARG = '--headless=new'\n\n/**\n * Names the prefix for isolated browser profiles created beneath the operating-system temp\n * directory, `'orkestrel-browser-'`.\n */\nexport const BROWSER_PROFILE_PREFIX = 'orkestrel-browser-'\n\n/**\n * Bounds each launched-process exit window during TERM-to-KILL teardown at `3_000`\n * milliseconds.\n */\nexport const BROWSER_KILL_GRACE_MS = 3_000\n\n/**\n * Bounds the `discover: false` port-occupancy probe before launching at `200` milliseconds,\n * which is short because the probe only needs to detect an already-listening CDP endpoint\n * rather than perform full discovery.\n */\nexport const BROWSER_PORT_PROBE_TIMEOUT_MS = 200\n\n/**\n * Matches the stderr line Chromium prints when its CDP endpoint accepts connections, and\n * captures the `ws://` endpoint the line names.\n *\n * @remarks\n * Chromium prints the line only when launched with `--remote-debugging-port`, which is why an\n * owned launch always passes that flag.\n */\nexport const BROWSER_DEVTOOLS_PATTERN = /DevTools listening on (ws:\\/\\/\\S+)/\n\n/**\n * Sets the interval in milliseconds between liveness probes of a terminated browser process\n * group.\n *\n * @remarks\n * Node raises an exit event for the direct child only. Neither the rest of a POSIX process\n * group nor a process a launcher handed the endpoint to raises one, so the bounded drain in\n * `Browser` probes on this interval until the group is gone or the grace period ends.\n */\nexport const BROWSER_DRAIN_INTERVAL_MS = 100\n\n/**\n * Defers once for `50` milliseconds when a transport loss is observed on an owned process,\n * so a near-simultaneous process-exit event, which libuv might reap slightly later than the\n * socket close, decides the diagnosis first.\n */\nexport const BROWSER_TRANSPORT_LOSS_DEFER_MS = 50\n\n/**\n * Names the machine-readable error-context cause for an owned browser process exiting,\n * `'process-exit'`.\n */\nexport const BROWSER_PROCESS_EXIT_CAUSE = 'process-exit'\n\n/**\n * Names the machine-readable error-context cause for a CDP transport disconnecting while its\n * browser remains alive, `'transport-loss'`.\n */\nexport const BROWSER_TRANSPORT_LOSS_CAUSE = 'transport-loss'\n\n/**\n * Lists the environment variables checked, in order, for an explicit browser executable path\n * override: `PLAYWRIGHT_EXECUTABLE_PATH`, then `CHROME_PATH`.\n */\nexport const BROWSER_ENV_PATH_KEYS: readonly string[] = Object.freeze([\n\t'PLAYWRIGHT_EXECUTABLE_PATH',\n\t'CHROME_PATH',\n])\n\n/**\n * Lists the well-known Chrome/Chromium/Edge executable paths with no platform-specific root,\n * keyed by `process.platform`, leaving `win32` empty because its roots come from\n * `BROWSER_WINDOWS_SUFFIXES`.\n */\nexport const BROWSER_EXECUTABLE_PATHS: Readonly<Record<string, readonly string[]>> = Object.freeze({\n\tlinux: Object.freeze([\n\t\t'/usr/bin/google-chrome',\n\t\t'/usr/bin/google-chrome-stable',\n\t\t'/usr/bin/microsoft-edge',\n\t\t'/usr/bin/microsoft-edge-stable',\n\t\t'/usr/bin/chromium',\n\t\t'/usr/bin/chromium-browser',\n\t\t'/snap/bin/chromium',\n\t\t'/opt/google/chrome/chrome',\n\t\t'/opt/microsoft/msedge/msedge',\n\t]),\n\tdarwin: Object.freeze([\n\t\t'/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',\n\t\t'/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',\n\t\t'/Applications/Chromium.app/Contents/MacOS/Chromium',\n\t]),\n\twin32: Object.freeze([]),\n})\n\n/** Lists the Windows install-root-relative suffixes for Chrome/Edge/Chromium, joined against each candidate root (`PROGRAMFILES`, `PROGRAMFILES(X86)`, `LOCALAPPDATA`). */\nexport const BROWSER_WINDOWS_SUFFIXES: readonly string[] = Object.freeze([\n\t'Google\\\\Chrome\\\\Application\\\\chrome.exe',\n\t'Microsoft\\\\Edge\\\\Application\\\\msedge.exe',\n\t'Chromium\\\\Application\\\\chrome.exe',\n])\n\n/**\n * Lists the fallback Windows install roots used when `PROGRAMFILES`, `PROGRAMFILES(X86)`, or\n * `LOCALAPPDATA` is absent.\n */\nexport const BROWSER_WINDOWS_ROOT_FALLBACKS: Readonly<Record<string, string>> = Object.freeze({\n\tPROGRAMFILES: 'C:\\\\Program Files',\n\t'PROGRAMFILES(X86)': 'C:\\\\Program Files (x86)',\n})\n\n/** Lists the command names probed on PATH when no well-known executable path exists. */\nexport const BROWSER_EXECUTABLE_NAMES: readonly string[] = Object.freeze([\n\t'google-chrome',\n\t'google-chrome-stable',\n\t'msedge',\n\t'microsoft-edge',\n\t'chromium',\n\t'chromium-browser',\n\t'chrome',\n])\n\n/**\n * Names the environment variable that carries an additional Playwright browser store base\n * directory, `'PLAYWRIGHT_BROWSERS_PATH'`.\n */\nexport const BROWSER_STORE_ENV_KEY = 'PLAYWRIGHT_BROWSERS_PATH'\n\n/**\n * Lists the well-known Playwright browser store base directories checked in addition to\n * `PLAYWRIGHT_BROWSERS_PATH`, starting with `/opt/pw-browsers`.\n */\nexport const BROWSER_STORE_DEFAULT_DIRS: readonly string[] = Object.freeze(['/opt/pw-browsers'])\n\n/** Names the per-OS default Playwright browser cache directory, relative to the home directory (win32 uses `LOCALAPPDATA` directly). */\nexport const BROWSER_STORE_CACHE_DIRS: Readonly<Record<string, string>> = Object.freeze({\n\tlinux: '.cache/ms-playwright',\n\tdarwin: 'Library/Caches/ms-playwright',\n})\n\n/**\n * Names the top-level Chromium symlink or binary Playwright maintains inside a browser store\n * base, `'chromium'`.\n */\nexport const BROWSER_STORE_LINK_NAME = 'chromium'\n\n/**\n * Lists the case-insensitive substrings identifying an executable path/name's browser\n * engine, checked by `parseBrowserEngine` in the order `edge` → `chromium` → `chrome`.\n */\nexport const BROWSER_ENGINE_HINTS: Readonly<Record<BrowserEngine, readonly string[]>> =\n\tObject.freeze({\n\t\tedge: Object.freeze(['msedge', 'microsoft-edge', 'edge']),\n\t\tchromium: Object.freeze([\n\t\t\t'chromium',\n\t\t\t'pw-browsers',\n\t\t\t'chrome-linux',\n\t\t\t'chrome-win',\n\t\t\t'chrome-mac',\n\t\t\t'chrome_headless',\n\t\t]),\n\t\tchrome: Object.freeze(['google-chrome', 'google/chrome', 'google\\\\chrome', 'chrome']),\n\t})\n\n/** Names the glob pattern (relative to a store base) matching a versioned Chromium binary, keyed by `process.platform`. */\nexport const BROWSER_STORE_GLOBS: Readonly<Record<string, string>> = Object.freeze({\n\tlinux: 'chromium-*/chrome-linux*/chrome',\n\tdarwin: 'chromium-*/chrome-mac*/Chromium.app/Contents/MacOS/Chromium',\n\twin32: 'chromium-*/chrome-win*/chrome.exe',\n})\n\n/** Names the persisted journey snapshot. */\nexport const BROWSER_JOURNEY_SNAPSHOT_FILE = 'journey.json'\n/** Names the retained journey revision counter. */\nexport const BROWSER_JOURNEY_REVISION_FILE = 'revision'\n/** Names the exclusive journey write lock directory. */\nexport const BROWSER_JOURNEY_LOCK_DIRECTORY = 'journey.lock'\n/** Bounds attempts to acquire a journey lock after concurrent recovery. */\nexport const BROWSER_JOURNEY_LOCK_ATTEMPTS = 8\n/** Names the persisted run snapshot. */\nexport const BROWSER_RUN_FILE = 'run.json'\n/** Names the journey directory holding its runs. */\nexport const BROWSER_RUN_DIRECTORY = 'runs'\n/** Bounds a file-store listing page by default. */\nexport const BROWSER_FILE_STORE_LIMIT = 100\n\n/** Names the refusal when no browser can serve a call. */\nexport const BROWSER_SERVER_UNAVAILABLE = 'SERVER_UNAVAILABLE'\n/** Names a failed attempt to warm a browser. */\nexport const BROWSER_SERVER_LAUNCH = 'SERVER_LAUNCH'\n/** Sets the default number of warm browsers to 1. */\nexport const BROWSER_SERVER_POOL_SIZE = 1\n/** Sets the default context capacity per browser, including the shared holder. */\nexport const BROWSER_SERVER_CONTEXTS = 2\n/** Limits context capacity to the largest measured per-browser count. */\nexport const BROWSER_SERVER_CONTEXTS_LIMIT = 4\n/** Limits the number of warm browsers to 3. */\nexport const BROWSER_SERVER_POOL_LIMIT = 3\n/** Permits one failed refill before the next failure spends the bound. */\nexport const BROWSER_SERVER_RESTARTS = 1\n/** Names the browser process record in each profile. */\nexport const BROWSER_SERVER_RECORD = 'browse.json'\n/** Names the diagnostic when the warm floor spends its restart bound. */\nexport const BROWSER_SERVER_EXHAUSTED = 'SERVER_EXHAUSTED'\n/** Names a failed browser server teardown. */\nexport const BROWSER_SERVER_TEARDOWN = 'SERVER_TEARDOWN'\n/** Names a failed profile sweep. */\nexport const BROWSER_SERVER_SWEEP = 'SERVER_SWEEP'\n/** Names a refused browser server option. */\nexport const BROWSER_SERVER_OPTIONS = 'ARGUMENT'\n/** Names the notice that a browser and its session state were lost. */\nexport const BROWSER_SERVER_CRASH = 'SERVER_CRASH'\n/** Names an interrupted call whose outcome is unknown. */\nexport const BROWSER_SERVER_UNRESOLVED = 'SERVER_UNRESOLVED'\n\n/** Names the refusal when every browser is admitted to a holder. */\nexport const BROWSER_SERVER_BUSY = 'SERVER_BUSY'\n/** Names the refusal for an unknown or ended holder. */\nexport const BROWSER_SERVER_HOLDER = 'SERVER_HOLDER'\n\n/** Defines the holder tools independently of the shared browser's vocabulary. */\nexport const BROWSER_SERVER_COPY: Readonly<Record<BrowserServerToolName, ToolDefinition>> =\n\tObject.freeze({\n\t\tacquire: Object.freeze({\n\t\t\tname: 'acquire',\n\t\t\tdescription:\n\t\t\t\t'Acquires an independent browser and returns its holder id and tool catalog. Destroy the holder when its work ends.',\n\t\t\tparameters: Object.freeze({\n\t\t\t\ttype: 'object',\n\t\t\t\tproperties: Object.freeze({\n\t\t\t\t\tpurpose: Object.freeze({\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: 'The work this browser will serve.',\n\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t\t\trequired: Object.freeze(['purpose']),\n\t\t\t}),\n\t\t}),\n\t\texecute: Object.freeze({\n\t\t\tname: 'execute',\n\t\t\tdescription:\n\t\t\t\t'Runs a tool on the selected holder, with that tool’s arguments inside arguments. Get its available tools with tools.',\n\t\t\tparameters: Object.freeze({\n\t\t\t\ttype: 'object',\n\t\t\t\tproperties: Object.freeze({\n\t\t\t\t\tholder: Object.freeze({\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: 'The holder id returned by acquire.',\n\t\t\t\t\t}),\n\t\t\t\t\tname: Object.freeze({\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: 'The tool name from this holder’s catalog.',\n\t\t\t\t\t}),\n\t\t\t\t\targuments: Object.freeze({\n\t\t\t\t\t\ttype: 'object',\n\t\t\t\t\t\tdescription: 'The arguments for the selected tool.',\n\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t\t\trequired: Object.freeze(['holder', 'name', 'arguments']),\n\t\t\t}),\n\t\t\tannotations: Object.freeze({ pure: false, untrusted: true }),\n\t\t}),\n\t\ttools: Object.freeze({\n\t\t\tname: 'tools',\n\t\t\tdescription: 'Lists the selected holder’s tools, including tools supplied by its page.',\n\t\t\tparameters: Object.freeze({\n\t\t\t\ttype: 'object',\n\t\t\t\tproperties: Object.freeze({\n\t\t\t\t\tholder: Object.freeze({\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: 'The holder id returned by acquire.',\n\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t\t\trequired: Object.freeze(['holder']),\n\t\t\t}),\n\t\t\tannotations: Object.freeze({ pure: true, untrusted: true }),\n\t\t}),\n\t\tdestroy: Object.freeze({\n\t\t\tname: 'destroy',\n\t\t\tdescription:\n\t\t\t\t'Ends the selected holder and destroys its browser. Calls still running on that holder report an unresolved outcome.',\n\t\t\tparameters: Object.freeze({\n\t\t\t\ttype: 'object',\n\t\t\t\tproperties: Object.freeze({\n\t\t\t\t\tholder: Object.freeze({\n\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\tdescription: 'The holder id returned by acquire.',\n\t\t\t\t\t}),\n\t\t\t\t}),\n\t\t\t\trequired: Object.freeze(['holder']),\n\t\t\t}),\n\t\t\tannotations: Object.freeze({ pure: false }),\n\t\t}),\n\t})\n","import type { ChildProcess } from 'node:child_process'\nimport type { Readable } from 'node:stream'\nimport type { BrowserViewport, CDPTarget } from '@src/core'\nimport type { Result } from '@orkestrel/contract'\nimport type {\n\tBrowserEngine,\n\tBrowserProfileRecord,\n\tBrowserProfileResult,\n\tSystemBrowser,\n\tSystemBrowserOptions,\n} from './types.js'\nimport { existsSync, globSync } from 'node:fs'\nimport { mkdtemp, rm } from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { basename, dirname, join, resolve, win32 as pathWin32, posix as pathPosix } from 'node:path'\nimport { spawn, spawnSync } from 'node:child_process'\nimport {\n\tisArray,\n\tisError,\n\tisNumber,\n\tisRecord,\n\tisString,\n\tparseInteger,\n\tparseJSON,\n\tisJSONValue,\n} from '@orkestrel/contract'\nimport { BrowserError, isBrowserError } from '@src/core'\nimport {\n\tBROWSER_CDP_PROTOCOL,\n\tBROWSER_CDP_LIST_PATH,\n\tBROWSER_DEVTOOLS_PATTERN,\n\tBROWSER_ENV_PATH_KEYS,\n\tBROWSER_EXECUTABLE_PATHS,\n\tBROWSER_EXECUTABLE_NAMES,\n\tBROWSER_WINDOWS_SUFFIXES,\n\tBROWSER_WINDOWS_ROOT_FALLBACKS,\n\tBROWSER_STORE_ENV_KEY,\n\tBROWSER_STORE_DEFAULT_DIRS,\n\tBROWSER_STORE_CACHE_DIRS,\n\tBROWSER_STORE_LINK_NAME,\n\tBROWSER_STORE_GLOBS,\n\tBROWSER_ENGINE_HINTS,\n\tBROWSER_LAUNCH_ARGS,\n\tBROWSER_HEADLESS_ARG,\n\tBROWSER_DEFAULT_HOST,\n\tBROWSER_PROFILE_PREFIX,\n\tBROWSER_SERVER_CRASH,\n\tBROWSER_SERVER_UNRESOLVED,\n\tBROWSER_SERVER_UNAVAILABLE,\n} from './constants.js'\n\n/**\n * Parses positive integer viewport dimensions in WIDTHxHEIGHT form.\n * @param value - The viewport environment variable, or undefined when unset\n * @returns The viewport, or undefined when absent or malformed\n * @example\n * parseBrowserViewport('1280x720') // { width: 1280, height: 720 }\n */\nexport function parseBrowserViewport(value: string | undefined): BrowserViewport | undefined {\n\tif (value === undefined) return undefined\n\tconst match = /^([0-9]+)x([0-9]+)$/u.exec(value)\n\tif (match === null || match[0] !== value) return undefined\n\tconst width = parseInteger(match[1])\n\tconst height = parseInteger(match[2])\n\tif (\n\t\twidth === undefined ||\n\t\theight === undefined ||\n\t\t!Number.isSafeInteger(width) ||\n\t\t!Number.isSafeInteger(height) ||\n\t\twidth <= 0 ||\n\t\theight <= 0\n\t)\n\t\treturn undefined\n\treturn { width, height }\n}\n\n/**\n * Probes whether a process has not been confirmed absent.\n * @param pid - Process identifier to probe with signal zero\n * @returns True if the host has not confirmed absence with ESRCH; false otherwise\n * @example\n * probeProcess(process.pid) // true\n */\nexport function probeProcess(pid: number): boolean {\n\ttry {\n\t\tprocess.kill(pid, 0)\n\t\treturn true\n\t} catch (error) {\n\t\treturn !(isError(error) && 'code' in error && error.code === 'ESRCH')\n\t}\n}\n\n/**\n * Parses a profile record naming a positive process identifier and a loopback DevTools endpoint.\n * @param text - JSON record read from a browse profile\n * @returns The record, or undefined when its shape or endpoint is refused\n * @example\n * parseBrowserProfileRecord('{\"pid\":123,\"endpoint\":\"ws://127.0.0.1:9222/devtools/browser/session\"}')\n */\nexport function parseBrowserProfileRecord(text: string): BrowserProfileRecord | undefined {\n\tconst record = parseJSON(text)\n\tif (!isRecord(record)) return undefined\n\tconst pid = record['pid']\n\tconst endpoint = record['endpoint']\n\tif (!isNumber(pid) || !Number.isSafeInteger(pid) || pid <= 0 || !isString(endpoint))\n\t\treturn undefined\n\tconst match = /^ws:\\/\\/127\\.0\\.0\\.1:([1-9]\\d*)\\/devtools\\/browser\\/[^/?#\\s\\\\]+$/.exec(endpoint)\n\tif (match === null || Number(match[1]) > 65535) return undefined\n\treturn { pid, endpoint }\n}\n\n/**\n * Describes a browser loss with its code, cause, and the session state it invalidates.\n * @param code - Browser server diagnostic code\n * @param cause - The loss or refusal, including its process context when present\n * @param url - The lost page's last URL, when known\n * @returns The coded diagnostic and any operation-lifecycle guidance\n * @example\n * describeBrowserServerLoss('SERVER_UNAVAILABLE', new Error('Browser exited'))\n */\nexport function describeBrowserServerLoss(code: string, cause: unknown, url?: string): string {\n\tconst pid = isBrowserError(cause) ? cause.context?.['pid'] : undefined\n\tconst detail =\n\t\tcause === undefined ? 'Browser session lost' : isError(cause) ? cause.message : String(cause)\n\tconst message = `${code}: ${detail.replace(/\\.+$/u, '')}${isNumber(pid) ? ` (pid ${pid})` : ''}.`\n\tif (code !== BROWSER_SERVER_CRASH && code !== BROWSER_SERVER_UNRESOLVED) return message\n\tconst lost = `Lost the page${url === undefined ? '' : ` at ${url}`}, its tabs, every element reference, the last projection, dialogs, holds, an unsaved recording, the active replay, and the isolated context's cookies.`\n\tconst next = `The next call acquires a browser that starts at about:blank, or answers ${BROWSER_SERVER_UNAVAILABLE} when none can serve.`\n\treturn code === BROWSER_SERVER_UNRESOLVED\n\t\t? `${message} The outcome is unknown. ${lost} Browse did not repeat the call. ${next}`\n\t\t: `${message} ${lost}`\n}\n\n/**\n * Formats a process identifier and UUID token as a lock entry name.\n * @param pid - Positive safe integer identifying the holder process\n * @param token - Lowercase UUID token identifying this acquisition\n * @returns The entry name\n * @example\n * formatBrowserLockEntry(123, '11111111-1111-4111-8111-111111111111')\n */\nexport function formatBrowserLockEntry(pid: number, token: string): string {\n\treturn `${pid}-${token}`\n}\n\n/**\n * Parses the holder process identifier from a lock entry name.\n * @remarks Requires a positive safe integer followed by a lowercase UUID token.\n * @param name - Directory entry name\n * @returns The process identifier, or undefined when the entry is malformed\n * @example\n * parseBrowserLockEntry('123-11111111-1111-4111-8111-111111111111') // 123\n */\nexport function parseBrowserLockEntry(name: string): number | undefined {\n\tconst match = /^([1-9]\\d*)-[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/.exec(\n\t\tname,\n\t)\n\tconst pid = Number(match?.[1])\n\treturn Number.isSafeInteger(pid) && pid > 0 ? pid : undefined\n}\n\n// === Discovery helpers\n\n/**\n * Enumerates every Chrome/Chromium/Edge executable discoverable on this\n * machine, deduplicated by normalized absolute path.\n *\n * @remarks\n * Resolution precedence (candidates appended in this order):\n * 1. `PLAYWRIGHT_EXECUTABLE_PATH`, then `CHROME_PATH` — explicit environment\n * overrides that exist on disk\n * 2. Well-known platform install locations (Chrome, Edge, Chromium); Windows\n * roots are derived from `PROGRAMFILES` / `PROGRAMFILES(X86)` / `LOCALAPPDATA`\n * 3. PATH probe for known command names (`which` on POSIX, `where` on Windows)\n * 4. Playwright-managed browser stores (`PLAYWRIGHT_BROWSERS_PATH`, `/opt/pw-browsers`,\n * and the per-OS Playwright cache directory) — the top-level `chromium`\n * link/binary, then the highest-revision `chromium-*` install found\n *\n * Each candidate is classified into a {@link BrowserEngine} through\n * `parseBrowserEngine` (unclassifiable candidates default to `'chromium'`),\n * and `options.engine` (when given) narrows the result to that engine.\n *\n * @param options - Overrides for the candidate sources; see {@link SystemBrowserOptions}\n * @returns Every discovered browser, in resolution-precedence order\n */\nexport function findSystemBrowsers(options?: SystemBrowserOptions): readonly SystemBrowser[] {\n\tconst platform = process.platform\n\tconst env = options?.env ?? process.env\n\n\tconst candidates: string[] = []\n\n\tcandidates.push(...findEnvOverrides(env))\n\n\tconst paths = options?.paths ?? buildInstallPaths(platform, env)\n\tcandidates.push(...findInstallPaths(paths))\n\n\tconst names = options?.names ?? BROWSER_EXECUTABLE_NAMES\n\tcandidates.push(...probePathNames(names, platform))\n\n\tconst stores = options?.stores ?? buildStoreBases(env, platform)\n\tfor (const store of stores) {\n\t\tcandidates.push(...findStorePaths(store, platform))\n\t}\n\n\tconst seen = new Set<string>()\n\tconst browsers: SystemBrowser[] = []\n\n\tfor (const executable of candidates) {\n\t\tconst key = normalizeExecutablePath(executable, platform)\n\t\tif (seen.has(key)) continue\n\t\tseen.add(key)\n\n\t\tconst engine = parseBrowserEngine(executable) ?? 'chromium'\n\t\tif (options?.engine !== undefined && engine !== options.engine) continue\n\n\t\tbrowsers.push({ executable, engine })\n\t}\n\n\treturn browsers\n}\n\n/**\n * Classifies an executable path/name into a {@link BrowserEngine} by\n * case-insensitive hint, checked in the order edge → chromium → chrome.\n *\n * @param executable - Executable path or command name to classify\n * @returns The classified engine, or undefined when no hint matches\n */\nexport function parseBrowserEngine(executable: string): BrowserEngine | undefined {\n\tconst lower = executable.toLowerCase()\n\tconst order: readonly BrowserEngine[] = ['edge', 'chromium', 'chrome']\n\tfor (const engine of order) {\n\t\tconst hints = BROWSER_ENGINE_HINTS[engine]\n\t\tif (hints.some((hint) => lower.includes(hint))) return engine\n\t}\n\treturn undefined\n}\n\n/** Normalizes an executable path for cross-source deduplication (case-insensitive on Windows). */\nexport function normalizeExecutablePath(path: string, platform: string): string {\n\tconst normalized = platform === 'win32' ? pathWin32.normalize(path) : pathPosix.normalize(path)\n\treturn platform === 'win32' ? normalized.toLowerCase() : normalized\n}\n\n/** Classifies a `/json/version` `Browser` string into a {@link BrowserEngine} (`Edg/` → edge, `Chrome/` → chrome, else chromium). */\nexport function browserToEngine(browser?: string): BrowserEngine {\n\tif (browser?.includes('Edg/') === true) return 'edge'\n\tif (browser?.includes('Chrome/') === true) return 'chrome'\n\treturn 'chromium'\n}\n\n/**\n * Resolves a persistent caller profile or creates an isolated temporary one.\n *\n * @param path - Optional caller-owned persistent user-data directory\n * @returns The resolved profile and whether the library owns its lifecycle\n */\nexport async function createBrowserProfile(path?: string): Promise<BrowserProfileResult> {\n\tif (path !== undefined) return { path, temporary: false }\n\tconst directory = await mkdtemp(join(tmpdir(), BROWSER_PROFILE_PREFIX))\n\treturn { path: directory, temporary: true }\n}\n\n/**\n * Removes a library-owned isolated browser profile.\n *\n * @remarks\n * The path must remain a direct child of the operating-system temp directory\n * with {@link BROWSER_PROFILE_PREFIX}; this defensive check prevents a\n * malformed profile value from widening recursive deletion.\n *\n * @param profile - Resolved profile lifecycle result\n */\nexport async function removeBrowserProfile(profile: BrowserProfileResult): Promise<void> {\n\tif (!profile.temporary) return\n\tconst path = resolve(profile.path)\n\tconst temporary = resolve(tmpdir())\n\tif (dirname(path) !== temporary || !basename(path).startsWith(BROWSER_PROFILE_PREFIX)) {\n\t\tthrow new BrowserError('ARGUMENT', 'Refusing to remove an unsafe browser profile path', {\n\t\t\tpath,\n\t\t})\n\t}\n\tawait rm(path, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 })\n}\n\n/** Checks the env-override keys (`PLAYWRIGHT_EXECUTABLE_PATH`, `CHROME_PATH`) in order and returns every one that exists. */\nexport function findEnvOverrides(\n\tenv: Readonly<Record<string, string | undefined>>,\n): readonly string[] {\n\tconst found: string[] = []\n\tfor (const key of BROWSER_ENV_PATH_KEYS) {\n\t\tconst value = env[key]\n\t\tif (value !== undefined && value.length > 0 && existsSync(value)) found.push(value)\n\t}\n\treturn found\n}\n\n/** Builds the default well-known install-path candidates for a platform, deriving Windows roots from env vars. */\nexport function buildInstallPaths(\n\tplatform: string,\n\tenv: Readonly<Record<string, string | undefined>>,\n): readonly string[] {\n\tif (platform !== 'win32') return BROWSER_EXECUTABLE_PATHS[platform] ?? []\n\n\tconst roots = buildWindowsRoots(env)\n\tconst paths: string[] = []\n\tfor (const root of roots) {\n\t\tfor (const suffix of BROWSER_WINDOWS_SUFFIXES) {\n\t\t\tpaths.push(pathWin32.join(root, suffix))\n\t\t}\n\t}\n\treturn paths\n}\n\n/** Derives Windows install roots from env vars, falling back to well-known literals when absent. */\nexport function buildWindowsRoots(\n\tenv: Readonly<Record<string, string | undefined>>,\n): readonly string[] {\n\tconst programFiles = env['PROGRAMFILES'] ?? BROWSER_WINDOWS_ROOT_FALLBACKS['PROGRAMFILES']\n\tconst programFilesX86 =\n\t\tenv['PROGRAMFILES(X86)'] ?? BROWSER_WINDOWS_ROOT_FALLBACKS['PROGRAMFILES(X86)']\n\tconst localAppData = env['LOCALAPPDATA']\n\n\tconst roots = [programFiles, programFilesX86, localAppData]\n\treturn roots.filter((root): root is string => root !== undefined)\n}\n\n/** Returns every candidate path that exists on disk, in the given order. */\nexport function findInstallPaths(paths: readonly string[]): readonly string[] {\n\treturn paths.filter((path) => existsSync(path))\n}\n\n/** Probes PATH (`which`/`where`) for every resolvable command name, in the given order. */\nexport function probePathNames(names: readonly string[], platform: string): readonly string[] {\n\tconst finder = platform === 'win32' ? 'where' : 'which'\n\tconst found: string[] = []\n\tfor (const name of names) {\n\t\tconst result = spawnSync(finder, [name], { stdio: 'pipe' })\n\t\tif (result.status === 0) {\n\t\t\tconst executable = readFirstLine(result.stdout.toString('utf-8'))\n\t\t\tif (executable !== undefined) found.push(executable)\n\t\t}\n\t}\n\treturn found\n}\n\n/**\n * Returns the first non-empty line of a command's output, without its\n * surrounding whitespace.\n *\n * @remarks\n * `where` reports every PATH match on its own CRLF-terminated line, so a\n * carriage return left on the first line would travel into `existsSync` and\n * `spawn` as part of the executable path.\n *\n * @param output - Raw decoded standard output of a command\n * @returns The first line carrying text, or undefined when the output has none\n *\n * @example\n * ```ts\n * readFirstLine('C:\\\\bin\\\\chrome.exe\\r\\nC:\\\\other\\\\chrome.exe\\r\\n') // 'C:\\\\bin\\\\chrome.exe'\n * ```\n */\nexport function readFirstLine(output: string): string | undefined {\n\tfor (const line of output.split(/\\r?\\n/)) {\n\t\tconst text = line.trim()\n\t\tif (text.length > 0) return text\n\t}\n\treturn undefined\n}\n\n/** Builds the default Playwright browser store base directories to search for a managed Chromium. */\nexport function buildStoreBases(\n\tenv: Readonly<Record<string, string | undefined>>,\n\tplatform: string,\n): readonly string[] {\n\tconst bases: string[] = []\n\n\tconst envBase = env[BROWSER_STORE_ENV_KEY]\n\tif (envBase !== undefined && envBase.length > 0) bases.push(envBase)\n\n\tbases.push(...BROWSER_STORE_DEFAULT_DIRS)\n\n\tif (platform === 'win32') {\n\t\tconst localAppData = env['LOCALAPPDATA']\n\t\tif (localAppData !== undefined) bases.push(pathWin32.join(localAppData, 'ms-playwright'))\n\t} else {\n\t\tconst cacheDir = BROWSER_STORE_CACHE_DIRS[platform]\n\t\tconst home = env['HOME']\n\t\tif (cacheDir !== undefined && home !== undefined) bases.push(pathPosix.join(home, cacheDir))\n\t}\n\n\treturn bases\n}\n\n/** Searches one store base for the top-level `chromium` link and every `chromium-*` install, highest revision first. */\nexport function findStorePaths(base: string, platform: string): readonly string[] {\n\tconst joiner = platform === 'win32' ? pathWin32.join : pathPosix.join\n\tconst found: string[] = []\n\n\tconst linkPath = joiner(base, BROWSER_STORE_LINK_NAME)\n\tif (existsSync(linkPath)) found.push(linkPath)\n\n\tconst glob = BROWSER_STORE_GLOBS[platform]\n\tif (glob === undefined) return found\n\n\tconst pattern = `${base.replaceAll('\\\\', '/')}/${glob}`\n\tconst matches = globSync(pattern).filter((match) => existsSync(match))\n\tmatches.sort((a, b) => b.localeCompare(a, undefined, { numeric: true }))\n\tfound.push(...matches)\n\n\treturn found\n}\n\n/**\n * Launches a browser process with raw-CDP debugging flags.\n *\n * @remarks\n * Merges every caller and library `--disable-features` value into one switch because Chromium\n * reads only the last occurrence. Keeps `msImplicitSignin` disabled alongside caller features;\n * Chrome and Chromium ignore this Edge feature name. Preserves the caller's other arguments.\n *\n * POSIX launches own an isolated process group so lifecycle teardown can\n * signal and await every Chromium subprocess without affecting the caller.\n * Windows launches are not detached and own no group, so teardown there\n * signals one process by identifier: the spawned process, or the process the\n * launcher handed the endpoint to when that spawned process re-executed the\n * browser and exited. Terminating a Chromium browser process takes its own\n * subprocesses with it, so that single signal drains the tree.\n *\n * @param executable - Absolute path to the browser executable\n * @param port - Port the browser exposes its CDP endpoint on, or undefined for a port the operating system picks\n * @param headless - Whether to launch in headless mode\n * @param profile - Optional user-data-dir for a persistent profile\n * @param extra - Additional command-line flags\n * @returns The spawned ChildProcess, whose standard error carries the endpoint line `readBrowserEndpoint` reads\n */\nexport function launchBrowserProcess(\n\texecutable: string,\n\tport: number | undefined,\n\theadless: boolean,\n\tprofile?: string,\n\textra?: readonly string[],\n): ChildProcess {\n\t// Caller-supplied args come first so a script path (for example `node <script>`,\n\t// used to spawn a Node stand-in executable cross-platform in tests) lands\n\t// as an early positional argv entry ahead of the CDP flags that follow —\n\t// Chromium itself accepts flags in any order, so production is unaffected.\n\tconst args: string[] = []\n\tconst features = new Set<string>()\n\tfor (const arg of [\n\t\t...(extra ?? []),\n\t\t`--remote-debugging-port=${port ?? 0}`,\n\t\t...BROWSER_LAUNCH_ARGS,\n\t]) {\n\t\tif (arg === '--disable-features') continue\n\t\tif (arg.startsWith('--disable-features=')) {\n\t\t\tfor (const feature of arg.slice('--disable-features='.length).split(',')) {\n\t\t\t\tif (feature.trim() !== '') features.add(feature.trim())\n\t\t\t}\n\t\t} else args.push(arg)\n\t}\n\targs.push(`--disable-features=${[...features].join(',')}`)\n\n\tif (headless) args.push(BROWSER_HEADLESS_ARG)\n\tif (profile !== undefined) args.push(`--user-data-dir=${profile}`)\n\n\treturn spawn(executable, args, {\n\t\tstdio: ['ignore', 'ignore', 'pipe'],\n\t\tdetached: process.platform !== 'win32',\n\t})\n}\n\n/**\n * Reads the CDP endpoint a launched browser announces on its standard error.\n *\n * @remarks\n * Chromium prints `DevTools listening on ws://HOST:PORT/devtools/browser/ID` after it binds the\n * debugging port. The read splits arriving text on line breaks across chunks, so a line split\n * between two chunks and a line ending `\\r\\n` both resolve. After resolving, the stream keeps\n * draining until it closes so the browser's logging never fills the pipe.\n *\n * @param stream - The browser's standard error\n * @param signal - Abort that rejects the read with its reason\n * @returns The `ws://` endpoint the browser announced\n *\n * @throws When the stream closes without the line, or the signal aborts first\n */\nexport function readBrowserEndpoint(stream: Readable, signal: AbortSignal): Promise<string> {\n\tconst read = Promise.withResolvers<string>()\n\tlet pending = ''\n\tlet found = false\n\n\tif (signal.aborted) read.reject(signal.reason)\n\tsignal.addEventListener('abort', () => read.reject(signal.reason), { once: true })\n\tstream.on('error', read.reject)\n\tstream.setEncoding('utf8')\n\tstream.on('data', (chunk) => {\n\t\tif (found || !isString(chunk)) return\n\t\tconst lines = (pending + chunk).split(/\\r\\n|\\n/)\n\t\tpending = lines.pop() ?? ''\n\t\tfor (const line of lines) {\n\t\t\tconst endpoint = BROWSER_DEVTOOLS_PATTERN.exec(line)?.[1]\n\t\t\tif (endpoint === undefined) continue\n\t\t\tfound = true\n\t\t\tpending = ''\n\t\t\tread.resolve(endpoint)\n\t\t\treturn\n\t\t}\n\t})\n\tstream.on('close', () => {\n\t\tconst endpoint = found ? undefined : BROWSER_DEVTOOLS_PATTERN.exec(pending)?.[1]\n\t\tif (endpoint !== undefined) read.resolve(endpoint)\n\t\telse {\n\t\t\tread.reject(\n\t\t\t\tnew BrowserError(\n\t\t\t\t\t'CONNECTION',\n\t\t\t\t\t'Browser closed its standard error before reporting a CDP endpoint',\n\t\t\t\t),\n\t\t\t)\n\t\t}\n\t})\n\n\treturn read.promise\n}\n\n/**\n * Fetches the current CDP target list from a browser's `/json/list` endpoint, as a `Result`\n * carrying either the targets or a coded `BrowserError`.\n *\n * @remarks\n * The endpoint is a network boundary, so an unreachable host, a non-2xx\n * response, and a body that is not a JSON array each come back as a failed\n * `Result` carrying a coded `BrowserError`. An entry missing a\n * required string field is skipped rather than failing the whole list.\n *\n * @param port - Port the browser exposes its CDP endpoint on\n * @param timeout - Request timeout in milliseconds\n * @param host - Host the browser exposes its CDP endpoint on (default `127.0.0.1`)\n * @returns The normalized CDP targets, or the fault that stopped the request\n *\n * @example\n * ```ts\n * import { fetchCDPTargets } from '@orkestrel/browser/server'\n *\n * const result = await fetchCDPTargets(9222, 2000)\n * if (result.success) log(result.value.length)\n * else log(result.error.code)\n * ```\n */\nexport async function fetchCDPTargets(\n\tport: number,\n\ttimeout: number,\n\thost: string = BROWSER_DEFAULT_HOST,\n): Promise<Result<readonly CDPTarget[], BrowserError>> {\n\tconst url = `${BROWSER_CDP_PROTOCOL}://${host}:${port}${BROWSER_CDP_LIST_PATH}`\n\tconst controller = new AbortController()\n\tconst timer = setTimeout(() => controller.abort(), timeout)\n\n\ttry {\n\t\tconst response = await fetch(url, { signal: controller.signal })\n\n\t\tif (!response.ok) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: new BrowserError('CONNECTION', 'CDP target list request was refused', {\n\t\t\t\t\turl,\n\t\t\t\t\tstatus: response.status,\n\t\t\t\t}),\n\t\t\t}\n\t\t}\n\n\t\tconst list: unknown = await response.json()\n\t\tif (!isArray(list)) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\terror: new BrowserError('CONNECTION', 'CDP target list is not a JSON array', { url }),\n\t\t\t}\n\t\t}\n\n\t\tconst targets: CDPTarget[] = []\n\t\tfor (const entry of list) {\n\t\t\tif (!isRecord(entry)) continue\n\t\t\tif (\n\t\t\t\t!isString(entry['id']) ||\n\t\t\t\t!isString(entry['type']) ||\n\t\t\t\t!isString(entry['title']) ||\n\t\t\t\t!isString(entry['url'])\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\ttargets.push({\n\t\t\t\tid: entry['id'],\n\t\t\t\tcategory: entry['type'],\n\t\t\t\ttitle: entry['title'],\n\t\t\t\turl: entry['url'],\n\t\t\t})\n\t\t}\n\n\t\treturn { success: true, value: targets }\n\t} catch (error) {\n\t\treturn {\n\t\t\tsuccess: false,\n\t\t\terror: new BrowserError('CONNECTION', 'CDP target list is unreachable', {\n\t\t\t\turl,\n\t\t\t\terror: isJSONValue(error) ? error : String(error),\n\t\t\t}),\n\t\t}\n\t} finally {\n\t\tclearTimeout(timer)\n\t}\n}\n","import type { CDPTransportEventMap, CDPTransportInterface } from '@src/core'\nimport type { EmitterInterface } from '@orkestrel/emitter'\nimport type { NodeWebSocketInterface } from '@orkestrel/websocket'\nimport type { WebSocketCDPTransportOptions } from '../types.js'\nimport type { ClientRequest, IncomingMessage, RequestOptions } from 'node:http'\nimport type { Duplex } from 'node:stream'\nimport { randomBytes } from 'node:crypto'\nimport { request as httpRequest } from 'node:http'\nimport { request as httpsRequest } from 'node:https'\nimport { attempt, isString, isJSONValue } from '@orkestrel/contract'\nimport { Emitter } from '@orkestrel/emitter'\nimport {\n\tcomputeWebSocketAccept,\n\tcreateNodeWebSocket,\n\tWEBSOCKET_READY_CLOSED,\n\tWEBSOCKET_READY_OPEN,\n\tWEBSOCKET_VERSION,\n} from '@orkestrel/websocket'\nimport { BROWSER_DEFAULT_TIMEOUT_MS, BrowserTransition, BrowserError } from '@src/core'\n\n// === WebSocketCDPTransport\n\n/**\n * Provides a raw CDP text transport backed by `@orkestrel/websocket`.\n *\n * @remarks\n * Performs and validates the RFC 6455 HTTP upgrade, then delegates frame\n * handling to `@orkestrel/websocket`. Concurrent and repeated `start()` /\n * `close()` calls share their active transition, and a later `start()` opens a\n * fresh socket after the prior one closes.\n *\n * @example\n * ```ts\n * import { WebSocketCDPTransport } from '@orkestrel/browser/server'\n *\n * const transport = new WebSocketCDPTransport({ url: 'ws://127.0.0.1:9222/devtools/browser/abc' })\n * await transport.start()\n * await transport.close()\n * ```\n */\nexport class WebSocketCDPTransport implements CDPTransportInterface {\n\treadonly #emitter: Emitter<CDPTransportEventMap>\n\treadonly #url: string\n\treadonly #timeout: number\n\t#socket: NodeWebSocketInterface | undefined\n\treadonly #starting: BrowserTransition = new BrowserTransition()\n\treadonly #closing: BrowserTransition = new BrowserTransition()\n\t#request: ClientRequest | undefined\n\t#resolve: ((socket: NodeWebSocketInterface) => void) | undefined\n\t#reject: ((error: unknown) => void) | undefined\n\t#timer: ReturnType<typeof setTimeout> | undefined\n\t#closeResolve: (() => void) | undefined\n\treadonly #socketCloseHandler = this.#handleSocketClose.bind(this)\n\n\tconstructor(options: WebSocketCDPTransportOptions) {\n\t\tthis.#emitter = new Emitter({\n\t\t\t...(options.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t\tthis.#url = options.url\n\t\tthis.#timeout = options.timeout ?? BROWSER_DEFAULT_TIMEOUT_MS\n\t}\n\n\tget emitter(): EmitterInterface<CDPTransportEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tasync start(): Promise<void> {\n\t\tconst closing = this.#closing.pending\n\t\tif (closing !== undefined) await closing\n\t\tif (this.#socket?.readyState === WEBSOCKET_READY_OPEN) return\n\n\t\tconst active = this.#starting.pending\n\t\tif (active !== undefined) {\n\t\t\tawait active\n\t\t\treturn\n\t\t}\n\n\t\tthis.#socket?.destroy()\n\t\tthis.#socket = undefined\n\t\tawait this.#starting.execute(() => this.#start())\n\t}\n\n\tasync send(data: string): Promise<void> {\n\t\tconst socket = this.#socket\n\t\tif (socket === undefined || socket.readyState !== WEBSOCKET_READY_OPEN) {\n\t\t\tthrow new BrowserError('CONNECTION', 'WebSocket CDP transport is not open', {\n\t\t\t\turl: this.#url,\n\t\t\t})\n\t\t}\n\t\tsocket.send(data)\n\t}\n\n\tasync close(): Promise<void> {\n\t\tawait this.#closing.execute(() => this.#close())\n\t}\n\n\t// === Private helpers\n\n\tasync #start(): Promise<void> {\n\t\tconst parsed = attempt(() => new URL(this.#url))\n\t\tif (!parsed.success) {\n\t\t\tthrow new BrowserError('CONNECTION', `WebSocket CDP URL is invalid: ${this.#url}`, {\n\t\t\t\turl: this.#url,\n\t\t\t\terror: isJSONValue(parsed.error) ? parsed.error : String(parsed.error),\n\t\t\t})\n\t\t}\n\t\tconst url = parsed.value\n\t\tif (url.protocol !== 'ws:' && url.protocol !== 'wss:') {\n\t\t\tthrow new BrowserError(\n\t\t\t\t'CONNECTION',\n\t\t\t\t`WebSocket CDP connection requires a ws: or wss: URL: ${this.#url}`,\n\t\t\t\t{ url: this.#url },\n\t\t\t)\n\t\t}\n\t\tconst key = randomBytes(16).toString('base64')\n\t\tconst deferred = Promise.withResolvers<NodeWebSocketInterface>()\n\t\tconst options: RequestOptions = {\n\t\t\thostname: url.hostname,\n\t\t\tport: url.port.length > 0 ? Number(url.port) : url.protocol === 'wss:' ? 443 : 80,\n\t\t\tpath: `${url.pathname}${url.search}`,\n\t\t\theaders: {\n\t\t\t\tConnection: 'Upgrade',\n\t\t\t\tUpgrade: 'websocket',\n\t\t\t\t'Sec-WebSocket-Key': key,\n\t\t\t\t'Sec-WebSocket-Version': WEBSOCKET_VERSION,\n\t\t\t},\n\t\t}\n\t\tconst request = url.protocol === 'wss:' ? httpsRequest(options) : httpRequest(options)\n\n\t\tthis.#request = request\n\t\tthis.#resolve = deferred.resolve\n\t\tthis.#reject = deferred.reject\n\t\tthis.#timer = setTimeout(() => this.#expire(request), this.#timeout)\n\n\t\trequest.on('upgrade', (response: IncomingMessage, socket: Duplex, head: Buffer) => {\n\t\t\tthis.#upgrade(request, key, response, socket, head)\n\t\t})\n\t\trequest.on('response', (response) => this.#decline(request, response))\n\t\trequest.on('error', (error) => this.#fail(request, error))\n\t\trequest.end()\n\n\t\tconst socket = await deferred.promise\n\t\tthis.#socket = socket\n\t\tthis.#bind(socket)\n\t}\n\n\tasync #close(): Promise<void> {\n\t\tconst request = this.#request\n\t\tif (request !== undefined) {\n\t\t\tthis.#rejectRequest(\n\t\t\t\trequest,\n\t\t\t\tnew BrowserError(\n\t\t\t\t\t'CONNECTION',\n\t\t\t\t\t`WebSocket CDP connection to ${this.#url} was closed before it finished connecting`,\n\t\t\t\t\t{ url: this.#url },\n\t\t\t\t),\n\t\t\t)\n\t\t\trequest.destroy()\n\t\t}\n\t\tawait this.#starting.pending?.catch(() => undefined)\n\n\t\tconst socket = this.#socket\n\t\tthis.#socket = undefined\n\t\tif (socket === undefined || socket.readyState === WEBSOCKET_READY_CLOSED) return\n\n\t\tconst closed = Promise.withResolvers<void>()\n\t\tthis.#closeResolve = closed.resolve\n\t\tsocket.emitter.on('close', this.#socketCloseHandler)\n\t\ttry {\n\t\t\tsocket.close()\n\t\t\tif (socket.readyState !== WEBSOCKET_READY_CLOSED) await closed.promise\n\t\t} catch {\n\t\t\tsocket.destroy()\n\t\t\tif (socket.readyState !== WEBSOCKET_READY_CLOSED) await closed.promise\n\t\t} finally {\n\t\t\tsocket.emitter.off('close', this.#socketCloseHandler)\n\t\t\tthis.#closeResolve = undefined\n\t\t}\n\t}\n\n\t#upgrade(\n\t\trequest: ClientRequest,\n\t\tkey: string,\n\t\tresponse: IncomingMessage,\n\t\tsocket: Duplex,\n\t\thead: Buffer,\n\t): void {\n\t\tif (this.#request !== request) {\n\t\t\tsocket.destroy()\n\t\t\treturn\n\t\t}\n\n\t\tconst accept = response.headers['sec-websocket-accept']\n\t\tif (!isString(accept) || accept !== computeWebSocketAccept(key)) {\n\t\t\tsocket.destroy()\n\t\t\tthis.#rejectRequest(\n\t\t\t\trequest,\n\t\t\t\tnew BrowserError(\n\t\t\t\t\t'CONNECTION',\n\t\t\t\t\t`WebSocket CDP connection to ${this.#url} failed: Sec-WebSocket-Accept mismatch`,\n\t\t\t\t\t{ url: this.#url },\n\t\t\t\t),\n\t\t\t)\n\t\t\treturn\n\t\t}\n\n\t\ttry {\n\t\t\tthis.#resolveRequest(request, createNodeWebSocket({ socket, head }))\n\t\t} catch (error) {\n\t\t\tsocket.destroy()\n\t\t\tthis.#rejectRequest(request, error)\n\t\t}\n\t}\n\n\t#decline(request: ClientRequest, response: IncomingMessage): void {\n\t\tresponse.resume()\n\t\tconst reason =\n\t\t\tresponse.statusCode === undefined\n\t\t\t\t? 'upgrade was declined without a status code'\n\t\t\t\t: `upgrade declined with status ${response.statusCode}`\n\t\tthis.#rejectRequest(\n\t\t\trequest,\n\t\t\tnew BrowserError('CONNECTION', `WebSocket CDP connection to ${this.#url} failed: ${reason}`, {\n\t\t\t\turl: this.#url,\n\t\t\t}),\n\t\t)\n\t}\n\n\t#fail(request: ClientRequest, error: Error): void {\n\t\tthis.#rejectRequest(\n\t\t\trequest,\n\t\t\tnew BrowserError(\n\t\t\t\t'CONNECTION',\n\t\t\t\t`WebSocket CDP connection to ${this.#url} failed: ${error.message}`,\n\t\t\t\t{ url: this.#url },\n\t\t\t),\n\t\t)\n\t}\n\n\t#expire(request: ClientRequest): void {\n\t\tthis.#rejectRequest(\n\t\t\trequest,\n\t\t\tnew BrowserError(\n\t\t\t\t'CONNECTION',\n\t\t\t\t`WebSocket CDP connection to ${this.#url} timed out after ${this.#timeout}ms`,\n\t\t\t\t{ url: this.#url, timeout: this.#timeout },\n\t\t\t),\n\t\t)\n\t\trequest.destroy()\n\t}\n\n\t#resolveRequest(request: ClientRequest, socket: NodeWebSocketInterface): void {\n\t\tif (this.#request !== request) {\n\t\t\tsocket.destroy()\n\t\t\treturn\n\t\t}\n\n\t\tconst resolve = this.#resolve\n\t\tthis.#clearRequest()\n\t\tresolve?.(socket)\n\t}\n\n\t#rejectRequest(request: ClientRequest, error: unknown): void {\n\t\tif (this.#request !== request) return\n\n\t\tconst reject = this.#reject\n\t\tthis.#clearRequest()\n\t\treject?.(error)\n\t}\n\n\t#clearRequest(): void {\n\t\tif (this.#timer !== undefined) clearTimeout(this.#timer)\n\t\tthis.#timer = undefined\n\t\tthis.#request = undefined\n\t\tthis.#resolve = undefined\n\t\tthis.#reject = undefined\n\t}\n\n\t#bind(socket: NodeWebSocketInterface): void {\n\t\tsocket.emitter.on('message', (data) => this.#emitter.emit('message', data))\n\t\tsocket.emitter.on('close', () => {\n\t\t\tif (this.#socket === socket) this.#socket = undefined\n\t\t\tthis.#emitter.emit('close')\n\t\t})\n\t\tsocket.emitter.on('error', (error) => this.#emitter.emit('error', error))\n\t}\n\n\t#handleSocketClose(): void {\n\t\tthis.#closeResolve?.()\n\t}\n}\n","import type { BrowserWriterInterface } from '@src/core'\nimport { mkdir, writeFile } from 'node:fs/promises'\nimport { dirname } from 'node:path'\n\n// === FileBrowserWriter\n\n/**\n * Persists captured browser bytes to the filesystem through `node:fs/promises`.\n *\n * @remarks\n * Creates every missing parent directory of the target path before writing, so\n * a caller may name a nested destination that does not exist yet.\n *\n * @example\n * ```ts\n * import { FileBrowserWriter } from '@orkestrel/browser/server'\n *\n * const writer = new FileBrowserWriter()\n * await writer.write('shots/hero.png', new Uint8Array([137, 80, 78, 71]))\n * ```\n */\nexport class FileBrowserWriter implements BrowserWriterInterface {\n\t/**\n\t * Writes the captured bytes to a path, creating its parent directories.\n\t *\n\t * @param path - Destination file path\n\t * @param data - Captured bytes to persist\n\t * @returns A promise resolving once the bytes are on disk\n\t */\n\tasync write(path: string, data: Uint8Array): Promise<void> {\n\t\tawait mkdir(dirname(path), { recursive: true })\n\t\tawait writeFile(path, data)\n\t}\n}\n","{\n\t\"name\": \"@orkestrel/browser\",\n\t\"version\": \"0.0.28\",\n\t\"description\": \"Chrome DevTools Protocol browser automation with an environment-agnostic core. Part of the @orkestrel line.\",\n\t\"keywords\": [\n\t\t\"automation\",\n\t\t\"browser\",\n\t\t\"cdp\",\n\t\t\"chrome\",\n\t\t\"chromium\",\n\t\t\"devtools\",\n\t\t\"orkestrel\",\n\t\t\"screenshot\",\n\t\t\"typescript\"\n\t],\n\t\"homepage\": \"https://github.com/orkestrel/browser#readme\",\n\t\"bugs\": \"https://github.com/orkestrel/browser/issues\",\n\t\"license\": \"MIT\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"git+https://github.com/orkestrel/browser.git\"\n\t},\n\t\"bin\": {\n\t\t\"browse\": \"dist/bin/main.js\"\n\t},\n\t\"files\": [\n\t\t\"dist/src\",\n\t\t\"dist/bin\",\n\t\t\"README.md\"\n\t],\n\t\"type\": \"module\",\n\t\"sideEffects\": false,\n\t\"main\": \"./dist/src/core/index.cjs\",\n\t\"module\": \"./dist/src/core/index.js\",\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"import\": {\n\t\t\t\t\"types\": \"./dist/src/core/index.d.ts\",\n\t\t\t\t\"default\": \"./dist/src/core/index.js\"\n\t\t\t},\n\t\t\t\"require\": {\n\t\t\t\t\"types\": \"./dist/src/core/index.d.cts\",\n\t\t\t\t\"default\": \"./dist/src/core/index.cjs\"\n\t\t\t}\n\t\t},\n\t\t\"./server\": {\n\t\t\t\"import\": {\n\t\t\t\t\"types\": \"./dist/src/server/index.d.ts\",\n\t\t\t\t\"default\": \"./dist/src/server/index.js\"\n\t\t\t},\n\t\t\t\"require\": {\n\t\t\t\t\"types\": \"./dist/src/server/index.d.cts\",\n\t\t\t\t\"default\": \"./dist/src/server/index.cjs\"\n\t\t\t}\n\t\t},\n\t\t\"./browser\": {\n\t\t\t\"types\": \"./dist/src/browser/index.d.ts\",\n\t\t\t\"default\": \"./dist/src/browser/index.js\"\n\t\t},\n\t\t\"./package.json\": \"./package.json\"\n\t},\n\t\"publishConfig\": {\n\t\t\"access\": \"public\"\n\t},\n\t\"scripts\": {\n\t\t\"clean\": \"node -e \\\"require('node:fs').rmSync('dist',{recursive:true,force:true})\\\"\",\n\t\t\"copy\": \"node -e \\\"const fs=require('node:fs'),p=require('node:path'),a=process.argv[1],b=process.argv[2];fs.mkdirSync(p.dirname(b),{recursive:true});fs.cpSync(a,b,{force:true});console.log('Copied: '+a+' to '+b)\\\"\",\n\t\t\"scaffold\": \"scaffold\",\n\t\t\"lint\": \"oxlint --config .oxlintrc.json --fix .\",\n\t\t\"check\": \"tsc --noEmit --project tsconfig.json && npm run check:src\",\n\t\t\"check:src\": \"npm run check:src:core && npm run check:src:server && npm run check:src:browser && npm run check:src:bin\",\n\t\t\"check:src:core\": \"tsc --noEmit -p configs/src/tsconfig.core.json\",\n\t\t\"check:src:server\": \"tsc --noEmit -p configs/src/tsconfig.server.json\",\n\t\t\"check:src:browser\": \"tsc --noEmit -p configs/src/tsconfig.browser.json\",\n\t\t\"check:src:bin\": \"tsc --noEmit -p configs/src/tsconfig.bin.json\",\n\t\t\"format\": \"oxfmt --config .oxfmtrc.json --write .\",\n\t\t\"format:check\": \"oxfmt --config .oxfmtrc.json --check .\",\n\t\t\"lint:check\": \"oxlint --config .oxlintrc.json --deny-warnings .\",\n\t\t\"test\": \"npm run test:src && npm run test:src:bin && npm run test:policy && npm run test:config && npm run test:setup && npm run test:setup:browser && npm run test:guides && npm run test:conformance\",\n\t\t\"test:conformance\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project conformance\",\n\t\t\"test:src\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project src:core --project src:server --project src:browser\",\n\t\t\"test:src:core\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project src:core\",\n\t\t\"test:src:server\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project src:server\",\n\t\t\"test:src:browser\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project src:browser\",\n\t\t\"test:src:bin\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project src:bin\",\n\t\t\"test:policy\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project policy\",\n\t\t\"test:config\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project config\",\n\t\t\"test:guides\": \"node --experimental-strip-types tests/guides.test.ts\",\n\t\t\"build\": \"npm run clean && npm run build:src\",\n\t\t\"build:src\": \"npm run build:src:core && npm run build:src:server && npm run build:src:browser && npm run build:src:bin\",\n\t\t\"build:src:core\": \"vite build --config configs/src/vite.core.config.ts && npm run copy dist/src/core/index.d.ts dist/src/core/index.d.cts\",\n\t\t\"build:src:server\": \"vite build --config configs/src/vite.server.config.ts && npm run copy dist/src/server/index.d.ts dist/src/server/index.d.cts\",\n\t\t\"build:src:browser\": \"vite build --config configs/src/vite.browser.config.ts\",\n\t\t\"build:src:bin\": \"vite build --config configs/src/vite.bin.config.ts\",\n\t\t\"prepack\": \"npm run build\",\n\t\t\"prepublishOnly\": \"npm run format:check && npm run lint:check && npm run check && npm run build && npm test && npm run test:distribution -- --mode release && npm run test:service\",\n\t\t\"test:distribution\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project distribution\",\n\t\t\"test:service\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project service\",\n\t\t\"test:probe\": \"vitest run --config vite.config.ts --no-cache --reporter=verbose --project probe\",\n\t\t\"test:bench\": \"vitest bench --config vite.config.ts --no-cache --project probe\",\n\t\t\"test:setup\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project setup\",\n\t\t\"test:setup:browser\": \"vitest run --config vite.config.ts --no-cache --reporter=dot --project setup:browser\"\n\t},\n\t\"dependencies\": {\n\t\t\"@orkestrel/codec\": \"^0.0.6\",\n\t\t\"@orkestrel/contract\": \"^0.0.19\",\n\t\t\"@orkestrel/emitter\": \"^0.0.12\",\n\t\t\"@orkestrel/html\": \"^0.0.12\",\n\t\t\"@orkestrel/markdown\": \"^0.0.17\",\n\t\t\"@orkestrel/mcp\": \"^0.0.38\",\n\t\t\"@orkestrel/pool\": \"^0.0.17\",\n\t\t\"@orkestrel/router\": \"^0.0.17\",\n\t\t\"@orkestrel/server\": \"^0.0.23\",\n\t\t\"@orkestrel/tool\": \"^0.0.19\",\n\t\t\"@orkestrel/websocket\": \"^0.0.15\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@microsoft/api-extractor\": \"^7.59.4\",\n\t\t\"@orkestrel/guide\": \"^0.0.24\",\n\t\t\"@orkestrel/probe\": \"^0.0.22\",\n\t\t\"@orkestrel/scaffold\": \"^0.0.96\",\n\t\t\"@orkestrel/test\": \"^0.0.25\",\n\t\t\"@types/node\": \"^26.6.4\",\n\t\t\"@vitest/browser-playwright\": \"^4.1.11\",\n\t\t\"oxfmt\": \"^0.72.0\",\n\t\t\"oxlint\": \"^1.87.0\",\n\t\t\"playwright\": \"^1.64.0\",\n\t\t\"typescript\": \"^6.0.3\",\n\t\t\"vite\": \"^8.3.3\",\n\t\t\"vitest\": \"^4.1.11\"\n\t},\n\t\"engines\": {\n\t\t\"node\": \">=22.12.0\"\n\t}\n}\n","import type {\n\tBrowserContextInterface,\n\tBrowserPageInterface,\n\tBrowserToolsetInterface,\n\tBrowserViewport,\n} from '@src/core'\nimport type { MCPCallResult, MCPExecutionContext, MCPMethodOptions } from '@orkestrel/mcp'\nimport type { PoolInterface, PoolToken } from '@orkestrel/pool'\nimport type { StdioServerInterface } from '@orkestrel/mcp/server'\nimport type { ToolContext, ToolInterface, ToolManagerInterface, ToolResult } from '@orkestrel/tool'\nimport type {\n\tBrowserInterface,\n\tBrowserLaunchFunction,\n\tBrowserMCPServerInterface,\n\tBrowserMCPServerOptions,\n\tBrowserServerCatalog,\n} from './types.js'\nimport { randomUUID } from 'node:crypto'\nimport { addAbortListener } from 'node:events'\nimport { mkdir, readFile, readdir, rename, rm, writeFile } from 'node:fs/promises'\nimport { join, resolve } from 'node:path'\nimport { isError, isInteger, isRecord, isString } from '@orkestrel/contract'\nimport { createMCPLegacy, createMCPServer, JSONRPC_SERVER_ERROR, MCPError } from '@orkestrel/mcp'\nimport { createPool, isPoolError } from '@orkestrel/pool'\nimport { createStdioServer } from '@orkestrel/mcp/server'\nimport { createTool, createToolManager, toolToDefinition } from '@orkestrel/tool'\nimport {\n\tBROWSER_JOURNEY_TOOL_NAMES,\n\tBROWSER_TOOL_COPY,\n\tBROWSER_TOOL_NAMES,\n\tBROWSER_TOOL_LIMIT,\n\tBROWSER_TOOL_CUT_FOOTER,\n\tboundBrowserText,\n\tBrowserError,\n\tcreateBrowserToolset,\n\tcreateCDPClient,\n\tisBrowserError,\n} from '@src/core'\nimport { version } from '../../package.json'\nimport {\n\tcreateBrowser,\n\tcreateWebSocketCDPTransport,\n\tcreateFileBrowserJourneyStore,\n\tcreateFileBrowserRunStore,\n} from './factories.js'\nimport {\n\tBROWSER_SERVER_EXHAUSTED,\n\tBROWSER_SERVER_BUSY,\n\tBROWSER_SERVER_HOLDER,\n\tBROWSER_SERVER_COPY,\n\tBROWSER_SERVER_LAUNCH,\n\tBROWSER_SERVER_OPTIONS,\n\tBROWSER_SERVER_POOL_LIMIT,\n\tBROWSER_SERVER_POOL_SIZE,\n\tBROWSER_SERVER_CONTEXTS,\n\tBROWSER_SERVER_CONTEXTS_LIMIT,\n\tBROWSER_SERVER_RECORD,\n\tBROWSER_SERVER_RESTARTS,\n\tBROWSER_SERVER_SWEEP,\n\tBROWSER_SERVER_TEARDOWN,\n\tBROWSER_SERVER_UNAVAILABLE,\n\tBROWSER_SERVER_CRASH,\n\tBROWSER_SERVER_UNRESOLVED,\n} from './constants.js'\nimport {\n\tdescribeBrowserServerLoss,\n\tformatBrowserLockEntry,\n\tparseBrowserLockEntry,\n\tparseBrowserProfileRecord,\n\tprobeProcess,\n} from './helpers.js'\n\n/**\n * Implements `BrowserMCPServerInterface`: serves the browser vocabulary and the journey tools over\n * the Model Context Protocol on stdio, and warms Chromium at server start.\n *\n * @remarks\n * The server's own manager holds one dispatcher per name of the vocabulary — `read`, `click`,\n * `type`, `press`, `navigate`, `wait`, `dialog`, `switch`, `record`, `save`, `journeys`, `edit`,\n * `replay`, `forget`, and `capture` — each carrying the description, parameters, and annotations\n * `BROWSER_TOOL_COPY` gives, so `tools/list` answers before Chromium starts and with Chromium\n * absent. After the launch, a tool the toolset's manager adds under another name, such as a page\n * tool it adopts, is mirrored as a dispatcher with that tool's definition, and the mirror is\n * removed when the toolset withdraws the tool, so the server's tool list changes and a subscribed\n * client is notified. The server also advertises `acquire`, `execute`, `tools`, and `destroy` with\n * `BROWSER_SERVER_COPY`. Startup warms the pool and assigns a prepared context to the shared holder. The legacy\n * handshake and browser calls await that setup. Named holders each own a lease, a pending grant,\n * and loss notices; concurrent calls on a holder share its replacement grant. Ending a holder\n * closes its context and releases its lease, and admission counts that holder until disposal settles.\n * A launch creates `ROOT/.profiles/PID-UUID/` exclusively, connects a browser that never attaches to an\n * existing endpoint, opens one page in an isolated context, and constructs the page toolset with\n * that context and the file journey and run stores under the root, on a manager the toolset owns.\n * A dispatcher forwards its arguments and the call's context, signal included, to the toolset's\n * manager and returns that manager's value, or rejects with its failure message; a text value\n * reaches the client as one text block rather than as its JSON text.\n * A disconnect retires its browser and every hosted generation. A current-page crash retires only\n * that holder's context. A failed call receives a liveness ping;\n * loss makes its outcome unresolved, while a known success remains successful. Pending losses\n * prefix the next outcome on a successor, or a refusal, and calls are never repeated.\n * Concurrent checks share one ping per slot. Cancelling a call ends only its wait; the ping keeps\n * its deadline and records loss for the next call.\n *\n * `start()` serves stdio and destroys the server at the end of its input, on `SIGINT`, and on\n * `SIGTERM`. `destroy()` stops reading requests and removes every dispatcher, then destroys every\n * slot through the pool — each toolset, which aborts its active replay, then its context and downloads,\n * then its browser and its\n * profile — and rechecks the profile folders this server made or kept.\n *\n * Chromium on Linux refuses to start as the root user unless its sandbox is disabled, so a server\n * running as root on Linux launches Chromium with `--no-sandbox`; a launch that could run\n * sandboxed is never changed.\n *\n * @example\n * ```ts\n * import { BrowserMCPServer } from '@orkestrel/browser/server'\n *\n * const server = new BrowserMCPServer({ root: 'tmp/browsers', journeys: { readonly: true } })\n * await server.start()\n * await server.destroy()\n * ```\n */\nexport class BrowserMCPServer implements BrowserMCPServerInterface {\n\treadonly #root: string\n\treadonly #headless: boolean\n\treadonly #executable: string | undefined\n\treadonly #viewport: BrowserViewport | undefined\n\treadonly #readonly: boolean\n\treadonly #launcher: BrowserLaunchFunction\n\treadonly #input: NodeJS.ReadableStream\n\treadonly #tools: ToolManagerInterface\n\treadonly #transport: StdioServerInterface\n\treadonly #abort = new AbortController()\n\treadonly #signal: () => void\n\treadonly #vocabulary: ReadonlySet<string>\n\t#mirrored:\n\t\t| {\n\t\t\t\treadonly lease: {\n\t\t\t\t\treadonly token: PoolToken<{\n\t\t\t\t\t\treadonly browser: BrowserInterface\n\t\t\t\t\t\treadonly profile: string\n\t\t\t\t\t}>\n\t\t\t\t\treadonly generation: {\n\t\t\t\t\t\treadonly context: BrowserContextInterface\n\t\t\t\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\t\t\t\treadonly directory: string\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treadonly added: (tool: ToolInterface) => void\n\t\t\t\treadonly removed: (tool: ToolInterface) => void\n\t\t\t\treadonly cleared: (tools: readonly ToolInterface[]) => void\n\t\t }\n\t\t| undefined\n\treadonly #pool: PoolInterface<{\n\t\treadonly browser: BrowserInterface\n\t\treadonly profile: string\n\t}>\n\treadonly #log: NodeJS.WritableStream\n\treadonly #folders = new Set<string>()\n\treadonly #faults = new Set<unknown>()\n\treadonly #losses = new WeakMap<\n\t\t{\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t},\n\t\t{ readonly cause: unknown }\n\t>()\n\treadonly #departures = new WeakMap<\n\t\t{\n\t\t\treadonly token: PoolToken<{\n\t\t\t\treadonly browser: BrowserInterface\n\t\t\t\treadonly profile: string\n\t\t\t}>\n\t\t\treadonly generation: {\n\t\t\t\treadonly context: BrowserContextInterface\n\t\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\t\treadonly directory: string\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\treadonly cause: unknown\n\t\t\treadonly url: string\n\t\t}\n\t>()\n\treadonly #pings = new WeakMap<\n\t\t{\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t},\n\t\tPromise<void>\n\t>()\n\treadonly #watches = new Map<\n\t\t{\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t},\n\t\t{\n\t\t\treadonly resolve: (cause: unknown) => void\n\t\t\treadonly disconnect: () => void\n\t\t\treadonly subscription: Disposable\n\t\t}\n\t>()\n\treadonly #observed = new Map<\n\t\t{\n\t\t\treadonly context: BrowserContextInterface\n\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\treadonly directory: string\n\t\t},\n\t\t{\n\t\t\treadonly page: (page: BrowserPageInterface) => void\n\t\t\treadonly crashes: ReadonlyMap<BrowserPageInterface, () => void>\n\t\t}\n\t>()\n\treadonly #prepared = new Map<\n\t\t{\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t},\n\t\t{\n\t\t\treadonly context: BrowserContextInterface\n\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\treadonly directory: string\n\t\t}\n\t>()\n\treadonly #owned = new Map<\n\t\t{\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t},\n\t\tSet<{\n\t\t\treadonly context: BrowserContextInterface\n\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\treadonly directory: string\n\t\t}>\n\t>()\n\treadonly #building = new Map<\n\t\t{\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t},\n\t\tSet<\n\t\t\tPromise<{\n\t\t\t\treadonly context: BrowserContextInterface\n\t\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\t\treadonly directory: string\n\t\t\t}>\n\t\t>\n\t>()\n\treadonly #cleaning = new WeakMap<\n\t\t{\n\t\t\treadonly context: BrowserContextInterface\n\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\treadonly directory: string\n\t\t},\n\t\tPromise<boolean>\n\t>()\n\treadonly #endings = new WeakMap<\n\t\t{\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t},\n\t\tPromiseWithResolvers<void>\n\t>()\n\treadonly #retentions = new Map<\n\t\t{\n\t\t\treadonly id: string\n\t\t\treadonly purpose: string\n\t\t\treadonly abort: AbortController\n\t\t},\n\t\tunknown\n\t>()\n\treadonly #shared: {\n\t\treadonly id: string\n\t\treadonly purpose: string\n\t\treadonly abort: AbortController\n\t} = {\n\t\tid: 'shared',\n\t\tpurpose: 'Shared browser',\n\t\tabort: this.#abort,\n\t}\n\treadonly #holders = new Map<\n\t\tstring,\n\t\t{\n\t\t\treadonly id: string\n\t\t\treadonly purpose: string\n\t\t\treadonly abort: AbortController\n\t\t}\n\t>([[this.#shared.id, this.#shared]])\n\treadonly #leases = new Map<\n\t\t{\n\t\t\treadonly id: string\n\t\t\treadonly purpose: string\n\t\t\treadonly abort: AbortController\n\t\t},\n\t\t{\n\t\t\treadonly token: PoolToken<{\n\t\t\t\treadonly browser: BrowserInterface\n\t\t\t\treadonly profile: string\n\t\t\t}>\n\t\t\treadonly generation: {\n\t\t\t\treadonly context: BrowserContextInterface\n\t\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\t\treadonly directory: string\n\t\t\t}\n\t\t}\n\t>()\n\treadonly #grants = new Map<\n\t\t{\n\t\t\treadonly id: string\n\t\t\treadonly purpose: string\n\t\t\treadonly abort: AbortController\n\t\t},\n\t\tPromise<{\n\t\t\treadonly token: PoolToken<{\n\t\t\t\treadonly browser: BrowserInterface\n\t\t\t\treadonly profile: string\n\t\t\t}>\n\t\t\treadonly generation: {\n\t\t\t\treadonly context: BrowserContextInterface\n\t\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\t\treadonly directory: string\n\t\t\t}\n\t\t}>\n\t>()\n\treadonly #notices = new Map<\n\t\t{\n\t\t\treadonly id: string\n\t\t\treadonly purpose: string\n\t\t\treadonly abort: AbortController\n\t\t},\n\t\tSet<{\n\t\t\treadonly token: PoolToken<{\n\t\t\t\treadonly browser: BrowserInterface\n\t\t\t\treadonly profile: string\n\t\t\t}>\n\t\t\treadonly generation: {\n\t\t\t\treadonly context: BrowserContextInterface\n\t\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\t\treadonly directory: string\n\t\t\t}\n\t\t}>\n\t>()\n\treadonly #disposals = new Map<string, Promise<void>>()\n\treadonly #drains = new Map<\n\t\t{\n\t\t\treadonly id: string\n\t\t\treadonly purpose: string\n\t\t\treadonly abort: AbortController\n\t\t},\n\t\tSet<Promise<void>>\n\t>()\n\treadonly #readers = new Map<string, Set<symbol>>()\n\treadonly #writers = new Set<string>()\n\treadonly #admission: number\n\treadonly #reference: () => string\n\t#references = 0\n\t#failure: unknown\n\t#stranded: unknown\n\t#starting: Promise<void> | undefined\n\t#sweeping: Promise<void> | undefined\n\t#closing: Promise<void> | undefined\n\n\t/**\n\t * Registers the dispatchers and binds the protocol to the stdio streams without reading them.\n\t *\n\t * @param options - The root, the launch, the journeys' read-only switch, and the streams\n\t */\n\tconstructor(options?: BrowserMCPServerOptions) {\n\t\tconst size = options?.pool?.size ?? BROWSER_SERVER_POOL_SIZE\n\t\tconst contexts = options?.pool?.contexts ?? BROWSER_SERVER_CONTEXTS\n\t\tif (!isInteger(size) || size < 1 || size > BROWSER_SERVER_POOL_LIMIT)\n\t\t\tthrow new BrowserError(\n\t\t\t\tBROWSER_SERVER_OPTIONS,\n\t\t\t\t`pool.size must be an integer from 1 through ${BROWSER_SERVER_POOL_LIMIT}`,\n\t\t\t\t{ subject: 'server' },\n\t\t\t)\n\t\tif (!isInteger(contexts) || contexts < 1 || contexts > BROWSER_SERVER_CONTEXTS_LIMIT)\n\t\t\tthrow new BrowserError(\n\t\t\t\tBROWSER_SERVER_OPTIONS,\n\t\t\t\t`pool.contexts must be an integer from 1 through ${BROWSER_SERVER_CONTEXTS_LIMIT}`,\n\t\t\t\t{ subject: 'server' },\n\t\t\t)\n\t\tthis.#admission = size * contexts\n\t\tthis.#log = options?.log ?? process.stderr\n\t\tthis.#reference = this.#issue.bind(this)\n\t\tthis.#pool = createPool<{\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t}>({\n\t\t\tcreate: this.#warm.bind(this),\n\t\t\tdestroy: this.#destroyRecord.bind(this),\n\t\t\tvalidate: this.#validate.bind(this),\n\t\t\twatch: this.#watch.bind(this),\n\t\t\terror: this.#fault.bind(this),\n\t\t\tmin: size,\n\t\t\tcapacity: contexts,\n\t\t\trestarts: BROWSER_SERVER_RESTARTS,\n\t\t})\n\t\tthis.#root = resolve(options?.root ?? 'tmp/browsers')\n\t\tthis.#headless = options?.browser?.headless ?? true\n\t\tthis.#executable = options?.browser?.executable\n\t\tthis.#viewport = options?.browser?.viewport\n\t\tthis.#readonly = options?.journeys?.readonly ?? false\n\t\tthis.#launcher = options?.pool?.launch ?? createBrowser\n\t\tthis.#input = options?.stdio?.input ?? process.stdin\n\t\tthis.#tools = createToolManager()\n\t\tconst names = [...BROWSER_TOOL_NAMES, ...BROWSER_JOURNEY_TOOL_NAMES]\n\t\tthis.#vocabulary = new Set([...names, ...Object.keys(BROWSER_SERVER_COPY)])\n\t\tfor (const name of names) {\n\t\t\tthis.#tools.add(\n\t\t\t\tcreateTool({\n\t\t\t\t\t...BROWSER_TOOL_COPY[name],\n\t\t\t\t\texecute: this.#forward.bind(this, this.#shared, name),\n\t\t\t\t}),\n\t\t\t)\n\t\t}\n\t\tthis.#tools.add(\n\t\t\tcreateTool({ ...BROWSER_SERVER_COPY.acquire, execute: this.#acquire.bind(this) }),\n\t\t)\n\t\tthis.#tools.add(\n\t\t\tcreateTool({ ...BROWSER_SERVER_COPY.execute, execute: this.#dispatch.bind(this) }),\n\t\t)\n\t\tthis.#tools.add(createTool({ ...BROWSER_SERVER_COPY.tools, execute: this.#catalog.bind(this) }))\n\t\tthis.#tools.add(\n\t\t\tcreateTool({ ...BROWSER_SERVER_COPY.destroy, execute: this.#dispose.bind(this) }),\n\t\t)\n\t\tconst server = createMCPServer({\n\t\t\tidentity: { name: 'browse', version },\n\t\t\ttools: this.#tools,\n\t\t\texecution: this.#execute.bind(this),\n\t\t\thandshake: this.#handshake.bind(this),\n\t\t})\n\t\tthis.#transport = createStdioServer(createMCPLegacy(server), {\n\t\t\tinput: this.#input,\n\t\t\t...(options?.stdio?.output === undefined ? {} : { output: options.stdio.output }),\n\t\t})\n\t\t// One reference serves the end of input and both signals, because a listener is removed by\n\t\t// identity.\n\t\tthis.#signal = this.#end.bind(this)\n\t}\n\n\tasync start(): Promise<void> {\n\t\tif (this.#closing !== undefined) throw this.#ended()\n\t\tthis.#starting ??= this.#setup()\n\t\treturn this.#starting\n\t}\n\n\tdestroy(): Promise<void> {\n\t\tthis.#closing ??= Promise.resolve().then(this.#destroy.bind(this))\n\t\treturn this.#closing\n\t}\n\n\tasync #setup(): Promise<void> {\n\t\tthis.#input.on('end', this.#signal)\n\t\tprocess.on('SIGINT', this.#signal)\n\t\tprocess.on('SIGTERM', this.#signal)\n\t\tthis.#transport.start()\n\t\ttry {\n\t\t\tawait mkdir(join(this.#root, '.profiles'), { recursive: true })\n\t\t\tif (this.#closing !== undefined) return\n\t\t\tthis.#sweeping = this.#sweep()\n\t\t\tconst warming = this.#pool.start().then(undefined, (error: unknown) => error)\n\t\t\tawait this.#grant(this.#shared, this.#abort.signal)\n\t\t\tif (this.#closing !== undefined) return\n\t\t\tvoid warming.then(this.#exhaust.bind(this))\n\t\t} catch (error) {\n\t\t\tif (this.#closing !== undefined) return\n\t\t\tif (isBrowserError(error) && error.code === BROWSER_SERVER_UNAVAILABLE) throw error\n\t\t\tthrow this.#unavailable(isPoolError(error) ? (error.cause ?? this.#failure) : error)\n\t\t}\n\t}\n\n\tasync #destroy(): Promise<void> {\n\t\t// The handlers go first: a second signal during a slow teardown asks for the process.\n\t\tprocess.removeListener('SIGINT', this.#signal)\n\t\tprocess.removeListener('SIGTERM', this.#signal)\n\t\tthis.#input.removeListener('end', this.#signal)\n\t\tthis.#transport.stop()\n\t\tfor (const tool of this.#tools.tools()) this.#tools.remove(tool.name)\n\t\tthis.#unmirror()\n\t\tfor (const generation of this.#observed.keys()) this.#untrack(generation)\n\t\tthis.#leases.clear()\n\t\tfor (const holder of this.#holders.values()) holder.abort.abort()\n\t\tthis.#abort.abort()\n\t\tconst barrier = this.#pool.destroy().catch((error: unknown) => {\n\t\t\tfor (const failure of isPoolError(error) ? (error.context?.failures ?? [error]) : [error])\n\t\t\t\tthis.#faults.add(failure)\n\t\t})\n\t\tawait this.#starting?.catch(() => undefined)\n\t\tawait barrier\n\t\tawait Promise.allSettled(this.#grants.values())\n\t\tawait Promise.allSettled(this.#disposals.values())\n\t\tthis.#holders.clear()\n\t\tawait this.#sweeping\n\t\tif (this.#stranded !== undefined) this.#faults.add(this.#stranded)\n\t\tfor (const folder of this.#folders) {\n\t\t\ttry {\n\t\t\t\tconst record = parseBrowserProfileRecord(\n\t\t\t\t\tawait readFile(join(folder, BROWSER_SERVER_RECORD), 'utf8'),\n\t\t\t\t)\n\t\t\t\tif (record === undefined || probeProcess(record.pid)) continue\n\t\t\t} catch (error) {\n\t\t\t\tif (!isError(error) || !('code' in error) || error.code !== 'ENOENT') continue\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait rm(folder, { recursive: true, force: true, maxRetries: 5 })\n\t\t\t\tthis.#folders.delete(folder)\n\t\t\t} catch (error) {\n\t\t\t\tthis.#faults.add(error)\n\t\t\t}\n\t\t}\n\t\tif (this.#faults.size > 0)\n\t\t\tthrow new AggregateError([...this.#faults], 'The browse server teardown failed')\n\t}\n\n\t// Runs the dispatcher and answers a text result as one text block, because the protocol's own\n\t// rendering of a value is its JSON text, which escapes every quote and line break of a receipt.\n\tasync #execute(context: MCPExecutionContext): Promise<ToolResult | MCPCallResult> {\n\t\tconst result = await context.tools.execute(context.call, {\n\t\t\tsignal: context.signal,\n\t\t\t...(context.caller === undefined ? {} : { caller: context.caller }),\n\t\t})\n\t\tif (!result.success)\n\t\t\treturn {\n\t\t\t\t...result,\n\t\t\t\terror: boundBrowserText(result.error, BROWSER_TOOL_LIMIT, BROWSER_TOOL_CUT_FOOTER),\n\t\t\t}\n\t\tif (typeof result.value !== 'string') return result\n\t\tconst text =\n\t\t\tcontext.call.name === 'acquire' || context.call.name === 'tools'\n\t\t\t\t? result.value\n\t\t\t\t: boundBrowserText(result.value, BROWSER_TOOL_LIMIT, BROWSER_TOOL_CUT_FOOTER)\n\t\treturn { resultType: 'complete', content: [{ type: 'text', text }] }\n\t}\n\n\t// Answers the end of input and a termination signal.\n\t#end(): void {\n\t\tif (this.#closing !== undefined) return\n\t\tvoid this.destroy().catch(this.#endFailure.bind(this))\n\t}\n\n\t#endFailure(error: unknown): void {\n\t\tprocess.exitCode = 1\n\t\tthis.#write(`browse: ${describeBrowserServerLoss(BROWSER_SERVER_TEARDOWN, error)}`)\n\t}\n\n\tasync #acquire(args: Readonly<Record<string, unknown>>, context: ToolContext): Promise<string> {\n\t\tcontext.signal.throwIfAborted()\n\t\tif (this.#closing !== undefined) throw this.#ended()\n\t\tconst purpose = args['purpose']\n\t\tif (!isString(purpose) || purpose.trim().length === 0)\n\t\t\tthrow new BrowserError('ARGUMENT', 'purpose must describe the work', { subject: 'toolset' })\n\t\tif (this.#holders.size >= this.#admission)\n\t\t\tthrow new BrowserError(\n\t\t\t\tBROWSER_SERVER_BUSY,\n\t\t\t\t`${BROWSER_SERVER_BUSY}: ${[...this.#holders.values()].map((holder) => `${holder.id} (${holder.purpose})`).join(', ')}. Call destroy for a holder no longer needed or call the named tools to share the shared browser.`,\n\t\t\t)\n\t\tconst holder: {\n\t\t\treadonly id: string\n\t\t\treadonly purpose: string\n\t\t\treadonly abort: AbortController\n\t\t} = { id: randomUUID(), purpose, abort: new AbortController() }\n\t\tthis.#holders.set(holder.id, holder)\n\t\tconst listener = addAbortListener(context.signal, () =>\n\t\t\tholder.abort.abort(context.signal.reason),\n\t\t)\n\t\ttry {\n\t\t\tconst lease = await this.#serve(holder, context.signal)\n\t\t\tcontext.signal.throwIfAborted()\n\t\t\tif (holder.abort.signal.aborted || this.#holders.get(holder.id) !== holder)\n\t\t\t\tthrow this.#ended()\n\t\t\tif (this.#leases.get(holder) !== lease)\n\t\t\t\tthrow this.#unavailable(this.#departures.get(lease)?.cause)\n\t\t\tconst catalog: BrowserServerCatalog = {\n\t\t\t\tholder: holder.id,\n\t\t\t\ttools: lease.generation.toolset.tools.definitions(),\n\t\t\t}\n\t\t\treturn JSON.stringify(catalog)\n\t\t} catch (error) {\n\t\t\tawait this.#retire(holder).catch(this.#fault.bind(this))\n\t\t\tthrow error\n\t\t} finally {\n\t\t\tlistener[Symbol.dispose]()\n\t\t}\n\t}\n\n\t#holder(value: unknown): {\n\t\treadonly id: string\n\t\treadonly purpose: string\n\t\treadonly abort: AbortController\n\t} {\n\t\tconst holder = isString(value) ? this.#holders.get(value) : undefined\n\t\tif (holder === undefined || holder === this.#shared || holder.abort.signal.aborted)\n\t\t\tthrow new BrowserError(\n\t\t\t\tBROWSER_SERVER_HOLDER,\n\t\t\t\t`${BROWSER_SERVER_HOLDER}: unknown or ended holder`,\n\t\t\t)\n\t\treturn holder\n\t}\n\n\tasync #dispatch(args: Readonly<Record<string, unknown>>, context: ToolContext): Promise<unknown> {\n\t\tconst holder = this.#holder(args['holder'])\n\t\tconst name = args['name']\n\t\tconst parameters = args['arguments']\n\t\tif (!isString(name) || !isRecord(parameters))\n\t\t\tthrow new BrowserError('ARGUMENT', 'execute requires name and arguments', {\n\t\t\t\tsubject: 'toolset',\n\t\t\t})\n\t\treturn this.#forward(holder, name, parameters, context)\n\t}\n\n\tasync #catalog(args: Readonly<Record<string, unknown>>, context: ToolContext): Promise<string> {\n\t\tconst holder = this.#holder(args['holder'])\n\t\tconst signal = AbortSignal.any([context.signal, holder.abort.signal])\n\t\ttry {\n\t\t\tconst lease = await this.#serve(holder, signal)\n\t\t\tsignal.throwIfAborted()\n\t\t\tif (this.#leases.get(holder) !== lease)\n\t\t\t\tthrow this.#unavailable(this.#departures.get(lease)?.cause)\n\t\t\tconst catalog: BrowserServerCatalog = {\n\t\t\t\tholder: holder.id,\n\t\t\t\ttools: lease.generation.toolset.tools.definitions(),\n\t\t\t}\n\t\t\treturn this.#annotate(holder, JSON.stringify(catalog))\n\t\t} catch (error) {\n\t\t\tcontext.signal.throwIfAborted()\n\t\t\tif (holder.abort.signal.aborted)\n\t\t\t\tthrow new BrowserError(\n\t\t\t\t\tBROWSER_SERVER_UNRESOLVED,\n\t\t\t\t\t`${BROWSER_SERVER_UNRESOLVED}: the holder ended during the call`,\n\t\t\t\t)\n\t\t\tif (isBrowserError(error))\n\t\t\t\tthrow new BrowserError(\n\t\t\t\t\terror.code,\n\t\t\t\t\tthis.#annotate(holder, `${error.code}: ${error.message}`),\n\t\t\t\t)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync #dispose(args: Readonly<Record<string, unknown>>): Promise<string> {\n\t\tconst id = args['holder']\n\t\tconst disposal = isString(id) ? this.#disposals.get(id) : undefined\n\t\tawait (disposal ?? this.#retire(this.#holder(id)))\n\t\treturn 'Holder destroyed.'\n\t}\n\n\t#retire(holder: {\n\t\treadonly id: string\n\t\treadonly purpose: string\n\t\treadonly abort: AbortController\n\t}): Promise<void> {\n\t\tconst pending = this.#disposals.get(holder.id)\n\t\tif (pending !== undefined) return pending\n\t\tholder.abort.abort()\n\t\tconst lease = this.#leases.get(holder)\n\t\tthis.#leases.delete(holder)\n\t\tif (lease !== undefined) this.#untrack(lease.generation)\n\t\tconst disposal = Promise.resolve().then(async () => {\n\t\t\ttry {\n\t\t\t\tawait this.#grants.get(holder)?.catch(() => undefined)\n\t\t\t\tif (lease !== undefined) await this.#release(holder, lease)\n\t\t\t\tawait Promise.all(this.#drains.get(holder) ?? [])\n\t\t\t\tawait Promise.all(\n\t\t\t\t\t[...(this.#notices.get(holder) ?? [])]\n\t\t\t\t\t\t.filter((lost) => this.#losses.has(lost.token.value))\n\t\t\t\t\t\t.map((lost) => this.#endings.get(lost.token.value)?.promise),\n\t\t\t\t)\n\t\t\t} catch (error) {\n\t\t\t\tthis.#faults.add(error)\n\t\t\t} finally {\n\t\t\t\tif (this.#holders.get(holder.id) === holder && !this.#retentions.has(holder))\n\t\t\t\t\tthis.#holders.delete(holder.id)\n\t\t\t\tthis.#notices.delete(holder)\n\t\t\t\tthis.#drains.delete(holder)\n\t\t\t}\n\t\t})\n\t\tthis.#disposals.set(holder.id, disposal)\n\t\treturn disposal\n\t}\n\n\tasync #forward(\n\t\tholder: {\n\t\t\treadonly id: string\n\t\t\treadonly purpose: string\n\t\t\treadonly abort: AbortController\n\t\t},\n\t\tname: string,\n\t\targs: Readonly<Record<string, unknown>>,\n\t\tcontext: ToolContext,\n\t): Promise<unknown> {\n\t\tcontext.signal.throwIfAborted()\n\t\tconst journey = args['journey']\n\t\tif ((name !== 'replay' && name !== 'forget') || !isString(journey))\n\t\t\treturn this.#perform(holder, name, args, context)\n\t\tif (this.#writers.has(journey) || (name === 'forget' && this.#readers.has(journey)))\n\t\t\tthrow new BrowserError(\n\t\t\t\t'STORE_LOCKED',\n\t\t\t\t`STORE_LOCKED: Journey ${journey} is locked; call ${name} again.`,\n\t\t\t\t{ name: journey },\n\t\t\t)\n\t\tconst reader = Symbol(journey)\n\t\tif (name === 'forget') this.#writers.add(journey)\n\t\telse {\n\t\t\tconst readers = this.#readers.get(journey) ?? new Set<symbol>()\n\t\t\treaders.add(reader)\n\t\t\tthis.#readers.set(journey, readers)\n\t\t}\n\t\ttry {\n\t\t\treturn await this.#perform(holder, name, args, context)\n\t\t} finally {\n\t\t\tif (name === 'forget') this.#writers.delete(journey)\n\t\t\telse {\n\t\t\t\tconst readers = this.#readers.get(journey)\n\t\t\t\treaders?.delete(reader)\n\t\t\t\tif (readers?.size === 0) this.#readers.delete(journey)\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #perform(\n\t\tholder: {\n\t\t\treadonly id: string\n\t\t\treadonly purpose: string\n\t\t\treadonly abort: AbortController\n\t\t},\n\t\tname: string,\n\t\targs: Readonly<Record<string, unknown>>,\n\t\tcontext: ToolContext,\n\t): Promise<unknown> {\n\t\tconst signal =\n\t\t\tholder === this.#shared\n\t\t\t\t? context.signal\n\t\t\t\t: AbortSignal.any([context.signal, holder.abort.signal])\n\t\tlet lease: {\n\t\t\treadonly token: PoolToken<{\n\t\t\t\treadonly browser: BrowserInterface\n\t\t\t\treadonly profile: string\n\t\t\t}>\n\t\t\treadonly generation: {\n\t\t\t\treadonly context: BrowserContextInterface\n\t\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\t\treadonly directory: string\n\t\t\t}\n\t\t}\n\t\ttry {\n\t\t\tlease = await this.#serve(holder, signal)\n\t\t} catch (error) {\n\t\t\tcontext.signal.throwIfAborted()\n\t\t\tif (holder !== this.#shared && holder.abort.signal.aborted)\n\t\t\t\tthrow new BrowserError(\n\t\t\t\t\tBROWSER_SERVER_UNRESOLVED,\n\t\t\t\t\t`${BROWSER_SERVER_UNRESOLVED}: the holder ended during the call`,\n\t\t\t\t)\n\t\t\tif (isBrowserError(error))\n\t\t\t\tthrow new BrowserError(\n\t\t\t\t\terror.code,\n\t\t\t\t\tthis.#annotate(holder, `${error.code}: ${error.message}`),\n\t\t\t\t)\n\t\t\tthrow error\n\t\t}\n\t\tlet result: ToolResult\n\t\ttry {\n\t\t\tconst execution = lease.generation.toolset.tools.execute(\n\t\t\t\t{ id: name, name, arguments: args },\n\t\t\t\t{ ...context, signal },\n\t\t\t)\n\t\t\t// A cancelled replay still persists its run before surrendering admission.\n\t\t\tconst outcome = await (name === 'replay' || name === 'forget'\n\t\t\t\t? execution\n\t\t\t\t: this.#race(execution, signal))\n\t\t\tif (outcome === undefined) throw this.#ended()\n\t\t\tresult = outcome\n\t\t} catch (error) {\n\t\t\tresult = {\n\t\t\t\tid: name,\n\t\t\t\tname,\n\t\t\t\tsuccess: false,\n\t\t\t\terror: isError(error) ? error.message : String(error),\n\t\t\t}\n\t\t}\n\t\tcontext.signal.throwIfAborted()\n\t\tif (holder !== this.#shared && holder.abort.signal.aborted)\n\t\t\tthrow new BrowserError(\n\t\t\t\tBROWSER_SERVER_UNRESOLVED,\n\t\t\t\tBROWSER_SERVER_UNRESOLVED + ': the holder ended during the call',\n\t\t\t)\n\t\tif (!result.success) {\n\t\t\tif (this.#leases.get(holder) === lease && !context.signal.aborted) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.#race(this.#ping(lease.token.value), context.signal)\n\t\t\t\t} catch {\n\t\t\t\t\t// The shared ping records loss even when this caller stops waiting.\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontext.signal.throwIfAborted()\n\t\t\tif (this.#leases.get(holder) !== lease) {\n\t\t\t\tconst loss = this.#departures.get(lease)\n\t\t\t\tthrow new BrowserError(\n\t\t\t\t\tBROWSER_SERVER_UNRESOLVED,\n\t\t\t\t\tthis.#annotate(\n\t\t\t\t\t\tholder,\n\t\t\t\t\t\tdescribeBrowserServerLoss(BROWSER_SERVER_UNRESOLVED, loss?.cause, loss?.url),\n\t\t\t\t\t\tlease,\n\t\t\t\t\t),\n\t\t\t\t)\n\t\t\t}\n\t\t\tthrow new BrowserError(\n\t\t\t\t'PROTOCOL',\n\t\t\t\tboundBrowserText(\n\t\t\t\t\tthis.#annotate(holder, result.error, lease),\n\t\t\t\t\tBROWSER_TOOL_LIMIT,\n\t\t\t\t\tBROWSER_TOOL_CUT_FOOTER,\n\t\t\t\t),\n\t\t\t)\n\t\t}\n\t\treturn typeof result.value === 'string'\n\t\t\t? this.#annotate(holder, result.value, lease)\n\t\t\t: result.value\n\t}\n\n\t#annotate(\n\t\tholder: {\n\t\t\treadonly id: string\n\t\t\treadonly purpose: string\n\t\t\treadonly abort: AbortController\n\t\t},\n\t\tvalue: string,\n\t\tlease?: {\n\t\t\treadonly token: PoolToken<{\n\t\t\t\treadonly browser: BrowserInterface\n\t\t\t\treadonly profile: string\n\t\t\t}>\n\t\t\treadonly generation: {\n\t\t\t\treadonly context: BrowserContextInterface\n\t\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\t\treadonly directory: string\n\t\t\t}\n\t\t},\n\t): string {\n\t\tconst notes: string[] = []\n\t\tfor (const lost of this.#notices.get(holder) ?? []) {\n\t\t\tif (lost === lease) continue\n\t\t\tconst loss = this.#departures.get(lost)\n\t\t\tnotes.push(describeBrowserServerLoss(BROWSER_SERVER_CRASH, loss?.cause, loss?.url))\n\t\t\tthis.#notices.get(holder)?.delete(lost)\n\t\t}\n\t\treturn [...notes, value].join('\\n')\n\t}\n\n\t#notice(context: BrowserContextInterface): string {\n\t\tconst entry = [...this.#leases].find(([, lease]) => lease.generation.context === context)\n\t\treturn entry === undefined ? '' : this.#annotate(entry[0], '')\n\t}\n\n\tasync #handshake(options: MCPMethodOptions): Promise<void> {\n\t\ttry {\n\t\t\tawait this.#race(this.#starting, options.signal)\n\t\t\tif (this.#closing !== undefined) throw this.#ended()\n\t\t} catch (error) {\n\t\t\toptions.signal.throwIfAborted()\n\t\t\tif (isBrowserError(error))\n\t\t\t\tthrow new MCPError(`${error.code}: ${error.message}`, JSONRPC_SERVER_ERROR, {\n\t\t\t\t\tcode: error.code,\n\t\t\t\t})\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync #race<T>(promise: Promise<T> | undefined, signal: AbortSignal): Promise<T | undefined> {\n\t\tsignal.throwIfAborted()\n\t\tconst aborted = Promise.withResolvers<never>()\n\t\tconst listener = addAbortListener(signal, () => aborted.reject(signal.reason))\n\t\ttry {\n\t\t\treturn await Promise.race([promise, aborted.promise])\n\t\t} finally {\n\t\t\tlistener[Symbol.dispose]()\n\t\t}\n\t}\n\n\tasync #grant(\n\t\tholder: {\n\t\t\treadonly id: string\n\t\t\treadonly purpose: string\n\t\t\treadonly abort: AbortController\n\t\t},\n\t\tsignal: AbortSignal,\n\t): Promise<{\n\t\treadonly token: PoolToken<{\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t}>\n\t\treadonly generation: {\n\t\t\treadonly context: BrowserContextInterface\n\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\treadonly directory: string\n\t\t}\n\t}> {\n\t\tconst held = this.#leases.get(holder)\n\t\tif (held !== undefined) return held\n\t\tlet granting = this.#grants.get(holder)\n\t\tif (granting === undefined) {\n\t\t\tgranting = Promise.resolve().then(async () => {\n\t\t\t\tawait Promise.allSettled(this.#drains.get(holder) ?? [])\n\t\t\t\tif (this.#retentions.has(holder)) throw this.#unavailable(this.#retentions.get(holder))\n\t\t\t\tconst token = await this.#pool.acquire(holder.abort.signal)\n\t\t\t\treturn this.#hold(holder, token)\n\t\t\t})\n\t\t\tthis.#grants.set(holder, granting)\n\t\t\tvoid granting\n\t\t\t\t.finally(() => {\n\t\t\t\t\tif (this.#grants.get(holder) === granting) this.#grants.delete(holder)\n\t\t\t\t})\n\t\t\t\t.catch(() => undefined)\n\t\t}\n\t\tconst lease = await this.#race(granting, signal)\n\t\tif (lease === undefined) throw this.#ended()\n\t\treturn lease\n\t}\n\n\tasync #hold(\n\t\tholder: {\n\t\t\treadonly id: string\n\t\t\treadonly purpose: string\n\t\t\treadonly abort: AbortController\n\t\t},\n\t\ttoken: PoolToken<{\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t}>,\n\t): Promise<{\n\t\treadonly token: PoolToken<{\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t}>\n\t\treadonly generation: {\n\t\t\treadonly context: BrowserContextInterface\n\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\treadonly directory: string\n\t\t}\n\t}> {\n\t\tconst slot = token.value\n\t\tif (\n\t\t\tthis.#closing !== undefined ||\n\t\t\tthis.#holders.get(holder.id) !== holder ||\n\t\t\tholder.abort.signal.aborted\n\t\t) {\n\t\t\ttoken.release()\n\t\t\tthrow this.#ended()\n\t\t}\n\t\tif (!this.#prepared.has(slot)) await this.#ping(slot)\n\t\tif (this.#closing !== undefined || holder.abort.signal.aborted) {\n\t\t\ttoken.release()\n\t\t\tthrow this.#ended()\n\t\t}\n\t\tif (this.#losses.has(slot)) {\n\t\t\ttoken.release()\n\t\t\tthrow this.#unavailable(this.#losses.get(slot)?.cause)\n\t\t}\n\t\tlet generation = this.#prepared.get(slot)\n\t\tthis.#prepared.delete(slot)\n\t\ttry {\n\t\t\tgeneration ??= await this.#build(slot, token)\n\t\t} catch (error) {\n\t\t\tif (this.#losses.has(slot)) await this.#endings.get(slot)?.promise\n\t\t\telse token.release()\n\t\t\tthrow this.#unavailable(error)\n\t\t}\n\t\tconst lease: {\n\t\t\treadonly token: PoolToken<{\n\t\t\t\treadonly browser: BrowserInterface\n\t\t\t\treadonly profile: string\n\t\t\t}>\n\t\t\treadonly generation: {\n\t\t\t\treadonly context: BrowserContextInterface\n\t\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\t\treadonly directory: string\n\t\t\t}\n\t\t} = { token, generation }\n\t\tif (\n\t\t\tthis.#closing !== undefined ||\n\t\t\tthis.#holders.get(holder.id) !== holder ||\n\t\t\tholder.abort.signal.aborted ||\n\t\t\tthis.#losses.has(slot)\n\t\t) {\n\t\t\tawait this.#release(holder, lease)\n\t\t\tthrow this.#ended()\n\t\t}\n\t\tthis.#leases.set(holder, lease)\n\t\tthis.#observe(slot, generation)\n\t\tif (holder === this.#shared) {\n\t\t\tconst tools = generation.toolset.tools\n\t\t\tconst mirrored: {\n\t\t\t\treadonly lease: {\n\t\t\t\t\treadonly token: PoolToken<{\n\t\t\t\t\t\treadonly browser: BrowserInterface\n\t\t\t\t\t\treadonly profile: string\n\t\t\t\t\t}>\n\t\t\t\t\treadonly generation: {\n\t\t\t\t\t\treadonly context: BrowserContextInterface\n\t\t\t\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\t\t\t\treadonly directory: string\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treadonly added: (tool: ToolInterface) => void\n\t\t\t\treadonly removed: (tool: ToolInterface) => void\n\t\t\t\treadonly cleared: (tools: readonly ToolInterface[]) => void\n\t\t\t} = {\n\t\t\t\tlease,\n\t\t\t\tadded: this.#mirror.bind(this, lease),\n\t\t\t\tremoved: this.#withdraw.bind(this, lease),\n\t\t\t\tcleared: this.#clear.bind(this, lease),\n\t\t\t}\n\t\t\tthis.#mirrored = mirrored\n\t\t\tfor (const tool of tools.tools()) this.#mirror(lease, tool)\n\t\t\ttools.emitter.on('add', mirrored.added)\n\t\t\ttools.emitter.on('remove', mirrored.removed)\n\t\t\ttools.emitter.on('clear', mirrored.cleared)\n\t\t}\n\t\treturn lease\n\t}\n\n\tasync #serve(\n\t\tholder: {\n\t\t\treadonly id: string\n\t\t\treadonly purpose: string\n\t\t\treadonly abort: AbortController\n\t\t},\n\t\tsignal: AbortSignal,\n\t): Promise<{\n\t\treadonly token: PoolToken<{\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t}>\n\t\treadonly generation: {\n\t\t\treadonly context: BrowserContextInterface\n\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\treadonly directory: string\n\t\t}\n\t}> {\n\t\tif (this.#closing !== undefined || holder.abort.signal.aborted) throw this.#ended()\n\t\tawait this.#race(this.#starting, signal)\n\t\tif (this.#closing !== undefined || holder.abort.signal.aborted) throw this.#ended()\n\t\tconst held = this.#leases.get(holder)\n\t\tif (held !== undefined) {\n\t\t\ttry {\n\t\t\t\tawait this.#race(this.#ping(held.token.value), signal)\n\t\t\t\tif (this.#leases.get(holder) === held) return held\n\t\t\t} catch {\n\t\t\t\tsignal.throwIfAborted()\n\t\t\t\tif (holder.abort.signal.aborted) throw this.#ended()\n\t\t\t}\n\t\t}\n\t\ttry {\n\t\t\tconst lease = await this.#grant(holder, signal)\n\t\t\tif (this.#leases.get(holder) !== lease)\n\t\t\t\tthrow this.#unavailable(this.#departures.get(lease)?.cause)\n\t\t\treturn lease\n\t\t} catch (error) {\n\t\t\tsignal.throwIfAborted()\n\t\t\tif (holder.abort.signal.aborted || (isPoolError(error) && error.code === 'destroyed'))\n\t\t\t\tthrow this.#ended()\n\t\t\tif (isPoolError(error) && (error.code === 'create' || error.code === 'cleanup')) {\n\t\t\t\tthis.#exhaust(error)\n\t\t\t\tthrow this.#unavailable(error.cause ?? this.#failure)\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t#ping(slot: { readonly browser: BrowserInterface; readonly profile: string }): Promise<void> {\n\t\tconst pending = this.#pings.get(slot)\n\t\tif (pending !== undefined) return pending\n\t\tconst ping = slot.browser\n\t\t\t.ping({ signal: this.#abort.signal })\n\t\t\t.catch((error: unknown) => {\n\t\t\t\tif (!this.#abort.signal.aborted) this.#lose(slot, error)\n\t\t\t})\n\t\t\t.finally(() => this.#pings.delete(slot))\n\t\tthis.#pings.set(slot, ping)\n\t\treturn ping\n\t}\n\n\tasync #validate(slot: {\n\t\treadonly browser: BrowserInterface\n\t\treadonly profile: string\n\t}): Promise<boolean> {\n\t\ttry {\n\t\t\tawait slot.browser.ping({ signal: this.#abort.signal })\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\tif (!this.#abort.signal.aborted) this.#lose(slot, error)\n\t\t\treturn false\n\t\t}\n\t}\n\n\t#lose(\n\t\tslot: {\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t},\n\t\tcause: unknown,\n\t): void {\n\t\tif (this.#closing !== undefined || this.#losses.has(slot)) return\n\t\tthis.#losses.set(slot, { cause })\n\t\tthis.#failure = cause\n\t\tfor (const [holder, lease] of this.#leases) {\n\t\t\tif (lease.token.value !== slot) continue\n\t\t\tthis.#detach(holder, lease, cause)\n\t\t}\n\t\tconst watch = this.#watches.get(slot)\n\t\tthis.#unwatch(slot)\n\t\twatch?.resolve(cause)\n\t}\n\n\t#detach(\n\t\tholder: {\n\t\t\treadonly id: string\n\t\t\treadonly purpose: string\n\t\t\treadonly abort: AbortController\n\t\t},\n\t\tlease: {\n\t\t\treadonly token: PoolToken<{\n\t\t\t\treadonly browser: BrowserInterface\n\t\t\t\treadonly profile: string\n\t\t\t}>\n\t\t\treadonly generation: {\n\t\t\t\treadonly context: BrowserContextInterface\n\t\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\t\treadonly directory: string\n\t\t\t}\n\t\t},\n\t\tcause: unknown,\n\t): void {\n\t\tif (this.#leases.get(holder) !== lease || this.#holders.get(holder.id) !== holder) return\n\t\tthis.#departures.set(lease, {\n\t\t\tcause,\n\t\t\turl: lease.generation.toolset.redact(lease.generation.toolset.view.url),\n\t\t})\n\t\tif (holder === this.#shared) this.#unmirror()\n\t\tthis.#leases.delete(holder)\n\t\tthis.#untrack(lease.generation)\n\t\tconst notices =\n\t\t\tthis.#notices.get(holder) ??\n\t\t\tnew Set<{\n\t\t\t\treadonly token: PoolToken<{\n\t\t\t\t\treadonly browser: BrowserInterface\n\t\t\t\t\treadonly profile: string\n\t\t\t\t}>\n\t\t\t\treadonly generation: {\n\t\t\t\t\treadonly context: BrowserContextInterface\n\t\t\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\t\t\treadonly directory: string\n\t\t\t\t}\n\t\t\t}>()\n\t\tnotices.add(lease)\n\t\tthis.#notices.set(holder, notices)\n\t}\n\n\t#watch(\n\t\tslot: {\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t},\n\t\tsignal: AbortSignal,\n\t): Promise<unknown> {\n\t\tconst loss = Promise.withResolvers<unknown>()\n\t\tconst disconnect = this.#disconnect.bind(this, slot)\n\t\tconst subscription = addAbortListener(signal, this.#unwatch.bind(this, slot))\n\t\tthis.#watches.set(slot, { resolve: loss.resolve, disconnect, subscription })\n\t\tslot.browser.emitter.on('disconnect', disconnect)\n\t\tif (signal.aborted) this.#unwatch(slot)\n\t\telse if (slot.browser.status !== 'connected') this.#disconnect(slot)\n\t\treturn loss.promise\n\t}\n\n\t#observe(\n\t\tslot: {\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t},\n\t\tgeneration: {\n\t\t\treadonly context: BrowserContextInterface\n\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\treadonly directory: string\n\t\t},\n\t): void {\n\t\tif (this.#observed.has(generation)) return\n\t\tconst page = this.#track.bind(this, slot, generation)\n\t\tthis.#observed.set(generation, { page, crashes: new Map() })\n\t\tgeneration.context.emitter.on('page', page)\n\t\tfor (const current of generation.context.pages()) this.#track(slot, generation, current)\n\t}\n\n\t#track(\n\t\tslot: {\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t},\n\t\tgeneration: {\n\t\t\treadonly context: BrowserContextInterface\n\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\treadonly directory: string\n\t\t},\n\t\tpage: BrowserPageInterface,\n\t): void {\n\t\tconst watch = this.#observed.get(generation)\n\t\tif (watch === undefined || watch.crashes.has(page)) return\n\t\tconst crash = this.#crash.bind(this, slot, generation, page)\n\t\tpage.emitter.on('crash', crash)\n\t\tthis.#observed.set(generation, {\n\t\t\t...watch,\n\t\t\tcrashes: new Map([...watch.crashes, [page, crash]]),\n\t\t})\n\t}\n\n\t#crash(\n\t\tslot: {\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t},\n\t\tgeneration: {\n\t\t\treadonly context: BrowserContextInterface\n\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\treadonly directory: string\n\t\t},\n\t\tpage: BrowserPageInterface,\n\t): void {\n\t\tif (this.#prepared.get(slot) === generation) {\n\t\t\tthis.#prepared.delete(slot)\n\t\t\tthis.#untrack(generation)\n\t\t\tvoid this.#clean(slot, generation).catch(this.#fault.bind(this))\n\t\t\treturn\n\t\t}\n\t\tconst held = [...this.#leases].find(([, lease]) => lease.generation === generation)\n\t\tif (held === undefined || page !== generation.toolset.view) return\n\t\tconst [holder, lease] = held\n\t\tthis.#detach(holder, lease, new Error('The current page renderer crashed'))\n\t\tconst drain = this.#release(holder, lease)\n\t\tconst drains = this.#drains.get(holder) ?? new Set<Promise<void>>()\n\t\tdrains.add(drain)\n\t\tthis.#drains.set(holder, drains)\n\t\tvoid drain.finally(() => drains.delete(drain)).catch(this.#fault.bind(this))\n\t}\n\n\t#untrack(generation: {\n\t\treadonly context: BrowserContextInterface\n\t\treadonly toolset: BrowserToolsetInterface\n\t\treadonly directory: string\n\t}): void {\n\t\tconst watch = this.#observed.get(generation)\n\t\tif (watch === undefined) return\n\t\tthis.#observed.delete(generation)\n\t\tgeneration.context.emitter.off('page', watch.page)\n\t\tfor (const [page, crash] of watch.crashes) page.emitter.off('crash', crash)\n\t}\n\n\t#disconnect(slot: { readonly browser: BrowserInterface; readonly profile: string }): void {\n\t\tthis.#lose(\n\t\t\tslot,\n\t\t\tnew Error(\n\t\t\t\tslot.browser.pid === undefined\n\t\t\t\t\t? 'The browser process exited'\n\t\t\t\t\t: 'The browser transport disconnected',\n\t\t\t),\n\t\t)\n\t}\n\n\t#unwatch(slot: { readonly browser: BrowserInterface; readonly profile: string }): void {\n\t\tconst watch = this.#watches.get(slot)\n\t\tif (watch === undefined) return\n\t\tthis.#watches.delete(slot)\n\t\tslot.browser.emitter.off('disconnect', watch.disconnect)\n\t\twatch.subscription[Symbol.dispose]()\n\t}\n\n\tasync #release(\n\t\tholder: {\n\t\t\treadonly id: string\n\t\t\treadonly purpose: string\n\t\t\treadonly abort: AbortController\n\t\t},\n\t\tlease: {\n\t\t\treadonly token: PoolToken<{\n\t\t\t\treadonly browser: BrowserInterface\n\t\t\t\treadonly profile: string\n\t\t\t}>\n\t\t\treadonly generation: {\n\t\t\t\treadonly context: BrowserContextInterface\n\t\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\t\treadonly directory: string\n\t\t\t}\n\t\t},\n\t): Promise<void> {\n\t\tconst slot = lease.token.value\n\t\tconst removed = await this.#clean(slot, lease.generation)\n\t\tconst disposal = lease.generation.context.disposal\n\t\tif (!removed)\n\t\t\tthis.#retentions.set(holder, new Error('The context downloads directory remains owned'))\n\t\tif (disposal?.confirmed !== true && !this.#losses.has(slot) && this.#closing === undefined) {\n\t\t\t// Releasing into a FIFO waiter would publish capacity on the dying browser.\n\t\t\tif (\n\t\t\t\t![...this.#leases.values()].some((held) => held.token.value === slot && held !== lease) &&\n\t\t\t\t(this.#building.get(slot)?.size ?? 0) === 0\n\t\t\t)\n\t\t\t\tlease.token.release()\n\t\t\tthis.#lose(slot, disposal?.error ?? new Error('The context disposal is unconfirmed'))\n\t\t\tawait this.#endings.get(slot)?.promise\n\t\t} else if (removed) lease.token.release()\n\t}\n\n\t#clean(\n\t\tslot: {\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t},\n\t\tgeneration: {\n\t\t\treadonly context: BrowserContextInterface\n\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\treadonly directory: string\n\t\t},\n\t): Promise<boolean> {\n\t\tlet cleaning = this.#cleaning.get(generation)\n\t\tif (cleaning !== undefined) return cleaning\n\t\tcleaning = Promise.resolve().then(async () => {\n\t\t\tawait generation.toolset.destroy().catch(this.#fault.bind(this))\n\t\t\tawait generation.context.close().catch((error: unknown) => {\n\t\t\t\tif (!this.#losses.has(slot) && slot.browser.status === 'connected') this.#fault(error)\n\t\t\t})\n\t\t\ttry {\n\t\t\t\tawait rm(generation.directory, { recursive: true, force: true })\n\t\t\t\tthis.#owned.get(slot)?.delete(generation)\n\t\t\t\treturn true\n\t\t\t} catch (error) {\n\t\t\t\tthis.#fault(error)\n\t\t\t\treturn false\n\t\t\t}\n\t\t})\n\t\tthis.#cleaning.set(generation, cleaning)\n\t\treturn cleaning\n\t}\n\n\t#build(\n\t\tslot: {\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t},\n\t\ttoken?: PoolToken<{\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t}>,\n\t): Promise<{\n\t\treadonly context: BrowserContextInterface\n\t\treadonly toolset: BrowserToolsetInterface\n\t\treadonly directory: string\n\t}> {\n\t\tconst construction = this.#construct(slot, token)\n\t\tconst building =\n\t\t\tthis.#building.get(slot) ??\n\t\t\tnew Set<\n\t\t\t\tPromise<{\n\t\t\t\t\treadonly context: BrowserContextInterface\n\t\t\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\t\t\treadonly directory: string\n\t\t\t\t}>\n\t\t\t>()\n\t\tbuilding.add(construction)\n\t\tthis.#building.set(slot, building)\n\t\tvoid construction.finally(() => building.delete(construction)).catch(() => undefined)\n\t\treturn construction\n\t}\n\n\tasync #construct(\n\t\tslot: {\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t},\n\t\ttoken?: PoolToken<{\n\t\t\treadonly browser: BrowserInterface\n\t\t\treadonly profile: string\n\t\t}>,\n\t): Promise<{\n\t\treadonly context: BrowserContextInterface\n\t\treadonly toolset: BrowserToolsetInterface\n\t\treadonly directory: string\n\t}> {\n\t\tconst directory = join(slot.profile, 'contexts', randomUUID(), 'downloads')\n\t\tlet context: BrowserContextInterface | undefined\n\t\tlet toolset: BrowserToolsetInterface | undefined\n\t\ttry {\n\t\t\tawait mkdir(directory, { recursive: true })\n\t\t\tlet page: BrowserPageInterface\n\t\t\ttry {\n\t\t\t\tcontext = await slot.browser.isolate({\n\t\t\t\t\treference: this.#reference,\n\t\t\t\t\tdownloads: { path: directory },\n\t\t\t\t\t...(this.#viewport === undefined ? {} : { emulation: { viewport: this.#viewport } }),\n\t\t\t\t})\n\t\t\t\tpage = await context.create()\n\t\t\t} catch (error) {\n\t\t\t\tif (token !== undefined) {\n\t\t\t\t\t// This construction still occupies one entry until its rejection settles.\n\t\t\t\t\tif (\n\t\t\t\t\t\t![...this.#leases.values()].some((lease) => lease.token.value === slot) &&\n\t\t\t\t\t\t(this.#building.get(slot)?.size ?? 0) === 1\n\t\t\t\t\t)\n\t\t\t\t\t\ttoken.release()\n\t\t\t\t\tthis.#lose(slot, error)\n\t\t\t\t}\n\t\t\t\tthrow error\n\t\t\t}\n\t\t\ttoolset = createBrowserToolset(page, {\n\t\t\t\tcontext,\n\t\t\t\tnotes: this.#notice.bind(this, context),\n\t\t\t\tjourneys: {\n\t\t\t\t\tstore: createFileBrowserJourneyStore({ root: this.#root }),\n\t\t\t\t\truns: createFileBrowserRunStore({ root: this.#root }),\n\t\t\t\t\treadonly: this.#readonly,\n\t\t\t\t},\n\t\t\t})\n\t\t\tawait toolset.start()\n\t\t\tconst generation: {\n\t\t\t\treadonly context: BrowserContextInterface\n\t\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\t\treadonly directory: string\n\t\t\t} = { context, toolset, directory }\n\t\t\tconst owned =\n\t\t\t\tthis.#owned.get(slot) ??\n\t\t\t\tnew Set<{\n\t\t\t\t\treadonly context: BrowserContextInterface\n\t\t\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\t\t\treadonly directory: string\n\t\t\t\t}>()\n\t\t\towned.add(generation)\n\t\t\tthis.#owned.set(slot, owned)\n\t\t\treturn generation\n\t\t} catch (error) {\n\t\t\tawait toolset?.destroy().catch(this.#fault.bind(this))\n\t\t\tawait context?.close().catch((failure: unknown) => {\n\t\t\t\t// A launched browser defers its loss event; CDP can already report the disconnection.\n\t\t\t\tif (\n\t\t\t\t\t!this.#losses.has(slot) &&\n\t\t\t\t\tslot.browser.status === 'connected' &&\n\t\t\t\t\tthis.#closing === undefined &&\n\t\t\t\t\t!(isBrowserError(failure) && failure.code === 'DISCONNECTED')\n\t\t\t\t)\n\t\t\t\t\tthis.#fault(failure)\n\t\t\t})\n\t\t\tawait rm(directory, { recursive: true, force: true }).catch(this.#fault.bind(this))\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync #destroyRecord(slot: {\n\t\treadonly browser: BrowserInterface\n\t\treadonly profile: string\n\t}): Promise<void> {\n\t\t// A timed-out browser cannot answer context cleanup; kill before awaiting that cleanup.\n\t\tconst cause = this.#losses.get(slot)?.cause\n\t\tif (isBrowserError(cause) && cause.code === 'TIMEOUT' && slot.browser.pid !== undefined) {\n\t\t\ttry {\n\t\t\t\tprocess.kill(slot.browser.pid, 'SIGKILL')\n\t\t\t} catch (error) {\n\t\t\t\tif (!isError(error) || !('code' in error) || error.code !== 'ESRCH') this.#faults.add(error)\n\t\t\t}\n\t\t}\n\t\ttry {\n\t\t\tawait Promise.allSettled(this.#building.get(slot) ?? [])\n\t\t\tconst prepared = this.#prepared.get(slot)\n\t\t\tif (prepared !== undefined) this.#untrack(prepared)\n\t\t\tthis.#prepared.delete(slot)\n\t\t\tawait Promise.all(\n\t\t\t\t[...(this.#owned.get(slot) ?? [])].map((generation) => this.#clean(slot, generation)),\n\t\t\t)\n\t\t\tawait this.#destroySlot(slot.profile, slot.browser)\n\t\t\tthis.#owned.delete(slot)\n\t\t\tthis.#building.delete(slot)\n\t\t\tthis.#endings.get(slot)?.resolve()\n\t\t} catch (error) {\n\t\t\tthis.#endings.get(slot)?.reject(error)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t#fault(error: unknown): void {\n\t\tthis.#faults.add(error)\n\t}\n\n\tasync #warm(): Promise<{\n\t\treadonly browser: BrowserInterface\n\t\treadonly profile: string\n\t}> {\n\t\tif (this.#closing !== undefined) throw this.#ended()\n\t\tif (this.#stranded !== undefined)\n\t\t\tthrow new BrowserError(\n\t\t\t\tBROWSER_SERVER_TEARDOWN,\n\t\t\t\tisError(this.#stranded) ? this.#stranded.message : String(this.#stranded),\n\t\t\t\tisBrowserError(this.#stranded) ? this.#stranded.context : undefined,\n\t\t\t)\n\t\tconst profile = join(this.#root, '.profiles', formatBrowserLockEntry(process.pid, randomUUID()))\n\t\t// Without `recursive`, an existing directory refuses with `EEXIST`, so no two launches share one.\n\t\tlet browser: BrowserInterface | undefined\n\t\tlet slot:\n\t\t\t| {\n\t\t\t\t\treadonly browser: BrowserInterface\n\t\t\t\t\treadonly profile: string\n\t\t\t }\n\t\t\t| undefined\n\t\ttry {\n\t\t\tawait mkdir(profile)\n\t\t\tthis.#folders.add(profile)\n\t\t\tbrowser = this.#launcher({\n\t\t\t\theadless: this.#headless,\n\t\t\t\tprofile,\n\t\t\t\tcdp: { discover: false },\n\t\t\t\tsignal: this.#abort.signal,\n\t\t\t\t...(this.#executable === undefined ? {} : { executable: this.#executable }),\n\t\t\t\t...(this.#viewport === undefined ? {} : { viewport: this.#viewport }),\n\t\t\t\t...(process.platform === 'linux' && process.getuid?.() === 0\n\t\t\t\t\t? { args: ['--no-sandbox'] }\n\t\t\t\t\t: {}),\n\t\t\t})\n\t\t\tawait browser.connect()\n\t\t\tif (browser.pid !== undefined && browser.endpoint !== undefined) {\n\t\t\t\tconst record = join(profile, BROWSER_SERVER_RECORD)\n\t\t\t\tawait writeFile(\n\t\t\t\t\t`${record}.tmp`,\n\t\t\t\t\tJSON.stringify({ pid: browser.pid, endpoint: browser.endpoint }),\n\t\t\t\t)\n\t\t\t\tawait rename(`${record}.tmp`, record)\n\t\t\t}\n\t\t\tslot = { browser, profile }\n\t\t\tconst ending = Promise.withResolvers<void>()\n\t\t\tvoid ending.promise.catch(() => undefined)\n\t\t\tthis.#endings.set(slot, ending)\n\t\t\tconst generation = await this.#build(slot)\n\t\t\tthis.#prepared.set(slot, generation)\n\t\t\tthis.#observe(slot, generation)\n\t\t\treturn slot\n\t\t} catch (error) {\n\t\t\tif (this.#folders.has(profile))\n\t\t\t\tawait (\n\t\t\t\t\tslot === undefined ? this.#destroySlot(profile, browser) : this.#destroyRecord(slot)\n\t\t\t\t).catch((failure: unknown) => {\n\t\t\t\t\tthis.#stranded = failure\n\t\t\t\t})\n\t\t\tif (this.#closing === undefined)\n\t\t\t\tthis.#write(`browse: ${describeBrowserServerLoss(BROWSER_SERVER_LAUNCH, error)}`)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync #destroySlot(profile: string, browser?: BrowserInterface): Promise<void> {\n\t\ttry {\n\t\t\tawait browser?.destroy()\n\t\t} catch (error) {\n\t\t\tif (this.#closing === undefined)\n\t\t\t\tthis.#write(`browse: ${describeBrowserServerLoss(BROWSER_SERVER_TEARDOWN, error)}`)\n\t\t\tthrow error\n\t\t}\n\t\ttry {\n\t\t\tawait rm(profile, { recursive: true, force: true, maxRetries: 5 })\n\t\t\tthis.#folders.delete(profile)\n\t\t} catch {\n\t\t\t// The shutdown recheck retries this folder; only its persistent failure reaches destroy.\n\t\t}\n\t}\n\n\tasync #sweep(): Promise<void> {\n\t\tconst profiles = join(this.#root, '.profiles')\n\t\ttry {\n\t\t\tfor (const entry of await readdir(profiles)) {\n\t\t\t\tif (this.#closing !== undefined) return\n\t\t\t\tconst pid = parseBrowserLockEntry(entry)\n\t\t\t\tif (pid === undefined || pid === process.pid || probeProcess(pid)) continue\n\t\t\t\tconst folder = join(profiles, entry)\n\t\t\t\tthis.#folders.add(folder)\n\t\t\t\ttry {\n\t\t\t\t\tconst record = parseBrowserProfileRecord(\n\t\t\t\t\t\tawait readFile(join(folder, BROWSER_SERVER_RECORD), 'utf8'),\n\t\t\t\t\t)\n\t\t\t\t\tif (record === undefined) continue\n\t\t\t\t\tif (probeProcess(record.pid)) {\n\t\t\t\t\t\tconst transport = createWebSocketCDPTransport({ url: record.endpoint })\n\t\t\t\t\t\tconst client = createCDPClient({ transport })\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// A file read can finish after shutdown; do not start an unobserved connection.\n\t\t\t\t\t\t\tthis.#abort.signal.throwIfAborted()\n\t\t\t\t\t\t\tawait this.#race(client.connect(), this.#abort.signal)\n\t\t\t\t\t\t\tawait client.send('Browser.close', undefined, { signal: this.#abort.signal })\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// A dead peer can close without acknowledging, and a live peer can refuse.\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t// Client close waits for connect; close the owned transport to end a held upgrade.\n\t\t\t\t\t\t\tawait transport.close()\n\t\t\t\t\t\t\tawait client.close()\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (probeProcess(record.pid)) continue\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!isError(error) || !('code' in error) || error.code !== 'ENOENT') continue\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tawait rm(folder, { recursive: true, force: true, maxRetries: 5 })\n\t\t\t\t\tthis.#folders.delete(folder)\n\t\t\t\t} catch {\n\t\t\t\t\t/* The shutdown recheck owns a later removal attempt. */\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.#write(`browse: ${describeBrowserServerLoss(BROWSER_SERVER_SWEEP, error)}`)\n\t\t}\n\t}\n\n\t#write(line: string): void {\n\t\ttry {\n\t\t\tthis.#log.write(`${line}\\n`, (error?: Error | null) => {\n\t\t\t\tif (error !== undefined && error !== null) this.#faults.add(error)\n\t\t\t})\n\t\t} catch (error) {\n\t\t\tthis.#faults.add(error)\n\t\t}\n\t}\n\n\t#exhaust(error: unknown): void {\n\t\tif (isPoolError(error) && error.code === 'create')\n\t\t\tthis.#write(\n\t\t\t\t`browse: ${describeBrowserServerLoss(BROWSER_SERVER_EXHAUSTED, error.cause ?? this.#failure)}`,\n\t\t\t)\n\t}\n\n\t#unavailable(cause: unknown): BrowserError {\n\t\tconst message = describeBrowserServerLoss(BROWSER_SERVER_UNAVAILABLE, cause)\n\t\treturn new BrowserError(\n\t\t\tBROWSER_SERVER_UNAVAILABLE,\n\t\t\tmessage.slice(BROWSER_SERVER_UNAVAILABLE.length + 2),\n\t\t)\n\t}\n\n\t#issue(): string {\n\t\treturn `e${++this.#references}`\n\t}\n\n\t// Adds a dispatcher for a tool the toolset's manager added under a name outside the vocabulary.\n\t#mirror(\n\t\tlease: {\n\t\t\treadonly token: PoolToken<{\n\t\t\t\treadonly browser: BrowserInterface\n\t\t\t\treadonly profile: string\n\t\t\t}>\n\t\t\treadonly generation: {\n\t\t\t\treadonly context: BrowserContextInterface\n\t\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\t\treadonly directory: string\n\t\t\t}\n\t\t},\n\t\ttool: ToolInterface,\n\t): void {\n\t\tif (this.#leases.get(this.#shared) !== lease || this.#vocabulary.has(tool.name)) return\n\t\tthis.#tools.add(\n\t\t\tcreateTool({\n\t\t\t\t...toolToDefinition(tool),\n\t\t\t\texecute: this.#forward.bind(this, this.#shared, tool.name),\n\t\t\t}),\n\t\t)\n\t}\n\n\t// Removes the dispatcher of a withdrawn tool; a replacement publishes `remove` while it is\n\t// installed, so the mirror follows the manager's current tool rather than the event.\n\t#withdraw(\n\t\tlease: {\n\t\t\treadonly token: PoolToken<{\n\t\t\t\treadonly browser: BrowserInterface\n\t\t\t\treadonly profile: string\n\t\t\t}>\n\t\t\treadonly generation: {\n\t\t\t\treadonly context: BrowserContextInterface\n\t\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\t\treadonly directory: string\n\t\t\t}\n\t\t},\n\t\ttool: ToolInterface,\n\t): void {\n\t\tif (this.#leases.get(this.#shared) !== lease || this.#vocabulary.has(tool.name)) return\n\t\tconst current = lease.generation.toolset.tools.tool(tool.name)\n\t\tif (current === undefined) this.#tools.remove(tool.name)\n\t\telse this.#mirror(lease, current)\n\t}\n\n\t#clear(\n\t\tlease: {\n\t\t\treadonly token: PoolToken<{\n\t\t\t\treadonly browser: BrowserInterface\n\t\t\t\treadonly profile: string\n\t\t\t}>\n\t\t\treadonly generation: {\n\t\t\t\treadonly context: BrowserContextInterface\n\t\t\t\treadonly toolset: BrowserToolsetInterface\n\t\t\t\treadonly directory: string\n\t\t\t}\n\t\t},\n\t\ttools: readonly ToolInterface[],\n\t): void {\n\t\tfor (const tool of tools) this.#withdraw(lease, tool)\n\t}\n\n\t#unmirror(): void {\n\t\tconst mirrored = this.#mirrored\n\t\tif (mirrored === undefined) return\n\t\tthis.#mirrored = undefined\n\t\tconst tools = mirrored.lease.generation.toolset.tools\n\t\tfor (const tool of tools.tools())\n\t\t\tif (!this.#vocabulary.has(tool.name)) this.#tools.remove(tool.name)\n\t\ttools.emitter.off('add', mirrored.added)\n\t\ttools.emitter.off('remove', mirrored.removed)\n\t\ttools.emitter.off('clear', mirrored.cleared)\n\t}\n\n\t#ended(): BrowserError {\n\t\treturn new BrowserError('CLOSED', 'the browser session ended', { subject: 'toolset' })\n\t}\n}\n","import type { BrowserStoreOptions, BrowserStorePage, BrowserStoreFault } from '@src/core'\nimport type { FileBrowserStoreOptions } from '../types.js'\nimport { realpathSync } from 'node:fs'\nimport { lstat, mkdir, open, readFile, readdir, rename, rmdir, unlink } from 'node:fs/promises'\nimport { dirname, relative, resolve, sep } from 'node:path'\nimport { randomUUID } from 'node:crypto'\nimport {\n\tBrowserError,\n\tBROWSER_JOURNEY_NAME_PATTERN,\n\tBROWSER_RUN_ID_PATTERN,\n\tvalidateBrowserStorePage,\n} from '@src/core'\nimport { BROWSER_FILE_STORE_LIMIT, BROWSER_JOURNEY_LOCK_ATTEMPTS } from '../constants.js'\nimport { formatBrowserLockEntry, parseBrowserLockEntry, probeProcess } from '../helpers.js'\n\n/**\n * Shares confined filesystem operations between the journey and run stores.\n * @remarks Requires an existing root directory. Links present during a component check are refused;\n * replacement between a check and its use by another filesystem writer is outside this boundary.\n * @example\n * const files = new FileBrowserStore({ root: directory })\n * files.validateName('check-ready')\n */\nexport class FileBrowserStore {\n\tstatic readonly #locks: Map<string, Promise<void>> = new Map()\n\treadonly #root: string\n\treadonly #limit: number\n\n\tconstructor(options: FileBrowserStoreOptions) {\n\t\tthis.#limit = options.limit ?? BROWSER_FILE_STORE_LIMIT\n\t\tif (!Number.isSafeInteger(this.#limit) || this.#limit < 1)\n\t\t\tthrow new BrowserError('ARGUMENT', 'The listing cap must be a positive integer', {\n\t\t\t\tsubject: 'store',\n\t\t\t})\n\t\ttry {\n\t\t\tthis.#root = realpathSync(options.root)\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && 'code' in error && error.code === 'ENOENT')\n\t\t\t\tthrow new BrowserError('STORE_PATH', `Missing root: ${options.root}`, {\n\t\t\t\t\tpath: options.root,\n\t\t\t\t})\n\t\t\tthrow this.translateError(options.root, error)\n\t\t}\n\t}\n\n\t/** Checks a journey name before filesystem access. @param name - Journey name */\n\tvalidateName(name: string): void {\n\t\tif (!BROWSER_JOURNEY_NAME_PATTERN.test(name))\n\t\t\tthrow new BrowserError('STORE_PATH', `Refused journey name: ${name}`)\n\t}\n\n\t/** Checks a run id before filesystem access. @param id - Producer id */\n\tvalidateId(id: string): void {\n\t\tif (!BROWSER_RUN_ID_PATTERN.test(id))\n\t\t\tthrow new BrowserError('STORE_PATH', `Refused run id: ${id}`)\n\t}\n\n\t/** Resolves a confined target. @param parts - Relative components @returns Absolute target */\n\tresolvePath(...parts: readonly string[]): string {\n\t\tconst path = resolve(this.#root, ...parts)\n\t\tif (\n\t\t\tpath !== this.#root &&\n\t\t\t!path.startsWith(this.#root.endsWith(sep) ? this.#root : this.#root + sep)\n\t\t)\n\t\t\tthrow new BrowserError('STORE_PATH', `Refused path: ${path}`)\n\t\treturn path\n\t}\n\n\t/**\n\t * Checks every existing component including the root and target.\n\t * @param path - Absolute target\n\t * @param options - Cancellation options\n\t * @returns True if the target exists; false if a component is missing\n\t */\n\tasync check(path: string, options?: BrowserStoreOptions): Promise<boolean> {\n\t\tthis.resolvePath(path)\n\t\tlet current = this.#root\n\t\tconst parts = relative(this.#root, path).split(sep).filter(Boolean)\n\t\tfor (let index = 0; index <= parts.length; index += 1) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\ttry {\n\t\t\t\tconst status = await lstat(current)\n\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\tif (status.isSymbolicLink())\n\t\t\t\t\tthrow new BrowserError('STORE_PATH', `Refused symbolic link: ${current}`)\n\t\t\t\tif (index < parts.length && !status.isDirectory())\n\t\t\t\t\tthrow new BrowserError('STORE_PATH', `Not a directory: ${current}`)\n\t\t\t} catch (error) {\n\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\tif (error instanceof Error && 'code' in error && error.code === 'ENOENT') return false\n\t\t\t\tthrow this.translateError(current, error)\n\t\t\t}\n\t\t\tconst part = parts[index]\n\t\t\tif (part !== undefined) current = this.resolvePath(current, part)\n\t\t}\n\t\treturn true\n\t}\n\n\t/** Creates checked directories one component at a time. @param path - Directory @param options - Cancellation options */\n\tasync createDirectory(path: string, options?: BrowserStoreOptions): Promise<void> {\n\t\tif (await this.check(path, options)) return\n\t\tif (path === this.#root) throw new BrowserError('STORE_PATH', `Missing root: ${path}`)\n\t\tawait this.createDirectory(dirname(path), options)\n\t\toptions?.signal?.throwIfAborted()\n\t\ttry {\n\t\t\tawait mkdir(path)\n\t\t} catch (error) {\n\t\t\tif (!(error instanceof Error && 'code' in error && error.code === 'EEXIST'))\n\t\t\t\tthrow this.translateError(path, error)\n\t\t}\n\t\tawait this.check(path, options)\n\t}\n\n\t/** Reads an existing file without collapsing a fault to absence. @param path - File @param options - Cancellation options @returns Bytes as UTF-8, or absence */\n\tasync read(path: string, options?: BrowserStoreOptions): Promise<string | undefined> {\n\t\tif (!(await this.check(path, options))) return undefined\n\t\ttry {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tconst value = await readFile(path, { encoding: 'utf8', signal: options?.signal })\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\treturn value\n\t\t} catch (error) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tif (error instanceof Error && 'code' in error && error.code === 'ENOENT') return undefined\n\t\t\tthrow this.translateError(path, error)\n\t\t}\n\t}\n\n\t/** Atomically replaces a file and cleans its owned temporary file on failure. @param path - Destination @param value - Bytes or UTF-8 @param options - Cancellation options */\n\tasync write(\n\t\tpath: string,\n\t\tvalue: string | Uint8Array,\n\t\toptions?: BrowserStoreOptions,\n\t): Promise<void> {\n\t\tconst temporary = this.resolvePath(dirname(path), `.${randomUUID()}.tmp`)\n\t\tlet owned = false\n\t\ttry {\n\t\t\tawait this.check(path, options)\n\t\t\tawait this.check(temporary, options)\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tconst file = await open(temporary, 'wx')\n\t\t\towned = true\n\t\t\ttry {\n\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\tawait file.writeFile(value, { signal: options?.signal })\n\t\t\t} finally {\n\t\t\t\tawait file.close()\n\t\t\t}\n\t\t\tawait this.check(path, options)\n\t\t\tawait this.check(temporary, options)\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\ttry {\n\t\t\t\tawait rename(temporary, path)\n\t\t\t} catch (error) {\n\t\t\t\t// A file cannot replace a directory: hosts report EISDIR or EPERM.\n\t\t\t\tconst target = await lstat(path).catch(() => undefined)\n\t\t\t\tif (\n\t\t\t\t\terror instanceof Error &&\n\t\t\t\t\t'code' in error &&\n\t\t\t\t\t(error.code === 'EISDIR' || error.code === 'EPERM') &&\n\t\t\t\t\ttarget?.isDirectory()\n\t\t\t\t)\n\t\t\t\t\tthrow new BrowserError('STORE_FILE', `Cannot replace directory: ${path}`, {\n\t\t\t\t\t\tpath,\n\t\t\t\t\t})\n\t\t\t\tthrow error\n\t\t\t}\n\t\t\towned = false\n\t\t} catch (error) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tthrow this.translateError(path, error)\n\t\t} finally {\n\t\t\tif (owned) await this.remove(temporary)\n\t\t}\n\t}\n\n\t/** Removes a checked file, accepting absence. @param path - File @param options - Cancellation options */\n\tasync remove(path: string, options?: BrowserStoreOptions): Promise<void> {\n\t\tif (!(await this.check(path, options))) return\n\t\ttry {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tawait unlink(path)\n\t\t} catch (error) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tif (!(error instanceof Error && 'code' in error && error.code === 'ENOENT'))\n\t\t\t\tthrow this.translateError(path, error)\n\t\t}\n\t}\n\n\t/**\n\t * Holds a directory lock through a mutation and releases only its named entry.\n\t * @remarks Reclaims dead or empty locks within a bounded attempt count; a live or unknown holder refuses.\n\t * @param path - Lock directory\n\t * @param action - Mutation inside the lock\n\t * @param options - Cancellation options\n\t * @returns The mutation result\n\t */\n\tasync lock<T>(path: string, action: () => Promise<T>, options?: BrowserStoreOptions): Promise<T> {\n\t\tconst key = this.resolvePath(path)\n\t\tconst previous = FileBrowserStore.#locks.get(key)\n\t\tconst released = Promise.withResolvers<void>()\n\t\tFileBrowserStore.#locks.set(key, released.promise)\n\t\ttry {\n\t\t\tawait previous\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\treturn await this.#lockFile(key, action, options)\n\t\t} finally {\n\t\t\treleased.resolve()\n\t\t\tif (FileBrowserStore.#locks.get(key) === released.promise) FileBrowserStore.#locks.delete(key)\n\t\t}\n\t}\n\n\tasync #lockFile<T>(\n\t\tpath: string,\n\t\taction: () => Promise<T>,\n\t\toptions?: BrowserStoreOptions,\n\t): Promise<T> {\n\t\tawait this.createDirectory(dirname(path), options)\n\t\tconst name = formatBrowserLockEntry(process.pid, randomUUID())\n\t\tconst entry = this.resolvePath(path, name)\n\t\tfor (let attempt = 0; attempt < BROWSER_JOURNEY_LOCK_ATTEMPTS; attempt += 1) {\n\t\t\tawait this.check(path, options)\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\ttry {\n\t\t\t\tawait mkdir(path)\n\t\t\t} catch (error) {\n\t\t\t\tif (!(error instanceof Error && 'code' in error && error.code === 'EEXIST'))\n\t\t\t\t\tthrow this.translateError(path, error)\n\t\t\t\tconst entries = await this.#readLock(path, options)\n\t\t\t\tif (entries === undefined) continue\n\t\t\t\tif (entries.length > 1) break\n\t\t\t\tconst holder = entries[0]\n\t\t\t\tif (holder !== undefined) {\n\t\t\t\t\tconst pid = parseBrowserLockEntry(holder)\n\t\t\t\t\tif (pid === undefined || probeProcess(pid)) break\n\t\t\t\t\tif (!(await this.#unlinkLock(this.resolvePath(path, holder)))) continue\n\t\t\t\t}\n\t\t\t\tawait this.#removeLock(path)\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tlet owned = false\n\t\t\ttry {\n\t\t\t\tawait this.check(entry, options)\n\t\t\t\ttry {\n\t\t\t\t\tconst file = await open(entry, 'wx')\n\t\t\t\t\towned = true\n\t\t\t\t\tawait file.close()\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (error instanceof Error && 'code' in error && error.code === 'ENOENT') continue\n\t\t\t\t\tthrow this.translateError(entry, error)\n\t\t\t\t}\n\t\t\t\t// An empty directory can be replaced between mkdir and entry creation.\n\t\t\t\tconst entries = await this.#readLock(path, options)\n\t\t\t\tif (entries?.length !== 1 || entries[0] !== name) break\n\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\treturn await action()\n\t\t\t} finally {\n\t\t\t\tif (owned) await this.#unlinkLock(entry)\n\t\t\t\tawait this.#removeLock(path)\n\t\t\t}\n\t\t}\n\t\tthrow new BrowserError('STORE_LOCKED', `Journey is locked: ${path}`)\n\t}\n\n\t/**\n\t * Lists readable entries in sorted order with a bounded page and one extra readable probe.\n\t * @param path - Parent directory\n\t * @param reader - Entry reader\n\t * @param options - Paging and cancellation\n\t * @returns Page and observed entry faults\n\t */\n\tasync list<T>(\n\t\tpath: string,\n\t\treader: (name: string) => Promise<T | undefined>,\n\t\toptions?: BrowserStoreOptions & { readonly offset?: number; readonly limit?: number },\n\t): Promise<BrowserStorePage<T>> {\n\t\tconst offset = options?.offset ?? 0\n\t\tconst requested = options?.limit ?? this.#limit\n\t\tvalidateBrowserStorePage(offset, requested)\n\t\tconst limit = Math.min(requested, this.#limit)\n\t\tconst entries: T[] = []\n\t\tconst faults: BrowserStoreFault[] = []\n\t\tif (!(await this.check(path, options))) return { entries, faults, truncated: false }\n\t\tlet names: string[]\n\t\ttry {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tnames = (await readdir(path)).sort()\n\t\t} catch (error) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tthrow this.translateError(path, error)\n\t\t}\n\t\tlet count = 0\n\t\tfor (const name of names) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\ttry {\n\t\t\t\tconst entry = await reader(name)\n\t\t\t\tif (entry === undefined) continue\n\t\t\t\tif (count++ < offset) continue\n\t\t\t\tif (entries.length === limit) return { entries, faults, truncated: true }\n\t\t\t\tentries.push(entry)\n\t\t\t} catch (error) {\n\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\tconst reason = error instanceof BrowserError ? error.context?.['reason'] : undefined\n\t\t\t\tfaults.push({\n\t\t\t\t\tname,\n\t\t\t\t\treason:\n\t\t\t\t\t\ttypeof reason === 'string'\n\t\t\t\t\t\t\t? reason\n\t\t\t\t\t\t\t: error instanceof BrowserError && error.code === 'STORE_PATH'\n\t\t\t\t\t\t\t\t? 'The entry path is refused'\n\t\t\t\t\t\t\t\t: error instanceof BrowserError && error.code === 'STORE_ACCESS'\n\t\t\t\t\t\t\t\t\t? 'Permission denied'\n\t\t\t\t\t\t\t\t\t: error instanceof BrowserError && error.code === 'STORE_FORMAT'\n\t\t\t\t\t\t\t\t\t\t? 'Unknown file format'\n\t\t\t\t\t\t\t\t\t\t: 'The stored entry is malformed or unreadable',\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t\treturn { entries, faults, truncated: false }\n\t}\n\n\t/**\n\t * Allocates a run directory exclusively, retrying colliding producer candidates.\n\t * @param parent - Checked parent directory\n\t * @param candidate - Producer id source\n\t * @param options - Cancellation options\n\t * @returns Allocated id and absolute directory\n\t */\n\tasync allocate(\n\t\tparent: string,\n\t\tcandidate: () => string,\n\t\toptions?: BrowserStoreOptions,\n\t): Promise<{ readonly id: string; readonly path: string }> {\n\t\tawait this.createDirectory(parent, options)\n\t\tfor (;;) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tconst id = candidate()\n\t\t\tthis.validateId(id)\n\t\t\tconst path = this.resolvePath(parent, id)\n\t\t\tawait this.check(path, options)\n\t\t\ttry {\n\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\tawait mkdir(path)\n\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\treturn { id, path }\n\t\t\t} catch (error) {\n\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\tif (error instanceof Error && 'code' in error && error.code === 'EEXIST') continue\n\t\t\t\tthrow this.translateError(path, error)\n\t\t\t}\n\t\t}\n\t}\n\n\t/** Translates filesystem and validation failures with their path. @param path - Failed path @param error - Cause @returns Coded error */\n\ttranslateError(path: string, error: unknown): BrowserError {\n\t\tconst code = error instanceof Error && 'code' in error ? error.code : undefined\n\t\treturn new BrowserError(\n\t\t\tcode === 'EACCES' || code === 'EPERM'\n\t\t\t\t? 'STORE_ACCESS'\n\t\t\t\t: error instanceof BrowserError && code !== 'JOURNEY_INVALID'\n\t\t\t\t\t? error.code\n\t\t\t\t\t: 'STORE_FILE',\n\t\t\t`${path}: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t{ path },\n\t\t)\n\t}\n\tasync #readLock(\n\t\tpath: string,\n\t\toptions?: BrowserStoreOptions,\n\t): Promise<readonly string[] | undefined> {\n\t\tawait this.check(path, options)\n\t\ttry {\n\t\t\tconst entries = await readdir(path, { withFileTypes: true })\n\t\t\tfor (const entry of entries) {\n\t\t\t\tawait this.check(this.resolvePath(path, entry.name), options)\n\t\t\t\tif (!entry.isFile()) throw new BrowserError('STORE_LOCKED', `Journey is locked: ${path}`)\n\t\t\t}\n\t\t\treturn entries.map((entry) => entry.name)\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && 'code' in error) {\n\t\t\t\tif (error.code === 'ENOENT') return undefined\n\t\t\t\tif (error.code === 'ENOTDIR')\n\t\t\t\t\tthrow new BrowserError('STORE_LOCKED', `Journey is locked: ${path}`)\n\t\t\t}\n\t\t\tthrow this.translateError(path, error)\n\t\t}\n\t}\n\n\tasync #unlinkLock(path: string): Promise<boolean> {\n\t\tawait this.check(path)\n\t\ttry {\n\t\t\tawait unlink(path)\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\tif (\n\t\t\t\terror instanceof Error &&\n\t\t\t\t'code' in error &&\n\t\t\t\t(error.code === 'ENOENT' || error.code === 'ENOTEMPTY')\n\t\t\t)\n\t\t\t\treturn false\n\t\t\tthrow new BrowserError('STORE_ACCESS', `Cannot remove lock entry: ${path}`, {\n\t\t\t\tpath,\n\t\t\t})\n\t\t}\n\t}\n\n\tasync #removeLock(path: string): Promise<void> {\n\t\tawait this.check(path)\n\t\ttry {\n\t\t\tawait rmdir(path)\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && 'code' in error) {\n\t\t\t\tif (error.code === 'ENOTEMPTY') return\n\t\t\t\tif (error.code === 'ENOENT' || error.code === 'EPERM') {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tif ((await lstat(path)).isDirectory()) return\n\t\t\t\t\t} catch (cause) {\n\t\t\t\t\t\tif (cause instanceof Error && 'code' in cause && cause.code === 'ENOENT') return\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow new BrowserError('STORE_ACCESS', `Cannot remove lock directory: ${path}`, {\n\t\t\t\tpath,\n\t\t\t})\n\t\t}\n\t}\n}\n","import type {\n\tBrowserJourney,\n\tBrowserJourneyRevision,\n\tBrowserJourneyStoreInterface,\n\tBrowserStoreOptions,\n\tBrowserStorePageOptions,\n\tBrowserJourneyWriteOptions,\n\tBrowserStorePage,\n} from '@src/core'\nimport type { FileBrowserStoreOptions } from '../types.js'\nimport { isRecord, parseJSON } from '@orkestrel/contract'\nimport {\n\tBROWSER_JOURNEY_NAME_PATTERN,\n\tBrowserError,\n\tvalidateBrowserJourney,\n\tvalidateBrowserJourneyWriteOptions,\n\tnormalizeBrowserJourneyReason,\n} from '@src/core'\nimport {\n\tBROWSER_JOURNEY_SNAPSHOT_FILE,\n\tBROWSER_JOURNEY_REVISION_FILE,\n\tBROWSER_JOURNEY_LOCK_DIRECTORY,\n} from '../constants.js'\nimport { FileBrowserStore } from './FileBrowserStore.js'\n\n/**\n * Persists journeys with exclusive writes and revision counters retained across deletion.\n * @remarks Requires an existing root. A live holder refuses immediately; dead or empty locks are reclaimed within a bounded attempt count.\n * @example\n * const store = new FileBrowserJourneyStore({ root: directory })\n * await store.set(journey)\n */\nexport class FileBrowserJourneyStore implements BrowserJourneyStoreInterface {\n\treadonly #files: FileBrowserStore\n\n\tconstructor(options: FileBrowserStoreOptions) {\n\t\tthis.#files = new FileBrowserStore(options)\n\t}\n\n\tasync get(\n\t\tname: string,\n\t\toptions?: BrowserStoreOptions,\n\t): Promise<BrowserJourneyRevision | undefined> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tthis.#files.validateName(name)\n\t\tconst path = this.#files.resolvePath(name, BROWSER_JOURNEY_SNAPSHOT_FILE)\n\t\tconst source = await this.#files.read(path, options)\n\t\tif (source === undefined) return undefined\n\t\ttry {\n\t\t\tconst value = parseJSON(source)\n\t\t\tif (\n\t\t\t\t!isRecord(value) ||\n\t\t\t\ttypeof value['revision'] !== 'number' ||\n\t\t\t\t!Number.isSafeInteger(value['revision']) ||\n\t\t\t\tvalue['revision'] < 1\n\t\t\t)\n\t\t\t\tthrow new BrowserError('STORE_FILE', 'Malformed journey revision')\n\t\t\tif (!isRecord(value['journey']) || !('format' in value['journey']))\n\t\t\t\tthrow new BrowserError('STORE_FILE', 'Missing journey format')\n\t\t\tvalidateBrowserJourney(value['journey'])\n\t\t\tif (value['journey'].name !== name)\n\t\t\t\tthrow new BrowserError('STORE_FILE', 'Journey name differs from its directory')\n\t\t\treturn { journey: value['journey'], revision: value['revision'] }\n\t\t} catch (error) {\n\t\t\tconst translated = this.#files.translateError(path, error)\n\t\t\tthrow new BrowserError(translated.code, translated.message, {\n\t\t\t\t...translated.context,\n\t\t\t\treason: normalizeBrowserJourneyReason(error),\n\t\t\t})\n\t\t}\n\t}\n\n\tasync set(\n\t\tjourney: BrowserJourney,\n\t\toptions?: BrowserJourneyWriteOptions,\n\t): Promise<BrowserJourneyRevision> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tvalidateBrowserJourneyWriteOptions(options)\n\t\tconst condition = { revision: options?.revision, exclusive: options?.exclusive }\n\t\tthis.#files.validateName(journey.name)\n\t\tvalidateBrowserJourney(journey)\n\t\tconst owned = structuredClone(journey)\n\t\tconst path = this.#files.resolvePath(owned.name, BROWSER_JOURNEY_SNAPSHOT_FILE)\n\t\tconst counter = this.#files.resolvePath(owned.name, BROWSER_JOURNEY_REVISION_FILE)\n\t\treturn this.#files.lock(\n\t\t\tthis.#files.resolvePath(owned.name, BROWSER_JOURNEY_LOCK_DIRECTORY),\n\t\t\tasync () => {\n\t\t\t\tconst current = await this.get(owned.name, options)\n\t\t\t\tif (\n\t\t\t\t\t(condition.exclusive === true && current !== undefined) ||\n\t\t\t\t\t(condition.revision !== undefined && condition.revision !== current?.revision)\n\t\t\t\t)\n\t\t\t\t\tthrow new BrowserError('JOURNEY_STALE', `Journey ${owned.name} changed since you read it`)\n\t\t\t\tconst source = await this.#files.read(counter, options)\n\t\t\t\tconst previous = source === undefined ? 0 : Number(source)\n\t\t\t\tif (!Number.isSafeInteger(previous) || previous < 0 || source?.trim() === '')\n\t\t\t\t\tthrow new BrowserError('STORE_FILE', `Malformed revision: ${counter}`)\n\t\t\t\tconst revision = Math.max(previous, current?.revision ?? 0) + 1\n\t\t\t\tif (!Number.isSafeInteger(revision))\n\t\t\t\t\tthrow new BrowserError('STORE_FILE', `Exhausted revision: ${counter}`)\n\t\t\t\tconst saved = { journey: owned, revision }\n\t\t\t\tawait this.#files.write(path, JSON.stringify(saved), options)\n\t\t\t\ttry {\n\t\t\t\t\tawait this.#files.write(counter, String(revision), options)\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Rollback and lock cleanup must finish even when the caller aborts.\n\t\t\t\t\tif (current === undefined) await this.#files.remove(path)\n\t\t\t\t\telse await this.#files.write(path, JSON.stringify(current))\n\t\t\t\t\tthrow error\n\t\t\t\t}\n\t\t\t\treturn saved\n\t\t\t},\n\t\t\toptions,\n\t\t)\n\t}\n\n\tasync delete(name: string, options?: BrowserStoreOptions): Promise<void> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tthis.#files.validateName(name)\n\t\tawait this.#files.lock(\n\t\t\tthis.#files.resolvePath(name, BROWSER_JOURNEY_LOCK_DIRECTORY),\n\t\t\tasync () => {\n\t\t\t\tconst current = await this.get(name, options)\n\t\t\t\tif (current === undefined) return\n\t\t\t\tconst counter = this.#files.resolvePath(name, BROWSER_JOURNEY_REVISION_FILE)\n\t\t\t\tconst source = await this.#files.read(counter, options)\n\t\t\t\tconst previous = source === undefined ? 0 : Number(source)\n\t\t\t\tif (!Number.isSafeInteger(previous) || previous < 0 || source?.trim() === '')\n\t\t\t\t\tthrow new BrowserError('STORE_FILE', `Malformed revision: ${counter}`)\n\t\t\t\t// Preserve the committed revision even if a process exited before updating its counter.\n\t\t\t\tawait this.#files.write(counter, String(Math.max(previous, current.revision ?? 0)), options)\n\t\t\t\tawait this.#files.remove(\n\t\t\t\t\tthis.#files.resolvePath(name, BROWSER_JOURNEY_SNAPSHOT_FILE),\n\t\t\t\t\toptions,\n\t\t\t\t)\n\t\t\t},\n\t\t\toptions,\n\t\t)\n\t}\n\n\tasync list(options?: BrowserStorePageOptions): Promise<BrowserStorePage<BrowserJourneyRevision>> {\n\t\toptions?.signal?.throwIfAborted()\n\t\treturn this.#files.list(\n\t\t\tthis.#files.resolvePath(),\n\t\t\tasync (name) => {\n\t\t\t\tif (!BROWSER_JOURNEY_NAME_PATTERN.test(name)) return undefined\n\t\t\t\treturn this.get(name, options)\n\t\t\t},\n\t\t\toptions,\n\t\t)\n\t}\n}\n","import type {\n\tBrowserRun,\n\tBrowserRunSlot,\n\tBrowserRunStoreInterface,\n\tBrowserStoreOptions,\n\tBrowserStorePageOptions,\n\tBrowserStorePage,\n} from '@src/core'\nimport type { FileBrowserStoreOptions } from '../types.js'\nimport { lstat, readdir, rm, writeFile } from 'node:fs/promises'\nimport { isRecord, parseJSON } from '@orkestrel/contract'\nimport {\n\tBROWSER_JOURNEY_FORMAT_VERSION,\n\tBrowserError,\n\tgenerateBrowserRunId,\n\tvalidateBrowserRun,\n} from '@src/core'\nimport {\n\tBROWSER_RUN_FILE,\n\tBROWSER_RUN_DIRECTORY,\n\tBROWSER_JOURNEY_LOCK_DIRECTORY,\n} from '../constants.js'\nimport { FileBrowserStore } from './FileBrowserStore.js'\n\n/**\n * Persists runs and captures only in directories allocated by this instance.\n * @remarks Requires an existing root. Reopened stores can read and delete saved runs.\n * Allocations of one journey share a process-local queue across instances; the filesystem lock\n * still refuses conflicting mutations and allocations from another process.\n * @example\n * const store = new FileBrowserRunStore({ root: directory })\n * const slot = await store.create('check-ready')\n */\nexport class FileBrowserRunStore implements BrowserRunStoreInterface {\n\tstatic readonly #allocations = new Map<string, Promise<void>>()\n\treadonly #files: FileBrowserStore\n\treadonly #slots = new WeakMap<BrowserRunSlot, string>()\n\treadonly #directories = new Set<string>()\n\n\tconstructor(options: FileBrowserStoreOptions) {\n\t\tthis.#files = new FileBrowserStore(options)\n\t}\n\n\tasync write(bytes: Uint8Array, options?: BrowserStoreOptions): Promise<string> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tconst owned = new Uint8Array(bytes)\n\t\tconst directory = await this.#files.allocate(\n\t\t\tthis.#files.resolvePath(BROWSER_RUN_DIRECTORY),\n\t\t\tgenerateBrowserRunId,\n\t\t\toptions,\n\t\t)\n\t\tconst path = this.#files.resolvePath(directory.path, 'view.png')\n\t\ttry {\n\t\t\tawait this.#files.check(path, options)\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tawait writeFile(path, owned, { flag: 'wx', signal: options?.signal })\n\t\t\treturn path\n\t\t} catch (error) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tthrow this.#files.translateError(path, error)\n\t\t}\n\t}\n\n\tasync create(name: string, options?: BrowserStoreOptions): Promise<BrowserRunSlot> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tthis.#files.validateName(name)\n\t\tconst path = this.#files.resolvePath(name, BROWSER_JOURNEY_LOCK_DIRECTORY)\n\t\tconst previous = FileBrowserRunStore.#allocations.get(path)\n\t\tconst allocation = Promise.withResolvers<void>()\n\t\tFileBrowserRunStore.#allocations.set(path, allocation.promise)\n\t\ttry {\n\t\t\tawait previous\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\treturn await this.#files.lock(\n\t\t\t\tpath,\n\t\t\t\tasync () => {\n\t\t\t\t\tconst directory = await this.#files.allocate(\n\t\t\t\t\t\tthis.#files.resolvePath(name, BROWSER_RUN_DIRECTORY),\n\t\t\t\t\t\tgenerateBrowserRunId,\n\t\t\t\t\t\toptions,\n\t\t\t\t\t)\n\t\t\t\t\tconst slot = Object.freeze({ id: directory.id, directory: directory.path })\n\t\t\t\t\tthis.#directories.add(directory.path)\n\t\t\t\t\tthis.#slots.set(slot, directory.path)\n\t\t\t\t\treturn slot\n\t\t\t\t},\n\t\t\t\toptions,\n\t\t\t)\n\t\t} finally {\n\t\t\tallocation.resolve()\n\t\t\tif (FileBrowserRunStore.#allocations.get(path) === allocation.promise)\n\t\t\t\tFileBrowserRunStore.#allocations.delete(path)\n\t\t}\n\t}\n\n\tasync get(\n\t\tname: string,\n\t\tid: string,\n\t\toptions?: BrowserStoreOptions,\n\t): Promise<BrowserRun | undefined> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tthis.#files.validateName(name)\n\t\tthis.#files.validateId(id)\n\t\tconst path = this.#files.resolvePath(name, BROWSER_RUN_DIRECTORY, id, BROWSER_RUN_FILE)\n\t\tconst source = await this.#files.read(path, options)\n\t\tif (source === undefined) return undefined\n\t\ttry {\n\t\t\tconst value = parseJSON(source)\n\t\t\tif (!isRecord(value) || !('format' in value))\n\t\t\t\tthrow new BrowserError('STORE_FILE', 'Missing run format')\n\t\t\tif (\n\t\t\t\tvalue['format'] === BROWSER_JOURNEY_FORMAT_VERSION &&\n\t\t\t\t(!isRecord(value['journey']) || !('format' in value['journey']))\n\t\t\t)\n\t\t\t\tthrow new BrowserError('STORE_FILE', 'Missing run journey format')\n\t\t\tvalidateBrowserRun(value)\n\t\t\tif (value.id !== id || value.journey.name !== name)\n\t\t\t\tthrow new BrowserError('STORE_FILE', 'Run identity differs from its directory')\n\t\t\treturn value\n\t\t} catch (error) {\n\t\t\tthrow this.#files.translateError(path, error)\n\t\t}\n\t}\n\n\tasync set(run: BrowserRun, options?: BrowserStoreOptions): Promise<void> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tthis.#files.validateName(run.journey.name)\n\t\tthis.#files.validateId(run.id)\n\t\tvalidateBrowserRun(run)\n\t\tconst source = JSON.stringify(run)\n\t\tconst directory = this.#files.resolvePath(run.journey.name, BROWSER_RUN_DIRECTORY, run.id)\n\t\tawait this.#requireDirectory(directory, options)\n\t\tawait this.#files.write(this.#files.resolvePath(directory, BROWSER_RUN_FILE), source, options)\n\t}\n\n\tasync capture(\n\t\tslot: BrowserRunSlot,\n\t\tname: string,\n\t\tbytes: Uint8Array,\n\t\toptions?: BrowserStoreOptions,\n\t): Promise<string> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tconst directory = this.#slots.get(slot)\n\t\tif (directory === undefined || !/^s[1-9]\\d*\\.png$/.test(name))\n\t\t\tthrow new BrowserError('STORE_PATH', 'Capture requires an opened slot and an sN.png name')\n\t\tconst owned = new Uint8Array(bytes)\n\t\tawait this.#requireDirectory(directory, options)\n\t\tawait this.#files.write(this.#files.resolvePath(directory, name), owned, options)\n\t\treturn name\n\t}\n\n\tasync delete(name: string, id: string, options?: BrowserStoreOptions): Promise<void> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tthis.#files.validateName(name)\n\t\tthis.#files.validateId(id)\n\t\tconst directory = this.#files.resolvePath(name, BROWSER_RUN_DIRECTORY, id)\n\t\tawait this.#files.check(this.#files.resolvePath(directory, BROWSER_RUN_FILE), options)\n\t\ttry {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tawait rm(directory, { recursive: true, force: true, maxRetries: 3 })\n\t\t\tthis.#directories.delete(directory)\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t} catch (error) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tthrow this.#files.translateError(directory, error)\n\t\t}\n\t}\n\n\tasync clear(name: string, options?: BrowserStoreOptions): Promise<number> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tthis.#files.validateName(name)\n\t\tconst parent = this.#files.resolvePath(name, BROWSER_RUN_DIRECTORY)\n\t\tif (!(await this.#files.check(parent, options))) return 0\n\t\treturn this.#files.lock(\n\t\t\tthis.#files.resolvePath(name, BROWSER_JOURNEY_LOCK_DIRECTORY),\n\t\t\tasync () => {\n\t\t\t\ttry {\n\t\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\t\tconst ids = await readdir(parent)\n\t\t\t\t\t// Check the whole removal before deleting any run, including unsaved slots.\n\t\t\t\t\tfor (const id of ids) {\n\t\t\t\t\t\tthis.#files.validateId(id)\n\t\t\t\t\t\tawait this.#files.check(this.#files.resolvePath(parent, id, BROWSER_RUN_FILE), options)\n\t\t\t\t\t}\n\t\t\t\t\tfor (const id of ids) await this.delete(name, id, options)\n\t\t\t\t\treturn ids.length\n\t\t\t\t} catch (error) {\n\t\t\t\t\toptions?.signal?.throwIfAborted()\n\t\t\t\t\tthrow this.#files.translateError(parent, error)\n\t\t\t\t}\n\t\t\t},\n\t\t\toptions,\n\t\t)\n\t}\n\n\tasync list(\n\t\tname: string,\n\t\toptions?: BrowserStorePageOptions,\n\t): Promise<BrowserStorePage<BrowserRun>> {\n\t\toptions?.signal?.throwIfAborted()\n\t\tthis.#files.validateName(name)\n\t\treturn this.#files.list(\n\t\t\tthis.#files.resolvePath(name, BROWSER_RUN_DIRECTORY),\n\t\t\t(id) => this.get(name, id, options),\n\t\t\toptions,\n\t\t)\n\t}\n\n\tasync #requireDirectory(directory: string, options?: BrowserStoreOptions): Promise<void> {\n\t\tif (!this.#directories.has(directory) || !(await this.#files.check(directory, options)))\n\t\t\tthrow new BrowserError(\n\t\t\t\t'STORE_PATH',\n\t\t\t\t`Run directory was not opened or is missing: ${directory}`,\n\t\t\t)\n\t\ttry {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tconst status = await lstat(directory)\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tif (!status.isDirectory())\n\t\t\t\tthrow new BrowserError('STORE_PATH', `Run directory is not a directory: ${directory}`)\n\t\t} catch (error) {\n\t\t\toptions?.signal?.throwIfAborted()\n\t\t\tthrow this.#files.translateError(directory, error)\n\t\t}\n\t}\n}\n","import type {\n\tBrowserJourneyStoreInterface,\n\tBrowserRunStoreInterface,\n\tCDPTransportInterface,\n\tBrowserWriterInterface,\n} from '@src/core'\nimport type {\n\tFileBrowserStoreOptions,\n\tBrowserInterface,\n\tBrowserMCPServerInterface,\n\tBrowserMCPServerOptions,\n\tBrowserOptions,\n\tWebSocketCDPTransportOptions,\n} from './types.js'\nimport { BrowserMCPServer } from './BrowserMCPServer.js'\nimport { FileBrowserJourneyStore } from './stores/FileBrowserJourneyStore.js'\nimport { FileBrowserRunStore } from './stores/FileBrowserRunStore.js'\nimport { Browser } from './Browser.js'\nimport { WebSocketCDPTransport } from './transports/WebSocketCDPTransport.js'\nimport { FileBrowserWriter } from './writers/FileBrowserWriter.js'\n\n/**\n * Creates a raw-CDP `BrowserInterface` façade with discovery, connection, and lifecycle\n * management.\n *\n * @param options - Connection, launch, and viewport configuration\n * @returns A {@link BrowserInterface}\n *\n * @example Connect to a browser and drive a page\n * ```ts\n * import { createBrowser } from '@orkestrel/browser/server'\n *\n * const browser = createBrowser({ headless: true })\n * await browser.connect() // CDP endpoint discovery → connect, else launch\n * const page = await browser.create({ url: 'https://example.com' })\n * await (await page.elements.find({ css: '#accept' }))[0]?.click()\n * const shot = await page.screenshot({ path: './out.png' })\n * await browser.destroy()\n * ```\n */\nexport function createBrowser(options?: BrowserOptions): BrowserInterface {\n\treturn new Browser(options)\n}\n\n/**\n * Creates a Node `WebSocket`-backed `CDPTransportInterface` for the given CDP debugger URL.\n *\n * @param options - The CDP WebSocket debugger URL (and optional timeout)\n * @returns A {@link CDPTransportInterface}\n */\nexport function createWebSocketCDPTransport(\n\toptions: WebSocketCDPTransportOptions,\n): CDPTransportInterface {\n\treturn new WebSocketCDPTransport(options)\n}\n\n/**\n * Creates a filesystem-backed `BrowserWriterInterface` that persists bytes through\n * `node:fs/promises`.\n *\n * @returns A {@link BrowserWriterInterface} that persists bytes through `node:fs/promises`\n */\nexport function createFileBrowserWriter(): BrowserWriterInterface {\n\treturn new FileBrowserWriter()\n}\n\n/**\n * Creates a journey store over an existing filesystem root.\n * @param options - Root and listing cap\n * @returns A durable journey store\n * @example\n * const store = createFileBrowserJourneyStore({ root: directory })\n */\nexport function createFileBrowserJourneyStore(\n\toptions: FileBrowserStoreOptions,\n): BrowserJourneyStoreInterface {\n\treturn new FileBrowserJourneyStore(options)\n}\n\n/**\n * Creates a run store over an existing filesystem root.\n * @param options - Root and listing cap\n * @returns A durable run and capture store\n * @example\n * const store = createFileBrowserRunStore({ root: directory })\n */\nexport function createFileBrowserRunStore(\n\toptions: FileBrowserStoreOptions,\n): BrowserRunStoreInterface {\n\treturn new FileBrowserRunStore(options)\n}\n\n/**\n * Creates the browse server, which serves the browser vocabulary and the journey tools over the\n * Model Context Protocol on stdio and warms Chromium at server start.\n *\n * @param options - The root, the launch, the journeys' read-only switch, and the streams\n * @returns A {@link BrowserMCPServerInterface} that reads nothing until `start()`\n *\n * @example\n * ```ts\n * import { createBrowserMCPServer } from '@orkestrel/browser/server'\n *\n * const server = createBrowserMCPServer({ root: 'tmp/browsers', browser: { headless: true } })\n * await server.start() // resolves after leasing a connected browser\n * await server.destroy()\n * ```\n */\nexport function createBrowserMCPServer(\n\toptions?: BrowserMCPServerOptions,\n): BrowserMCPServerInterface {\n\treturn new BrowserMCPServer(options)\n}\n","import type { ChildProcess } from 'node:child_process'\nimport type {\n\tBrowserConnection,\n\tBrowserDiscoveryResult,\n\tBrowserEngine,\n\tBrowserEventMap,\n\tBrowserInterface,\n\tBrowserOptions,\n\tBrowserProfileResult,\n\tBrowserStatus,\n} from './types.js'\nimport type {\n\tBrowserCallOptions,\n\tBrowserContextInterface,\n\tBrowserIsolateOptions,\n\tBrowserPageInterface,\n\tBrowserPageOptions,\n\tCDPTarget,\n\tCDPTransportInterface,\n} from '@src/core'\nimport type { EmitterInterface } from '@orkestrel/emitter'\nimport { addAbortListener, once } from 'node:events'\nimport { isArray, isError, isInteger, isRecord, isString, isJSONValue } from '@orkestrel/contract'\nimport { Emitter } from '@orkestrel/emitter'\nimport {\n\tBrowserContext,\n\tBrowserTransition,\n\tBROWSER_DEFAULT_TIMEOUT_MS,\n\tCDPClient,\n\tvalidateBrowserContextOptions,\n\tBrowserError,\n\tisBrowserError,\n} from '@src/core'\nimport {\n\tBROWSER_CDP_PROTOCOL,\n\tBROWSER_CDP_VERSION_PATH,\n\tBROWSER_DEFAULT_CDP_PORT,\n\tBROWSER_DEFAULT_HOST,\n\tBROWSER_DRAIN_INTERVAL_MS,\n\tBROWSER_KILL_GRACE_MS,\n\tBROWSER_PORT_PROBE_TIMEOUT_MS,\n\tBROWSER_PROCESS_EXIT_CAUSE,\n\tBROWSER_TRANSPORT_LOSS_CAUSE,\n\tBROWSER_TRANSPORT_LOSS_DEFER_MS,\n} from './constants.js'\nimport {\n\tbrowserToEngine,\n\tcreateBrowserProfile,\n\tfindSystemBrowsers,\n\tlaunchBrowserProcess,\n\tparseBrowserEngine,\n\treadBrowserEndpoint,\n\tremoveBrowserProfile,\n} from './helpers.js'\nimport { createWebSocketCDPTransport, createFileBrowserWriter } from './factories.js'\n\n// === Browser\n\n/**\n * Discovers, launches, connects to, and owns Chromium-family browser sessions.\n *\n * @example\n * ```ts\n * import { Browser } from '@orkestrel/browser/server'\n *\n * const browser = new Browser({ headless: true })\n * await browser.connect()\n * const page = await browser.create({ url: 'https://example.com' })\n * await browser.destroy()\n * ```\n */\nexport class Browser implements BrowserInterface {\n\treadonly #emitter: Emitter<BrowserEventMap>\n\treadonly #options: BrowserOptions\n\treadonly #abort = new AbortController()\n\treadonly #cdpPort: number\n\treadonly #cdpHost: string\n\t#engine: BrowserEngine\n\t#status: BrowserStatus = 'idle'\n\t#connection: BrowserConnection | undefined\n\t#owned: boolean | undefined\n\t#endpoint: string | undefined\n\t#client: CDPClient | undefined\n\t#process: ChildProcess | undefined\n\t// Identifier the launcher handed the endpoint to when it re-executed the\n\t// browser and exited before CDP became ready. Undefined whenever the\n\t// spawned child is itself the process serving the endpoint.\n\t#servingPid: number | undefined\n\t#profile: BrowserProfileResult | undefined\n\t#contexts: BrowserContext[] = []\n\treadonly #isolating = new Set<Promise<BrowserContextInterface>>()\n\t#destroyed = false\n\treadonly #connecting: BrowserTransition = new BrowserTransition()\n\treadonly #disconnecting: BrowserTransition = new BrowserTransition()\n\t#exitCleanup: Promise<void> | undefined\n\t#shutdown: Promise<void> | undefined\n\t#transport: CDPTransportInterface | undefined\n\treadonly #transportCloseHandler = this.#handleTransportLoss.bind(this)\n\treadonly #transportErrorHandler = this.#handleTransportLoss.bind(this)\n\treadonly #processExitHandler = this.#handleProcessExit.bind(this)\n\n\tconstructor(options?: BrowserOptions) {\n\t\tthis.#emitter = new Emitter({\n\t\t\t...(options?.on !== undefined ? { on: options.on } : {}),\n\t\t\t...(options?.error !== undefined ? { error: options.error } : {}),\n\t\t})\n\t\tthis.#options = options ?? {}\n\t\tthis.#engine =\n\t\t\tthis.#options.executable !== undefined\n\t\t\t\t? (parseBrowserEngine(this.#options.executable) ?? 'chromium')\n\t\t\t\t: (this.#options.browsers?.engine ?? 'chromium')\n\t\tthis.#cdpPort = this.#options.cdp?.port ?? BROWSER_DEFAULT_CDP_PORT\n\t\tthis.#cdpHost = this.#options.cdp?.host ?? BROWSER_DEFAULT_HOST\n\n\t\tqueueMicrotask(() => this.#emitter.emit('idle'))\n\t}\n\n\tget emitter(): EmitterInterface<BrowserEventMap> {\n\t\treturn this.#emitter\n\t}\n\n\tget engine(): BrowserEngine {\n\t\treturn this.#engine\n\t}\n\n\tget status(): BrowserStatus {\n\t\treturn this.#status\n\t}\n\n\tget connection(): BrowserConnection | undefined {\n\t\treturn this.#connection\n\t}\n\n\tget owned(): boolean | undefined {\n\t\treturn this.#owned\n\t}\n\n\tget pid(): number | undefined {\n\t\treturn this.#servingPid ?? this.#process?.pid\n\t}\n\n\tget endpoint(): string | undefined {\n\t\treturn this.#endpoint\n\t}\n\n\tasync ping(options?: BrowserCallOptions): Promise<void> {\n\t\tif (this.#destroyed)\n\t\t\tthrow new BrowserError('CLOSED', 'Browser has been destroyed', { subject: 'browser' })\n\t\tconst client = this.#client\n\t\tif (this.#status !== 'connected' || client === undefined) {\n\t\t\tthrow new BrowserError('DISCONNECTED', 'Browser is not connected')\n\t\t}\n\t\tawait client.send('Browser.getVersion', undefined, options)\n\t}\n\n\tasync discover(): Promise<BrowserDiscoveryResult> {\n\t\tconst result = await this.#discoverCDP()\n\t\tthis.#emitter.emit('discover', result)\n\t\treturn result\n\t}\n\n\tasync connect(): Promise<void> {\n\t\tif (this.#destroyed)\n\t\t\tthrow new BrowserError('CLOSED', 'Browser has been destroyed', { subject: 'browser' })\n\n\t\tconst active = this.#connecting.pending\n\t\tif (active !== undefined) {\n\t\t\tawait active\n\t\t\treturn\n\t\t}\n\t\tif (this.#status === 'connected') return\n\n\t\tawait this.#connecting.execute(() => this.#establish())\n\t}\n\n\tadopt(): void {\n\t\tif (this.#destroyed)\n\t\t\tthrow new BrowserError('CLOSED', 'Browser has been destroyed', { subject: 'browser' })\n\t\tif (\n\t\t\tthis.#status !== 'connected' ||\n\t\t\tthis.#client === undefined ||\n\t\t\tthis.#endpoint === undefined\n\t\t) {\n\t\t\tthrow new BrowserError('DISCONNECTED', 'Browser is not connected')\n\t\t}\n\t\tthis.#owned = true\n\t}\n\n\tasync disconnect(): Promise<void> {\n\t\tif (this.#destroyed) return\n\n\t\tconst disconnecting = this.#disconnecting.pending\n\t\tconst connecting = this.#connecting.pending\n\t\tif (disconnecting !== undefined) await disconnecting\n\t\tif (connecting !== undefined) await connecting.catch(() => undefined)\n\t\tif (this.#destroyed) return\n\t\tif (this.#status !== 'connected' || this.#client === undefined) return\n\n\t\tawait this.#disconnecting.execute(() => this.#detach())\n\t}\n\n\tcontext(index?: number): BrowserContextInterface | undefined {\n\t\tconst i = index ?? 0\n\t\tif (i < 0 || i >= this.#contexts.length) return undefined\n\t\treturn this.#contexts[i]\n\t}\n\n\tcontexts(): readonly BrowserContextInterface[] {\n\t\treturn [...this.#contexts]\n\t}\n\n\tasync isolate(options?: BrowserIsolateOptions): Promise<BrowserContextInterface> {\n\t\tconst attempt = this.#isolate(options)\n\t\tthis.#isolating.add(attempt)\n\t\ttry {\n\t\t\treturn await attempt\n\t\t} finally {\n\t\t\tthis.#isolating.delete(attempt)\n\t\t}\n\t}\n\n\tasync create(options?: BrowserPageOptions): Promise<BrowserPageInterface> {\n\t\tif (this.#destroyed)\n\t\t\tthrow new BrowserError('CLOSED', 'Browser has been destroyed', { subject: 'browser' })\n\t\tconst client = this.#client\n\t\tif (this.#status !== 'connected' || client === undefined) {\n\t\t\tthrow new BrowserError('DISCONNECTED', 'Browser is not connected')\n\t\t}\n\n\t\tlet context = this.#contexts[0]\n\t\tif (context === undefined) {\n\t\t\tcontext = new BrowserContext(client, {\n\t\t\t\t...(this.#options.viewport === undefined ? {} : { viewport: this.#options.viewport }),\n\t\t\t\twriter: createFileBrowserWriter(),\n\t\t\t})\n\t\t\tthis.#registerContext(context)\n\t\t}\n\n\t\tconst page = await context.create(options)\n\t\tthis.#emitter.emit('page', page)\n\t\treturn page\n\t}\n\n\tdestroy(): Promise<void> {\n\t\tconst active = this.#shutdown\n\t\tif (active !== undefined) return active\n\t\tif (this.#destroyed) return Promise.resolve()\n\n\t\tthis.#destroyed = true\n\t\tthis.#abort.abort()\n\t\tconst shutdown = this.#destroyResources()\n\t\tthis.#shutdown = shutdown\n\t\treturn shutdown\n\t}\n\n\tclose(): Promise<void> {\n\t\tconst active = this.#shutdown\n\t\tif (active !== undefined) return active\n\t\tif (this.#destroyed) return Promise.resolve()\n\n\t\tthis.#destroyed = true\n\t\tthis.#abort.abort()\n\t\tconst shutdown = this.#closeResources()\n\t\tthis.#shutdown = shutdown\n\t\treturn shutdown\n\t}\n\n\t// === Private helpers\n\n\tasync #isolate(options?: BrowserIsolateOptions): Promise<BrowserContextInterface> {\n\t\tif (this.#destroyed)\n\t\t\tthrow new BrowserError('CLOSED', 'Browser has been destroyed', { subject: 'browser' })\n\t\tconst client = this.#client\n\t\tif (this.#status !== 'connected' || client === undefined) {\n\t\t\tthrow new BrowserError('DISCONNECTED', 'Browser is not connected')\n\t\t}\n\t\tvalidateBrowserContextOptions(options)\n\t\tif (options !== undefined && 'id' in options && options.id !== undefined)\n\t\t\tthrow new BrowserError('ARGUMENT', 'An isolated context receives its id from the browser')\n\t\tconst params: Record<string, unknown> = { disposeOnDetach: false }\n\t\tif (options?.proxy !== undefined) {\n\t\t\tparams['proxyServer'] = options.proxy.server\n\t\t\tif (options.proxy.bypass !== undefined) {\n\t\t\t\tparams['proxyBypassList'] = options.proxy.bypass.join(',')\n\t\t\t}\n\t\t}\n\t\tif (options?.origins !== undefined) {\n\t\t\tparams['originsWithUniversalNetworkAccess'] = [...options.origins]\n\t\t}\n\t\tconst result = await client.send('Target.createBrowserContext', params)\n\t\tif (!isRecord(result) || !isString(result['browserContextId'])) {\n\t\t\tthrow new BrowserError('CONNECTION', 'Failed to create isolated browser context')\n\t\t}\n\t\tconst id = result['browserContextId']\n\t\tconst { proxy: _proxy, origins: _origins, ...defaults } = options ?? {}\n\t\tconst viewport = options?.viewport ?? options?.emulation?.viewport ?? this.#options.viewport\n\t\tconst context = new BrowserContext(client, {\n\t\t\t...defaults,\n\t\t\tid,\n\t\t\t...(viewport === undefined ? {} : { viewport }),\n\t\t\twriter: options?.writer ?? createFileBrowserWriter(),\n\t\t})\n\n\t\ttry {\n\t\t\tif (this.#destroyed || this.#client !== client)\n\t\t\t\tthrow new BrowserError('CLOSED', 'Browser has been destroyed', { subject: 'browser' })\n\t\t\tif (options?.downloads !== undefined) {\n\t\t\t\tawait client.send('Browser.setDownloadBehavior', {\n\t\t\t\t\tbehavior: options.downloads.named === true ? 'allowAndName' : 'allow',\n\t\t\t\t\tbrowserContextId: id,\n\t\t\t\t\tdownloadPath: options.downloads.path,\n\t\t\t\t\teventsEnabled: true,\n\t\t\t\t})\n\t\t\t}\n\t\t\tif (this.#destroyed || this.#client !== client)\n\t\t\t\tthrow new BrowserError('CLOSED', 'Browser has been destroyed', { subject: 'browser' })\n\t\t} catch (error) {\n\t\t\tawait context.close().catch(() => undefined)\n\t\t\tthrow error\n\t\t}\n\n\t\tthis.#registerContext(context)\n\t\treturn context\n\t}\n\n\tasync #establish(): Promise<void> {\n\t\tconst disconnecting = this.#disconnecting.pending\n\t\tif (disconnecting !== undefined) await disconnecting\n\t\tawait this.#settleExit()\n\t\tif (this.#destroyed)\n\t\t\tthrow new BrowserError('CLOSED', 'Browser has been destroyed', { subject: 'browser' })\n\t\tif (this.#status === 'connected') return\n\n\t\tthis.#assertNotAborted()\n\t\tthis.#status = 'connecting'\n\n\t\ttry {\n\t\t\tif (this.#owned === true && this.#endpoint !== undefined) {\n\t\t\t\tawait this.#connectCDP(this.#endpoint)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst endpoint = this.#options.cdp?.endpoint\n\t\t\tif (endpoint !== undefined) {\n\t\t\t\tawait this.#connectCDP(endpoint)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst discover = this.#options.cdp?.discover ?? true\n\t\t\tif (discover) {\n\t\t\t\tconst discovery = await this.#raceAbort(this.#discoverCDP(this.#signal()))\n\t\t\t\tif (discovery.endpoint !== undefined) {\n\t\t\t\t\tthis.#engine = browserToEngine(discovery.browser)\n\t\t\t\t\tawait this.#connectCDP(discovery.endpoint)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t} else if (this.#options.cdp?.port !== undefined) {\n\t\t\t\tawait this.#raceAbort(this.#assertPortFree())\n\t\t\t}\n\n\t\t\tthis.#assertNotAborted()\n\t\t\tawait this.#launch()\n\t\t} catch (error) {\n\t\t\tif (this.#destroyed)\n\t\t\t\tthrow new BrowserError('CLOSED', 'Browser has been destroyed', { subject: 'browser' })\n\n\t\t\tthis.#status = 'error'\n\t\t\tthis.#emitter.emit('error', error)\n\t\t\tif (isBrowserError(error) && error.code === 'CONNECTION') throw error\n\n\t\t\tconst message = isError(error) ? error.message : String(error)\n\t\t\tthrow new BrowserError(\n\t\t\t\t'CONNECTION',\n\t\t\t\tmessage,\n\t\t\t\tthis.#options.executable === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: { executable: this.#options.executable },\n\t\t\t)\n\t\t}\n\t}\n\n\tasync #detach(): Promise<void> {\n\t\tthis.#status = 'disconnected'\n\t\tthis.#connection = undefined\n\t\tthis.#unbindTransport()\n\n\t\tconst client = this.#client\n\t\tthis.#client = undefined\n\t\tawait this.#destroyContexts()\n\t\tthis.#contexts = []\n\n\t\tif (this.#owned !== true) {\n\t\t\tthis.#owned = undefined\n\t\t\tthis.#endpoint = undefined\n\t\t}\n\n\t\tawait this.#closeClient(client)\n\t\tif (this.#destroyed) return\n\n\t\tthis.#emitter.emit('disconnect')\n\t\tthis.#emitter.emit('idle')\n\t}\n\n\t#assertNotAborted(): void {\n\t\tif (this.#signal().aborted) throw new BrowserError('CONNECTION', 'Connection aborted')\n\t}\n\n\t#signal(): AbortSignal {\n\t\tconst external = this.#options.signal\n\t\treturn external === undefined\n\t\t\t? this.#abort.signal\n\t\t\t: AbortSignal.any([this.#abort.signal, external])\n\t}\n\n\tasync #raceAbort<T>(promise: Promise<T>): Promise<T> {\n\t\tconst signal = this.#signal()\n\t\tif (signal.aborted) throw new BrowserError('CONNECTION', 'Connection aborted')\n\n\t\tconst aborted = Promise.withResolvers<never>()\n\t\tconst listener = addAbortListener(signal, () => {\n\t\t\taborted.reject(new BrowserError('CONNECTION', 'Connection aborted'))\n\t\t})\n\n\t\ttry {\n\t\t\treturn await Promise.race([promise, aborted.promise])\n\t\t} finally {\n\t\t\tlistener[Symbol.dispose]()\n\t\t\tvoid promise.catch(() => undefined)\n\t\t}\n\t}\n\n\t#handleProcessExit(): void {\n\t\tif (this.#destroyed) return\n\n\t\tconst connected = this.#status === 'connected'\n\t\tconst client = this.#client\n\t\tconst contexts = this.#contexts\n\t\tconst process = this.#process\n\t\tthis.#unbindTransport()\n\t\tthis.#unbindProcess()\n\t\tthis.#process = undefined\n\t\tthis.#servingPid = undefined\n\t\tconst cleanup = this.#cleanupExitedProcess(process, contexts, client)\n\t\tthis.#exitCleanup = cleanup\n\t\tvoid cleanup.catch((error: unknown) => this.#emitter.emit('error', error))\n\t\tthis.#client = undefined\n\t\tthis.#contexts = []\n\t\tthis.#connection = undefined\n\t\tthis.#owned = undefined\n\t\tthis.#endpoint = undefined\n\t\tif (connected) this.#status = 'disconnected'\n\n\t\tthis.#emitter.emit(\n\t\t\t'error',\n\t\t\tnew BrowserError('CONNECTION', 'The browser process exited unexpectedly', {\n\t\t\t\tcause: BROWSER_PROCESS_EXIT_CAUSE,\n\t\t\t}),\n\t\t)\n\n\t\tif (connected) {\n\t\t\tthis.#emitter.emit('disconnect')\n\t\t\tthis.#emitter.emit('idle')\n\t\t}\n\t}\n\n\t#handleTransportLoss(): void {\n\t\tif (this.#destroyed || this.#status !== 'connected') return\n\n\t\tif (this.#process === undefined) {\n\t\t\tthis.#confirmTransportLoss()\n\t\t\treturn\n\t\t}\n\n\t\tif (!this.#alive()) {\n\t\t\tthis.#handleProcessExit()\n\t\t\treturn\n\t\t}\n\n\t\t// A spawned child that is already dead is diagnosed by its own `exit`\n\t\t// event, never by a probe here: Node sets `exitCode` in the same callback\n\t\t// that emits `exit`, and reports ESRCH from `ChildProcess.kill(0)` as a\n\t\t// `false` return rather than a throw, so no reading of the handle can see\n\t\t// the death before the event does. The defer only has to outlast the loop\n\t\t// turn that delivers it.\n\t\tsetTimeout(() => this.#confirmTransportLoss(), BROWSER_TRANSPORT_LOSS_DEFER_MS)\n\t}\n\n\t#confirmTransportLoss(): void {\n\t\tif (this.#destroyed || this.#status !== 'connected') return\n\n\t\tif (this.#process !== undefined && !this.#alive()) {\n\t\t\tthis.#handleProcessExit()\n\t\t\treturn\n\t\t}\n\n\t\tconst client = this.#client\n\t\tconst owned = this.#owned === true\n\t\tconst contexts = this.#contexts\n\t\tthis.#unbindTransport()\n\t\tthis.#client = undefined\n\t\tthis.#contexts = []\n\t\tthis.#connection = undefined\n\t\tthis.#status = 'disconnected'\n\n\t\tif (!owned) {\n\t\t\tthis.#owned = undefined\n\t\t\tthis.#endpoint = undefined\n\t\t}\n\n\t\tvoid this.#destroyContextList(contexts)\n\t\tvoid this.#closeClient(client)\n\t\tthis.#emitter.emit(\n\t\t\t'error',\n\t\t\tnew BrowserError('CONNECTION', 'The CDP transport connection was lost', {\n\t\t\t\tcause: BROWSER_TRANSPORT_LOSS_CAUSE,\n\t\t\t}),\n\t\t)\n\t\tthis.#emitter.emit('disconnect')\n\t\tthis.#emitter.emit('idle')\n\t}\n\n\t#bindTransport(transport: CDPTransportInterface): void {\n\t\tthis.#unbindTransport()\n\t\tthis.#transport = transport\n\t\ttransport.emitter.on('close', this.#transportCloseHandler)\n\t\ttransport.emitter.on('error', this.#transportErrorHandler)\n\t}\n\n\t#unbindTransport(): void {\n\t\tconst transport = this.#transport\n\t\tif (transport === undefined) return\n\t\ttransport.emitter.off('close', this.#transportCloseHandler)\n\t\ttransport.emitter.off('error', this.#transportErrorHandler)\n\t\tthis.#transport = undefined\n\t}\n\n\t#bindProcess(process: ChildProcess): void {\n\t\tthis.#unbindProcess()\n\t\t// A launcher that handed the endpoint on has already exited, and its exit\n\t\t// says nothing about the browser now serving CDP. That browser has no\n\t\t// child handle, so the transport reports its death.\n\t\tif (this.#servingPid !== undefined) return\n\t\tprocess.once('exit', this.#processExitHandler)\n\t\tif (process.exitCode !== null || process.signalCode !== null) {\n\t\t\tqueueMicrotask(this.#processExitHandler)\n\t\t}\n\t}\n\n\t#unbindProcess(): void {\n\t\tthis.#process?.off('exit', this.#processExitHandler)\n\t}\n\n\t#timeout(): number {\n\t\treturn this.#options.timeout ?? BROWSER_DEFAULT_TIMEOUT_MS\n\t}\n\n\tasync #discoverCDP(signal?: AbortSignal): Promise<BrowserDiscoveryResult> {\n\t\tconst url = `${BROWSER_CDP_PROTOCOL}://${this.#cdpHost}:${this.#cdpPort}${BROWSER_CDP_VERSION_PATH}`\n\t\tconst requestSignal =\n\t\t\tsignal === undefined\n\t\t\t\t? AbortSignal.timeout(this.#timeout())\n\t\t\t\t: AbortSignal.any([signal, AbortSignal.timeout(this.#timeout())])\n\n\t\ttry {\n\t\t\tconst response = await fetch(url, { signal: requestSignal })\n\t\t\tif (!response.ok) return this.#notFound()\n\n\t\t\tconst info: unknown = await response.json()\n\t\t\tif (!isRecord(info)) return this.#notFound()\n\n\t\t\tconst endpoint = isString(info['webSocketDebuggerUrl'])\n\t\t\t\t? info['webSocketDebuggerUrl']\n\t\t\t\t: undefined\n\t\t\tconst browser = isString(info['Browser']) ? info['Browser'] : undefined\n\n\t\t\treturn { endpoint, browser }\n\t\t} catch (error) {\n\t\t\tif (signal?.aborted === true) throw error\n\t\t\treturn this.#notFound()\n\t\t}\n\t}\n\n\t#notFound(): BrowserDiscoveryResult {\n\t\treturn { endpoint: undefined, browser: undefined }\n\t}\n\n\tasync #assertPortFree(): Promise<void> {\n\t\tif (await this.#probePort()) {\n\t\t\tthrow new BrowserError(\n\t\t\t\t'CONNECTION',\n\t\t\t\t`Port ${this.#cdpPort} on ${this.#cdpHost} is already occupied by another CDP endpoint`,\n\t\t\t\t{ port: this.#cdpPort, host: this.#cdpHost },\n\t\t\t)\n\t\t}\n\t}\n\n\tasync #probePort(): Promise<boolean> {\n\t\tconst url = `${BROWSER_CDP_PROTOCOL}://${this.#cdpHost}:${this.#cdpPort}${BROWSER_CDP_VERSION_PATH}`\n\n\t\ttry {\n\t\t\tconst response = await fetch(url, {\n\t\t\t\tsignal: AbortSignal.timeout(BROWSER_PORT_PROBE_TIMEOUT_MS),\n\t\t\t})\n\t\t\treturn response.ok\n\t\t} catch {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tasync #connectCDP(endpoint: string): Promise<void> {\n\t\tconst transport = createWebSocketCDPTransport({ url: endpoint, timeout: this.#timeout() })\n\t\tconst client = new CDPClient({ transport, timeout: this.#timeout() })\n\t\tconst retained = this.#owned === true && this.#endpoint === endpoint\n\n\t\ttry {\n\t\t\tawait this.#raceAbort(client.connect())\n\n\t\t\tthis.#client = client\n\t\t\tthis.#endpoint = endpoint\n\t\t\tthis.#connection = retained ? this.#retainedConnection() : 'cdp'\n\t\t\tthis.#owned = retained\n\t\t\tthis.#status = 'connected'\n\t\t\tthis.#bindTransport(transport)\n\n\t\t\tawait this.#syncContexts()\n\t\t\tthis.#emitter.emit('connect', this.#connection)\n\t\t} catch (error) {\n\t\t\tthis.#unbindTransport()\n\t\t\tif (this.#client === client) this.#client = undefined\n\t\t\tthis.#contexts = []\n\t\t\tthis.#connection = undefined\n\t\t\tif (!retained) {\n\t\t\t\tthis.#owned = undefined\n\t\t\t\tthis.#endpoint = undefined\n\t\t\t}\n\t\t\tawait this.#closeClient(client)\n\t\t\tthrow error\n\t\t}\n\t}\n\n\tasync #launch(): Promise<void> {\n\t\tif (this.#process !== undefined) {\n\t\t\tthrow new BrowserError('CONNECTION', 'A browser process is already active on this instance')\n\t\t}\n\n\t\tconst requestedEngine = this.#options.browsers?.engine\n\t\tlet executable = this.#options.executable\n\t\tlet resolvedEngine: BrowserEngine | undefined\n\n\t\tif (executable !== undefined) {\n\t\t\tresolvedEngine = parseBrowserEngine(executable) ?? 'chromium'\n\t\t} else {\n\t\t\tconst found = findSystemBrowsers({\n\t\t\t\t...this.#options.browsers,\n\t\t\t\t...(requestedEngine !== undefined ? { engine: requestedEngine } : {}),\n\t\t\t})[0]\n\t\t\texecutable = found?.executable\n\t\t\tresolvedEngine = found?.engine\n\t\t}\n\n\t\tif (executable === undefined) {\n\t\t\tthrow new BrowserError(\n\t\t\t\t'CONNECTION',\n\t\t\t\t'No Chromium browser found. Install Chrome, Edge, or Chromium.',\n\t\t\t\trequestedEngine === undefined ? undefined : { engine: requestedEngine },\n\t\t\t)\n\t\t}\n\n\t\tthis.#engine = resolvedEngine ?? 'chromium'\n\t\tawait this.#releaseProfile()\n\t\tconst profile = await createBrowserProfile(this.#options.profile)\n\t\tthis.#profile = profile\n\t\tlet process: ChildProcess\n\t\ttry {\n\t\t\tprocess = launchBrowserProcess(\n\t\t\t\texecutable,\n\t\t\t\tthis.#options.cdp?.port,\n\t\t\t\tthis.#options.headless ?? true,\n\t\t\t\tprofile.path,\n\t\t\t\tthis.#options.args,\n\t\t\t)\n\t\t} catch (error) {\n\t\t\tawait this.#releaseProfile()\n\t\t\tthrow error\n\t\t}\n\t\tthis.#process = process\n\n\t\tlet client: CDPClient | undefined\n\n\t\ttry {\n\t\t\tconst endpoint = await this.#waitForLaunch(process, executable, this.#options.args)\n\t\t\tconst transport = createWebSocketCDPTransport({ url: endpoint, timeout: this.#timeout() })\n\t\t\tclient = new CDPClient({ transport, timeout: this.#timeout() })\n\t\t\tawait this.#raceAbort(client.connect())\n\t\t\tawait this.#takeEndpointOwner(process, client)\n\n\t\t\tconst connection = this.#options.profile === undefined ? 'launch' : 'persistent'\n\t\t\tthis.#client = client\n\t\t\tthis.#endpoint = endpoint\n\t\t\tthis.#connection = connection\n\t\t\tthis.#owned = true\n\t\t\tthis.#status = 'connected'\n\t\t\tthis.#bindTransport(transport)\n\t\t\tthis.#bindProcess(process)\n\n\t\t\tawait this.#syncContexts()\n\t\t\tthis.#emitter.emit('launch', this.#engine)\n\t\t\tthis.#emitter.emit('connect', connection)\n\t\t} catch (error) {\n\t\t\tthis.#unbindTransport()\n\t\t\tthis.#unbindProcess()\n\t\t\tawait this.#closeClient(client)\n\t\t\tawait this.#terminate(process)\n\t\t\tawait this.#releaseProfile()\n\t\t\tthis.#process = undefined\n\t\t\tthis.#servingPid = undefined\n\t\t\tthis.#client = undefined\n\t\t\tthis.#endpoint = undefined\n\t\t\tthis.#owned = undefined\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Takes over the process serving the CDP endpoint when the spawned child is\n\t * no longer it.\n\t *\n\t * @remarks\n\t * A Windows launcher — Microsoft Edge — re-executes the browser with the\n\t * same `--remote-debugging-port` and exits 0 before the endpoint answers, so\n\t * the child this instance spawned parents the real tree without being part\n\t * of it. Chromium names the process behind the endpoint as the `browser`\n\t * entry of `SystemInfo.getProcessInfo`, which identifies it without a\n\t * platform branch. An endpoint that names no such process cannot be owned,\n\t * so the launch closes it and fails rather than leaking it.\n\t */\n\tasync #takeEndpointOwner(process: ChildProcess, client: CDPClient): Promise<void> {\n\t\tif (process.exitCode === null && process.signalCode === null) return\n\n\t\tlet result: unknown\n\t\ttry {\n\t\t\tresult = await client.send('SystemInfo.getProcessInfo')\n\t\t} catch {\n\t\t\tresult = undefined\n\t\t}\n\n\t\tlet pid: number | undefined\n\t\tif (isRecord(result) && isArray(result['processInfo'])) {\n\t\t\tfor (const entry of result['processInfo']) {\n\t\t\t\tif (!isRecord(entry) || entry['type'] !== 'browser' || !isInteger(entry['id'])) continue\n\t\t\t\tpid = entry['id']\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif (pid === undefined) {\n\t\t\tawait this.#closeRemote(client)\n\t\t\tthrow new BrowserError(\n\t\t\t\t'CONNECTION',\n\t\t\t\t'The browser launcher exited without naming the process serving its CDP endpoint',\n\t\t\t\t{\n\t\t\t\t\t...(this.#options.executable === undefined\n\t\t\t\t\t\t? {}\n\t\t\t\t\t\t: { executable: this.#options.executable }),\n\t\t\t\t\t...(process.pid === undefined ? {} : { pid: process.pid }),\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\n\t\tthis.#servingPid = pid\n\t}\n\n\tasync #waitForLaunch(\n\t\tprocess: ChildProcess,\n\t\texecutable: string,\n\t\targs?: readonly string[],\n\t): Promise<string> {\n\t\tconst context = { executable, ...(args === undefined ? {} : { args }) }\n\t\tconst timeout = this.#timeout()\n\t\tconst controller = new AbortController()\n\t\tconst deadline = AbortSignal.timeout(timeout)\n\t\tconst signal = AbortSignal.any([controller.signal, this.#signal(), deadline])\n\t\tconst stderr = process.stderr\n\t\tif (stderr === null) {\n\t\t\tthrow new BrowserError(\n\t\t\t\t'CONNECTION',\n\t\t\t\t'The browser process has no standard error to read',\n\t\t\t\tcontext,\n\t\t\t)\n\t\t}\n\t\tconst exit = once(process, 'exit', { signal })\n\t\tvoid exit.catch(() => undefined)\n\t\tconst ready = readBrowserEndpoint(stderr, signal).catch(async (error: unknown) => {\n\t\t\t// A stream that closes without the line ends the launch, and the exit\n\t\t\t// that closed it names the cause: a nonzero exit is the launch-exit\n\t\t\t// fault, while a clean exit leaves the readiness failure standing.\n\t\t\tif (signal.aborted) throw error\n\t\t\tconst values = await exit\n\t\t\tif (values[0] === 0 && values[1] === null) throw error\n\t\t\tthrow new BrowserError(\n\t\t\t\t'CONNECTION',\n\t\t\t\tthis.#formatLaunchExit(\n\t\t\t\t\tisInteger(values[0]) ? values[0] : null,\n\t\t\t\t\tisString(values[1]) ? values[1] : null,\n\t\t\t\t),\n\t\t\t\tcontext,\n\t\t\t)\n\t\t})\n\t\tconst exited = exit.then((values) => {\n\t\t\tconst code = isInteger(values[0]) ? values[0] : null\n\t\t\tconst exitSignal = isString(values[1]) ? values[1] : null\n\t\t\t// A launcher that re-executes the browser exits cleanly and hands the\n\t\t\t// inherited standard error to the process it spawned, so a clean exit\n\t\t\t// ends the child rather than the launch. Keep reading the same pipe on\n\t\t\t// the same readiness budget, which still fails when the line never\n\t\t\t// arrives.\n\t\t\tif (code === 0 && exitSignal === null) return ready\n\t\t\tthrow new BrowserError('CONNECTION', this.#formatLaunchExit(code, exitSignal), context)\n\t\t})\n\n\t\ttry {\n\t\t\treturn await Promise.race([ready, exited])\n\t\t} catch (error) {\n\t\t\tif (isBrowserError(error) && error.code === 'CONNECTION') throw error\n\t\t\tif (this.#signal().aborted)\n\t\t\t\tthrow new BrowserError('CONNECTION', 'Connection aborted', context)\n\t\t\tif (deadline.aborted) {\n\t\t\t\tthrow new BrowserError(\n\t\t\t\t\t'CONNECTION',\n\t\t\t\t\t`Browser did not report a CDP endpoint within ${timeout}ms`,\n\t\t\t\t\t{ ...context, timeout },\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tconst message = isError(error) ? error.message : String(error)\n\t\t\tthrow new BrowserError('CONNECTION', message, context)\n\t\t} finally {\n\t\t\tcontroller.abort()\n\t\t\tvoid ready.catch(() => undefined)\n\t\t\tvoid exited.catch(() => undefined)\n\t\t}\n\t}\n\n\t#formatLaunchExit(code: number | null, signal: string | null): string {\n\t\tif (signal !== null) {\n\t\t\treturn `Browser process exited before CDP became ready (signal: ${signal})`\n\t\t}\n\t\tif (code !== null) return `Browser process exited before CDP became ready (code: ${code})`\n\t\treturn 'Browser process exited before CDP became ready'\n\t}\n\n\t#retainedConnection(): BrowserConnection {\n\t\tif (this.#process === undefined) return 'cdp'\n\t\treturn this.#options.profile === undefined ? 'launch' : 'persistent'\n\t}\n\n\tasync #syncContexts(): Promise<void> {\n\t\tconst client = this.#client\n\t\tif (client === undefined) return\n\n\t\tlet result: unknown\n\t\ttry {\n\t\t\tresult = await client.send('Target.getTargets')\n\t\t} catch {\n\t\t\treturn\n\t\t}\n\t\tif (!isRecord(result) || !isArray(result['targetInfos'])) return\n\n\t\tconst pages: CDPTarget[] = []\n\t\tfor (const target of result['targetInfos']) {\n\t\t\tif (\n\t\t\t\t!isRecord(target) ||\n\t\t\t\t!isString(target['targetId']) ||\n\t\t\t\ttarget['type'] !== 'page' ||\n\t\t\t\t!isString(target['title']) ||\n\t\t\t\t!isString(target['url'])\n\t\t\t) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tpages.push({\n\t\t\t\tid: target['targetId'],\n\t\t\t\tcategory: target['type'],\n\t\t\t\ttitle: target['title'],\n\t\t\t\turl: target['url'],\n\t\t\t})\n\t\t}\n\t\tif (pages.length === 0 || this.#contexts.length > 0) return\n\n\t\tconst context = new BrowserContext(client, {\n\t\t\t...(this.#options.viewport === undefined ? {} : { viewport: this.#options.viewport }),\n\t\t\twriter: createFileBrowserWriter(),\n\t\t})\n\t\tawait context.sync(pages)\n\t\tthis.#registerContext(context)\n\t}\n\n\tasync #destroyResources(): Promise<void> {\n\t\tlet terminated = false\n\t\ttry {\n\t\t\tawait this.#settle()\n\t\t\tthis.#unbindTransport()\n\t\t\tthis.#unbindProcess()\n\n\t\t\tconst client = this.#client\n\t\t\tif (this.#owned === true) {\n\t\t\t\tawait this.#closeContexts()\n\t\t\t\tif (this.#process === undefined) await this.#closeRemote(client)\n\t\t\t} else {\n\t\t\t\tawait this.#destroyContexts()\n\t\t\t}\n\t\t\tthis.#contexts = []\n\n\t\t\tawait this.#terminate(this.#process)\n\t\t\tthis.#process = undefined\n\t\t\tthis.#servingPid = undefined\n\t\t\tterminated = true\n\t\t} finally {\n\t\t\tconst contexts = this.#contexts\n\t\t\tthis.#contexts = []\n\t\t\tconst client = this.#client\n\t\t\tthis.#client = undefined\n\t\t\ttry {\n\t\t\t\tawait this.#cleanupLocal(contexts, client)\n\t\t\t\tif (terminated) await this.#releaseProfile()\n\t\t\t} finally {\n\t\t\t\tthis.#finish()\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #closeResources(): Promise<void> {\n\t\tlet terminated = false\n\t\ttry {\n\t\t\tawait this.#settle()\n\t\t\tthis.#unbindTransport()\n\t\t\tthis.#unbindProcess()\n\n\t\t\tconst client = this.#client\n\t\t\tawait this.#closeContexts()\n\t\t\tthis.#contexts = []\n\t\t\tawait this.#closeRemote(client)\n\n\t\t\tconst process = this.#process\n\t\t\tif (process !== undefined) {\n\t\t\t\tconst exited = await this.#waitForTerminationWithin(process, BROWSER_KILL_GRACE_MS)\n\t\t\t\tif (!exited) await this.#terminate(process)\n\t\t\t\tawait this.#closeProcessPipe(process)\n\t\t\t}\n\t\t\tthis.#process = undefined\n\t\t\tthis.#servingPid = undefined\n\t\t\tterminated = true\n\t\t} finally {\n\t\t\tconst contexts = this.#contexts\n\t\t\tthis.#contexts = []\n\t\t\tconst client = this.#client\n\t\t\tthis.#client = undefined\n\t\t\ttry {\n\t\t\t\tawait this.#cleanupLocal(contexts, client)\n\t\t\t\tif (terminated) await this.#releaseProfile()\n\t\t\t} finally {\n\t\t\t\tthis.#finish()\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #settle(): Promise<void> {\n\t\tawait Promise.allSettled(this.#isolating)\n\t\tawait this.#connecting.pending?.catch(() => undefined)\n\t\tawait this.#disconnecting.pending?.catch(() => undefined)\n\t\tawait this.#settleExit()\n\t}\n\n\tasync #settleExit(): Promise<void> {\n\t\tconst cleanup = this.#exitCleanup\n\t\tif (cleanup === undefined) return\n\t\tawait cleanup\n\t\tif (this.#exitCleanup === cleanup) this.#exitCleanup = undefined\n\t}\n\n\tasync #closeRemote(client: CDPClient | undefined): Promise<void> {\n\t\tlet remote = client\n\t\tlet temporary = false\n\n\t\tif (remote === undefined && this.#owned === true && this.#endpoint !== undefined) {\n\t\t\tconst transport = createWebSocketCDPTransport({\n\t\t\t\turl: this.#endpoint,\n\t\t\t\ttimeout: this.#timeout(),\n\t\t\t})\n\t\t\tremote = new CDPClient({ transport, timeout: this.#timeout() })\n\t\t\ttry {\n\t\t\t\tawait remote.connect()\n\t\t\t\ttemporary = true\n\t\t\t} catch {\n\t\t\t\tawait this.#closeClient(remote)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\n\t\tif (remote !== undefined) {\n\t\t\ttry {\n\t\t\t\tawait remote.send('Browser.close')\n\t\t\t} catch {\n\t\t\t\t// The remote may already be gone or close before acknowledging.\n\t\t\t}\n\t\t}\n\n\t\tif (temporary) await this.#closeClient(remote)\n\t}\n\n\tasync #closeContexts(): Promise<void> {\n\t\tfor (const context of [...this.#contexts]) {\n\t\t\ttry {\n\t\t\t\tawait context.close()\n\t\t\t} catch {\n\t\t\t\t// Teardown is best-effort after the browser begins shutting down.\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #destroyContexts(): Promise<void> {\n\t\tawait this.#destroyContextList([...this.#contexts])\n\t}\n\n\t#registerContext(context: BrowserContext): void {\n\t\tthis.#contexts.push(context)\n\t\tcontext.emitter.on('close', () => {\n\t\t\tconst index = this.#contexts.indexOf(context)\n\t\t\tif (index >= 0) this.#contexts.splice(index, 1)\n\t\t})\n\t\tthis.#emitter.emit('context', context)\n\t}\n\n\tasync #destroyContextList(contexts: readonly BrowserContext[]): Promise<void> {\n\t\tfor (const context of contexts) {\n\t\t\ttry {\n\t\t\t\tawait context.destroy()\n\t\t\t} catch {\n\t\t\t\t// The transport may already be unavailable.\n\t\t\t}\n\t\t}\n\t}\n\n\tasync #closeClient(client: CDPClient | undefined): Promise<void> {\n\t\tif (client === undefined) return\n\t\ttry {\n\t\t\tawait client.close()\n\t\t} catch {\n\t\t\t// Teardown is best-effort after a connection fault.\n\t\t}\n\t}\n\n\tasync #releaseProfile(): Promise<void> {\n\t\tconst profile = this.#profile\n\t\tthis.#profile = undefined\n\t\tif (profile !== undefined) await removeBrowserProfile(profile)\n\t}\n\n\tasync #cleanupExitedProcess(\n\t\tprocess: ChildProcess | undefined,\n\t\tcontexts: readonly BrowserContext[],\n\t\tclient: CDPClient | undefined,\n\t): Promise<void> {\n\t\tlet terminated = false\n\t\ttry {\n\t\t\tawait this.#terminate(process)\n\t\t\tterminated = true\n\t\t} finally {\n\t\t\tawait this.#cleanupLocal(contexts, client)\n\t\t}\n\t\tif (terminated) await this.#releaseProfile()\n\t}\n\n\tasync #cleanupLocal(\n\t\tcontexts: readonly BrowserContext[],\n\t\tclient: CDPClient | undefined,\n\t): Promise<void> {\n\t\tawait this.#destroyContextList(contexts)\n\t\tawait this.#closeClient(client)\n\t}\n\n\tasync #waitForProcessWithin(process: ChildProcess, timeout: number): Promise<boolean> {\n\t\tif (process.exitCode !== null || process.signalCode !== null) return true\n\n\t\tconst signal = AbortSignal.timeout(timeout)\n\t\ttry {\n\t\t\tawait once(process, 'exit', { signal })\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\tif (signal.aborted) {\n\t\t\t\treturn process.exitCode !== null || process.signalCode !== null\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t#hasProcessGroup(process: ChildProcess): boolean {\n\t\tconst pid = process.pid\n\t\treturn globalThis.process.platform !== 'win32' && pid !== undefined && pid > 0\n\t}\n\n\t// Whether the process serving the CDP endpoint is still running. The spawned\n\t// child reports through its own handle; a process the launcher handed the\n\t// endpoint to has none, so it is probed by identifier.\n\t#alive(): boolean {\n\t\tconst process = this.#process\n\t\tif (process === undefined) return false\n\t\tif (this.#servingPid !== undefined) return this.#signalProcess(process, 0) !== false\n\t\treturn process.exitCode === null && process.signalCode === null\n\t}\n\n\t// Whether the launch retains a process the reaped child does not account\n\t// for: the POSIX process group, or the process the launcher handed the\n\t// endpoint to.\n\t#inspectRemainder(process: ChildProcess): boolean | undefined {\n\t\tif (!this.#hasProcessGroup(process) && this.#servingPid === undefined) return false\n\t\treturn this.#signalProcess(process, 0)\n\t}\n\n\t#signalProcess(process: ChildProcess, signal: NodeJS.Signals | 0): boolean | undefined {\n\t\tconst pid = process.pid\n\t\tconst serving = this.#servingPid\n\t\ttry {\n\t\t\tif (this.#hasProcessGroup(process) && pid !== undefined) {\n\t\t\t\treturn globalThis.process.kill(-pid, signal)\n\t\t\t}\n\t\t\t// Terminating the Chromium browser process takes its whole tree with\n\t\t\t// it, so Windows needs no separate tree walk to reach the renderers,\n\t\t\t// GPU, and utility children the serving process parents.\n\t\t\tif (serving !== undefined) return globalThis.process.kill(serving, signal)\n\t\t\treturn process.kill(signal)\n\t\t} catch (error) {\n\t\t\tconst code =\n\t\t\t\tisError(error) && 'code' in error && isString(error.code) ? error.code : undefined\n\t\t\tif (code === 'ESRCH') return false\n\t\t\tif (signal === 0) return code === 'EPERM' ? true : undefined\n\t\t\tconst target = serving ?? pid\n\t\t\tthrow new BrowserError('CONNECTION', 'Failed to signal the browser process', {\n\t\t\t\t...(target === undefined ? {} : { pid: target }),\n\t\t\t\tsignal,\n\t\t\t\tcause: isJSONValue(error) ? error : String(error),\n\t\t\t})\n\t\t}\n\t}\n\n\t/**\n\t * Waits within a bound for the rest of a terminated process group, or the process a\n\t * launcher handed the endpoint to, to disappear.\n\t *\n\t * @remarks\n\t * This is the one interval loop in the server. Node raises an exit event for the direct\n\t * child only, so no event source reports the remainder of a POSIX process group or a\n\t * handed-off process, and the drain probes on `BROWSER_DRAIN_INTERVAL_MS` until the\n\t * remainder is gone or `timeout` elapses.\n\t */\n\tasync #waitForRemainderWithin(\n\t\tprocess: ChildProcess,\n\t\ttimeout: number,\n\t): Promise<boolean | undefined> {\n\t\tconst deadline = performance.now() + timeout\n\t\tlet confirmed = false\n\t\twhile (true) {\n\t\t\tconst alive = this.#inspectRemainder(process)\n\t\t\tif (alive === false) return true\n\t\t\tif (alive === true) confirmed = true\n\t\t\tconst remaining = deadline - performance.now()\n\t\t\tif (remaining <= 0) return confirmed ? false : undefined\n\t\t\tawait new Promise<void>((resolve) =>\n\t\t\t\tsetTimeout(resolve, Math.min(BROWSER_DRAIN_INTERVAL_MS, remaining)),\n\t\t\t)\n\t\t}\n\t}\n\n\tasync #waitForTerminationWithin(\n\t\tprocess: ChildProcess,\n\t\ttimeout: number,\n\t\tfinal = false,\n\t): Promise<boolean> {\n\t\tconst exited = this.#waitForProcessWithin(process, timeout)\n\t\tconst drained = this.#waitForRemainderWithin(process, timeout)\n\t\tconst results = await Promise.all([exited, drained])\n\t\treturn results[0] && (results[1] === true || (final && results[1] === undefined))\n\t}\n\n\tasync #terminate(process: ChildProcess | undefined): Promise<void> {\n\t\ttry {\n\t\t\tif (\n\t\t\t\tprocess === undefined ||\n\t\t\t\t((process.exitCode !== null || process.signalCode !== null) &&\n\t\t\t\t\tthis.#inspectRemainder(process) === false)\n\t\t\t) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (this.#signalProcess(process, 'SIGTERM') === false) return\n\t\t\tif (await this.#waitForTerminationWithin(process, BROWSER_KILL_GRACE_MS)) return\n\n\t\t\tif (this.#signalProcess(process, 'SIGKILL') === false) return\n\t\t\tif (await this.#waitForTerminationWithin(process, BROWSER_KILL_GRACE_MS, true)) return\n\n\t\t\tconst target = this.#servingPid ?? process.pid\n\t\t\tthrow new BrowserError('CONNECTION', 'Browser process did not exit after SIGKILL', {\n\t\t\t\t...(target === undefined ? {} : { pid: target }),\n\t\t\t})\n\t\t} finally {\n\t\t\tawait this.#closeProcessPipe(process)\n\t\t}\n\t}\n\n\tasync #closeProcessPipe(process: ChildProcess | undefined): Promise<void> {\n\t\tconst stream = process?.stderr\n\t\tif (stream === undefined || stream === null || stream.closed) return\n\t\t// A descendant can inherit the writer after the browser exits, especially on Windows.\n\t\t// Release our read end explicitly and await its close before teardown settles.\n\t\tconst closed = once(stream, 'close')\n\t\tstream.destroy()\n\t\tawait closed\n\t}\n\n\t#finish(): void {\n\t\tthis.#unbindTransport()\n\t\tthis.#unbindProcess()\n\t\tthis.#status = 'disconnected'\n\t\tthis.#connection = undefined\n\t\tthis.#owned = undefined\n\t\tthis.#endpoint = undefined\n\t\tthis.#client = undefined\n\t\tthis.#process = undefined\n\t\tthis.#servingPid = undefined\n\t\tthis.#exitCleanup = undefined\n\t\tthis.#contexts = []\n\t\tthis.#emitter.emit('destroy')\n\t\tthis.#emitter.destroy()\n\t}\n}\n"],"mappings":"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"}