agents 0.27.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/abortable-C1SpfVoi.js +21 -0
- package/dist/abortable-C1SpfVoi.js.map +1 -0
- package/dist/{agent-routing-Bhdbvf7s.d.ts → agent-routing-QDcchcQP.d.ts} +10 -15
- package/dist/agent-routing.d.ts +1 -1
- package/dist/agent-tool-types.d.ts +1 -1
- package/dist/{agent-tools-bJZwBMfq.d.ts → agent-tools-DHL2XI7u.d.ts} +2 -2
- package/dist/agent-tools.d.ts +1 -1
- package/dist/ai-ahruGw7e.d.ts +239 -0
- package/dist/{ai-sdk-OoGkFy3s.js → ai-sdk-Bdsf6mSA.js} +2 -2
- package/dist/{ai-sdk-OoGkFy3s.js.map → ai-sdk-Bdsf6mSA.js.map} +1 -1
- package/dist/browser/ai.d.ts +8 -227
- package/dist/browser/ai.js +259 -1
- package/dist/browser/ai.js.map +1 -0
- package/dist/browser/index.d.ts +56 -46
- package/dist/browser/index.js +4 -361
- package/dist/browser/{ai-sdk.d.ts → tools/ai-sdk.d.ts} +7 -7
- package/dist/browser/{ai-sdk.js → tools/ai-sdk.js} +5 -4
- package/dist/browser/tools/ai-sdk.js.map +1 -0
- package/dist/browser/tools/pi.d.ts +111 -0
- package/dist/browser/tools/pi.js +119 -0
- package/dist/browser/tools/pi.js.map +1 -0
- package/dist/browser/{tanstack-ai.d.ts → tools/tanstack-ai.d.ts} +39 -37
- package/dist/browser/{tanstack-ai.js → tools/tanstack-ai.js} +73 -59
- package/dist/browser/tools/tanstack-ai.js.map +1 -0
- package/dist/browser-CEdNlsaD.js +481 -0
- package/dist/browser-CEdNlsaD.js.map +1 -0
- package/dist/{browser-tmkcAAI3.d.ts → browser-D30VlpcA.d.ts} +63 -37
- package/dist/{browser-tool-CBqs6hqa.js → browser-tool-4iomavs_.js} +145 -49
- package/dist/browser-tool-4iomavs_.js.map +1 -0
- package/dist/{browser-tool-Bn-nzJQI.d.ts → browser-tool-vtrPOV8e.d.ts} +24 -5
- package/dist/{capability-B4WbF81e.js → capability-DBAKc6UZ.js} +1 -3
- package/dist/capability-DBAKc6UZ.js.map +1 -0
- package/dist/{capability-runner-O5VbQzqg.d.ts → capability-runner-BiVUtjqC.d.ts} +1 -7
- package/dist/chat/index.d.ts +4 -4
- package/dist/chat/index.js +1 -1
- package/dist/chat-sdk/index.d.ts +1 -1
- package/dist/chat-sdk/index.js +1 -1
- package/dist/{client-DS3Dz9l0.d.ts → client-BGIQKJhX.d.ts} +2 -2
- package/dist/{client-1tEQ1Oqz.js → client-BnYbNT3z.js} +3 -4
- package/dist/client-BnYbNT3z.js.map +1 -0
- package/dist/client.d.ts +1 -1
- package/dist/{connector-58XDGvc3.js → connector-CtZylXdk.js} +3 -603
- package/dist/connector-CtZylXdk.js.map +1 -0
- package/dist/{connector-Cl-VqPmA.d.ts → connector-DEXzVoaY.d.ts} +9 -374
- package/dist/{conversations-DH0ut_8n.d.ts → conversations-FjHDRZyD.d.ts} +4 -4
- package/dist/{current-agent-C07C5o5Y.d.ts → current-agent-CKgT5d1O.d.ts} +3 -5
- package/dist/current-agent-DhoDkSnH.js.map +1 -1
- package/dist/{durable-object-lifecycle-DRqp475_.d.ts → durable-object-lifecycle-DOI_bzCH.d.ts} +2 -2
- package/dist/experimental/channels/index.d.ts +2 -2
- package/dist/experimental/channels/index.js +2 -2
- package/dist/experimental/channels/web/index.d.ts +2 -2
- package/dist/experimental/channels/web/index.js +1 -1
- package/dist/{gateway-BDC07gYO.d.ts → gateway-BFO6vRDn.d.ts} +2 -2
- package/dist/harness/ai-sdk/index.d.ts +2 -2
- package/dist/harness/ai-sdk/index.js +1 -1
- package/dist/harness/container/index.d.ts +2 -2
- package/dist/harness/container/index.js +3 -3
- package/dist/harness/opencode/index.d.ts +1 -1
- package/dist/harness/opencode/index.js +2 -2
- package/dist/harness/pi/index.d.ts +2 -2
- package/dist/harness/pi/index.js +3 -3
- package/dist/harness/store/index.d.ts +1 -1
- package/dist/harness/store/index.js +1 -1
- package/dist/harness/think/index.d.ts +2 -2
- package/dist/harness/think/index.js +363 -171
- package/dist/harness/think/index.js.map +1 -1
- package/dist/{index-D0A5tbWu.d.ts → index-BEL3ZV-s.d.ts} +2 -6
- package/dist/{index-Ib_4dwOo.d.ts → index-CBt8oRJt.d.ts} +3 -5
- package/dist/index.d.ts +4 -4
- package/dist/index.js +2 -2
- package/dist/input-schema-BQykTEp_.js +20 -0
- package/dist/input-schema-BQykTEp_.js.map +1 -0
- package/dist/{input-schema-DNrpTu49.js → input-schema-D2QAtHZH.js} +3 -3
- package/dist/input-schema-D2QAtHZH.js.map +1 -0
- package/dist/internal_context.d.ts +1 -1
- package/dist/lifecycle/index.d.ts +3 -3
- package/dist/lifecycle/index.js +2 -2
- package/dist/{lifecycle-CFu6OV03.js → lifecycle-DGorpAmA.js} +2 -4
- package/dist/lifecycle-DGorpAmA.js.map +1 -0
- package/dist/mcp/client/index.d.ts +1 -1
- package/dist/mcp/client/index.js +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +2 -2
- package/dist/models/ai-sdk/index.js +1 -1
- package/dist/models/opencode/index.js +1 -1
- package/dist/models/pi-ai/index.js +1 -1
- package/dist/{options-pwTNq9z6.d.ts → options-CiIsJHXR.d.ts} +2 -6
- package/dist/queue/index.d.ts +1 -1
- package/dist/queue/index.js +1 -1
- package/dist/{queue-BB-zfIYF.js → queue-CcIjVYTE.js} +2 -2
- package/dist/{queue-BB-zfIYF.js.map → queue-CcIjVYTE.js.map} +1 -1
- package/dist/react.d.ts +2 -2
- package/dist/routing/index.d.ts +2 -2
- package/dist/routing/index.js +1 -1
- package/dist/{scheduler-CrFCnv_J.d.ts → scheduler-BCLESHSC.d.ts} +2 -12
- package/dist/{scheduler-DZ3xQfeK.js → scheduler-FIHv2-kJ.js} +2 -4
- package/dist/scheduler-FIHv2-kJ.js.map +1 -0
- package/dist/schedules/index.d.ts +1 -1
- package/dist/schedules/index.js +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/session-store-Do4xkDcf.js +606 -0
- package/dist/session-store-Do4xkDcf.js.map +1 -0
- package/dist/session-store-DoPY12xM.d.ts +383 -0
- package/dist/sessions/index.d.ts +1 -1
- package/dist/sessions/index.js +1 -1
- package/dist/{sessions-B9pNuxdT.js → sessions-_vN5BEZX.js} +2 -2
- package/dist/{sessions-B9pNuxdT.js.map → sessions-_vN5BEZX.js.map} +1 -1
- package/dist/{src-DgCbZtIR.js → src-CQxJFv4l.js} +8 -8
- package/dist/src-CQxJFv4l.js.map +1 -0
- package/dist/state/index.d.ts +1 -1
- package/dist/state/index.js +1 -3
- package/dist/state/index.js.map +1 -1
- package/dist/{store-DLeqKuj3.d.ts → store-BKM4Xm9M.d.ts} +23 -1
- package/dist/{store-vgcPYo8K.js → store-CslVzfN7.js} +28 -2
- package/dist/store-CslVzfN7.js.map +1 -0
- package/dist/streams/index.d.ts +1 -1
- package/dist/streams/index.js +1 -1
- package/dist/{streams-CITClVer.js → streams-lsHMJhRW.js} +2 -2
- package/dist/{streams-CITClVer.js.map → streams-lsHMJhRW.js.map} +1 -1
- package/dist/{streams-fbG61qM8.d.ts → streams-vrCtbUIn.d.ts} +2 -2
- package/dist/sub-routing.d.ts +1 -1
- package/dist/tasks/index.d.ts +1 -1
- package/dist/tasks/index.js +1 -1
- package/dist/{tasks-CkTZNaV1.js → tasks-BN_5AWqI.js} +2 -2
- package/dist/{tasks-CkTZNaV1.js.map → tasks-BN_5AWqI.js.map} +1 -1
- package/dist/{tasks-PtlB4Uyn.d.ts → tasks-E89KdwkS.d.ts} +2 -2
- package/dist/{tool-BPJEbwaX.d.ts → tool-CTp72Jb_.d.ts} +4 -4
- package/dist/tool-CxKsvxjm.js +1126 -0
- package/dist/tool-CxKsvxjm.js.map +1 -0
- package/dist/tool-DoVberpN.d.ts +301 -0
- package/dist/{tool-3PA8xjB_.js → tool-cQRkwSZZ.js} +6 -17
- package/dist/tool-cQRkwSZZ.js.map +1 -0
- package/dist/tool-helpers-O5BDVEAY.js +58 -0
- package/dist/tool-helpers-O5BDVEAY.js.map +1 -0
- package/dist/voice/index.d.ts +2 -2
- package/dist/web/fetch/index.d.ts +89 -0
- package/dist/web/fetch/index.js +20 -0
- package/dist/web/fetch/index.js.map +1 -0
- package/dist/web/fetch/tools/ai-sdk.d.ts +80 -0
- package/dist/web/fetch/tools/ai-sdk.js +47 -0
- package/dist/web/fetch/tools/ai-sdk.js.map +1 -0
- package/dist/web/fetch/tools/pi.d.ts +84 -0
- package/dist/web/fetch/tools/pi.js +88 -0
- package/dist/web/fetch/tools/pi.js.map +1 -0
- package/dist/web/fetch/tools/tanstack-ai.d.ts +78 -0
- package/dist/web/fetch/tools/tanstack-ai.js +45 -0
- package/dist/web/fetch/tools/tanstack-ai.js.map +1 -0
- package/dist/{websearch → web/search}/index.d.ts +1 -1
- package/dist/{websearch → web/search}/index.js +1 -1
- package/dist/{websearch → web/search}/tools/ai-sdk.d.ts +2 -2
- package/dist/{websearch → web/search}/tools/ai-sdk.js +3 -3
- package/dist/web/search/tools/ai-sdk.js.map +1 -0
- package/dist/{websearch → web/search}/tools/pi.d.ts +3 -3
- package/dist/{websearch → web/search}/tools/pi.js +2 -2
- package/dist/web/search/tools/pi.js.map +1 -0
- package/dist/{websearch → web/search}/tools/tanstack-ai.d.ts +2 -2
- package/dist/{websearch → web/search}/tools/tanstack-ai.js +3 -3
- package/dist/web/search/tools/tanstack-ai.js.map +1 -0
- package/dist/websockets/index.d.ts +2 -2
- package/dist/websockets/index.js +1 -1
- package/dist/{websockets-CmENGb-Z.js → websockets-C3zy8YR0.js} +3 -5
- package/dist/websockets-C3zy8YR0.js.map +1 -0
- package/dist/workflow-types.d.ts +1 -1
- package/dist/workflows.d.ts +1 -1
- package/dist/workflows.js +1 -1
- package/docs/browse-the-web.md +26 -1
- package/docs/fetch-the-web.md +276 -0
- package/docs/harnesses/pi.md +25 -0
- package/docs/index.md +99 -76
- package/docs/lifecycle.md +2 -3
- package/docs/queue.md +2 -3
- package/docs/scheduling.md +2 -6
- package/docs/search-the-web.md +2 -0
- package/package.json +44 -19
- package/dist/ai-fm7xx1BK.js +0 -312
- package/dist/ai-fm7xx1BK.js.map +0 -1
- package/dist/browser/ai-sdk.js.map +0 -1
- package/dist/browser/index.js.map +0 -1
- package/dist/browser/tanstack-ai.js.map +0 -1
- package/dist/browser-tool-CBqs6hqa.js.map +0 -1
- package/dist/capability-B4WbF81e.js.map +0 -1
- package/dist/client-1tEQ1Oqz.js.map +0 -1
- package/dist/connector-58XDGvc3.js.map +0 -1
- package/dist/input-schema-DNrpTu49.js.map +0 -1
- package/dist/lifecycle-CFu6OV03.js.map +0 -1
- package/dist/scheduler-DZ3xQfeK.js.map +0 -1
- package/dist/src-DgCbZtIR.js.map +0 -1
- package/dist/store-vgcPYo8K.js.map +0 -1
- package/dist/tool-3PA8xjB_.js.map +0 -1
- package/dist/websearch/tools/ai-sdk.js.map +0 -1
- package/dist/websearch/tools/pi.js.map +0 -1
- package/dist/websearch/tools/tanstack-ai.js.map +0 -1
- package/dist/websockets-CmENGb-Z.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-store-Do4xkDcf.js","names":[],"sources":["../src/browser/cdp-connection.ts","../src/browser/browser-run.ts","../src/browser/connector-validation.ts","../src/browser/live-view.ts","../src/browser/spec.ts","../src/browser/session-store.ts"],"sourcesContent":["interface PendingCommand {\n resolve: (result: unknown) => void;\n reject: (error: Error) => void;\n timeoutId: ReturnType<typeof setTimeout>;\n method: string;\n sessionId?: string;\n startedAt: number;\n}\n\ninterface DebugEntry {\n at: string;\n type: string;\n [key: string]: unknown;\n}\n\nexport interface CdpSendOptions {\n timeoutMs?: number;\n sessionId?: string;\n}\n\nexport interface CdpAttachOptions {\n timeoutMs?: number;\n}\n\n/** Construction options for {@link CdpConnection}. */\nexport interface CdpConnectionOptions {\n /** Default per-command timeout. Defaults to 10 seconds. */\n timeoutMs?: number;\n /**\n * Invoked exactly once when the session reaches a terminal state — an\n * explicit `close()`, peer closure, or a socket error.\n */\n onClose?: () => void;\n /** Browser Run session id, when connected to a session-scoped browser. */\n sessionId?: string;\n /** Invoked on every CDP command sent — an activity signal for idle tracking. */\n onActivity?: () => void;\n}\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\n/** JSON-RPC's \"method not found\" code, which Chrome also uses for CDP. */\nexport const CDP_METHOD_NOT_FOUND = -32601;\n\n/** The browser answered a command with a JSON-RPC error. */\nexport class CdpProtocolError extends Error {\n override readonly name = \"CdpProtocolError\";\n /** JSON-RPC error code, e.g. {@link CDP_METHOD_NOT_FOUND}. */\n readonly code: number | undefined;\n /** The CDP method that failed. */\n readonly method: string;\n\n constructor(method: string, code: number | undefined, message: string) {\n super(`CDP error ${code ?? \"unknown\"}: ${message} for ${method}`);\n this.code = code;\n this.method = method;\n }\n}\nconst MAX_DEBUG_ENTRIES = 400;\n\n/**\n * One Chrome DevTools Protocol connection over an open WebSocket. Manages\n * command correlation, timeouts, per-tab CDP sessions, and a debug event\n * ring buffer.\n *\n * Used host-side (not in the sandbox) — the sandbox calls into this\n * via DynamicWorkerExecutor's ToolDispatcher RPC.\n */\nexport class CdpConnection {\n #socket: WebSocket;\n #nextId = 1;\n #pending = new Map<number, PendingCommand>();\n #debugLog: DebugEntry[] = [];\n #defaultTimeoutMs: number;\n #dispose?: () => void;\n #disposed = false;\n #onActivity?: () => void;\n readonly sessionId?: string;\n\n constructor(socket: WebSocket, options?: CdpConnectionOptions);\n /**\n * @deprecated Pass a {@link CdpConnectionOptions} object instead —\n * `new CdpConnection(socket, { timeoutMs, onClose, sessionId })`. The\n * positional form will be removed.\n */\n constructor(\n socket: WebSocket,\n timeoutMs?: number,\n onClose?: () => void,\n sessionId?: string\n );\n constructor(\n socket: WebSocket,\n optionsOrTimeoutMs?: CdpConnectionOptions | number,\n onClose?: () => void,\n sessionId?: string\n ) {\n const options: CdpConnectionOptions =\n typeof optionsOrTimeoutMs === \"object\"\n ? optionsOrTimeoutMs\n : { timeoutMs: optionsOrTimeoutMs, onClose, sessionId };\n this.#socket = socket;\n this.#defaultTimeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n this.#dispose = options.onClose;\n this.sessionId = options.sessionId;\n this.#onActivity = options.onActivity;\n\n socket.addEventListener(\"message\", (event) => this.#handleMessage(event));\n socket.addEventListener(\"error\", () => {\n this.#rejectAll(new Error(\"CDP socket error\"));\n this.#runDispose();\n });\n socket.addEventListener(\"close\", () => {\n this.#rejectAll(new Error(\"CDP connection closed\"));\n this.#runDispose();\n });\n }\n\n send(\n method: string,\n params?: unknown,\n options: CdpSendOptions = {}\n ): Promise<unknown> {\n this.#onActivity?.();\n const id = this.#nextId++;\n const timeoutMs = options.timeoutMs ?? this.#defaultTimeoutMs;\n const sessionId =\n typeof options.sessionId === \"string\" && options.sessionId.length > 0\n ? options.sessionId\n : undefined;\n\n const domain = typeof method === \"string\" ? method.split(\".\")[0] : \"\";\n if (!sessionId && domain && ![\"Browser\", \"Target\"].includes(domain)) {\n this.#recordDebug(\"warning\", {\n id,\n method,\n reason: \"target-scoped method sent without sessionId\"\n });\n }\n\n const result = new Promise<unknown>((resolve, reject) => {\n const startedAt = performance.now();\n const timeoutId = setTimeout(() => {\n this.#pending.delete(id);\n reject(\n new Error(`CDP command timed out after ${timeoutMs}ms: ${method}`)\n );\n }, timeoutMs);\n this.#pending.set(id, {\n resolve,\n reject,\n timeoutId,\n method,\n sessionId,\n startedAt\n });\n });\n\n this.#recordDebug(\"send\", { id, method, sessionId, timeoutMs });\n try {\n this.#socket.send(JSON.stringify({ id, method, params, sessionId }));\n } catch (error) {\n // A closed socket throws on send: fail this command now rather than\n // leave it pending until it times out.\n const pending = this.#pending.get(id);\n if (pending) {\n clearTimeout(pending.timeoutId);\n this.#pending.delete(id);\n pending.reject(\n error instanceof Error ? error : new Error(String(error))\n );\n }\n }\n return result;\n }\n\n async attachToTarget(\n targetId: string,\n options: CdpAttachOptions = {}\n ): Promise<string> {\n if (typeof targetId !== \"string\" || !targetId) {\n throw new Error(\n \"attachToTarget requires a targetId — list open tabs with \" +\n \"send('Target.getTargets') or create one with \" +\n \"send('Target.createTarget', { url })\"\n );\n }\n\n const result = (await this.send(\n \"Target.attachToTarget\",\n {\n targetId,\n flatten: true\n },\n { timeoutMs: options.timeoutMs }\n )) as { sessionId?: string };\n\n const sessionId = result?.sessionId ?? \"\";\n if (!sessionId) {\n throw new Error(\n `Target.attachToTarget did not return a sessionId for target ${targetId}`\n );\n }\n\n this.#recordDebug(\"attach\", { targetId, sessionId });\n return sessionId;\n }\n\n getDebugLog(limit = 50): DebugEntry[] {\n const normalized = Number.isFinite(limit)\n ? Math.max(1, Math.floor(limit))\n : 50;\n return this.#debugLog.slice(-normalized);\n }\n\n clearDebugLog(): void {\n this.#debugLog = [];\n }\n\n disconnect(): void {\n this.#rejectAll(new Error(\"CDP session disconnected\"));\n try {\n this.#socket.close(1000, \"Done\");\n } catch {\n // socket may already be closed\n }\n }\n\n close(): void {\n this.disconnect();\n this.#runDispose();\n }\n\n /**\n * Run the dispose callback exactly once, on the first terminal event —\n * an explicit {@link close}, peer closure, or a socket error.\n */\n #runDispose(): void {\n if (this.#disposed) return;\n this.#disposed = true;\n this.#dispose?.();\n }\n\n #rejectAll(error: Error): void {\n for (const [id, pending] of this.#pending.entries()) {\n clearTimeout(pending.timeoutId);\n this.#pending.delete(id);\n pending.reject(error);\n }\n }\n\n #handleMessage(event: MessageEvent): void {\n if (typeof event.data !== \"string\") {\n return;\n }\n\n let payload: Record<string, unknown>;\n try {\n payload = JSON.parse(event.data) as Record<string, unknown>;\n } catch {\n return;\n }\n\n this.#recordDebug(\"receive\", {\n id: payload.id,\n method: payload.method,\n sessionId: payload.sessionId,\n hasError: !!payload.error\n });\n\n if (typeof payload.id !== \"number\") {\n return;\n }\n\n const pending = this.#pending.get(payload.id);\n if (!pending) {\n return;\n }\n\n clearTimeout(pending.timeoutId);\n this.#pending.delete(payload.id);\n\n if (payload.error) {\n const err = payload.error as { code?: unknown; message?: string };\n pending.reject(\n new CdpProtocolError(\n pending.method,\n typeof err.code === \"number\" ? err.code : undefined,\n err.message ?? \"CDP error\"\n )\n );\n return;\n }\n\n pending.resolve(payload.result);\n }\n\n #recordDebug(type: string, data: Record<string, unknown>): void {\n this.#debugLog.push({\n at: new Date().toISOString(),\n type,\n ...data\n });\n if (this.#debugLog.length > MAX_DEBUG_ENTRIES) {\n this.#debugLog.splice(0, this.#debugLog.length - MAX_DEBUG_ENTRIES);\n }\n }\n}\n\nconst LOCALHOST_HOSTS = new Set([\n \"localhost\",\n \"127.0.0.1\",\n \"0.0.0.0\",\n \"::1\",\n \"[::1]\"\n]);\n\n/**\n * Connect to a browser via a CDP base URL (e.g. http://localhost:9222).\n * Discovers the WebSocket debugger URL via /json/version,\n * rewrites localhost URLs to the base URL host, and opens the WebSocket.\n *\n * Useful for local development with `chrome --remote-debugging-port=9222`\n * or when connecting through a tunnel.\n */\nexport async function connectUrl(\n baseUrl: string,\n options?: { timeoutMs?: number; headers?: Record<string, string> }\n): Promise<CdpConnection> {\n const endpoint = new URL(\"/json/version\", baseUrl).toString();\n const response = await fetch(endpoint, {\n headers: options?.headers\n });\n if (!response.ok) {\n throw new Error(\n `Failed to discover CDP endpoint at ${endpoint}: ${response.status}`\n );\n }\n\n const payload = (await response.json()) as {\n webSocketDebuggerUrl?: string;\n };\n if (!payload.webSocketDebuggerUrl) {\n throw new Error(\"CDP /json/version did not include webSocketDebuggerUrl\");\n }\n\n let wsUrl = payload.webSocketDebuggerUrl;\n const parsed = new URL(wsUrl);\n if (LOCALHOST_HOSTS.has(parsed.hostname)) {\n const base = new URL(baseUrl);\n parsed.hostname = base.hostname;\n parsed.port = base.port;\n parsed.protocol = base.protocol;\n } else {\n // Workers runtime requires fetch + Upgrade header for outbound WebSockets\n parsed.protocol = parsed.protocol === \"wss:\" ? \"https:\" : \"http:\";\n }\n const fetchUrl = parsed.toString();\n\n const wsResponse = await fetch(fetchUrl, {\n headers: { ...options?.headers, Upgrade: \"websocket\" }\n });\n const ws = wsResponse.webSocket;\n if (!ws) {\n throw new Error(\n `Failed to establish CDP WebSocket at ${fetchUrl} (status ${wsResponse.status})`\n );\n }\n ws.accept();\n\n return new CdpConnection(ws, { timeoutMs: options?.timeoutMs });\n}\n\n/** @deprecated Renamed to {@link CdpConnection}. */\nexport const CdpSession = CdpConnection;\n/** @deprecated Renamed to {@link CdpConnection}. */\nexport type CdpSession = CdpConnection;\n","import { CdpConnection } from \"./cdp-connection\";\n\n/**\n * A Browser Rendering binding. Structural so it accepts both the classic\n * `Fetcher`-typed binding and the newer `BrowserRun` type generated by\n * `wrangler types` — we only ever use its `fetch` surface.\n */\nexport interface BrowserBinding {\n fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;\n}\n\n/**\n * Browser Run [hostname guardrails](https://developers.cloudflare.com/browser-run/features/guardrails/):\n * restrict which hostnames the session's HTTP/HTTPS requests may reach. Fixed\n * at session launch for every connection to the session, including Live View.\n * Omitted entirely, the platform default applies: all hostnames are allowed.\n * Not supported by Kitesurf.\n */\nexport interface BrowserSessionGuardrails {\n /**\n * Hostname patterns the browser may request — bare hostnames only (no\n * protocol, port, or path). `*.example.com` matches subdomains; add\n * `example.com` separately to allow the apex.\n */\n allowedDomains?: string[];\n /** Named Cloudflare-maintained domain sets, e.g. `\"common-cdns\"`. */\n allowedDomainSets?: string[];\n}\n\nexport interface BrowserTargetInfo {\n id: string;\n type?: string;\n url?: string;\n title?: string;\n description?: string;\n devtoolsFrontendUrl?: string;\n webSocketDebuggerUrl?: string;\n}\n\nexport interface BrowserSessionInfo {\n sessionId: string;\n targets?: BrowserTargetInfo[];\n webSocketDebuggerUrl?: string;\n}\n\n/** {@link connectBrowser} options for the default Chromium engine. */\nexport interface ConnectChromiumBrowserOptions {\n /** Select the browser engine. Defaults to Chromium. */\n browser?: \"chromium\";\n timeoutMs?: number;\n keepAliveMs?: number;\n includeTargets?: boolean;\n /**\n * Opt into Browser Run [session recording](https://developers.cloudflare.com/browser-run/features/session-recording/):\n * an rrweb capture of DOM changes, input, and navigation, finalized when the\n * session closes. Set at session-launch time. Retrieve later with\n * {@link getBrowserRecording}.\n */\n recording?: boolean;\n}\n\n/**\n * {@link connectBrowser} options for Kitesurf, Cloudflare's connection-scoped,\n * agent-first browser engine. A Kitesurf browser lives and dies with its\n * WebSocket, so the Chromium-only options (`keepAliveMs`, `includeTargets`,\n * `recording`) do not exist on this arm.\n */\nexport interface ConnectKitesurfBrowserOptions {\n browser: \"kitesurf\";\n timeoutMs?: number;\n}\n\n/**\n * Engine-discriminated {@link connectBrowser} options: selecting\n * `browser: \"kitesurf\"` removes the Chromium-only options at the type level.\n */\nexport type ConnectBrowserOptions =\n | ConnectChromiumBrowserOptions\n | ConnectKitesurfBrowserOptions;\n\n/** An rrweb session recording for a closed Browser Run session. */\nexport interface BrowserRecording {\n sessionId: string;\n /** Recording length in milliseconds. */\n duration: number;\n /**\n * rrweb event arrays keyed by CDP target id (one per tab). Each value can be\n * passed directly to `rrweb-player` to replay that tab.\n */\n events: Record<string, unknown[]>;\n}\n\nexport class BrowserRenderingError extends Error {\n constructor(\n message: string,\n readonly status: number\n ) {\n super(message);\n this.name = \"BrowserRenderingError\";\n }\n}\n\n/**\n * Whether an error means the platform session is gone: Browser Run uses 404\n * for unknown ids and 410 after `keep_alive` expiry.\n */\nexport function isMissingBrowserSession(error: unknown): boolean {\n return (\n error instanceof BrowserRenderingError &&\n (error.status === 404 || error.status === 410)\n );\n}\n\nfunction browserSessionEndpoint(\n sessionId?: string,\n options?: {\n keepAliveMs?: number;\n includeTargets?: boolean;\n recording?: boolean;\n browser?: \"kitesurf\";\n }\n): string {\n const path = sessionId\n ? `/v1/devtools/browser/${sessionId}`\n : \"/v1/devtools/browser\";\n const url = new URL(`https://localhost${path}`);\n\n if (options?.keepAliveMs !== undefined) {\n url.searchParams.set(\"keep_alive\", String(options.keepAliveMs));\n }\n if (options?.includeTargets) {\n url.searchParams.set(\"targets\", \"true\");\n }\n if (options?.recording) {\n url.searchParams.set(\"recording\", \"true\");\n }\n if (options?.browser) {\n url.searchParams.set(\"browser\", options.browser);\n }\n\n return url.toString();\n}\n\nasync function parseBrowserSessionInfo(\n response: Response\n): Promise<BrowserSessionInfo> {\n const payload = (await response.json()) as {\n sessionId?: unknown;\n targets?: unknown;\n webSocketDebuggerUrl?: unknown;\n };\n const sessionId =\n typeof payload.sessionId === \"string\" ? payload.sessionId : \"\";\n\n if (!sessionId) {\n throw new Error(\"Browser Rendering response did not include a sessionId\");\n }\n\n return {\n sessionId,\n targets: Array.isArray(payload.targets)\n ? (payload.targets as BrowserTargetInfo[])\n : undefined,\n webSocketDebuggerUrl:\n typeof payload.webSocketDebuggerUrl === \"string\"\n ? payload.webSocketDebuggerUrl\n : undefined\n };\n}\n\nexport async function createBrowserSession(\n browser: BrowserBinding,\n options?: {\n keepAliveMs?: number;\n includeTargets?: boolean;\n recording?: boolean;\n guardrails?: BrowserSessionGuardrails;\n }\n): Promise<BrowserSessionInfo> {\n // Guardrails ride the acquire request's JSON body (the query string only\n // carries scalar options). The endpoint accepts an empty `{}` body —\n // verified against the live acquire API — so the request shape stays\n // uniform whether or not guardrails are set.\n const response = await browser.fetch(\n browserSessionEndpoint(undefined, options),\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(\n options?.guardrails ? { guardrails: options.guardrails } : {}\n )\n }\n );\n\n if (!response.ok) {\n throw new BrowserRenderingError(\n `Failed to create Browser Rendering session: ${response.status}`,\n response.status\n );\n }\n\n return parseBrowserSessionInfo(response);\n}\n\nexport async function listBrowserTargets(\n browser: BrowserBinding,\n sessionId: string\n): Promise<BrowserTargetInfo[]> {\n const response = await browser.fetch(\n `https://localhost/v1/devtools/browser/${sessionId}/json/list`\n );\n\n if (!response.ok) {\n throw new BrowserRenderingError(\n `Failed to list Browser Rendering targets for ${sessionId}: ${response.status}`,\n response.status\n );\n }\n\n const payload = (await response.json()) as unknown;\n return Array.isArray(payload) ? (payload as BrowserTargetInfo[]) : [];\n}\n\nexport async function deleteBrowserSession(\n browser: BrowserBinding,\n sessionId: string\n): Promise<void> {\n const response = await browser.fetch(\n `https://localhost/v1/devtools/browser/${sessionId}`,\n { method: \"DELETE\" }\n );\n\n if (!response.ok && response.status !== 404) {\n throw new BrowserRenderingError(\n `Failed to delete Browser Rendering session ${sessionId}: ${response.status}`,\n response.status\n );\n }\n}\n\n/**\n * Connect to a Browser Rendering session and delete it when closed.\n */\nexport async function connectBrowser(\n browser: BrowserBinding,\n options?: number | ConnectBrowserOptions\n): Promise<CdpConnection> {\n const normalizedOptions: ConnectBrowserOptions =\n typeof options === \"number\" ? { timeoutMs: options } : (options ?? {});\n if (normalizedOptions.browser === \"kitesurf\") {\n // The options union already rejects these at the type level for literal\n // call sites; plain-JS callers and spreads can still smuggle them in.\n // Explicitly disabled values are tolerated but never sent — `keep_alive=0`\n // is not a valid Kitesurf query parameter.\n const smuggled = normalizedOptions as {\n keepAliveMs?: number;\n includeTargets?: boolean;\n recording?: boolean;\n };\n if (smuggled.keepAliveMs || smuggled.includeTargets || smuggled.recording) {\n throw new Error(\n \"Kitesurf does not support keepAliveMs, includeTargets, or recording\"\n );\n }\n }\n\n const response = await browser.fetch(\n browserSessionEndpoint(\n undefined,\n normalizedOptions.browser === \"kitesurf\"\n ? { browser: \"kitesurf\" }\n : {\n keepAliveMs: normalizedOptions.keepAliveMs,\n includeTargets: normalizedOptions.includeTargets,\n recording: normalizedOptions.recording\n }\n ),\n { headers: { Upgrade: \"websocket\" } }\n );\n\n const ws = response.webSocket;\n if (!ws) {\n throw new Error(\n \"Browser Rendering binding did not return a WebSocket. \" +\n \"Ensure the 'browser' binding is configured in wrangler.jsonc.\"\n );\n }\n\n if (normalizedOptions.browser === \"kitesurf\") {\n // A Kitesurf browser is scoped to this WebSocket. Browser Run may return\n // an ID for analytics correlation, but it cannot be used with the\n // session-scoped reconnect or delete endpoints.\n ws.accept();\n return new CdpConnection(ws, { timeoutMs: normalizedOptions.timeoutMs });\n }\n\n const sessionId = response.headers.get(\"cf-browser-session-id\");\n if (!sessionId) {\n throw new Error(\n \"Browser Rendering binding did not include a session ID when opening the CDP WebSocket\"\n );\n }\n\n ws.accept();\n return new CdpConnection(ws, {\n timeoutMs: normalizedOptions.timeoutMs,\n onClose: () => {\n deleteBrowserSession(browser, sessionId).catch((error: unknown) => {\n console.warn(\n `[agents/browser] Failed to delete one-shot Browser Run session ${sessionId}`,\n error\n );\n });\n },\n sessionId\n });\n}\n\n/**\n * Fetch a Browser Run [session recording](https://developers.cloudflare.com/browser-run/features/session-recording/)\n * by session id, via the Browser Rendering REST API.\n *\n * A recording is only available **after** the session closes (explicit\n * `closeSession()`, idle `keep_alive` expiry, or sweep) and is retained for 30\n * days. Capture the session id while the session is alive — e.g. from\n * `connector.liveView()`/`sessionInfo()` — then call this once it has ended.\n *\n * Unlike the binding-based helpers, this hits `api.cloudflare.com` directly, so\n * it needs an account id and an API token with `Browser Rendering` read access\n * (the Workers Browser Run binding cannot read recordings).\n */\nexport async function getBrowserRecording(options: {\n accountId: string;\n apiToken: string;\n sessionId: string;\n /** Override for testing; defaults to the global `fetch`. */\n fetchImpl?: typeof fetch;\n}): Promise<BrowserRecording> {\n const { accountId, apiToken, sessionId } = options;\n const fetchImpl = options.fetchImpl ?? fetch;\n const endpoint = `https://api.cloudflare.com/client/v4/accounts/${accountId}/browser-rendering/recording/${sessionId}`;\n\n const response = await fetchImpl(endpoint, {\n headers: { Authorization: `Bearer ${apiToken}` }\n });\n\n if (!response.ok) {\n throw new BrowserRenderingError(\n `Failed to fetch Browser Run recording for ${sessionId}: ${response.status}`,\n response.status\n );\n }\n\n // The recording endpoint returns the recording object directly; tolerate a\n // standard v4 `{ result }` envelope in case that changes.\n const payload = (await response.json()) as\n | BrowserRecording\n | { result?: BrowserRecording };\n const recording =\n \"result\" in payload && payload.result ? payload.result : payload;\n\n return recording as BrowserRecording;\n}\n\nexport interface ConnectBrowserSessionOptions {\n timeoutMs?: number;\n /**\n * Invoked once when the returned {@link CdpConnection} reaches a terminal\n * state — an explicit `close()`, peer closure, or a socket error. The\n * session itself is never deleted on close — pass an `onClose` that\n * deletes it for one-shot (create-and-close) semantics.\n */\n onClose?: () => void;\n /**\n * Invoked on every CDP command sent over the returned {@link CdpConnection} —\n * an activity signal for idle tracking. Keep it cheap and synchronous;\n * throttle any I/O it triggers.\n */\n onActivity?: () => void;\n}\n\n/**\n * Connect to an existing Browser Rendering session without deleting it on close.\n */\nexport async function connectBrowserSession(\n browser: BrowserBinding,\n sessionId: string,\n options?: ConnectBrowserSessionOptions\n): Promise<CdpConnection>;\n/**\n * @deprecated Pass `{ timeoutMs }` instead of a bare number — the numeric\n * form will be removed.\n */\nexport async function connectBrowserSession(\n browser: BrowserBinding,\n sessionId: string,\n timeoutMs?: number\n): Promise<CdpConnection>;\nexport async function connectBrowserSession(\n browser: BrowserBinding,\n sessionId: string,\n options?: number | ConnectBrowserSessionOptions\n): Promise<CdpConnection> {\n const normalized =\n typeof options === \"number\" ? { timeoutMs: options } : (options ?? {});\n const response = await browser.fetch(browserSessionEndpoint(sessionId), {\n headers: { Upgrade: \"websocket\" }\n });\n\n const ws = response.webSocket;\n if (!ws) {\n // Carry the upgrade status: a 404/410 here means the browser expired\n // after the caller last saw it alive (see isMissingBrowserSession).\n throw new BrowserRenderingError(\n `Browser Rendering binding did not return a WebSocket for session ${sessionId} (${response.status})`,\n response.status\n );\n }\n\n ws.accept();\n return new CdpConnection(ws, {\n timeoutMs: normalized.timeoutMs,\n onClose: normalized.onClose,\n sessionId,\n onActivity: normalized.onActivity\n });\n}\n\n/** One-shot session options for the default Chromium engine. */\nexport interface OneShotChromiumSessionOptions {\n /** Select the browser engine. Defaults to Chromium. */\n browser?: \"chromium\";\n timeoutMs?: number;\n /** Platform `keep_alive` in milliseconds. */\n keepAliveMs?: number;\n /** Opt into Browser Run session recording (rrweb capture). */\n recording?: boolean;\n /** Hostname guardrails, fixed at launch. */\n guardrails?: BrowserSessionGuardrails;\n}\n\n/**\n * One-shot session options for Kitesurf. The Chromium-only options —\n * `guardrails`, `keepAliveMs`, `recording` — do not exist on this arm:\n * Kitesurf does not support them.\n */\nexport interface OneShotKitesurfSessionOptions {\n browser: \"kitesurf\";\n timeoutMs?: number;\n}\n\n/**\n * Engine-discriminated {@link openOneShotBrowserSession} options: selecting\n * `browser: \"kitesurf\"` removes the Chromium-only options at the type level.\n */\nexport type OneShotBrowserSessionOptions =\n | OneShotChromiumSessionOptions\n | OneShotKitesurfSessionOptions;\n\n/**\n * Open a one-shot browser session: create, connect, and delete the platform\n * session when the returned {@link CdpConnection} closes. No store involved —\n * one-shot sessions have no name and no durability.\n */\nexport async function openOneShotBrowserSession(\n browser: BrowserBinding,\n options: OneShotBrowserSessionOptions = {}\n): Promise<CdpConnection> {\n if (options.browser === \"kitesurf\") {\n // The options union already rejects these at the type level for literal\n // call sites; plain-JS callers and spreads can still smuggle them in, so\n // fail loudly in one place with one message.\n const smuggled = options as {\n guardrails?: unknown;\n keepAliveMs?: unknown;\n recording?: unknown;\n };\n if (smuggled.guardrails || smuggled.keepAliveMs || smuggled.recording) {\n throw new Error(\n \"Kitesurf does not support guardrails, keepAliveMs, or recording\"\n );\n }\n // Kitesurf browsers are scoped to their WebSocket — connectBrowser is\n // already one-shot there.\n return connectBrowser(browser, {\n browser: \"kitesurf\",\n timeoutMs: options.timeoutMs\n });\n }\n\n const info = await createBrowserSession(browser, {\n keepAliveMs: options.keepAliveMs,\n recording: options.recording,\n guardrails: options.guardrails\n });\n try {\n return await connectBrowserSession(browser, info.sessionId, {\n timeoutMs: options.timeoutMs,\n onClose: () => {\n deleteBrowserSession(browser, info.sessionId).catch(\n (error: unknown) => {\n console.warn(\n `[agents/browser] Failed to delete one-shot Browser Run session ${info.sessionId}`,\n error\n );\n }\n );\n }\n });\n } catch (error) {\n // The session was allocated but never got its delete-on-close owner —\n // reclaim it now instead of leaving it to expire.\n try {\n await deleteBrowserSession(browser, info.sessionId);\n } catch {\n // Best-effort: keep_alive expiry reclaims it.\n }\n throw error;\n }\n}\n","import { Validator, type OutputUnit, type Schema } from \"@cfworker/json-schema\";\nimport type { ConnectorTool } from \"@cloudflare/codemode\";\n\nfunction formatToolValidationError(\n connector: string,\n tool: string,\n errors: OutputUnit[]\n): string {\n // A failing property emits both a generic parent `properties` error and a\n // specific child error. Prefer the latter so the model sees what to fix.\n const specific = errors.filter((error) => error.keyword !== \"properties\");\n const relevant = specific.length > 0 ? specific : errors;\n const details = relevant.map((error) => {\n const location = error.instanceLocation\n .replace(/^#\\/?/, \"\")\n .replaceAll(\"~1\", \"/\")\n .replaceAll(\"~0\", \"~\")\n .replaceAll(\"/\", \".\");\n return `${location ? ` at ${location}` : \"\"}: ${error.error}`;\n });\n return `Invalid arguments for ${connector}.${tool}${details.join(\";\")}`;\n}\n\n/**\n * Validate a connector tool's arguments against its input schema before it\n * runs, so the model gets a precise error instead of a failure deep inside\n * browser work. An omitted argument counts as `{}`: argumentless tools are\n * documented as `cdp.spec()`.\n */\nexport function validateConnectorArgs(\n connector: string,\n name: string,\n tool: ConnectorTool\n): ConnectorTool {\n if (!tool.inputSchema) return tool;\n\n // Both types describe draft-7 schemas, but @cfworker's `Schema` type is\n // narrower than JSONSchema7 around boolean subschemas.\n const schema = tool.inputSchema as unknown as Schema;\n const validator = new Validator(schema, \"7\", false);\n return {\n ...tool,\n execute: async (args, ctx) => {\n const input = args === undefined ? {} : args;\n const result = validator.validate(input);\n if (!result.valid) {\n throw new Error(\n formatToolValidationError(connector, name, result.errors)\n );\n }\n return await tool.execute(input, ctx);\n }\n };\n}\n","/**\n * Live View vocabulary shared by every host-side surface that mints links:\n * the connector's `getLiveViewUrl` tool and `Browser.liveView()`. Live View\n * URLs are bearer credentials — mint them fresh from a target listing when a\n * human is about to view, and never persist them.\n */\n\nimport type { BrowserTargetInfo } from \"./browser-run\";\n\n/**\n * Live View rendering mode (the `mode` query param the hosted UI at\n * `live.browser.run` understands):\n *\n * - `\"tab\"` — a standalone, interactive page view (best for handing control\n * to a human).\n * - `\"devtools\"` — the full DevTools inspector panel (Elements, Console,\n * Network, …).\n *\n * Omit it to use whatever mode the binding's `devtoolsFrontendUrl` defaults\n * to.\n */\nexport type LiveViewMode = \"tab\" | \"devtools\";\n\n/** A single tab's Live View URL. */\nexport interface BrowserLiveViewUrl {\n /** Open this in a browser to watch/control the tab in real time. */\n url: string;\n /** CDP target (tab) id the URL points at. */\n targetId: string;\n /** Milliseconds the URL stays valid from when it was generated (~5 min). */\n expiresInMs: number;\n}\n\nexport interface BrowserLiveViewTarget {\n targetId: string;\n /** Embeddable Live View URL (the `devtoolsFrontendUrl`) for this tab. */\n url: string;\n /** The page the tab is currently showing (e.g. `https://example.com`). */\n pageUrl?: string;\n title?: string;\n type?: string;\n}\n\n/** Live View URLs for every tab in a session. */\nexport interface BrowserLiveView {\n sessionId: string;\n targets: BrowserLiveViewTarget[];\n /** Milliseconds the URLs stay valid from when they were generated (~5 min). */\n expiresInMs: number;\n}\n\n/**\n * Browser Run mints `devtoolsFrontendUrl`s (the Live View links) that are\n * valid for ~5 minutes. We surface the window so callers can decide how long\n * a shared link is good for before re-listing targets.\n */\nexport const LIVE_VIEW_URL_TTL_MS = 5 * 60 * 1000;\n\n/**\n * Rewrite the hosted Live View UI's `mode` query param (`tab` | `devtools`).\n * The raw `devtoolsFrontendUrl` is returned unchanged when no mode is asked\n * for or the URL can't be parsed.\n */\nexport function applyLiveViewMode(rawUrl: string, mode?: LiveViewMode): string {\n if (!mode) return rawUrl;\n try {\n const url = new URL(rawUrl);\n url.searchParams.set(\"mode\", mode === \"devtools\" ? \"devtools\" : \"tab\");\n return url.toString();\n } catch {\n return rawUrl;\n }\n}\n\n/**\n * Project a fresh target listing into Live View links — one per tab that has\n * a `devtoolsFrontendUrl`. Pure; the caller supplies just-listed targets.\n */\nexport function createLiveView(\n sessionId: string,\n targets: BrowserTargetInfo[],\n mode?: LiveViewMode\n): BrowserLiveView {\n return {\n sessionId,\n targets: targets\n .filter((target) => target.devtoolsFrontendUrl)\n .map((target) => ({\n targetId: target.id,\n url: applyLiveViewMode(target.devtoolsFrontendUrl!, mode),\n pageUrl: target.url,\n title: target.title,\n type: target.type\n })),\n expiresInMs: LIVE_VIEW_URL_TTL_MS\n };\n}\n","/**\n * Chrome DevTools Protocol spec fetching + caching.\n *\n * The raw `/json/protocol` payload is normalized into a searchable shape and\n * cached per source: `cdpUrl` specs by endpoint + headers, Browser Rendering\n * specs by the binding itself (a WeakMap) so two different bindings in the\n * same isolate don't share an entry. The CDP protocol is identical across\n * bindings, but per-binding keys avoid surprising cross-binding cache reads.\n */\n\nimport type { BrowserBinding } from \"./browser-run\";\n\n/** A parameter, return value, or type property in the raw protocol. */\ninterface RawCdpField {\n name: string;\n description?: string;\n optional?: boolean;\n experimental?: boolean;\n deprecated?: boolean;\n type?: string;\n $ref?: string;\n enum?: string[];\n items?: { type?: string; $ref?: string; enum?: string[] };\n}\n\ninterface RawCdpCommand {\n name: string;\n description?: string;\n experimental?: boolean;\n deprecated?: boolean;\n parameters?: RawCdpField[];\n returns?: RawCdpField[];\n}\n\ninterface RawCdpEvent {\n name: string;\n description?: string;\n experimental?: boolean;\n deprecated?: boolean;\n parameters?: RawCdpField[];\n}\n\ninterface RawCdpType {\n id: string;\n description?: string;\n experimental?: boolean;\n deprecated?: boolean;\n type?: string;\n enum?: string[];\n properties?: RawCdpField[];\n items?: { type?: string; $ref?: string; enum?: string[] };\n}\n\n/** Raw CDP protocol domain from `/json/protocol` */\ninterface RawCdpDomain {\n domain: string;\n description?: string;\n experimental?: boolean;\n deprecated?: boolean;\n commands?: RawCdpCommand[];\n events?: RawCdpEvent[];\n types?: RawCdpType[];\n}\n\n/**\n * The element type of an array field or type. `$ref` is always\n * domain-qualified (`\"Network.Cookie\"`), matching a type's `name`.\n */\nexport interface CdpItems {\n type?: string;\n $ref?: string;\n enum?: string[];\n}\n\n/**\n * A command parameter, return value, event parameter, or type property.\n * Either `type` (a JSON type such as `\"string\"` or `\"array\"`) or `$ref`\n * (a domain-qualified type name matching a type's `name`) is set.\n */\nexport interface CdpField {\n name: string;\n description?: string;\n optional?: boolean;\n experimental?: boolean;\n deprecated?: boolean;\n type?: string;\n $ref?: string;\n enum?: string[];\n items?: CdpItems;\n}\n\nexport interface SearchableCdpSpec {\n domains: Array<{\n name: string;\n description?: string;\n experimental?: boolean;\n deprecated?: boolean;\n commands: Array<{\n name: string;\n method: string;\n description?: string;\n experimental?: boolean;\n deprecated?: boolean;\n parameters: CdpField[];\n returns: CdpField[];\n }>;\n events: Array<{\n name: string;\n event: string;\n description?: string;\n experimental?: boolean;\n deprecated?: boolean;\n parameters: CdpField[];\n }>;\n types: Array<{\n id: string;\n name: string;\n description?: string;\n experimental?: boolean;\n deprecated?: boolean;\n /** JSON type of the value, e.g. `\"string\"`, `\"object\"`, `\"array\"`. */\n type?: string;\n enum?: string[];\n properties: CdpField[];\n items?: CdpItems;\n }>;\n }>;\n}\n\nexport interface CdpSpecSource {\n /** Browser Rendering binding (Fetcher) — used in production */\n browser?: BrowserBinding;\n /** CDP base URL override (e.g. http://localhost:9222) */\n cdpUrl?: string;\n /** Headers to send with CDP URL discovery requests */\n cdpHeaders?: Record<string, string>;\n /**\n * An existing Browser Run session to read the protocol from. Without it,\n * loading through the binding creates (and deletes) a throwaway session.\n */\n sessionId?: string;\n}\n\nconst MISSING_BROWSER_CONFIG =\n \"Either 'browser' (Fetcher binding) or 'cdpUrl' must be provided\";\n\ninterface SpecCacheEntry {\n spec: SearchableCdpSpec;\n cachedAt: number;\n}\n\nconst urlSpecCache = new Map<string, SpecCacheEntry>();\nconst bindingSpecCache = new WeakMap<BrowserBinding, SpecCacheEntry>();\n\nconst CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes\n\n/** Qualify a same-domain `$ref` (`\"FrameId\"` → `\"Page.FrameId\"`). */\nfunction qualifyRef(domain: string, ref: string | undefined) {\n if (ref === undefined) return undefined;\n return ref.includes(\".\") ? ref : `${domain}.${ref}`;\n}\n\nfunction normalizeItems(\n domain: string,\n items: RawCdpType[\"items\"]\n): CdpItems | undefined {\n if (!items) return undefined;\n return {\n type: items.type,\n $ref: qualifyRef(domain, items.$ref),\n enum: items.enum\n };\n}\n\nfunction normalizeFields(\n domain: string,\n fields: RawCdpField[] | undefined\n): CdpField[] {\n return (fields ?? []).map((field) => ({\n name: field.name,\n description: field.description,\n optional: field.optional,\n experimental: field.experimental,\n deprecated: field.deprecated,\n type: field.type,\n $ref: qualifyRef(domain, field.$ref),\n enum: field.enum,\n items: normalizeItems(domain, field.items)\n }));\n}\n\nfunction normalizeCdpSpec(spec: {\n domains?: RawCdpDomain[];\n}): SearchableCdpSpec {\n return {\n domains: (spec.domains ?? []).map(({ domain, ...raw }) => ({\n name: domain,\n description: raw.description,\n experimental: raw.experimental,\n deprecated: raw.deprecated,\n commands: (raw.commands ?? []).map((command) => ({\n name: command.name,\n method: `${domain}.${command.name}`,\n description: command.description,\n experimental: command.experimental,\n deprecated: command.deprecated,\n parameters: normalizeFields(domain, command.parameters),\n returns: normalizeFields(domain, command.returns)\n })),\n events: (raw.events ?? []).map((event) => ({\n name: event.name,\n event: `${domain}.${event.name}`,\n description: event.description,\n experimental: event.experimental,\n deprecated: event.deprecated,\n parameters: normalizeFields(domain, event.parameters)\n })),\n types: (raw.types ?? []).map((type) => ({\n id: type.id,\n name: `${domain}.${type.id}`,\n description: type.description,\n experimental: type.experimental,\n deprecated: type.deprecated,\n type: type.type,\n enum: type.enum,\n properties: normalizeFields(domain, type.properties),\n items: normalizeItems(domain, type.items)\n }))\n }))\n };\n}\n\nfunction getSpecCacheKey(\n source: string,\n headers?: Record<string, string>\n): string {\n const headerEntries = Object.entries(headers ?? {}).sort(([a], [b]) =>\n a.localeCompare(b)\n );\n return `${source}:${JSON.stringify(headerEntries)}`;\n}\n\nasync function getCachedSpec<K>(\n cache: {\n get(key: K): SpecCacheEntry | undefined;\n set(key: K, entry: SpecCacheEntry): void;\n },\n key: K,\n load: () => Promise<{ domains?: RawCdpDomain[] }>\n): Promise<SearchableCdpSpec> {\n const cached = cache.get(key);\n if (cached && Date.now() - cached.cachedAt < CACHE_TTL_MS) {\n return cached.spec;\n }\n\n const spec = normalizeCdpSpec(await load());\n cache.set(key, { spec, cachedAt: Date.now() });\n return spec;\n}\n\nasync function fetchCdpSpecFromUrl(\n cdpBaseUrl: string,\n headers?: Record<string, string>\n): Promise<SearchableCdpSpec> {\n const endpoint = new URL(\"/json/protocol\", cdpBaseUrl).toString();\n\n return getCachedSpec(\n urlSpecCache,\n getSpecCacheKey(endpoint, headers),\n async () => {\n const response = await fetch(endpoint, { headers });\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch CDP spec from ${endpoint}: ${response.status}`\n );\n }\n\n return (await response.json()) as { domains?: RawCdpDomain[] };\n }\n );\n}\n\nasync function fetchCdpSpecFromSession(\n browser: BrowserBinding,\n sessionId: string\n): Promise<SearchableCdpSpec> {\n return getCachedSpec(bindingSpecCache, browser, async () => {\n const response = await browser.fetch(\n `https://localhost/v1/devtools/browser/${sessionId}/json/protocol`\n );\n if (!response.ok) {\n throw new Error(\n `Failed to fetch CDP spec from Browser Rendering: ${response.status}`\n );\n }\n return (await response.json()) as { domains?: RawCdpDomain[] };\n });\n}\n\nasync function fetchCdpSpecFromBrowser(\n browser: BrowserBinding\n): Promise<SearchableCdpSpec> {\n return getCachedSpec(bindingSpecCache, browser, async () => {\n const createResponse = await browser.fetch(\n \"https://localhost/v1/devtools/browser\",\n {\n method: \"POST\"\n }\n );\n\n if (!createResponse.ok) {\n throw new Error(\n \"Failed to create Browser Rendering session for protocol fetch: \" +\n `${createResponse.status}`\n );\n }\n\n const payload = (await createResponse.json()) as { sessionId?: string };\n const sessionId = payload.sessionId;\n if (!sessionId) {\n throw new Error(\n \"Browser Rendering session response did not include a sessionId\"\n );\n }\n\n try {\n const response = await browser.fetch(\n `https://localhost/v1/devtools/browser/${sessionId}/json/protocol`\n );\n\n if (!response.ok) {\n throw new Error(\n \"Failed to fetch CDP spec from Browser Rendering: \" +\n `${response.status}`\n );\n }\n\n return (await response.json()) as { domains?: RawCdpDomain[] };\n } finally {\n try {\n await browser.fetch(\n `https://localhost/v1/devtools/browser/${sessionId}`,\n {\n method: \"DELETE\"\n }\n );\n } catch {\n // Cleanup failure should not mask the original result or error\n }\n }\n });\n}\n\n/** Load the (cached) searchable CDP spec for a browser source. */\nexport async function loadCdpSpec(\n source: CdpSpecSource\n): Promise<SearchableCdpSpec> {\n if (source.cdpUrl) {\n return fetchCdpSpecFromUrl(source.cdpUrl, source.cdpHeaders);\n }\n if (source.browser && source.sessionId) {\n return fetchCdpSpecFromSession(source.browser, source.sessionId);\n }\n if (source.browser) {\n return fetchCdpSpecFromBrowser(source.browser);\n }\n throw new Error(MISSING_BROWSER_CONFIG);\n}\n","type MaybePromise<T> = T | Promise<T>;\n\nexport interface StoredBrowserSession {\n sessionId: string;\n createdAt: number;\n updatedAt: number;\n /**\n * Set when a sweep closed this entry's Browser Run session but kept the\n * entry as a tombstone, so a later resume of the owning execution fails\n * loudly instead of silently continuing in a fresh browser.\n */\n closedAt?: number;\n /**\n * Browser scope records only: the tab (CDP `targetId`) the scope last\n * worked in, so `sessionId: \"active\"` in a later execution lands on the\n * same page. CDP session ids die with each connection; target ids live as\n * long as the tab.\n */\n activeTargetId?: string;\n}\n\nexport interface BrowserSessionLock {\n release(): MaybePromise<void>;\n}\n\nexport interface BrowserSessionStore {\n /**\n * Acquire an exclusive lock for this session key. The lock must serialize\n * all holders using the same key. Held only around storage reads/writes —\n * never across Browser Rendering network calls.\n */\n acquireLock(key: string): MaybePromise<BrowserSessionLock>;\n get(key: string): MaybePromise<StoredBrowserSession | undefined>;\n set(key: string, session: StoredBrowserSession): MaybePromise<void>;\n delete(key: string): MaybePromise<void>;\n /**\n * List stored sessions by key prefix. Optional — used by sweeps to find\n * orphaned per-execution sessions; without it only the shared session key\n * is swept.\n */\n list?(prefix: string): MaybePromise<Map<string, StoredBrowserSession>>;\n}\n\n/**\n * A {@link BrowserSessionStore} that can list by prefix, as `Browser` needs:\n * it lists a browser's scope records to cap them and to see which tabs\n * other scopes are working in.\n */\nexport type ListableBrowserSessionStore = BrowserSessionStore &\n Required<Pick<BrowserSessionStore, \"list\">>;\n\nexport class DurableBrowserSessionStore implements BrowserSessionStore {\n static #queues = new WeakMap<\n DurableObjectStorage,\n Map<string, Promise<void>>\n >();\n\n constructor(private readonly storage: DurableObjectStorage) {}\n\n async acquireLock(key: string): Promise<BrowserSessionLock> {\n let queues = DurableBrowserSessionStore.#queues.get(this.storage);\n if (!queues) {\n queues = new Map();\n DurableBrowserSessionStore.#queues.set(this.storage, queues);\n }\n\n const previous = queues.get(key) ?? Promise.resolve();\n let releaseQueue: () => void = () => undefined;\n const current = previous.then(\n () =>\n new Promise<void>((resolve) => {\n releaseQueue = resolve;\n })\n );\n queues.set(key, current);\n await previous;\n\n let released = false;\n return {\n release: () => {\n if (released) return;\n released = true;\n if (queues.get(key) === current) {\n queues.delete(key);\n }\n releaseQueue();\n }\n };\n }\n\n async get(key: string): Promise<StoredBrowserSession | undefined> {\n return this.storage.get<StoredBrowserSession>(this.#storageKey(key));\n }\n\n async set(key: string, session: StoredBrowserSession): Promise<void> {\n await this.storage.put(this.#storageKey(key), session);\n }\n\n async delete(key: string): Promise<void> {\n await this.storage.delete(this.#storageKey(key));\n }\n\n async list(prefix: string): Promise<Map<string, StoredBrowserSession>> {\n const storagePrefix = this.#storageKey(prefix);\n const entries = await this.storage.list<StoredBrowserSession>({\n prefix: storagePrefix\n });\n const result = new Map<string, StoredBrowserSession>();\n for (const [storageKey, value] of entries) {\n result.set(storageKey.slice(\"browser-session:\".length), value);\n }\n return result;\n }\n\n #storageKey(key: string): string {\n return `browser-session:${key}`;\n }\n}\n\n/**\n * Default idle window used by {@link BrowserConnector.sweep} for the shared\n * (reuse/promoted) session entry.\n */\nexport const DEFAULT_SWEEP_IDLE_MS = 10 * 60 * 1000;\n"],"mappings":"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"}
|
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
//#region src/browser/cdp-connection.d.ts
|
|
2
|
+
interface DebugEntry {
|
|
3
|
+
at: string;
|
|
4
|
+
type: string;
|
|
5
|
+
[key: string]: unknown;
|
|
6
|
+
}
|
|
7
|
+
interface CdpSendOptions {
|
|
8
|
+
timeoutMs?: number;
|
|
9
|
+
sessionId?: string;
|
|
10
|
+
}
|
|
11
|
+
interface CdpAttachOptions {
|
|
12
|
+
timeoutMs?: number;
|
|
13
|
+
}
|
|
14
|
+
/** Construction options for {@link CdpConnection}. */
|
|
15
|
+
interface CdpConnectionOptions {
|
|
16
|
+
/** Default per-command timeout. Defaults to 10 seconds. */
|
|
17
|
+
timeoutMs?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Invoked exactly once when the session reaches a terminal state — an
|
|
20
|
+
* explicit `close()`, peer closure, or a socket error.
|
|
21
|
+
*/
|
|
22
|
+
onClose?: () => void;
|
|
23
|
+
/** Browser Run session id, when connected to a session-scoped browser. */
|
|
24
|
+
sessionId?: string;
|
|
25
|
+
/** Invoked on every CDP command sent — an activity signal for idle tracking. */
|
|
26
|
+
onActivity?: () => void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* One Chrome DevTools Protocol connection over an open WebSocket. Manages
|
|
30
|
+
* command correlation, timeouts, per-tab CDP sessions, and a debug event
|
|
31
|
+
* ring buffer.
|
|
32
|
+
*
|
|
33
|
+
* Used host-side (not in the sandbox) — the sandbox calls into this
|
|
34
|
+
* via DynamicWorkerExecutor's ToolDispatcher RPC.
|
|
35
|
+
*/
|
|
36
|
+
declare class CdpConnection {
|
|
37
|
+
#private;
|
|
38
|
+
readonly sessionId?: string;
|
|
39
|
+
constructor(socket: WebSocket, options?: CdpConnectionOptions);
|
|
40
|
+
/**
|
|
41
|
+
* @deprecated Pass a {@link CdpConnectionOptions} object instead —
|
|
42
|
+
* `new CdpConnection(socket, { timeoutMs, onClose, sessionId })`. The
|
|
43
|
+
* positional form will be removed.
|
|
44
|
+
*/
|
|
45
|
+
constructor(
|
|
46
|
+
socket: WebSocket,
|
|
47
|
+
timeoutMs?: number,
|
|
48
|
+
onClose?: () => void,
|
|
49
|
+
sessionId?: string
|
|
50
|
+
);
|
|
51
|
+
send(
|
|
52
|
+
method: string,
|
|
53
|
+
params?: unknown,
|
|
54
|
+
options?: CdpSendOptions
|
|
55
|
+
): Promise<unknown>;
|
|
56
|
+
attachToTarget(targetId: string, options?: CdpAttachOptions): Promise<string>;
|
|
57
|
+
getDebugLog(limit?: number): DebugEntry[];
|
|
58
|
+
clearDebugLog(): void;
|
|
59
|
+
disconnect(): void;
|
|
60
|
+
close(): void;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Connect to a browser via a CDP base URL (e.g. http://localhost:9222).
|
|
64
|
+
* Discovers the WebSocket debugger URL via /json/version,
|
|
65
|
+
* rewrites localhost URLs to the base URL host, and opens the WebSocket.
|
|
66
|
+
*
|
|
67
|
+
* Useful for local development with `chrome --remote-debugging-port=9222`
|
|
68
|
+
* or when connecting through a tunnel.
|
|
69
|
+
*/
|
|
70
|
+
declare function connectUrl(
|
|
71
|
+
baseUrl: string,
|
|
72
|
+
options?: {
|
|
73
|
+
timeoutMs?: number;
|
|
74
|
+
headers?: Record<string, string>;
|
|
75
|
+
}
|
|
76
|
+
): Promise<CdpConnection>;
|
|
77
|
+
/** @deprecated Renamed to {@link CdpConnection}. */
|
|
78
|
+
declare const CdpSession: typeof CdpConnection;
|
|
79
|
+
/** @deprecated Renamed to {@link CdpConnection}. */
|
|
80
|
+
type CdpSession = CdpConnection;
|
|
81
|
+
//#endregion
|
|
82
|
+
//#region src/browser/browser-run.d.ts
|
|
83
|
+
/**
|
|
84
|
+
* A Browser Rendering binding. Structural so it accepts both the classic
|
|
85
|
+
* `Fetcher`-typed binding and the newer `BrowserRun` type generated by
|
|
86
|
+
* `wrangler types` — we only ever use its `fetch` surface.
|
|
87
|
+
*/
|
|
88
|
+
interface BrowserBinding {
|
|
89
|
+
fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Browser Run [hostname guardrails](https://developers.cloudflare.com/browser-run/features/guardrails/):
|
|
93
|
+
* restrict which hostnames the session's HTTP/HTTPS requests may reach. Fixed
|
|
94
|
+
* at session launch for every connection to the session, including Live View.
|
|
95
|
+
* Omitted entirely, the platform default applies: all hostnames are allowed.
|
|
96
|
+
* Not supported by Kitesurf.
|
|
97
|
+
*/
|
|
98
|
+
interface BrowserSessionGuardrails {
|
|
99
|
+
/**
|
|
100
|
+
* Hostname patterns the browser may request — bare hostnames only (no
|
|
101
|
+
* protocol, port, or path). `*.example.com` matches subdomains; add
|
|
102
|
+
* `example.com` separately to allow the apex.
|
|
103
|
+
*/
|
|
104
|
+
allowedDomains?: string[];
|
|
105
|
+
/** Named Cloudflare-maintained domain sets, e.g. `"common-cdns"`. */
|
|
106
|
+
allowedDomainSets?: string[];
|
|
107
|
+
}
|
|
108
|
+
interface BrowserTargetInfo {
|
|
109
|
+
id: string;
|
|
110
|
+
type?: string;
|
|
111
|
+
url?: string;
|
|
112
|
+
title?: string;
|
|
113
|
+
description?: string;
|
|
114
|
+
devtoolsFrontendUrl?: string;
|
|
115
|
+
webSocketDebuggerUrl?: string;
|
|
116
|
+
}
|
|
117
|
+
interface BrowserSessionInfo {
|
|
118
|
+
sessionId: string;
|
|
119
|
+
targets?: BrowserTargetInfo[];
|
|
120
|
+
webSocketDebuggerUrl?: string;
|
|
121
|
+
}
|
|
122
|
+
/** {@link connectBrowser} options for the default Chromium engine. */
|
|
123
|
+
interface ConnectChromiumBrowserOptions {
|
|
124
|
+
/** Select the browser engine. Defaults to Chromium. */
|
|
125
|
+
browser?: "chromium";
|
|
126
|
+
timeoutMs?: number;
|
|
127
|
+
keepAliveMs?: number;
|
|
128
|
+
includeTargets?: boolean;
|
|
129
|
+
/**
|
|
130
|
+
* Opt into Browser Run [session recording](https://developers.cloudflare.com/browser-run/features/session-recording/):
|
|
131
|
+
* an rrweb capture of DOM changes, input, and navigation, finalized when the
|
|
132
|
+
* session closes. Set at session-launch time. Retrieve later with
|
|
133
|
+
* {@link getBrowserRecording}.
|
|
134
|
+
*/
|
|
135
|
+
recording?: boolean;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* {@link connectBrowser} options for Kitesurf, Cloudflare's connection-scoped,
|
|
139
|
+
* agent-first browser engine. A Kitesurf browser lives and dies with its
|
|
140
|
+
* WebSocket, so the Chromium-only options (`keepAliveMs`, `includeTargets`,
|
|
141
|
+
* `recording`) do not exist on this arm.
|
|
142
|
+
*/
|
|
143
|
+
interface ConnectKitesurfBrowserOptions {
|
|
144
|
+
browser: "kitesurf";
|
|
145
|
+
timeoutMs?: number;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Engine-discriminated {@link connectBrowser} options: selecting
|
|
149
|
+
* `browser: "kitesurf"` removes the Chromium-only options at the type level.
|
|
150
|
+
*/
|
|
151
|
+
type ConnectBrowserOptions =
|
|
152
|
+
| ConnectChromiumBrowserOptions
|
|
153
|
+
| ConnectKitesurfBrowserOptions;
|
|
154
|
+
/** An rrweb session recording for a closed Browser Run session. */
|
|
155
|
+
interface BrowserRecording {
|
|
156
|
+
sessionId: string;
|
|
157
|
+
/** Recording length in milliseconds. */
|
|
158
|
+
duration: number;
|
|
159
|
+
/**
|
|
160
|
+
* rrweb event arrays keyed by CDP target id (one per tab). Each value can be
|
|
161
|
+
* passed directly to `rrweb-player` to replay that tab.
|
|
162
|
+
*/
|
|
163
|
+
events: Record<string, unknown[]>;
|
|
164
|
+
}
|
|
165
|
+
declare class BrowserRenderingError extends Error {
|
|
166
|
+
readonly status: number;
|
|
167
|
+
constructor(message: string, status: number);
|
|
168
|
+
}
|
|
169
|
+
declare function createBrowserSession(
|
|
170
|
+
browser: BrowserBinding,
|
|
171
|
+
options?: {
|
|
172
|
+
keepAliveMs?: number;
|
|
173
|
+
includeTargets?: boolean;
|
|
174
|
+
recording?: boolean;
|
|
175
|
+
guardrails?: BrowserSessionGuardrails;
|
|
176
|
+
}
|
|
177
|
+
): Promise<BrowserSessionInfo>;
|
|
178
|
+
declare function listBrowserTargets(
|
|
179
|
+
browser: BrowserBinding,
|
|
180
|
+
sessionId: string
|
|
181
|
+
): Promise<BrowserTargetInfo[]>;
|
|
182
|
+
declare function deleteBrowserSession(
|
|
183
|
+
browser: BrowserBinding,
|
|
184
|
+
sessionId: string
|
|
185
|
+
): Promise<void>;
|
|
186
|
+
/**
|
|
187
|
+
* Connect to a Browser Rendering session and delete it when closed.
|
|
188
|
+
*/
|
|
189
|
+
declare function connectBrowser(
|
|
190
|
+
browser: BrowserBinding,
|
|
191
|
+
options?: number | ConnectBrowserOptions
|
|
192
|
+
): Promise<CdpConnection>;
|
|
193
|
+
/**
|
|
194
|
+
* Fetch a Browser Run [session recording](https://developers.cloudflare.com/browser-run/features/session-recording/)
|
|
195
|
+
* by session id, via the Browser Rendering REST API.
|
|
196
|
+
*
|
|
197
|
+
* A recording is only available **after** the session closes (explicit
|
|
198
|
+
* `closeSession()`, idle `keep_alive` expiry, or sweep) and is retained for 30
|
|
199
|
+
* days. Capture the session id while the session is alive — e.g. from
|
|
200
|
+
* `connector.liveView()`/`sessionInfo()` — then call this once it has ended.
|
|
201
|
+
*
|
|
202
|
+
* Unlike the binding-based helpers, this hits `api.cloudflare.com` directly, so
|
|
203
|
+
* it needs an account id and an API token with `Browser Rendering` read access
|
|
204
|
+
* (the Workers Browser Run binding cannot read recordings).
|
|
205
|
+
*/
|
|
206
|
+
declare function getBrowserRecording(options: {
|
|
207
|
+
accountId: string;
|
|
208
|
+
apiToken: string;
|
|
209
|
+
sessionId: string /** Override for testing; defaults to the global `fetch`. */;
|
|
210
|
+
fetchImpl?: typeof fetch;
|
|
211
|
+
}): Promise<BrowserRecording>;
|
|
212
|
+
interface ConnectBrowserSessionOptions {
|
|
213
|
+
timeoutMs?: number;
|
|
214
|
+
/**
|
|
215
|
+
* Invoked once when the returned {@link CdpConnection} reaches a terminal
|
|
216
|
+
* state — an explicit `close()`, peer closure, or a socket error. The
|
|
217
|
+
* session itself is never deleted on close — pass an `onClose` that
|
|
218
|
+
* deletes it for one-shot (create-and-close) semantics.
|
|
219
|
+
*/
|
|
220
|
+
onClose?: () => void;
|
|
221
|
+
/**
|
|
222
|
+
* Invoked on every CDP command sent over the returned {@link CdpConnection} —
|
|
223
|
+
* an activity signal for idle tracking. Keep it cheap and synchronous;
|
|
224
|
+
* throttle any I/O it triggers.
|
|
225
|
+
*/
|
|
226
|
+
onActivity?: () => void;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Connect to an existing Browser Rendering session without deleting it on close.
|
|
230
|
+
*/
|
|
231
|
+
declare function connectBrowserSession(
|
|
232
|
+
browser: BrowserBinding,
|
|
233
|
+
sessionId: string,
|
|
234
|
+
options?: ConnectBrowserSessionOptions
|
|
235
|
+
): Promise<CdpConnection>;
|
|
236
|
+
/**
|
|
237
|
+
* @deprecated Pass `{ timeoutMs }` instead of a bare number — the numeric
|
|
238
|
+
* form will be removed.
|
|
239
|
+
*/
|
|
240
|
+
declare function connectBrowserSession(
|
|
241
|
+
browser: BrowserBinding,
|
|
242
|
+
sessionId: string,
|
|
243
|
+
timeoutMs?: number
|
|
244
|
+
): Promise<CdpConnection>;
|
|
245
|
+
//#endregion
|
|
246
|
+
//#region src/browser/live-view.d.ts
|
|
247
|
+
/**
|
|
248
|
+
* Live View rendering mode (the `mode` query param the hosted UI at
|
|
249
|
+
* `live.browser.run` understands):
|
|
250
|
+
*
|
|
251
|
+
* - `"tab"` — a standalone, interactive page view (best for handing control
|
|
252
|
+
* to a human).
|
|
253
|
+
* - `"devtools"` — the full DevTools inspector panel (Elements, Console,
|
|
254
|
+
* Network, …).
|
|
255
|
+
*
|
|
256
|
+
* Omit it to use whatever mode the binding's `devtoolsFrontendUrl` defaults
|
|
257
|
+
* to.
|
|
258
|
+
*/
|
|
259
|
+
type LiveViewMode = "tab" | "devtools";
|
|
260
|
+
/** A single tab's Live View URL. */
|
|
261
|
+
interface BrowserLiveViewUrl {
|
|
262
|
+
/** Open this in a browser to watch/control the tab in real time. */
|
|
263
|
+
url: string;
|
|
264
|
+
/** CDP target (tab) id the URL points at. */
|
|
265
|
+
targetId: string;
|
|
266
|
+
/** Milliseconds the URL stays valid from when it was generated (~5 min). */
|
|
267
|
+
expiresInMs: number;
|
|
268
|
+
}
|
|
269
|
+
interface BrowserLiveViewTarget {
|
|
270
|
+
targetId: string;
|
|
271
|
+
/** Embeddable Live View URL (the `devtoolsFrontendUrl`) for this tab. */
|
|
272
|
+
url: string;
|
|
273
|
+
/** The page the tab is currently showing (e.g. `https://example.com`). */
|
|
274
|
+
pageUrl?: string;
|
|
275
|
+
title?: string;
|
|
276
|
+
type?: string;
|
|
277
|
+
}
|
|
278
|
+
/** Live View URLs for every tab in a session. */
|
|
279
|
+
interface BrowserLiveView {
|
|
280
|
+
sessionId: string;
|
|
281
|
+
targets: BrowserLiveViewTarget[];
|
|
282
|
+
/** Milliseconds the URLs stay valid from when they were generated (~5 min). */
|
|
283
|
+
expiresInMs: number;
|
|
284
|
+
}
|
|
285
|
+
//#endregion
|
|
286
|
+
//#region src/browser/session-store.d.ts
|
|
287
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
288
|
+
interface StoredBrowserSession {
|
|
289
|
+
sessionId: string;
|
|
290
|
+
createdAt: number;
|
|
291
|
+
updatedAt: number;
|
|
292
|
+
/**
|
|
293
|
+
* Set when a sweep closed this entry's Browser Run session but kept the
|
|
294
|
+
* entry as a tombstone, so a later resume of the owning execution fails
|
|
295
|
+
* loudly instead of silently continuing in a fresh browser.
|
|
296
|
+
*/
|
|
297
|
+
closedAt?: number;
|
|
298
|
+
/**
|
|
299
|
+
* Browser scope records only: the tab (CDP `targetId`) the scope last
|
|
300
|
+
* worked in, so `sessionId: "active"` in a later execution lands on the
|
|
301
|
+
* same page. CDP session ids die with each connection; target ids live as
|
|
302
|
+
* long as the tab.
|
|
303
|
+
*/
|
|
304
|
+
activeTargetId?: string;
|
|
305
|
+
}
|
|
306
|
+
interface BrowserSessionLock {
|
|
307
|
+
release(): MaybePromise<void>;
|
|
308
|
+
}
|
|
309
|
+
interface BrowserSessionStore {
|
|
310
|
+
/**
|
|
311
|
+
* Acquire an exclusive lock for this session key. The lock must serialize
|
|
312
|
+
* all holders using the same key. Held only around storage reads/writes —
|
|
313
|
+
* never across Browser Rendering network calls.
|
|
314
|
+
*/
|
|
315
|
+
acquireLock(key: string): MaybePromise<BrowserSessionLock>;
|
|
316
|
+
get(key: string): MaybePromise<StoredBrowserSession | undefined>;
|
|
317
|
+
set(key: string, session: StoredBrowserSession): MaybePromise<void>;
|
|
318
|
+
delete(key: string): MaybePromise<void>;
|
|
319
|
+
/**
|
|
320
|
+
* List stored sessions by key prefix. Optional — used by sweeps to find
|
|
321
|
+
* orphaned per-execution sessions; without it only the shared session key
|
|
322
|
+
* is swept.
|
|
323
|
+
*/
|
|
324
|
+
list?(prefix: string): MaybePromise<Map<string, StoredBrowserSession>>;
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* A {@link BrowserSessionStore} that can list by prefix, as `Browser` needs:
|
|
328
|
+
* it lists a browser's scope records to cap them and to see which tabs
|
|
329
|
+
* other scopes are working in.
|
|
330
|
+
*/
|
|
331
|
+
type ListableBrowserSessionStore = BrowserSessionStore &
|
|
332
|
+
Required<Pick<BrowserSessionStore, "list">>;
|
|
333
|
+
declare class DurableBrowserSessionStore implements BrowserSessionStore {
|
|
334
|
+
#private;
|
|
335
|
+
private readonly storage;
|
|
336
|
+
constructor(storage: DurableObjectStorage);
|
|
337
|
+
acquireLock(key: string): Promise<BrowserSessionLock>;
|
|
338
|
+
get(key: string): Promise<StoredBrowserSession | undefined>;
|
|
339
|
+
set(key: string, session: StoredBrowserSession): Promise<void>;
|
|
340
|
+
delete(key: string): Promise<void>;
|
|
341
|
+
list(prefix: string): Promise<Map<string, StoredBrowserSession>>;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Default idle window used by {@link BrowserConnector.sweep} for the shared
|
|
345
|
+
* (reuse/promoted) session entry.
|
|
346
|
+
*/
|
|
347
|
+
declare const DEFAULT_SWEEP_IDLE_MS: number;
|
|
348
|
+
//#endregion
|
|
349
|
+
export {
|
|
350
|
+
CdpSendOptions as A,
|
|
351
|
+
createBrowserSession as C,
|
|
352
|
+
CdpAttachOptions as D,
|
|
353
|
+
listBrowserTargets as E,
|
|
354
|
+
connectUrl as M,
|
|
355
|
+
CdpConnection as O,
|
|
356
|
+
connectBrowserSession as S,
|
|
357
|
+
getBrowserRecording as T,
|
|
358
|
+
ConnectBrowserOptions as _,
|
|
359
|
+
ListableBrowserSessionStore as a,
|
|
360
|
+
ConnectKitesurfBrowserOptions as b,
|
|
361
|
+
BrowserLiveViewTarget as c,
|
|
362
|
+
BrowserBinding as d,
|
|
363
|
+
BrowserRecording as f,
|
|
364
|
+
BrowserTargetInfo as g,
|
|
365
|
+
BrowserSessionInfo as h,
|
|
366
|
+
DurableBrowserSessionStore as i,
|
|
367
|
+
CdpSession as j,
|
|
368
|
+
CdpConnectionOptions as k,
|
|
369
|
+
BrowserLiveViewUrl as l,
|
|
370
|
+
BrowserSessionGuardrails as m,
|
|
371
|
+
BrowserSessionStore as n,
|
|
372
|
+
StoredBrowserSession as o,
|
|
373
|
+
BrowserRenderingError as p,
|
|
374
|
+
DEFAULT_SWEEP_IDLE_MS as r,
|
|
375
|
+
BrowserLiveView as s,
|
|
376
|
+
BrowserSessionLock as t,
|
|
377
|
+
LiveViewMode as u,
|
|
378
|
+
ConnectBrowserSessionOptions as v,
|
|
379
|
+
deleteBrowserSession as w,
|
|
380
|
+
connectBrowser as x,
|
|
381
|
+
ConnectChromiumBrowserOptions as y
|
|
382
|
+
};
|
|
383
|
+
//# sourceMappingURL=session-store-DoPY12xM.d.ts.map
|
package/dist/sessions/index.d.ts
CHANGED
package/dist/sessions/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as isCompactionMessage, i as createCompactFunction, n as Session, r as COMPACTION_PREFIX, t as Sessions } from "../sessions-
|
|
1
|
+
import { a as isCompactionMessage, i as createCompactFunction, n as Session, r as COMPACTION_PREFIX, t as Sessions } from "../sessions-_vN5BEZX.js";
|
|
2
2
|
export { COMPACTION_PREFIX, Session, Sessions, createCompactFunction, isCompactionMessage };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as _classPrivateFieldInitSpec, n as _classPrivateFieldSet2, r as _assertClassBrand, t as _classPrivateFieldGet2 } from "./classPrivateFieldGet2-DZBYAB34.js";
|
|
2
2
|
import { t as _classPrivateMethodInitSpec } from "./classPrivateMethodInitSpec-qMjJ6sHQ.js";
|
|
3
|
-
import { t as LifecycleCapability } from "./capability-
|
|
3
|
+
import { t as LifecycleCapability } from "./capability-DBAKc6UZ.js";
|
|
4
4
|
import { SqlError } from "./sql-error.js";
|
|
5
5
|
import { n as sanitizeMessage, t as byteLength } from "./sanitize-D9TujEK8.js";
|
|
6
6
|
import { i as estimatedDataUrlBytes, n as estimateMessageTokens, r as estimateStringTokens, t as estimateAttachmentTokens } from "./tokens-nHAKcN6M.js";
|
|
@@ -2269,4 +2269,4 @@ var Sessions = class extends LifecycleCapability {
|
|
|
2269
2269
|
//#endregion
|
|
2270
2270
|
export { isCompactionMessage as a, createCompactFunction as i, Session as n, COMPACTION_PREFIX as r, Sessions as t };
|
|
2271
2271
|
|
|
2272
|
-
//# sourceMappingURL=sessions-
|
|
2272
|
+
//# sourceMappingURL=sessions-_vN5BEZX.js.map
|