@effect-uai/browser 0.12.0 → 0.13.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/Connect.d.mts +0 -2
- package/dist/Connect.d.mts.map +1 -1
- package/dist/Connect.mjs +1 -1
- package/dist/Connect.mjs.map +1 -1
- package/dist/{cdp-DZgualSC.d.mts → cdp-BjBngEpt.d.mts} +69 -71
- package/dist/cdp-BjBngEpt.d.mts.map +1 -0
- package/dist/internal/cdp.d.mts +1 -1
- package/dist/internal/cdp.mjs.map +1 -1
- package/dist/internal/injected.d.mts +0 -1
- package/dist/internal/injected.d.mts.map +1 -1
- package/dist/internal/injected.mjs +1 -1
- package/dist/internal/injected.mjs.map +1 -1
- package/dist/internal/session.d.mts +5 -4
- package/dist/internal/session.d.mts.map +1 -1
- package/dist/internal/session.mjs.map +1 -1
- package/package.json +5 -5
- package/src/Connect.ts +4 -6
- package/src/internal/session.ts +17 -21
- package/dist/cdp-DZgualSC.d.mts.map +0 -1
- /package/dist/{chunk-CfYAbeIz.mjs → rolldown-runtime-D7D4PA-g.mjs} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.mjs","names":[],"sources":["../../src/internal/session.ts"],"sourcesContent":["/**\n * Builds a core `BrowserSession` over one attached CDP target.\n *\n * Verb mechanics (the hybrid split):\n * - Real input (`click`, `dblclick`, `hover`, `press`, `type`, `check`)\n * goes through the CDP `Input` domain, so events are trusted where the\n * engine distinguishes (obscura implements `Input.dispatch*`; full\n * Chrome obviously does).\n * - Everything DOM-shaped (`query`, `fill`, `select`, `waitFor`,\n * `content`, scrolling) runs as injected TypeScript from `injected.ts`\n * via `Runtime.evaluate`, the lowest-common-denominator CDP method.\n * Results are decoded with the wire schemas, never cast.\n * - `goto` awaits the `Page` load event through the transport's event\n * demux; `waitFor` parks a `MutationObserver` promise in the page via\n * `awaitPromise`. The host never polls.\n *\n * Failures: transport `CdpError`s are mapped here onto the public\n * `BrowserError` taxonomy with the operation each verb knows. Expiry (max\n * lifetime / idle) is enforced locally by scoped reaper fibers; after\n * expiry every verb fails `BrowserSessionExpired`.\n */\nimport * as CoreBrowser from \"@effect-uai/core/Browser\"\nimport * as BrowserError from \"@effect-uai/core/BrowserError\"\nimport { Clock, Duration, Effect, Encoding, Option, PubSub, Ref, Schema, type Scope } from \"effect\"\nimport type { Cdp, CdpError, CdpEvent, CdpParams, CdpReturn } from \"./cdp.js\"\nimport {\n agentExpression,\n InjectedBox,\n InjectedElementInfo,\n InjectedPoint,\n InjectedSize,\n type PageAgentApi,\n} from \"./injected.js\"\n\n// Per-operation defaults. `waitFor` runs the same budget inside the page\n// (the MutationObserver self-times-out) with the host bound as a backstop.\nconst NAVIGATE_BUDGET = Duration.seconds(30)\nconst WAITFOR_BUDGET = Duration.seconds(10)\nconst ACTION_BUDGET = Duration.seconds(30)\nconst WAITFOR_BACKSTOP = Duration.millis(Duration.toMillis(WAITFOR_BUDGET) + 5000)\n\n/** `query` returns at most this many matches to bound payload size. */\nconst QUERY_LIMIT = 100\n\n/** Reply errors that mean \"this endpoint does not implement the method\". */\nexport const isMethodMissing = (e: CdpError): boolean =>\n e.kind === \"reply\" &&\n /wasn't found|not found|unknown method|not implemented|unsupported/i.test(e.reason ?? \"\")\n\nconst KEY_DETAILS: Record<\n string,\n { readonly code: string; readonly keyCode: number; readonly text?: string }\n> = {\n Enter: { code: \"Enter\", keyCode: 13, text: \"\\r\" },\n Tab: { code: \"Tab\", keyCode: 9 },\n Escape: { code: \"Escape\", keyCode: 27 },\n Backspace: { code: \"Backspace\", keyCode: 8 },\n Delete: { code: \"Delete\", keyCode: 46 },\n ArrowUp: { code: \"ArrowUp\", keyCode: 38 },\n ArrowDown: { code: \"ArrowDown\", keyCode: 40 },\n ArrowLeft: { code: \"ArrowLeft\", keyCode: 37 },\n ArrowRight: { code: \"ArrowRight\", keyCode: 39 },\n Home: { code: \"Home\", keyCode: 36 },\n End: { code: \"End\", keyCode: 35 },\n PageUp: { code: \"PageUp\", keyCode: 33 },\n PageDown: { code: \"PageDown\", keyCode: 34 },\n}\n\n// ---------------------------------------------------------------------------\n// Boundary decoders: CDP leaves these values untyped (`any`), so they are\n// decoded rather than cast.\n// ---------------------------------------------------------------------------\n\nconst decodeLifecycleParams = Schema.decodeUnknownOption(Schema.Struct({ name: Schema.String }))\nconst decodeAxString = Schema.decodeUnknownOption(Schema.String)\nconst decodeAxValue = Schema.decodeUnknownOption(Schema.Union([Schema.String, Schema.Number]))\nconst decodeElements = Schema.decodeUnknownEffect(Schema.Array(InjectedElementInfo))\n\n// ---------------------------------------------------------------------------\n// Accessibility tree: flat AXNode list -> recursive core AxNode. Ignored\n// nodes are elided, their children promoted.\n// ---------------------------------------------------------------------------\n\ntype RawAxNode = CdpReturn<\"Accessibility.getFullAXTree\">[\"nodes\"][number]\n\nconst buildAxTree = (nodes: ReadonlyArray<RawAxNode>): CoreBrowser.AxNode => {\n const byId = new Map(nodes.map((n) => [n.nodeId, n]))\n const childrenOf = (node: RawAxNode): Array<CoreBrowser.AxNode> =>\n (node.childIds ?? []).flatMap((childId) => {\n const child = byId.get(childId)\n if (child === undefined) return []\n return child.ignored ? childrenOf(child) : [build(child)]\n })\n const build = (node: RawAxNode): CoreBrowser.AxNode => {\n const name = Option.filter(decodeAxString(node.name?.value), (s) => s !== \"\")\n const value = Option.filter(\n Option.map(decodeAxValue(node.value?.value), String),\n (s) => s !== \"\",\n )\n return {\n role: Option.getOrElse(decodeAxString(node.role?.value), () => \"unknown\"),\n ...(Option.isSome(name) ? { name: name.value } : {}),\n ...(Option.isSome(value) ? { value: value.value } : {}),\n children: childrenOf(node),\n }\n }\n const root = nodes.find((n) => n.parentId === undefined) ?? nodes[0]\n if (root === undefined) return { role: \"document\", children: [] }\n return root.ignored ? { role: \"document\", children: childrenOf(root) } : build(root)\n}\n\n// ---------------------------------------------------------------------------\n// Session builder\n// ---------------------------------------------------------------------------\n\nexport type MakeSessionOptions = {\n readonly cdp: Cdp\n readonly id: CoreBrowser.BrowserSessionId\n /** CDP target session id (flatten mode); routes every command. */\n readonly sessionId: string\n readonly provider: string\n readonly request: CoreBrowser.CommonSessionRequest\n /** Best-effort provider-side teardown, run when the session expires. */\n readonly dispose: Effect.Effect<void>\n}\n\nexport const makeSession = (\n options: MakeSessionOptions,\n): Effect.Effect<CoreBrowser.BrowserSession, never, Scope.Scope> =>\n Effect.gen(function* () {\n const { cdp, dispose, id, provider, request, sessionId } = options\n\n // -- expiry: local reaper fibers, scoped to the session -------------------\n\n const expired = yield* Ref.make(false)\n const lastActivity = yield* Ref.make(yield* Clock.currentTimeMillis)\n const expire = Ref.set(expired, true).pipe(Effect.andThen(Effect.ignore(dispose)))\n\n if (request.timeout !== undefined) {\n yield* Effect.sleep(request.timeout).pipe(Effect.andThen(expire), Effect.forkScoped)\n }\n if (request.idleTimeout !== undefined) {\n const idleMs = Duration.toMillis(Duration.fromInputUnsafe(request.idleTimeout))\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n while (true) {\n const elapsed = (yield* Clock.currentTimeMillis) - (yield* Ref.get(lastActivity))\n if (elapsed >= idleMs) return yield* expire\n yield* Effect.sleep(Duration.millis(idleMs - elapsed))\n }\n }),\n )\n }\n\n // -- error mapping and shared wrappers -------------------------------------\n\n const sessionExpired = () => new BrowserError.BrowserSessionExpired({ provider, id })\n\n const mapCdp =\n (operation: BrowserError.BrowserActionFailed[\"operation\"], selector?: string) =>\n (e: CdpError): BrowserError.BrowserError =>\n e.kind === \"closed\"\n ? sessionExpired()\n : new BrowserError.BrowserActionFailed({\n provider,\n operation,\n ...(selector !== undefined ? { selector } : {}),\n ...(e.reason !== undefined ? { reason: e.reason } : {}),\n raw: e,\n })\n\n const guarded = <A, E>(\n effect: Effect.Effect<A, E>,\n ): Effect.Effect<A, E | BrowserError.BrowserSessionExpired> =>\n Effect.gen(function* () {\n if (yield* Ref.get(expired)) return yield* Effect.fail(sessionExpired())\n yield* Ref.set(lastActivity, yield* Clock.currentTimeMillis)\n return yield* effect\n })\n\n const withBudget = <A, E>(\n operation: BrowserError.BrowserTimeout[\"operation\"],\n budget: Duration.Duration,\n effect: Effect.Effect<A, E>,\n ): Effect.Effect<A, E | BrowserError.BrowserTimeout> =>\n Effect.timeoutOrElse(effect, {\n duration: budget,\n orElse: () => Effect.fail(new BrowserError.BrowserTimeout({ provider, operation, budget })),\n })\n\n const evalInPage = (\n expression: string,\n operation: BrowserError.BrowserActionFailed[\"operation\"],\n selector?: string,\n ): Effect.Effect<unknown, BrowserError.BrowserError> =>\n cdp\n .send(\n \"Runtime.evaluate\",\n { expression, returnByValue: true, awaitPromise: true },\n sessionId,\n )\n .pipe(\n Effect.mapError(mapCdp(operation, selector)),\n Effect.flatMap((reply) =>\n reply.exceptionDetails !== undefined\n ? Effect.fail(\n new BrowserError.BrowserActionFailed({\n provider,\n operation,\n ...(selector !== undefined ? { selector } : {}),\n reason:\n reply.exceptionDetails.exception?.description ?? reply.exceptionDetails.text,\n raw: reply.exceptionDetails,\n }),\n )\n : Effect.succeed(reply.result.value as unknown),\n ),\n )\n\n /** Call a page-agent helper and decode its result with `schema`. */\n const agent = <S extends Schema.Top & { readonly DecodingServices: never }>(\n operation: BrowserError.BrowserActionFailed[\"operation\"],\n fn: keyof PageAgentApi,\n args: ReadonlyArray<unknown>,\n schema: S,\n selector?: string,\n ): Effect.Effect<S[\"Type\"], BrowserError.BrowserError> =>\n evalInPage(agentExpression(fn, args), operation, selector).pipe(\n Effect.flatMap((value) =>\n Schema.decodeUnknownEffect(schema)(value).pipe(\n Effect.mapError(\n (e) =>\n new BrowserError.BrowserActionFailed({\n provider,\n operation,\n ...(selector !== undefined ? { selector } : {}),\n reason: \"page agent returned an unexpected shape\",\n raw: e,\n }),\n ),\n ),\n ),\n )\n\n /** Call a page-agent helper whose result is irrelevant. */\n const agentVoid = (\n operation: BrowserError.BrowserActionFailed[\"operation\"],\n fn: keyof PageAgentApi,\n args: ReadonlyArray<unknown>,\n selector?: string,\n ): Effect.Effect<void, BrowserError.BrowserError> =>\n evalInPage(agentExpression(fn, args), operation, selector).pipe(Effect.asVoid)\n\n // -- input primitives (trusted events via the Input domain) ----------------\n\n const mouse = (params: CdpParams<\"Input.dispatchMouseEvent\">) =>\n cdp.send(\"Input.dispatchMouseEvent\", params, sessionId)\n\n const clickAt = (point: InjectedPoint, clickCount: number): Effect.Effect<void, CdpError> =>\n Effect.gen(function* () {\n yield* mouse({ type: \"mouseMoved\", x: point.x, y: point.y })\n yield* mouse({ type: \"mousePressed\", x: point.x, y: point.y, button: \"left\", clickCount })\n yield* mouse({ type: \"mouseReleased\", x: point.x, y: point.y, button: \"left\", clickCount })\n })\n\n const clickSelector = (selector: string, clickCount: number) =>\n agent(\"interact\", \"targetPoint\", [selector], InjectedPoint, selector).pipe(\n Effect.flatMap((point) =>\n clickAt(point, clickCount).pipe(Effect.mapError(mapCdp(\"interact\", selector))),\n ),\n )\n\n const keyEvents = (key: string): Effect.Effect<void, CdpError> => {\n const detail = KEY_DETAILS[key]\n const text = detail?.text ?? (key.length === 1 ? key : undefined)\n const common =\n detail === undefined\n ? {}\n : {\n code: detail.code,\n windowsVirtualKeyCode: detail.keyCode,\n nativeVirtualKeyCode: detail.keyCode,\n }\n return cdp\n .send(\n \"Input.dispatchKeyEvent\",\n { type: \"keyDown\", key, ...common, ...(text !== undefined ? { text } : {}) },\n sessionId,\n )\n .pipe(\n Effect.andThen(\n cdp.send(\"Input.dispatchKeyEvent\", { type: \"keyUp\", key, ...common }, sessionId),\n ),\n Effect.asVoid,\n )\n }\n\n // -- navigation --------------------------------------------------------------\n\n const isLoadEvent = (event: CdpEvent): boolean =>\n (event.sessionId === undefined || event.sessionId === sessionId) &&\n (event.method === \"Page.loadEventFired\" ||\n (event.method === \"Page.lifecycleEvent\" &&\n Option.getOrUndefined(decodeLifecycleParams(event.params))?.name === \"load\"))\n\n const goto = (url: string) =>\n guarded(\n Effect.scoped(\n Effect.gen(function* () {\n // Subscribe BEFORE navigating so the load event cannot slip past.\n const sub = yield* cdp.subscribe\n const reply = yield* cdp\n .send(\"Page.navigate\", { url }, sessionId)\n .pipe(Effect.mapError(mapCdp(\"navigate\")))\n if (reply.errorText !== undefined && reply.errorText !== \"\") {\n return yield* Effect.fail(\n new BrowserError.BrowserActionFailed({\n provider,\n operation: \"navigate\",\n reason: reply.errorText,\n raw: reply,\n }),\n )\n }\n yield* PubSub.take(sub).pipe(Effect.repeat({ until: isLoadEvent }))\n }),\n ).pipe((effect) =>\n Effect.timeoutOrElse(effect, {\n duration: NAVIGATE_BUDGET,\n // Endpoints that don't emit load events still settle the\n // document; accept a complete readyState before failing.\n orElse: () =>\n agent(\"navigate\", \"readyState\", [], Schema.String).pipe(\n Effect.option,\n Effect.flatMap((state) =>\n Option.isSome(state) && state.value === \"complete\"\n ? Effect.void\n : Effect.fail(\n new BrowserError.BrowserTimeout({\n provider,\n operation: \"navigate\",\n budget: NAVIGATE_BUDGET,\n }),\n ),\n ),\n ),\n }),\n ),\n )\n\n const waitFor = (selector: string) =>\n guarded(\n withBudget(\n \"query\",\n WAITFOR_BACKSTOP,\n agent(\n \"observe\",\n \"waitForSelector\",\n [selector, Duration.toMillis(WAITFOR_BUDGET)],\n Schema.Boolean,\n selector,\n ).pipe(\n Effect.flatMap((found) =>\n found\n ? Effect.void\n : Effect.fail(\n new BrowserError.BrowserTimeout({\n provider,\n operation: \"query\",\n budget: WAITFOR_BUDGET,\n }),\n ),\n ),\n ),\n ),\n )\n\n // -- observation ---------------------------------------------------------------\n\n const content = (format?: CoreBrowser.PageFormat) =>\n guarded(\n withBudget(\n \"action\",\n ACTION_BUDGET,\n agent(\"observe\", format === \"html\" ? \"html\" : \"markdown\", [], Schema.String),\n ),\n )\n\n const screenshot = (opts?: CoreBrowser.ScreenshotOptions) =>\n guarded(\n withBudget(\n \"action\",\n ACTION_BUDGET,\n Effect.gen(function* () {\n const clip =\n opts?.selector !== undefined\n ? yield* agent(\"observe\", \"pageBox\", [opts.selector], InjectedBox, opts.selector)\n : opts?.fullPage === true\n ? { x: 0, y: 0, ...(yield* agent(\"observe\", \"contentSize\", [], InjectedSize)) }\n : undefined\n const reply = yield* cdp\n .send(\n \"Page.captureScreenshot\",\n {\n format: \"png\",\n ...(clip !== undefined\n ? { clip: { ...clip, scale: 1 }, captureBeyondViewport: true }\n : {}),\n },\n sessionId,\n )\n .pipe(Effect.mapError(mapCdp(\"observe\")))\n return yield* Effect.fromResult(Encoding.decodeBase64(reply.data)).pipe(\n Effect.mapError(\n (e) =>\n new BrowserError.BrowserActionFailed({\n provider,\n operation: \"observe\",\n reason: \"invalid base64 screenshot payload\",\n raw: e,\n }),\n ),\n )\n }),\n ),\n )\n\n const snapshot = guarded(\n withBudget(\n \"query\",\n ACTION_BUDGET,\n cdp.send(\"Accessibility.getFullAXTree\", {}, sessionId).pipe(\n Effect.mapError((e) =>\n isMethodMissing(e)\n ? new BrowserError.BrowserUnsupported({\n provider,\n capability: \"snapshot\",\n reason: \"endpoint does not implement the CDP Accessibility domain\",\n })\n : mapCdp(\"observe\")(e),\n ),\n Effect.map((reply) => buildAxTree(reply.nodes)),\n ),\n ),\n )\n\n const query = (selector: string) =>\n guarded(\n withBudget(\n \"query\",\n ACTION_BUDGET,\n evalInPage(agentExpression(\"query\", [selector, QUERY_LIMIT]), \"observe\", selector).pipe(\n Effect.flatMap((value) =>\n decodeElements(value).pipe(\n Effect.mapError(\n (e) =>\n new BrowserError.BrowserActionFailed({\n provider,\n operation: \"observe\",\n selector,\n reason: \"page agent returned an unexpected shape\",\n raw: e,\n }),\n ),\n ),\n ),\n Effect.map((els) =>\n els.map(\n (el): CoreBrowser.ElementInfo => ({\n ref: el.ref,\n tag: el.tag,\n ...(el.text !== \"\" ? { text: el.text } : {}),\n attributes: el.attributes,\n box: el.box,\n }),\n ),\n ),\n ),\n ),\n )\n\n // -- state -----------------------------------------------------------------------\n\n const cookies: CoreBrowser.CookieApi = {\n get: guarded(\n cdp.send(\"Network.getCookies\", {}, sessionId).pipe(\n Effect.mapError(mapCdp(\"cookies\")),\n Effect.map((reply) =>\n reply.cookies.map(\n (c): CoreBrowser.Cookie => ({\n name: c.name,\n value: c.value,\n domain: c.domain,\n path: c.path,\n expires: c.expires,\n httpOnly: c.httpOnly,\n secure: c.secure,\n ...(c.sameSite !== undefined ? { sameSite: c.sameSite } : {}),\n }),\n ),\n ),\n ),\n ),\n set: (toSet) =>\n guarded(\n cdp\n .send(\n \"Network.setCookies\",\n {\n cookies: toSet.map((c) => ({\n name: c.name,\n value: c.value,\n ...(c.domain !== undefined ? { domain: c.domain } : {}),\n ...(c.path !== undefined ? { path: c.path } : {}),\n ...(c.expires !== undefined ? { expires: c.expires } : {}),\n ...(c.httpOnly !== undefined ? { httpOnly: c.httpOnly } : {}),\n ...(c.secure !== undefined ? { secure: c.secure } : {}),\n ...(c.sameSite !== undefined ? { sameSite: c.sameSite } : {}),\n })),\n },\n sessionId,\n )\n .pipe(Effect.mapError(mapCdp(\"cookies\")), Effect.asVoid),\n ),\n }\n\n // -- assemble ----------------------------------------------------------------------\n\n const interact = <A>(effect: Effect.Effect<A, BrowserError.BrowserError>) =>\n guarded(withBudget(\"action\", ACTION_BUDGET, effect))\n\n const session: CoreBrowser.BrowserSession = {\n id,\n\n goto,\n waitFor,\n\n click: (selector) => interact(clickSelector(selector, 1)),\n dblclick: (selector) =>\n interact(\n // Two pairs, the second with clickCount 2, matching real\n // double-click event streams.\n agent(\"interact\", \"targetPoint\", [selector], InjectedPoint, selector).pipe(\n Effect.flatMap((point) =>\n clickAt(point, 1).pipe(\n Effect.andThen(clickAt(point, 2)),\n Effect.mapError(mapCdp(\"interact\", selector)),\n ),\n ),\n ),\n ),\n fill: (selector, text) => interact(agentVoid(\"interact\", \"fill\", [selector, text], selector)),\n type: (selector, text) =>\n interact(\n agentVoid(\"interact\", \"focusEl\", [selector], selector).pipe(\n Effect.andThen(\n Effect.forEach(Array.from(text), keyEvents).pipe(\n Effect.asVoid,\n Effect.mapError(mapCdp(\"interact\", selector)),\n ),\n ),\n ),\n ),\n press: (key) => interact(keyEvents(key).pipe(Effect.mapError(mapCdp(\"interact\")))),\n hover: (selector) =>\n interact(\n agent(\"interact\", \"targetPoint\", [selector], InjectedPoint, selector).pipe(\n Effect.flatMap((point) =>\n mouse({ type: \"mouseMoved\", x: point.x, y: point.y }).pipe(\n Effect.asVoid,\n Effect.mapError(mapCdp(\"interact\", selector)),\n ),\n ),\n ),\n ),\n focus: (selector) => interact(agentVoid(\"interact\", \"focusEl\", [selector], selector)),\n select: (selector, value) =>\n interact(agentVoid(\"interact\", \"selectValue\", [selector, value], selector)),\n check: (selector) =>\n interact(\n agent(\"interact\", \"isChecked\", [selector], Schema.Boolean, selector).pipe(\n Effect.flatMap((checked) => (checked ? Effect.void : clickSelector(selector, 1))),\n ),\n ),\n uncheck: (selector) =>\n interact(\n agent(\"interact\", \"isChecked\", [selector], Schema.Boolean, selector).pipe(\n Effect.flatMap((checked) => (checked ? clickSelector(selector, 1) : Effect.void)),\n ),\n ),\n scroll: (opts) =>\n interact(agentVoid(\"interact\", \"scrollBy\", [opts.direction, opts.pixels ?? 600])),\n scrollIntoView: (selector) =>\n interact(agentVoid(\"interact\", \"scrollIntoView\", [selector], selector)),\n\n content,\n screenshot,\n snapshot,\n query,\n\n cookies,\n evaluate: (script) => interact(evalInPage(script, \"evaluate\")),\n }\n\n return session\n })\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"session.mjs","names":[],"sources":["../../src/internal/session.ts"],"sourcesContent":["/**\n * Builds a core `BrowserSession` over one attached CDP target.\n *\n * Verb mechanics (the hybrid split):\n * - Real input (`click`, `dblclick`, `hover`, `press`, `type`, `check`)\n * goes through the CDP `Input` domain, so events are trusted where the\n * engine distinguishes (obscura implements `Input.dispatch*`; full\n * Chrome obviously does).\n * - Everything DOM-shaped (`query`, `fill`, `select`, `waitFor`,\n * `content`, scrolling) runs as injected TypeScript from `injected.ts`\n * via `Runtime.evaluate`, the lowest-common-denominator CDP method.\n * Results are decoded with the wire schemas, never cast.\n * - `goto` awaits the `Page` load event through the transport's event\n * demux; `waitFor` parks a `MutationObserver` promise in the page via\n * `awaitPromise`. The host never polls.\n *\n * Failures: transport `CdpError`s are mapped here onto the public\n * `BrowserError` taxonomy with the operation each verb knows. Expiry (max\n * lifetime / idle) is enforced locally by scoped reaper fibers; after\n * expiry every verb fails `BrowserSessionExpired`.\n */\nimport * as CoreBrowser from \"@effect-uai/core/Browser\"\nimport * as BrowserError from \"@effect-uai/core/BrowserError\"\nimport { Clock, Duration, Effect, Encoding, Option, PubSub, Ref, Schema, type Scope } from \"effect\"\nimport type { Cdp, CdpError, CdpEvent, CdpParams, CdpReturn } from \"./cdp.js\"\nimport {\n agentExpression,\n InjectedBox,\n InjectedElementInfo,\n InjectedPoint,\n InjectedSize,\n type PageAgentApi,\n} from \"./injected.js\"\n\n// Per-operation defaults. `waitFor` runs the same budget inside the page\n// (the MutationObserver self-times-out) with the host bound as a backstop.\nconst NAVIGATE_BUDGET = Duration.seconds(30)\nconst WAITFOR_BUDGET = Duration.seconds(10)\nconst ACTION_BUDGET = Duration.seconds(30)\nconst WAITFOR_BACKSTOP = Duration.millis(Duration.toMillis(WAITFOR_BUDGET) + 5000)\n\n/** `query` returns at most this many matches to bound payload size. */\nconst QUERY_LIMIT = 100\n\n/** Reply errors that mean \"this endpoint does not implement the method\". */\nexport const isMethodMissing = (e: CdpError): boolean =>\n e.kind === \"reply\" &&\n /wasn't found|not found|unknown method|not implemented|unsupported/i.test(e.reason ?? \"\")\n\nconst KEY_DETAILS: Record<\n string,\n { readonly code: string; readonly keyCode: number; readonly text?: string }\n> = {\n Enter: { code: \"Enter\", keyCode: 13, text: \"\\r\" },\n Tab: { code: \"Tab\", keyCode: 9 },\n Escape: { code: \"Escape\", keyCode: 27 },\n Backspace: { code: \"Backspace\", keyCode: 8 },\n Delete: { code: \"Delete\", keyCode: 46 },\n ArrowUp: { code: \"ArrowUp\", keyCode: 38 },\n ArrowDown: { code: \"ArrowDown\", keyCode: 40 },\n ArrowLeft: { code: \"ArrowLeft\", keyCode: 37 },\n ArrowRight: { code: \"ArrowRight\", keyCode: 39 },\n Home: { code: \"Home\", keyCode: 36 },\n End: { code: \"End\", keyCode: 35 },\n PageUp: { code: \"PageUp\", keyCode: 33 },\n PageDown: { code: \"PageDown\", keyCode: 34 },\n}\n\n// ---------------------------------------------------------------------------\n// Boundary decoders: CDP leaves these values untyped (`any`), so they are\n// decoded rather than cast.\n// ---------------------------------------------------------------------------\n\nconst decodeLifecycleParams = Schema.decodeUnknownOption(Schema.Struct({ name: Schema.String }))\nconst decodeAxString = Schema.decodeUnknownOption(Schema.String)\nconst decodeAxValue = Schema.decodeUnknownOption(Schema.Union([Schema.String, Schema.Number]))\nconst decodeElements = Schema.decodeUnknownEffect(Schema.Array(InjectedElementInfo))\n\n// ---------------------------------------------------------------------------\n// Accessibility tree: flat AXNode list -> recursive core AxNode. Ignored\n// nodes are elided, their children promoted.\n// ---------------------------------------------------------------------------\n\ntype RawAxNode = CdpReturn<\"Accessibility.getFullAXTree\">[\"nodes\"][number]\n\nconst buildAxTree = (nodes: ReadonlyArray<RawAxNode>): CoreBrowser.AxNode => {\n const byId = new Map(nodes.map((n) => [n.nodeId, n]))\n const childrenOf = (node: RawAxNode): Array<CoreBrowser.AxNode> =>\n (node.childIds ?? []).flatMap((childId) => {\n const child = byId.get(childId)\n if (child === undefined) return []\n return child.ignored ? childrenOf(child) : [build(child)]\n })\n const build = (node: RawAxNode): CoreBrowser.AxNode => {\n const name = Option.filter(decodeAxString(node.name?.value), (s) => s !== \"\")\n const value = Option.filter(\n Option.map(decodeAxValue(node.value?.value), String),\n (s) => s !== \"\",\n )\n return {\n role: Option.getOrElse(decodeAxString(node.role?.value), () => \"unknown\"),\n ...(Option.isSome(name) ? { name: name.value } : {}),\n ...(Option.isSome(value) ? { value: value.value } : {}),\n children: childrenOf(node),\n }\n }\n const root = nodes.find((n) => n.parentId === undefined) ?? nodes[0]\n if (root === undefined) return { role: \"document\", children: [] }\n return root.ignored ? { role: \"document\", children: childrenOf(root) } : build(root)\n}\n\n// ---------------------------------------------------------------------------\n// Session builder\n// ---------------------------------------------------------------------------\n\nexport type MakeSessionOptions = {\n readonly cdp: Cdp\n readonly id: CoreBrowser.BrowserSessionId\n /** CDP target session id (flatten mode); routes every command. */\n readonly sessionId: string\n readonly provider: string\n readonly request: CoreBrowser.CommonSessionRequest\n /** Best-effort provider-side teardown, run when the session expires. */\n readonly dispose: Effect.Effect<void>\n}\n\nexport const makeSession = (\n options: MakeSessionOptions,\n): Effect.Effect<CoreBrowser.BrowserSession, never, Scope.Scope> =>\n Effect.gen(function* () {\n const { cdp, dispose, id, provider, request, sessionId } = options\n\n // -- expiry: local reaper fibers, scoped to the session -------------------\n\n const expired = yield* Ref.make(false)\n const lastActivity = yield* Ref.make(yield* Clock.currentTimeMillis)\n const expire = Ref.set(expired, true).pipe(Effect.andThen(Effect.ignore(dispose)))\n\n if (request.timeout !== undefined) {\n yield* Effect.sleep(request.timeout).pipe(Effect.andThen(expire), Effect.forkScoped)\n }\n if (request.idleTimeout !== undefined) {\n const idleMs = Duration.toMillis(Duration.fromInputUnsafe(request.idleTimeout))\n yield* Effect.forkScoped(\n Effect.gen(function* () {\n while (true) {\n const elapsed = (yield* Clock.currentTimeMillis) - (yield* Ref.get(lastActivity))\n if (elapsed >= idleMs) return yield* expire\n yield* Effect.sleep(Duration.millis(idleMs - elapsed))\n }\n }),\n )\n }\n\n // -- error mapping and shared wrappers -------------------------------------\n\n const sessionExpired = () => new BrowserError.BrowserSessionExpired({ provider, id })\n\n const mapCdp =\n (operation: BrowserError.BrowserActionFailed[\"operation\"], selector?: string) =>\n (e: CdpError): BrowserError.BrowserError =>\n e.kind === \"closed\"\n ? sessionExpired()\n : new BrowserError.BrowserActionFailed({\n provider,\n operation,\n ...(selector !== undefined ? { selector } : {}),\n ...(e.reason !== undefined ? { reason: e.reason } : {}),\n raw: e,\n })\n\n const guarded = <A, E>(\n effect: Effect.Effect<A, E>,\n ): Effect.Effect<A, E | BrowserError.BrowserSessionExpired> =>\n Effect.gen(function* () {\n if (yield* Ref.get(expired)) return yield* Effect.fail(sessionExpired())\n yield* Ref.set(lastActivity, yield* Clock.currentTimeMillis)\n return yield* effect\n })\n\n const withBudget = <A, E>(\n operation: BrowserError.BrowserTimeout[\"operation\"],\n budget: Duration.Duration,\n effect: Effect.Effect<A, E>,\n ): Effect.Effect<A, E | BrowserError.BrowserTimeout> =>\n Effect.timeoutOrElse(effect, {\n duration: budget,\n orElse: () => Effect.fail(new BrowserError.BrowserTimeout({ provider, operation, budget })),\n })\n\n const evalInPage = (\n expression: string,\n operation: BrowserError.BrowserActionFailed[\"operation\"],\n selector?: string,\n ): Effect.Effect<unknown, BrowserError.BrowserError> =>\n cdp\n .send(\n \"Runtime.evaluate\",\n { expression, returnByValue: true, awaitPromise: true },\n sessionId,\n )\n .pipe(\n Effect.mapError(mapCdp(operation, selector)),\n Effect.flatMap((reply) =>\n reply.exceptionDetails !== undefined\n ? Effect.fail(\n new BrowserError.BrowserActionFailed({\n provider,\n operation,\n ...(selector !== undefined ? { selector } : {}),\n reason:\n reply.exceptionDetails.exception?.description ?? reply.exceptionDetails.text,\n raw: reply.exceptionDetails,\n }),\n )\n : Effect.succeed(reply.result.value as unknown),\n ),\n )\n\n /** Call a page-agent helper and decode its result with `schema`. */\n const agent = <S extends Schema.Top & { readonly DecodingServices: never }>(\n operation: BrowserError.BrowserActionFailed[\"operation\"],\n fn: keyof PageAgentApi,\n args: ReadonlyArray<unknown>,\n schema: S,\n selector?: string,\n ): Effect.Effect<S[\"Type\"], BrowserError.BrowserError> =>\n evalInPage(agentExpression(fn, args), operation, selector).pipe(\n Effect.flatMap((value) =>\n Schema.decodeUnknownEffect(schema)(value).pipe(\n Effect.mapError(\n (e) =>\n new BrowserError.BrowserActionFailed({\n provider,\n operation,\n ...(selector !== undefined ? { selector } : {}),\n reason: \"page agent returned an unexpected shape\",\n raw: e,\n }),\n ),\n ),\n ),\n )\n\n /** Call a page-agent helper whose result is irrelevant. */\n const agentVoid = (\n operation: BrowserError.BrowserActionFailed[\"operation\"],\n fn: keyof PageAgentApi,\n args: ReadonlyArray<unknown>,\n selector?: string,\n ): Effect.Effect<void, BrowserError.BrowserError> =>\n evalInPage(agentExpression(fn, args), operation, selector).pipe(Effect.asVoid)\n\n // -- input primitives (trusted events via the Input domain) ----------------\n\n const mouse = (params: CdpParams<\"Input.dispatchMouseEvent\">) =>\n cdp.send(\"Input.dispatchMouseEvent\", params, sessionId)\n\n const clickAt = (point: InjectedPoint, clickCount: number): Effect.Effect<void, CdpError> =>\n Effect.gen(function* () {\n yield* mouse({ type: \"mouseMoved\", x: point.x, y: point.y })\n yield* mouse({ type: \"mousePressed\", x: point.x, y: point.y, button: \"left\", clickCount })\n yield* mouse({ type: \"mouseReleased\", x: point.x, y: point.y, button: \"left\", clickCount })\n })\n\n const clickSelector = (selector: string, clickCount: number) =>\n agent(\"interact\", \"targetPoint\", [selector], InjectedPoint, selector).pipe(\n Effect.flatMap((point) =>\n clickAt(point, clickCount).pipe(Effect.mapError(mapCdp(\"interact\", selector))),\n ),\n )\n\n const keyEvents = (key: string): Effect.Effect<void, CdpError> => {\n const detail = KEY_DETAILS[key]\n const text = detail?.text ?? (key.length === 1 ? key : undefined)\n const common =\n detail === undefined\n ? {}\n : {\n code: detail.code,\n windowsVirtualKeyCode: detail.keyCode,\n nativeVirtualKeyCode: detail.keyCode,\n }\n return cdp\n .send(\n \"Input.dispatchKeyEvent\",\n { type: \"keyDown\", key, ...common, ...(text !== undefined ? { text } : {}) },\n sessionId,\n )\n .pipe(\n Effect.andThen(\n cdp.send(\"Input.dispatchKeyEvent\", { type: \"keyUp\", key, ...common }, sessionId),\n ),\n Effect.asVoid,\n )\n }\n\n // -- navigation --------------------------------------------------------------\n\n const isLoadEvent = (event: CdpEvent): boolean =>\n (event.sessionId === undefined || event.sessionId === sessionId) &&\n (event.method === \"Page.loadEventFired\" ||\n (event.method === \"Page.lifecycleEvent\" &&\n Option.getOrUndefined(decodeLifecycleParams(event.params))?.name === \"load\"))\n\n const goto = (url: string) =>\n guarded(\n Effect.scoped(\n Effect.gen(function* () {\n // Subscribe BEFORE navigating so the load event cannot slip past.\n const sub = yield* cdp.subscribe\n const reply = yield* cdp\n .send(\"Page.navigate\", { url }, sessionId)\n .pipe(Effect.mapError(mapCdp(\"navigate\")))\n if (reply.errorText !== undefined && reply.errorText !== \"\") {\n return yield* Effect.fail(\n new BrowserError.BrowserActionFailed({\n provider,\n operation: \"navigate\",\n reason: reply.errorText,\n raw: reply,\n }),\n )\n }\n yield* PubSub.take(sub).pipe(Effect.repeat({ until: isLoadEvent }))\n }),\n ).pipe((effect) =>\n Effect.timeoutOrElse(effect, {\n duration: NAVIGATE_BUDGET,\n // Endpoints that don't emit load events still settle the\n // document; accept a complete readyState before failing.\n orElse: () =>\n agent(\"navigate\", \"readyState\", [], Schema.String).pipe(\n Effect.option,\n Effect.flatMap((state) =>\n Option.isSome(state) && state.value === \"complete\"\n ? Effect.void\n : Effect.fail(\n new BrowserError.BrowserTimeout({\n provider,\n operation: \"navigate\",\n budget: NAVIGATE_BUDGET,\n }),\n ),\n ),\n ),\n }),\n ),\n )\n\n const waitFor = (selector: string) =>\n guarded(\n withBudget(\n \"query\",\n WAITFOR_BACKSTOP,\n agent(\n \"observe\",\n \"waitForSelector\",\n [selector, Duration.toMillis(WAITFOR_BUDGET)],\n Schema.Boolean,\n selector,\n ).pipe(\n Effect.flatMap((found) =>\n found\n ? Effect.void\n : Effect.fail(\n new BrowserError.BrowserTimeout({\n provider,\n operation: \"query\",\n budget: WAITFOR_BUDGET,\n }),\n ),\n ),\n ),\n ),\n )\n\n // -- observation ---------------------------------------------------------------\n\n const content = (format?: CoreBrowser.PageFormat) =>\n guarded(\n withBudget(\n \"action\",\n ACTION_BUDGET,\n agent(\"observe\", format === \"html\" ? \"html\" : \"markdown\", [], Schema.String),\n ),\n )\n\n const screenshot = (opts?: CoreBrowser.ScreenshotOptions) =>\n guarded(\n withBudget(\n \"action\",\n ACTION_BUDGET,\n Effect.gen(function* () {\n const clip =\n opts?.selector !== undefined\n ? yield* agent(\"observe\", \"pageBox\", [opts.selector], InjectedBox, opts.selector)\n : opts?.fullPage === true\n ? { x: 0, y: 0, ...(yield* agent(\"observe\", \"contentSize\", [], InjectedSize)) }\n : undefined\n const reply = yield* cdp\n .send(\n \"Page.captureScreenshot\",\n {\n format: \"png\",\n ...(clip !== undefined\n ? { clip: { ...clip, scale: 1 }, captureBeyondViewport: true }\n : {}),\n },\n sessionId,\n )\n .pipe(Effect.mapError(mapCdp(\"observe\")))\n return yield* Effect.fromResult(Encoding.decodeBase64(reply.data)).pipe(\n Effect.mapError(\n (e) =>\n new BrowserError.BrowserActionFailed({\n provider,\n operation: \"observe\",\n reason: \"invalid base64 screenshot payload\",\n raw: e,\n }),\n ),\n )\n }),\n ),\n )\n\n const snapshot = guarded(\n withBudget(\n \"query\",\n ACTION_BUDGET,\n cdp.send(\"Accessibility.getFullAXTree\", {}, sessionId).pipe(\n Effect.mapError((e) =>\n isMethodMissing(e)\n ? new BrowserError.BrowserUnsupported({\n provider,\n capability: \"snapshot\",\n reason: \"endpoint does not implement the CDP Accessibility domain\",\n })\n : mapCdp(\"observe\")(e),\n ),\n Effect.map((reply) => buildAxTree(reply.nodes)),\n ),\n ),\n )\n\n const query = (selector: string) =>\n guarded(\n withBudget(\n \"query\",\n ACTION_BUDGET,\n evalInPage(agentExpression(\"query\", [selector, QUERY_LIMIT]), \"observe\", selector).pipe(\n Effect.flatMap((value) =>\n decodeElements(value).pipe(\n Effect.mapError(\n (e) =>\n new BrowserError.BrowserActionFailed({\n provider,\n operation: \"observe\",\n selector,\n reason: \"page agent returned an unexpected shape\",\n raw: e,\n }),\n ),\n ),\n ),\n Effect.map((els) =>\n els.map((el): CoreBrowser.ElementInfo => ({\n ref: el.ref,\n tag: el.tag,\n ...(el.text !== \"\" ? { text: el.text } : {}),\n attributes: el.attributes,\n box: el.box,\n })),\n ),\n ),\n ),\n )\n\n // -- state -----------------------------------------------------------------------\n\n const cookies: CoreBrowser.CookieApi = {\n get: guarded(\n cdp.send(\"Network.getCookies\", {}, sessionId).pipe(\n Effect.mapError(mapCdp(\"cookies\")),\n Effect.map((reply) =>\n reply.cookies.map((c): CoreBrowser.Cookie => ({\n name: c.name,\n value: c.value,\n domain: c.domain,\n path: c.path,\n expires: c.expires,\n httpOnly: c.httpOnly,\n secure: c.secure,\n ...(c.sameSite !== undefined ? { sameSite: c.sameSite } : {}),\n })),\n ),\n ),\n ),\n set: (toSet) =>\n guarded(\n cdp\n .send(\n \"Network.setCookies\",\n {\n cookies: toSet.map((c) => ({\n name: c.name,\n value: c.value,\n ...(c.domain !== undefined ? { domain: c.domain } : {}),\n ...(c.path !== undefined ? { path: c.path } : {}),\n ...(c.expires !== undefined ? { expires: c.expires } : {}),\n ...(c.httpOnly !== undefined ? { httpOnly: c.httpOnly } : {}),\n ...(c.secure !== undefined ? { secure: c.secure } : {}),\n ...(c.sameSite !== undefined ? { sameSite: c.sameSite } : {}),\n })),\n },\n sessionId,\n )\n .pipe(Effect.mapError(mapCdp(\"cookies\")), Effect.asVoid),\n ),\n }\n\n // -- assemble ----------------------------------------------------------------------\n\n const interact = <A>(effect: Effect.Effect<A, BrowserError.BrowserError>) =>\n guarded(withBudget(\"action\", ACTION_BUDGET, effect))\n\n const session: CoreBrowser.BrowserSession = {\n id,\n\n goto,\n waitFor,\n\n click: (selector) => interact(clickSelector(selector, 1)),\n dblclick: (selector) =>\n interact(\n // Two pairs, the second with clickCount 2, matching real\n // double-click event streams.\n agent(\"interact\", \"targetPoint\", [selector], InjectedPoint, selector).pipe(\n Effect.flatMap((point) =>\n clickAt(point, 1).pipe(\n Effect.andThen(clickAt(point, 2)),\n Effect.mapError(mapCdp(\"interact\", selector)),\n ),\n ),\n ),\n ),\n fill: (selector, text) => interact(agentVoid(\"interact\", \"fill\", [selector, text], selector)),\n type: (selector, text) =>\n interact(\n agentVoid(\"interact\", \"focusEl\", [selector], selector).pipe(\n Effect.andThen(\n Effect.forEach(Array.from(text), keyEvents).pipe(\n Effect.asVoid,\n Effect.mapError(mapCdp(\"interact\", selector)),\n ),\n ),\n ),\n ),\n press: (key) => interact(keyEvents(key).pipe(Effect.mapError(mapCdp(\"interact\")))),\n hover: (selector) =>\n interact(\n agent(\"interact\", \"targetPoint\", [selector], InjectedPoint, selector).pipe(\n Effect.flatMap((point) =>\n mouse({ type: \"mouseMoved\", x: point.x, y: point.y }).pipe(\n Effect.asVoid,\n Effect.mapError(mapCdp(\"interact\", selector)),\n ),\n ),\n ),\n ),\n focus: (selector) => interact(agentVoid(\"interact\", \"focusEl\", [selector], selector)),\n select: (selector, value) =>\n interact(agentVoid(\"interact\", \"selectValue\", [selector, value], selector)),\n check: (selector) =>\n interact(\n agent(\"interact\", \"isChecked\", [selector], Schema.Boolean, selector).pipe(\n Effect.flatMap((checked) => (checked ? Effect.void : clickSelector(selector, 1))),\n ),\n ),\n uncheck: (selector) =>\n interact(\n agent(\"interact\", \"isChecked\", [selector], Schema.Boolean, selector).pipe(\n Effect.flatMap((checked) => (checked ? clickSelector(selector, 1) : Effect.void)),\n ),\n ),\n scroll: (opts) =>\n interact(agentVoid(\"interact\", \"scrollBy\", [opts.direction, opts.pixels ?? 600])),\n scrollIntoView: (selector) =>\n interact(agentVoid(\"interact\", \"scrollIntoView\", [selector], selector)),\n\n content,\n screenshot,\n snapshot,\n query,\n\n cookies,\n evaluate: (script) => interact(evalInPage(script, \"evaluate\")),\n }\n\n return session\n })\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effect-uai/browser",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Generic Chrome DevTools Protocol browser provider for @effect-uai/core.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agents",
|
|
@@ -46,13 +46,13 @@
|
|
|
46
46
|
"dependencies": {},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"devtools-protocol": "^0.0.1651496",
|
|
49
|
-
"effect": "4.0.0-
|
|
50
|
-
"typescript": "^
|
|
51
|
-
"@effect-uai/core": "0.
|
|
49
|
+
"effect": "4.0.0-rc.111",
|
|
50
|
+
"typescript": "^7.0.2",
|
|
51
|
+
"@effect-uai/core": "0.13.0"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
54
|
"@effect-uai/core": ">=0.5.0 <1",
|
|
55
|
-
"effect": ">=4.0.0-
|
|
55
|
+
"effect": ">=4.0.0-rc.111 <5.0.0"
|
|
56
56
|
},
|
|
57
57
|
"scripts": {
|
|
58
58
|
"build": "tsdown",
|
package/src/Connect.ts
CHANGED
|
@@ -143,12 +143,10 @@ const makeService = (config: CdpConnectConfig): CoreBrowser.BrowserService => ({
|
|
|
143
143
|
const { targetInfos } = yield* cdp.send("Target.getTargets").pipe(Effect.mapError(mapCreate))
|
|
144
144
|
return targetInfos
|
|
145
145
|
.filter((target) => target.type === "page")
|
|
146
|
-
.map(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}),
|
|
151
|
-
)
|
|
146
|
+
.map((target): CoreBrowser.BrowserSessionRef => ({
|
|
147
|
+
id: CoreBrowser.BrowserSessionId(target.targetId),
|
|
148
|
+
...(target.url !== "" ? { url: target.url } : {}),
|
|
149
|
+
}))
|
|
152
150
|
}),
|
|
153
151
|
),
|
|
154
152
|
|
package/src/internal/session.ts
CHANGED
|
@@ -465,15 +465,13 @@ export const makeSession = (
|
|
|
465
465
|
),
|
|
466
466
|
),
|
|
467
467
|
Effect.map((els) =>
|
|
468
|
-
els.map(
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
}),
|
|
476
|
-
),
|
|
468
|
+
els.map((el): CoreBrowser.ElementInfo => ({
|
|
469
|
+
ref: el.ref,
|
|
470
|
+
tag: el.tag,
|
|
471
|
+
...(el.text !== "" ? { text: el.text } : {}),
|
|
472
|
+
attributes: el.attributes,
|
|
473
|
+
box: el.box,
|
|
474
|
+
})),
|
|
477
475
|
),
|
|
478
476
|
),
|
|
479
477
|
),
|
|
@@ -486,18 +484,16 @@ export const makeSession = (
|
|
|
486
484
|
cdp.send("Network.getCookies", {}, sessionId).pipe(
|
|
487
485
|
Effect.mapError(mapCdp("cookies")),
|
|
488
486
|
Effect.map((reply) =>
|
|
489
|
-
reply.cookies.map(
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
}),
|
|
500
|
-
),
|
|
487
|
+
reply.cookies.map((c): CoreBrowser.Cookie => ({
|
|
488
|
+
name: c.name,
|
|
489
|
+
value: c.value,
|
|
490
|
+
domain: c.domain,
|
|
491
|
+
path: c.path,
|
|
492
|
+
expires: c.expires,
|
|
493
|
+
httpOnly: c.httpOnly,
|
|
494
|
+
secure: c.secure,
|
|
495
|
+
...(c.sameSite !== undefined ? { sameSite: c.sameSite } : {}),
|
|
496
|
+
})),
|
|
501
497
|
),
|
|
502
498
|
),
|
|
503
499
|
),
|