@browserbasehq/orca 3.1.0-patch.4 → 3.2.0-preview.2
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/cjs/lib/inference.js +1 -4
- package/dist/cjs/lib/inference.js.map +1 -1
- package/dist/cjs/lib/utils.d.ts +1 -0
- package/dist/cjs/lib/utils.js +4 -0
- package/dist/cjs/lib/utils.js.map +1 -1
- package/dist/cjs/lib/v3/agent/AgentProvider.js +0 -1
- package/dist/cjs/lib/v3/agent/AgentProvider.js.map +1 -1
- package/dist/cjs/lib/v3/agent/AnthropicCUAClient.js +4 -6
- package/dist/cjs/lib/v3/agent/AnthropicCUAClient.js.map +1 -1
- package/dist/cjs/lib/v3/agent/GoogleCUAClient.js +4 -6
- package/dist/cjs/lib/v3/agent/GoogleCUAClient.js.map +1 -1
- package/dist/cjs/lib/v3/agent/OpenAICUAClient.js +4 -6
- package/dist/cjs/lib/v3/agent/OpenAICUAClient.js.map +1 -1
- package/dist/cjs/lib/v3/agent/prompts/agentSystemPrompt.d.ts +2 -0
- package/dist/cjs/lib/v3/agent/prompts/agentSystemPrompt.js +2 -2
- package/dist/cjs/lib/v3/agent/prompts/agentSystemPrompt.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/act.d.ts +1 -1
- package/dist/cjs/lib/v3/agent/tools/act.js +20 -4
- package/dist/cjs/lib/v3/agent/tools/act.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/ariaTree.d.ts +8 -1
- package/dist/cjs/lib/v3/agent/tools/ariaTree.js +60 -22
- package/dist/cjs/lib/v3/agent/tools/ariaTree.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/{search.js → braveSearch.js} +1 -1
- package/dist/cjs/lib/v3/agent/tools/braveSearch.js.map +1 -0
- package/dist/cjs/lib/v3/agent/tools/browserbaseSearch.d.ts +13 -0
- package/dist/cjs/lib/v3/agent/tools/browserbaseSearch.js +70 -0
- package/dist/cjs/lib/v3/agent/tools/browserbaseSearch.js.map +1 -0
- package/dist/cjs/lib/v3/agent/tools/click.js +23 -31
- package/dist/cjs/lib/v3/agent/tools/click.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/dragAndDrop.js +22 -30
- package/dist/cjs/lib/v3/agent/tools/dragAndDrop.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/extract.d.ts +2 -2
- package/dist/cjs/lib/v3/agent/tools/extract.js +16 -3
- package/dist/cjs/lib/v3/agent/tools/extract.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/fillFormVision.js +30 -30
- package/dist/cjs/lib/v3/agent/tools/fillFormVision.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/fillform.d.ts +7 -1
- package/dist/cjs/lib/v3/agent/tools/fillform.js +60 -37
- package/dist/cjs/lib/v3/agent/tools/fillform.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/index.d.ts +19 -3
- package/dist/cjs/lib/v3/agent/tools/index.js +12 -8
- package/dist/cjs/lib/v3/agent/tools/index.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/screenshot.d.ts +8 -0
- package/dist/cjs/lib/v3/agent/tools/screenshot.js +32 -15
- package/dist/cjs/lib/v3/agent/tools/screenshot.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/scroll.js +12 -0
- package/dist/cjs/lib/v3/agent/tools/scroll.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/type.js +23 -31
- package/dist/cjs/lib/v3/agent/tools/type.js.map +1 -1
- package/dist/cjs/lib/v3/agent/tools/wait.js +6 -0
- package/dist/cjs/lib/v3/agent/tools/wait.js.map +1 -1
- package/dist/cjs/lib/v3/agent/utils/handleDoneToolCall.js +4 -0
- package/dist/cjs/lib/v3/agent/utils/handleDoneToolCall.js.map +1 -1
- package/dist/cjs/lib/v3/api.d.ts +2 -2
- package/dist/cjs/lib/v3/api.js +1 -1
- package/dist/cjs/lib/v3/api.js.map +1 -1
- package/dist/cjs/lib/v3/cache/ActCache.d.ts +0 -1
- package/dist/cjs/lib/v3/cache/ActCache.js +2 -18
- package/dist/cjs/lib/v3/cache/ActCache.js.map +1 -1
- package/dist/cjs/lib/v3/eventStore.d.ts +41 -0
- package/dist/cjs/lib/v3/eventStore.js +375 -0
- package/dist/cjs/lib/v3/eventStore.js.map +1 -0
- package/dist/cjs/lib/v3/flowLogger.d.ts +62 -103
- package/dist/cjs/lib/v3/flowLogger.js +362 -773
- package/dist/cjs/lib/v3/flowLogger.js.map +1 -1
- package/dist/cjs/lib/v3/handlers/actHandler.js +1 -2
- package/dist/cjs/lib/v3/handlers/actHandler.js.map +1 -1
- package/dist/cjs/lib/v3/handlers/extractHandler.js +2 -2
- package/dist/cjs/lib/v3/handlers/extractHandler.js.map +1 -1
- package/dist/cjs/lib/v3/handlers/handlerUtils/actHandlerUtils.js +21 -33
- package/dist/cjs/lib/v3/handlers/handlerUtils/actHandlerUtils.js.map +1 -1
- package/dist/cjs/lib/v3/handlers/observeHandler.js +1 -2
- package/dist/cjs/lib/v3/handlers/observeHandler.js.map +1 -1
- package/dist/cjs/lib/v3/handlers/v3AgentHandler.d.ts +0 -4
- package/dist/cjs/lib/v3/handlers/v3AgentHandler.js +23 -48
- package/dist/cjs/lib/v3/handlers/v3AgentHandler.js.map +1 -1
- package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js +10 -12
- package/dist/cjs/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
- package/dist/cjs/lib/v3/index.d.ts +2 -1
- package/dist/cjs/lib/v3/launch/browserbase.d.ts +1 -1
- package/dist/cjs/lib/v3/launch/browserbase.js +4 -9
- package/dist/cjs/lib/v3/launch/browserbase.js.map +1 -1
- package/dist/cjs/lib/v3/llm/LLMProvider.js +0 -5
- package/dist/cjs/lib/v3/llm/LLMProvider.js.map +1 -1
- package/dist/cjs/lib/v3/llm/aisdk.js +10 -16
- package/dist/cjs/lib/v3/llm/aisdk.js.map +1 -1
- package/dist/cjs/lib/v3/runtimePaths.js +2 -1
- package/dist/cjs/lib/v3/runtimePaths.js.map +1 -1
- package/dist/cjs/lib/v3/shutdown/supervisor.js +2 -2
- package/dist/cjs/lib/v3/shutdown/supervisor.js.map +1 -1
- package/dist/cjs/lib/v3/timeoutConfig.d.ts +1 -1
- package/dist/cjs/lib/v3/timeoutConfig.js +5 -0
- package/dist/cjs/lib/v3/timeoutConfig.js.map +1 -1
- package/dist/cjs/lib/v3/types/private/shutdown.d.ts +1 -1
- package/dist/cjs/lib/v3/types/private/shutdown.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/agent.d.ts +28 -3
- package/dist/cjs/lib/v3/types/public/agent.js +0 -1
- package/dist/cjs/lib/v3/types/public/agent.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/api.d.ts +3 -0
- package/dist/cjs/lib/v3/types/public/api.js +1 -0
- package/dist/cjs/lib/v3/types/public/api.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/model.d.ts +4 -2
- package/dist/cjs/lib/v3/types/public/model.js.map +1 -1
- package/dist/cjs/lib/v3/types/public/options.d.ts +6 -0
- package/dist/cjs/lib/v3/types/public/options.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/cdp.d.ts +8 -13
- package/dist/cjs/lib/v3/understudy/cdp.js +137 -17
- package/dist/cjs/lib/v3/understudy/cdp.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/context.d.ts +1 -0
- package/dist/cjs/lib/v3/understudy/context.js +142 -60
- package/dist/cjs/lib/v3/understudy/context.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/frame.js +23 -6
- package/dist/cjs/lib/v3/understudy/frame.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/page.d.ts +13 -0
- package/dist/cjs/lib/v3/understudy/page.js +88 -20
- package/dist/cjs/lib/v3/understudy/page.js.map +1 -1
- package/dist/cjs/lib/v3/understudy/screenshotUtils.d.ts +0 -1
- package/dist/cjs/lib/v3/understudy/screenshotUtils.js +0 -18
- package/dist/cjs/lib/v3/understudy/screenshotUtils.js.map +1 -1
- package/dist/cjs/lib/v3/v3.d.ts +10 -0
- package/dist/cjs/lib/v3/v3.js +210 -172
- package/dist/cjs/lib/v3/v3.js.map +1 -1
- package/dist/cjs/tests/integration/cdp-session-detached.spec.js +1 -1
- package/dist/cjs/tests/integration/cdp-session-detached.spec.js.map +1 -1
- package/dist/cjs/tests/integration/context-addInitScript.spec.js +104 -11
- package/dist/cjs/tests/integration/context-addInitScript.spec.js.map +1 -1
- package/dist/cjs/tests/integration/iframe-ctx-addInitScript-race.spec.js +219 -0
- package/dist/cjs/tests/integration/iframe-ctx-addInitScript-race.spec.js.map +1 -0
- package/dist/cjs/tests/integration/page-extra-http-headers.spec.js +85 -0
- package/dist/cjs/tests/integration/page-extra-http-headers.spec.js.map +1 -0
- package/dist/cjs/tests/integration/page-screenshot.spec.js +1 -1
- package/dist/cjs/tests/integration/page-screenshot.spec.js.map +1 -1
- package/dist/cjs/tests/integration/timeouts.spec.js +168 -0
- package/dist/cjs/tests/integration/timeouts.spec.js.map +1 -1
- package/dist/cjs/tests/unit/model-deprecation.test.js +5 -8
- package/dist/cjs/tests/unit/model-deprecation.test.js.map +1 -1
- package/dist/cjs/tests/unit/page-extra-http-headers.test.d.ts +1 -0
- package/dist/cjs/tests/unit/page-extra-http-headers.test.js +92 -0
- package/dist/cjs/tests/unit/page-extra-http-headers.test.js.map +1 -0
- package/dist/cjs/tests/unit/public-api/llm-and-agents.test.js +13 -1
- package/dist/cjs/tests/unit/public-api/llm-and-agents.test.js.map +1 -1
- package/dist/cjs/tests/unit/public-api/public-types.test.js.map +1 -1
- package/dist/esm/lib/inference.js +1 -4
- package/dist/esm/lib/inference.js.map +1 -1
- package/dist/esm/lib/utils.d.ts +1 -0
- package/dist/esm/lib/utils.js +3 -0
- package/dist/esm/lib/utils.js.map +1 -1
- package/dist/esm/lib/v3/agent/AgentProvider.js +0 -1
- package/dist/esm/lib/v3/agent/AgentProvider.js.map +1 -1
- package/dist/esm/lib/v3/agent/AnthropicCUAClient.js +5 -7
- package/dist/esm/lib/v3/agent/AnthropicCUAClient.js.map +1 -1
- package/dist/esm/lib/v3/agent/GoogleCUAClient.js +5 -7
- package/dist/esm/lib/v3/agent/GoogleCUAClient.js.map +1 -1
- package/dist/esm/lib/v3/agent/OpenAICUAClient.js +5 -7
- package/dist/esm/lib/v3/agent/OpenAICUAClient.js.map +1 -1
- package/dist/esm/lib/v3/agent/prompts/agentSystemPrompt.d.ts +2 -0
- package/dist/esm/lib/v3/agent/prompts/agentSystemPrompt.js +2 -2
- package/dist/esm/lib/v3/agent/prompts/agentSystemPrompt.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/act.d.ts +1 -1
- package/dist/esm/lib/v3/agent/tools/act.js +20 -4
- package/dist/esm/lib/v3/agent/tools/act.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/ariaTree.d.ts +8 -1
- package/dist/esm/lib/v3/agent/tools/ariaTree.js +60 -22
- package/dist/esm/lib/v3/agent/tools/ariaTree.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/{search.js → braveSearch.js} +1 -1
- package/dist/esm/lib/v3/agent/tools/braveSearch.js.map +1 -0
- package/dist/esm/lib/v3/agent/tools/browserbaseSearch.d.ts +13 -0
- package/dist/esm/lib/v3/agent/tools/browserbaseSearch.js +66 -0
- package/dist/esm/lib/v3/agent/tools/browserbaseSearch.js.map +1 -0
- package/dist/esm/lib/v3/agent/tools/click.js +23 -31
- package/dist/esm/lib/v3/agent/tools/click.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/dragAndDrop.js +22 -30
- package/dist/esm/lib/v3/agent/tools/dragAndDrop.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/extract.d.ts +2 -2
- package/dist/esm/lib/v3/agent/tools/extract.js +16 -3
- package/dist/esm/lib/v3/agent/tools/extract.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/fillFormVision.js +30 -30
- package/dist/esm/lib/v3/agent/tools/fillFormVision.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/fillform.d.ts +7 -1
- package/dist/esm/lib/v3/agent/tools/fillform.js +60 -37
- package/dist/esm/lib/v3/agent/tools/fillform.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/index.d.ts +19 -3
- package/dist/esm/lib/v3/agent/tools/index.js +12 -8
- package/dist/esm/lib/v3/agent/tools/index.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/screenshot.d.ts +8 -0
- package/dist/esm/lib/v3/agent/tools/screenshot.js +32 -15
- package/dist/esm/lib/v3/agent/tools/screenshot.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/scroll.js +12 -0
- package/dist/esm/lib/v3/agent/tools/scroll.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/type.js +23 -31
- package/dist/esm/lib/v3/agent/tools/type.js.map +1 -1
- package/dist/esm/lib/v3/agent/tools/wait.js +6 -0
- package/dist/esm/lib/v3/agent/tools/wait.js.map +1 -1
- package/dist/esm/lib/v3/agent/utils/handleDoneToolCall.js +4 -0
- package/dist/esm/lib/v3/agent/utils/handleDoneToolCall.js.map +1 -1
- package/dist/esm/lib/v3/api.d.ts +2 -2
- package/dist/esm/lib/v3/api.js +1 -1
- package/dist/esm/lib/v3/api.js.map +1 -1
- package/dist/esm/lib/v3/cache/ActCache.d.ts +0 -1
- package/dist/esm/lib/v3/cache/ActCache.js +2 -18
- package/dist/esm/lib/v3/cache/ActCache.js.map +1 -1
- package/dist/esm/lib/v3/eventStore.d.ts +41 -0
- package/dist/esm/lib/v3/eventStore.js +363 -0
- package/dist/esm/lib/v3/eventStore.js.map +1 -0
- package/dist/esm/lib/v3/flowLogger.d.ts +62 -103
- package/dist/esm/lib/v3/flowLogger.js +356 -762
- package/dist/esm/lib/v3/flowLogger.js.map +1 -1
- package/dist/esm/lib/v3/handlers/actHandler.js +1 -2
- package/dist/esm/lib/v3/handlers/actHandler.js.map +1 -1
- package/dist/esm/lib/v3/handlers/extractHandler.js +2 -2
- package/dist/esm/lib/v3/handlers/extractHandler.js.map +1 -1
- package/dist/esm/lib/v3/handlers/handlerUtils/actHandlerUtils.js +22 -34
- package/dist/esm/lib/v3/handlers/handlerUtils/actHandlerUtils.js.map +1 -1
- package/dist/esm/lib/v3/handlers/observeHandler.js +1 -2
- package/dist/esm/lib/v3/handlers/observeHandler.js.map +1 -1
- package/dist/esm/lib/v3/handlers/v3AgentHandler.d.ts +0 -4
- package/dist/esm/lib/v3/handlers/v3AgentHandler.js +25 -50
- package/dist/esm/lib/v3/handlers/v3AgentHandler.js.map +1 -1
- package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js +11 -13
- package/dist/esm/lib/v3/handlers/v3CuaAgentHandler.js.map +1 -1
- package/dist/esm/lib/v3/index.d.ts +2 -1
- package/dist/esm/lib/v3/launch/browserbase.d.ts +1 -1
- package/dist/esm/lib/v3/launch/browserbase.js +4 -9
- package/dist/esm/lib/v3/launch/browserbase.js.map +1 -1
- package/dist/esm/lib/v3/llm/LLMProvider.js +0 -5
- package/dist/esm/lib/v3/llm/LLMProvider.js.map +1 -1
- package/dist/esm/lib/v3/llm/aisdk.js +11 -17
- package/dist/esm/lib/v3/llm/aisdk.js.map +1 -1
- package/dist/esm/lib/v3/runtimePaths.js +2 -1
- package/dist/esm/lib/v3/runtimePaths.js.map +1 -1
- package/dist/esm/lib/v3/shutdown/supervisor.js +2 -2
- package/dist/esm/lib/v3/shutdown/supervisor.js.map +1 -1
- package/dist/esm/lib/v3/timeoutConfig.d.ts +1 -1
- package/dist/esm/lib/v3/timeoutConfig.js +5 -0
- package/dist/esm/lib/v3/timeoutConfig.js.map +1 -1
- package/dist/esm/lib/v3/types/private/shutdown.d.ts +1 -1
- package/dist/esm/lib/v3/types/private/shutdown.js.map +1 -1
- package/dist/esm/lib/v3/types/public/agent.d.ts +28 -3
- package/dist/esm/lib/v3/types/public/agent.js +0 -1
- package/dist/esm/lib/v3/types/public/agent.js.map +1 -1
- package/dist/esm/lib/v3/types/public/api.d.ts +3 -0
- package/dist/esm/lib/v3/types/public/api.js +1 -0
- package/dist/esm/lib/v3/types/public/api.js.map +1 -1
- package/dist/esm/lib/v3/types/public/model.d.ts +4 -2
- package/dist/esm/lib/v3/types/public/model.js.map +1 -1
- package/dist/esm/lib/v3/types/public/options.d.ts +6 -0
- package/dist/esm/lib/v3/types/public/options.js.map +1 -1
- package/dist/esm/lib/v3/understudy/cdp.d.ts +8 -13
- package/dist/esm/lib/v3/understudy/cdp.js +138 -18
- package/dist/esm/lib/v3/understudy/cdp.js.map +1 -1
- package/dist/esm/lib/v3/understudy/context.d.ts +1 -0
- package/dist/esm/lib/v3/understudy/context.js +142 -60
- package/dist/esm/lib/v3/understudy/context.js.map +1 -1
- package/dist/esm/lib/v3/understudy/frame.js +23 -6
- package/dist/esm/lib/v3/understudy/frame.js.map +1 -1
- package/dist/esm/lib/v3/understudy/page.d.ts +13 -0
- package/dist/esm/lib/v3/understudy/page.js +91 -23
- package/dist/esm/lib/v3/understudy/page.js.map +1 -1
- package/dist/esm/lib/v3/understudy/screenshotUtils.d.ts +0 -1
- package/dist/esm/lib/v3/understudy/screenshotUtils.js +0 -17
- package/dist/esm/lib/v3/understudy/screenshotUtils.js.map +1 -1
- package/dist/esm/lib/v3/v3.d.ts +10 -0
- package/dist/esm/lib/v3/v3.js +211 -173
- package/dist/esm/lib/v3/v3.js.map +1 -1
- package/dist/esm/tests/integration/cdp-session-detached.spec.js +1 -1
- package/dist/esm/tests/integration/cdp-session-detached.spec.js.map +1 -1
- package/dist/esm/tests/integration/context-addInitScript.spec.js +104 -11
- package/dist/esm/tests/integration/context-addInitScript.spec.js.map +1 -1
- package/dist/esm/tests/integration/iframe-ctx-addInitScript-race.spec.d.ts +1 -0
- package/dist/esm/tests/integration/iframe-ctx-addInitScript-race.spec.js +217 -0
- package/dist/esm/tests/integration/iframe-ctx-addInitScript-race.spec.js.map +1 -0
- package/dist/esm/tests/integration/page-extra-http-headers.spec.d.ts +1 -0
- package/dist/esm/tests/integration/page-extra-http-headers.spec.js +83 -0
- package/dist/esm/tests/integration/page-extra-http-headers.spec.js.map +1 -0
- package/dist/esm/tests/integration/page-screenshot.spec.js +1 -1
- package/dist/esm/tests/integration/page-screenshot.spec.js.map +1 -1
- package/dist/esm/tests/integration/timeouts.spec.js +168 -0
- package/dist/esm/tests/integration/timeouts.spec.js.map +1 -1
- package/dist/esm/tests/unit/model-deprecation.test.js +5 -8
- package/dist/esm/tests/unit/model-deprecation.test.js.map +1 -1
- package/dist/esm/tests/unit/page-extra-http-headers.test.d.ts +1 -0
- package/dist/esm/tests/unit/page-extra-http-headers.test.js +90 -0
- package/dist/esm/tests/unit/page-extra-http-headers.test.js.map +1 -0
- package/dist/esm/tests/unit/public-api/llm-and-agents.test.js +13 -1
- package/dist/esm/tests/unit/public-api/llm-and-agents.test.js.map +1 -1
- package/dist/esm/tests/unit/public-api/public-types.test.js.map +1 -1
- package/package.json +2 -2
- package/dist/cjs/lib/v3/agent/tools/search.js.map +0 -1
- package/dist/cjs/tests/unit/rerender-missing-shadows.test.js +0 -209
- package/dist/cjs/tests/unit/rerender-missing-shadows.test.js.map +0 -1
- package/dist/esm/lib/v3/agent/tools/search.js.map +0 -1
- package/dist/esm/tests/unit/rerender-missing-shadows.test.js +0 -207
- package/dist/esm/tests/unit/rerender-missing-shadows.test.js.map +0 -1
- /package/dist/cjs/lib/v3/agent/tools/{search.d.ts → braveSearch.d.ts} +0 -0
- /package/dist/cjs/tests/{unit/rerender-missing-shadows.test.d.ts → integration/iframe-ctx-addInitScript-race.spec.d.ts} +0 -0
- /package/dist/{esm/tests/unit/rerender-missing-shadows.test.d.ts → cjs/tests/integration/page-extra-http-headers.spec.d.ts} +0 -0
- /package/dist/esm/lib/v3/agent/tools/{search.d.ts → braveSearch.d.ts} +0 -0
|
@@ -7,21 +7,21 @@ exports.CdpSession = exports.CdpConnection = void 0;
|
|
|
7
7
|
// lib/v3/understudy/cdp.ts
|
|
8
8
|
const ws_1 = __importDefault(require("ws"));
|
|
9
9
|
const version_js_1 = require("../../version.js");
|
|
10
|
+
const flowLogger_js_1 = require("../flowLogger.js");
|
|
10
11
|
const sdkErrors_js_1 = require("../types/public/sdkErrors.js");
|
|
11
12
|
class CdpConnection {
|
|
12
13
|
ws;
|
|
13
14
|
nextId = 1;
|
|
14
15
|
inflight = new Map();
|
|
16
|
+
latestCdpCallEvent = new Map();
|
|
15
17
|
eventHandlers = new Map();
|
|
16
18
|
sessions = new Map();
|
|
17
19
|
/** Maps sessionId -> targetId (1:1 mapping) */
|
|
18
20
|
sessionToTarget = new Map();
|
|
21
|
+
sessionDispatchWaiters = new Set();
|
|
19
22
|
id = null; // root
|
|
20
23
|
transportCloseHandlers = new Set();
|
|
21
|
-
|
|
22
|
-
cdpLogger;
|
|
23
|
-
/** Optional CDP event logger - set this to receive all incoming CDP events */
|
|
24
|
-
cdpEventLogger;
|
|
24
|
+
flowLoggerContext;
|
|
25
25
|
onTransportClosed(handler) {
|
|
26
26
|
this.transportCloseHandlers.add(handler);
|
|
27
27
|
}
|
|
@@ -53,13 +53,14 @@ class CdpConnection {
|
|
|
53
53
|
});
|
|
54
54
|
this.ws.on("message", (data) => this.onMessage(data.toString()));
|
|
55
55
|
}
|
|
56
|
-
static async connect(wsUrl) {
|
|
56
|
+
static async connect(wsUrl, options) {
|
|
57
57
|
// Include User-Agent header for server-side observability and version tracking
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
58
|
+
// Merge user-provided headers, letting them override defaults
|
|
59
|
+
const headers = {
|
|
60
|
+
"User-Agent": `Stagehand/${version_js_1.STAGEHAND_VERSION}`,
|
|
61
|
+
...options?.headers,
|
|
62
|
+
};
|
|
63
|
+
const ws = new ws_1.default(wsUrl, { headers });
|
|
63
64
|
await new Promise((resolve, reject) => {
|
|
64
65
|
ws.once("open", () => resolve());
|
|
65
66
|
ws.once("error", (e) => reject(e));
|
|
@@ -78,6 +79,26 @@ class CdpConnection {
|
|
|
78
79
|
const id = this.nextId++;
|
|
79
80
|
const payload = { id, method, params };
|
|
80
81
|
const stack = new Error().stack?.split("\n").slice(1, 4).join("\n");
|
|
82
|
+
let flowLoggerContext = null;
|
|
83
|
+
try {
|
|
84
|
+
flowLoggerContext = flowLogger_js_1.FlowLogger.currentContext;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
flowLoggerContext = this.flowLoggerContext ?? null;
|
|
88
|
+
}
|
|
89
|
+
const cdpCallEvent = flowLoggerContext
|
|
90
|
+
? flowLogger_js_1.FlowLogger.logCdpCallEvent(flowLoggerContext, {
|
|
91
|
+
method,
|
|
92
|
+
params,
|
|
93
|
+
targetId: null,
|
|
94
|
+
})
|
|
95
|
+
: null;
|
|
96
|
+
if (flowLoggerContext && cdpCallEvent) {
|
|
97
|
+
this.latestCdpCallEvent.set(null, {
|
|
98
|
+
flowLoggerContext,
|
|
99
|
+
cdpCallEvent,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
81
102
|
const p = new Promise((resolve, reject) => {
|
|
82
103
|
this.inflight.set(id, {
|
|
83
104
|
resolve,
|
|
@@ -87,11 +108,12 @@ class CdpConnection {
|
|
|
87
108
|
params,
|
|
88
109
|
stack,
|
|
89
110
|
ts: Date.now(),
|
|
111
|
+
flowLoggerContext,
|
|
112
|
+
cdpCallEvent,
|
|
90
113
|
});
|
|
91
114
|
});
|
|
92
115
|
// Prevent unhandledRejection if a session detaches before the caller awaits.
|
|
93
116
|
void p.catch(() => { });
|
|
94
|
-
this.cdpLogger?.({ method, params, targetId: null });
|
|
95
117
|
this.ws.send(JSON.stringify(payload));
|
|
96
118
|
return p;
|
|
97
119
|
}
|
|
@@ -118,10 +140,32 @@ class CdpConnection {
|
|
|
118
140
|
entry.reject(new sdkErrors_js_1.CdpConnectionClosedError(why));
|
|
119
141
|
this.inflight.delete(id);
|
|
120
142
|
}
|
|
143
|
+
this.latestCdpCallEvent.clear();
|
|
144
|
+
for (const waiter of Array.from(this.sessionDispatchWaiters)) {
|
|
145
|
+
waiter.reject(new sdkErrors_js_1.CdpConnectionClosedError(why));
|
|
146
|
+
}
|
|
121
147
|
}
|
|
122
148
|
getSession(sessionId) {
|
|
123
149
|
return this.sessions.get(sessionId);
|
|
124
150
|
}
|
|
151
|
+
waitForSessionDispatch(sessionId, method, match) {
|
|
152
|
+
return new Promise((resolve, reject) => {
|
|
153
|
+
const waiter = {
|
|
154
|
+
sessionId,
|
|
155
|
+
method,
|
|
156
|
+
match,
|
|
157
|
+
resolve: () => {
|
|
158
|
+
this.sessionDispatchWaiters.delete(waiter);
|
|
159
|
+
resolve();
|
|
160
|
+
},
|
|
161
|
+
reject: (error) => {
|
|
162
|
+
this.sessionDispatchWaiters.delete(waiter);
|
|
163
|
+
reject(error);
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
this.sessionDispatchWaiters.add(waiter);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
125
169
|
async attachToTarget(targetId) {
|
|
126
170
|
const { sessionId } = (await this.send("Target.attachToTarget", { targetId, flatten: true }));
|
|
127
171
|
let session = this.sessions.get(sessionId);
|
|
@@ -144,9 +188,29 @@ class CdpConnection {
|
|
|
144
188
|
return;
|
|
145
189
|
this.inflight.delete(msg.id);
|
|
146
190
|
if ("error" in msg && msg.error) {
|
|
191
|
+
if (rec.flowLoggerContext && rec.cdpCallEvent) {
|
|
192
|
+
const targetId = rec.sessionId != null
|
|
193
|
+
? (this.sessionToTarget.get(rec.sessionId) ?? rec.sessionId)
|
|
194
|
+
: null;
|
|
195
|
+
flowLogger_js_1.FlowLogger.logCdpResponseEvent(rec.flowLoggerContext, rec.cdpCallEvent, {
|
|
196
|
+
method: rec.method,
|
|
197
|
+
error: `${msg.error.code} ${msg.error.message}`,
|
|
198
|
+
targetId,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
147
201
|
rec.reject(new Error(`${msg.error.code} ${msg.error.message}`));
|
|
148
202
|
}
|
|
149
203
|
else {
|
|
204
|
+
if (rec.flowLoggerContext && rec.cdpCallEvent) {
|
|
205
|
+
const targetId = rec.sessionId != null
|
|
206
|
+
? (this.sessionToTarget.get(rec.sessionId) ?? rec.sessionId)
|
|
207
|
+
: null;
|
|
208
|
+
flowLogger_js_1.FlowLogger.logCdpResponseEvent(rec.flowLoggerContext, rec.cdpCallEvent, {
|
|
209
|
+
method: rec.method,
|
|
210
|
+
result: msg.result,
|
|
211
|
+
targetId,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
150
214
|
rec.resolve(msg.result);
|
|
151
215
|
}
|
|
152
216
|
return;
|
|
@@ -165,12 +229,18 @@ class CdpConnection {
|
|
|
165
229
|
.params;
|
|
166
230
|
for (const [id, entry] of this.inflight.entries()) {
|
|
167
231
|
if (entry.sessionId === p.sessionId) {
|
|
168
|
-
entry.reject(new
|
|
232
|
+
entry.reject(new sdkErrors_js_1.PageNotFoundError(`target closed before CDP response (sessionId=${p.sessionId}, targetId=${p.targetId})`));
|
|
169
233
|
this.inflight.delete(id);
|
|
170
234
|
}
|
|
171
235
|
}
|
|
236
|
+
for (const waiter of Array.from(this.sessionDispatchWaiters)) {
|
|
237
|
+
if (waiter.sessionId === p.sessionId) {
|
|
238
|
+
waiter.reject(new sdkErrors_js_1.PageNotFoundError(`target closed before CDP send (sessionId=${p.sessionId}, targetId=${p.targetId})`));
|
|
239
|
+
}
|
|
240
|
+
}
|
|
172
241
|
this.sessions.delete(p.sessionId);
|
|
173
242
|
this.sessionToTarget.delete(p.sessionId);
|
|
243
|
+
this.latestCdpCallEvent.delete(p.sessionId);
|
|
174
244
|
}
|
|
175
245
|
else if (msg.method === "Target.targetDestroyed") {
|
|
176
246
|
const p = msg.params;
|
|
@@ -178,17 +248,36 @@ class CdpConnection {
|
|
|
178
248
|
for (const [sessionId, targetId] of this.sessionToTarget.entries()) {
|
|
179
249
|
if (targetId === p.targetId) {
|
|
180
250
|
this.sessionToTarget.delete(sessionId);
|
|
251
|
+
this.latestCdpCallEvent.delete(sessionId);
|
|
181
252
|
break;
|
|
182
253
|
}
|
|
183
254
|
}
|
|
184
255
|
}
|
|
185
256
|
const { method, params, sessionId } = msg;
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
257
|
+
const latestCdpCallEvent = this.latestCdpCallEvent.get(sessionId ?? null) ??
|
|
258
|
+
(sessionId ? this.latestCdpCallEvent.get(null) : null);
|
|
259
|
+
const targetId = sessionId != null
|
|
260
|
+
? (this.sessionToTarget.get(sessionId) ?? sessionId)
|
|
261
|
+
: null;
|
|
262
|
+
if (latestCdpCallEvent) {
|
|
263
|
+
flowLogger_js_1.FlowLogger.logCdpMessageEvent(latestCdpCallEvent.flowLoggerContext, latestCdpCallEvent.cdpCallEvent, {
|
|
264
|
+
method,
|
|
265
|
+
params,
|
|
266
|
+
targetId,
|
|
267
|
+
});
|
|
268
|
+
}
|
|
189
269
|
if (sessionId) {
|
|
190
270
|
const session = this.sessions.get(sessionId);
|
|
191
271
|
session?.dispatch(method, params);
|
|
272
|
+
// Forward target lifecycle events to root listeners as well.
|
|
273
|
+
// Some browsers emit these via a parent session rather than the root
|
|
274
|
+
// connection; fan-out keeps target tracking consistent.
|
|
275
|
+
if (method.startsWith("Target.")) {
|
|
276
|
+
const handlers = this.eventHandlers.get(method);
|
|
277
|
+
if (handlers)
|
|
278
|
+
for (const h of handlers)
|
|
279
|
+
h(params);
|
|
280
|
+
}
|
|
192
281
|
}
|
|
193
282
|
else {
|
|
194
283
|
const handlers = this.eventHandlers.get(method);
|
|
@@ -202,6 +291,27 @@ class CdpConnection {
|
|
|
202
291
|
const id = this.nextId++;
|
|
203
292
|
const payload = { id, method, params, sessionId };
|
|
204
293
|
const stack = new Error().stack?.split("\n").slice(1, 4).join("\n");
|
|
294
|
+
let flowLoggerContext = null;
|
|
295
|
+
try {
|
|
296
|
+
flowLoggerContext = flowLogger_js_1.FlowLogger.currentContext;
|
|
297
|
+
}
|
|
298
|
+
catch {
|
|
299
|
+
flowLoggerContext = this.flowLoggerContext ?? null;
|
|
300
|
+
}
|
|
301
|
+
const targetId = this.sessionToTarget.get(sessionId) ?? null;
|
|
302
|
+
const cdpCallEvent = flowLoggerContext
|
|
303
|
+
? flowLogger_js_1.FlowLogger.logCdpCallEvent(flowLoggerContext, {
|
|
304
|
+
method,
|
|
305
|
+
params,
|
|
306
|
+
targetId,
|
|
307
|
+
})
|
|
308
|
+
: null;
|
|
309
|
+
if (flowLoggerContext && cdpCallEvent) {
|
|
310
|
+
this.latestCdpCallEvent.set(sessionId, {
|
|
311
|
+
flowLoggerContext,
|
|
312
|
+
cdpCallEvent,
|
|
313
|
+
});
|
|
314
|
+
}
|
|
205
315
|
const p = new Promise((resolve, reject) => {
|
|
206
316
|
this.inflight.set(id, {
|
|
207
317
|
resolve,
|
|
@@ -211,12 +321,22 @@ class CdpConnection {
|
|
|
211
321
|
params,
|
|
212
322
|
stack,
|
|
213
323
|
ts: Date.now(),
|
|
324
|
+
flowLoggerContext,
|
|
325
|
+
cdpCallEvent,
|
|
214
326
|
});
|
|
215
327
|
});
|
|
216
328
|
// Prevent unhandledRejection if a session detaches before the caller awaits.
|
|
217
329
|
void p.catch(() => { });
|
|
218
|
-
const
|
|
219
|
-
|
|
330
|
+
for (const waiter of Array.from(this.sessionDispatchWaiters)) {
|
|
331
|
+
if (waiter.sessionId !== sessionId)
|
|
332
|
+
continue;
|
|
333
|
+
if (waiter.method !== method)
|
|
334
|
+
continue;
|
|
335
|
+
if (waiter.match && !waiter.match(params))
|
|
336
|
+
continue;
|
|
337
|
+
waiter.resolve();
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
220
340
|
this.ws.send(JSON.stringify(payload));
|
|
221
341
|
return p;
|
|
222
342
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cdp.js","sourceRoot":"","sources":["../../../../../lib/v3/understudy/cdp.ts"],"names":[],"mappings":"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","sourcesContent":["// lib/v3/understudy/cdp.ts\nimport WebSocket from \"ws\";\nimport type { Protocol } from \"devtools-protocol\";\nimport { STAGEHAND_VERSION } from \"../../version.js\";\nimport { CdpConnectionClosedError } from \"../types/public/sdkErrors.js\";\n\n/**\n * CDP transport & session multiplexer\n *\n * Owns the browser WebSocket and multiplexes flattened Target sessions.\n * Tracks inflight CDP calls, routes responses to the right session, and forwards events.\n *\n * This does not interpret Page/DOM/Runtime semantics — callers own that logic.\n */\nexport interface CDPSessionLike {\n send<R = unknown>(method: string, params?: object): Promise<R>;\n on<P = unknown>(event: string, handler: (params: P) => void): void;\n off<P = unknown>(event: string, handler: (params: P) => void): void;\n close(): Promise<void>;\n readonly id: string | null;\n}\n\ntype Inflight = {\n resolve: (v: unknown) => void;\n reject: (e: Error) => void;\n sessionId?: string | null;\n method: string;\n params?: object;\n stack?: string;\n ts: number;\n};\n\ntype EventHandler = (params: unknown) => void;\n\ntype RawMessage =\n | {\n id: number;\n result?: unknown;\n error?: { code: number; message: string; data?: unknown };\n sessionId?: string;\n }\n | { method: string; params?: unknown; sessionId?: string };\n\nexport class CdpConnection implements CDPSessionLike {\n private ws: WebSocket;\n private nextId = 1;\n private inflight = new Map<number, Inflight>();\n private eventHandlers = new Map<string, Set<EventHandler>>();\n private sessions = new Map<string, CdpSession>();\n /** Maps sessionId -> targetId (1:1 mapping) */\n private sessionToTarget = new Map<string, string>();\n public readonly id: string | null = null; // root\n private transportCloseHandlers = new Set<(why: string) => void>();\n\n /** Optional CDP logger - set this to receive all outgoing CDP method calls */\n public cdpLogger?: (info: {\n method: string;\n params?: object;\n targetId?: string | null;\n }) => void;\n\n /** Optional CDP event logger - set this to receive all incoming CDP events */\n public cdpEventLogger?: (info: {\n method: string;\n params?: unknown;\n targetId?: string | null;\n }) => void;\n\n public onTransportClosed(handler: (why: string) => void): void {\n this.transportCloseHandlers.add(handler);\n }\n public offTransportClosed(handler: (why: string) => void): void {\n this.transportCloseHandlers.delete(handler);\n }\n\n private emitTransportClosed(why: string) {\n for (const h of this.transportCloseHandlers) {\n try {\n h(why);\n } catch {\n //\n }\n }\n }\n\n private constructor(ws: WebSocket) {\n this.ws = ws;\n this.ws.on(\"close\", (code, reason) => {\n // Reason is a Buffer in ws; stringify defensively\n const why = `socket-close code=${code} reason=${String(reason || \"\")}`;\n this.rejectAllInflight(why);\n this.emitTransportClosed(why);\n });\n\n this.ws.on(\"error\", (err) => {\n const why = `socket-error ${err?.message ?? String(err)}`;\n this.rejectAllInflight(why);\n this.emitTransportClosed(why);\n });\n this.ws.on(\"message\", (data) => this.onMessage(data.toString()));\n }\n\n static async connect(wsUrl: string): Promise<CdpConnection> {\n // Include User-Agent header for server-side observability and version tracking\n const ws = new WebSocket(wsUrl, {\n headers: {\n \"User-Agent\": `Stagehand/${STAGEHAND_VERSION}`,\n },\n });\n await new Promise<void>((resolve, reject) => {\n ws.once(\"open\", () => resolve());\n ws.once(\"error\", (e) => reject(e));\n });\n return new CdpConnection(ws);\n }\n\n async enableAutoAttach(): Promise<void> {\n await this.send(\"Target.setAutoAttach\", {\n autoAttach: true,\n flatten: true,\n waitForDebuggerOnStart: true,\n });\n await this.send(\"Target.setDiscoverTargets\", { discover: true });\n }\n\n async send<R = unknown>(method: string, params?: object): Promise<R> {\n const id = this.nextId++;\n const payload = { id, method, params };\n const stack = new Error().stack?.split(\"\\n\").slice(1, 4).join(\"\\n\");\n const p = new Promise<R>((resolve, reject) => {\n this.inflight.set(id, {\n resolve,\n reject,\n sessionId: null,\n method,\n params,\n stack,\n ts: Date.now(),\n });\n });\n // Prevent unhandledRejection if a session detaches before the caller awaits.\n void p.catch(() => {});\n this.cdpLogger?.({ method, params, targetId: null });\n this.ws.send(JSON.stringify(payload));\n return p;\n }\n\n on<P = unknown>(event: string, handler: (params: P) => void): void {\n const set = this.eventHandlers.get(event) ?? new Set<EventHandler>();\n set.add(handler as EventHandler);\n this.eventHandlers.set(event, set);\n }\n\n off<P = unknown>(event: string, handler: (params: P) => void): void {\n const set = this.eventHandlers.get(event);\n if (set) set.delete(handler as EventHandler);\n }\n\n async close(): Promise<void> {\n if (this.ws.readyState === WebSocket.CLOSED) return;\n await new Promise<void>((resolve) => {\n this.ws.once(\"close\", () => resolve());\n this.ws.close();\n });\n }\n\n private rejectAllInflight(why: string): void {\n for (const [id, entry] of this.inflight.entries()) {\n entry.reject(new CdpConnectionClosedError(why));\n this.inflight.delete(id);\n }\n }\n\n getSession(sessionId: string): CdpSession | undefined {\n return this.sessions.get(sessionId);\n }\n\n async attachToTarget(targetId: string): Promise<CdpSession> {\n const { sessionId } = (await this.send<{ sessionId: string }>(\n \"Target.attachToTarget\",\n { targetId, flatten: true },\n )) as { sessionId: string };\n\n let session = this.sessions.get(sessionId);\n if (!session) {\n session = new CdpSession(this, sessionId);\n this.sessions.set(sessionId, session);\n }\n this.sessionToTarget.set(sessionId, targetId);\n return session;\n }\n\n async getTargets(): Promise<Protocol.Target.TargetInfo[]> {\n const res = await this.send<{\n targetInfos: Protocol.Target.TargetInfo[];\n }>(\"Target.getTargets\");\n return res.targetInfos;\n }\n\n private onMessage(json: string): void {\n const msg = JSON.parse(json) as RawMessage;\n\n if (\"id\" in msg) {\n const rec = this.inflight.get(msg.id);\n if (!rec) return;\n\n this.inflight.delete(msg.id);\n\n if (\"error\" in msg && msg.error) {\n rec.reject(new Error(`${msg.error.code} ${msg.error.message}`));\n } else {\n rec.resolve((msg as { result?: unknown }).result);\n }\n return;\n }\n\n if (\"method\" in msg) {\n if (msg.method === \"Target.attachedToTarget\") {\n const p = (msg as { params: Protocol.Target.AttachedToTargetEvent })\n .params;\n if (!this.sessions.has(p.sessionId)) {\n this.sessions.set(p.sessionId, new CdpSession(this, p.sessionId));\n }\n this.sessionToTarget.set(p.sessionId, p.targetInfo.targetId);\n } else if (msg.method === \"Target.detachedFromTarget\") {\n const p = (msg as { params: Protocol.Target.DetachedFromTargetEvent })\n .params;\n for (const [id, entry] of this.inflight.entries()) {\n if (entry.sessionId === p.sessionId) {\n entry.reject(new Error(\"CDP session detached\"));\n this.inflight.delete(id);\n }\n }\n this.sessions.delete(p.sessionId);\n this.sessionToTarget.delete(p.sessionId);\n } else if (msg.method === \"Target.targetDestroyed\") {\n const p = (msg as { params: { targetId: string } }).params;\n // Remove any session mapping for this target\n for (const [sessionId, targetId] of this.sessionToTarget.entries()) {\n if (targetId === p.targetId) {\n this.sessionToTarget.delete(sessionId);\n break;\n }\n }\n }\n\n const { method, params, sessionId } = msg;\n\n // Log incoming CDP events\n const targetId = this.sessionToTarget.get(sessionId) || sessionId;\n this.cdpEventLogger?.({ method, params, targetId });\n\n if (sessionId) {\n const session = this.sessions.get(sessionId);\n session?.dispatch(method, params);\n } else {\n const handlers = this.eventHandlers.get(method);\n if (handlers) for (const h of handlers) h(params);\n }\n }\n }\n\n _sendViaSession<R = unknown>(\n sessionId: string,\n method: string,\n params?: object,\n ): Promise<R> {\n const id = this.nextId++;\n const payload = { id, method, params, sessionId };\n const stack = new Error().stack?.split(\"\\n\").slice(1, 4).join(\"\\n\");\n\n const p = new Promise<R>((resolve, reject) => {\n this.inflight.set(id, {\n resolve,\n reject,\n sessionId,\n method,\n params,\n stack,\n ts: Date.now(),\n });\n });\n // Prevent unhandledRejection if a session detaches before the caller awaits.\n void p.catch(() => {});\n const targetId = this.sessionToTarget.get(sessionId) ?? null;\n this.cdpLogger?.({ method, params, targetId });\n this.ws.send(JSON.stringify(payload));\n return p;\n }\n\n _onSessionEvent(\n sessionId: string,\n event: string,\n handler: EventHandler,\n ): void {\n const key = `${sessionId}:${event}`;\n const set = this.eventHandlers.get(key) ?? new Set<EventHandler>();\n set.add(handler);\n this.eventHandlers.set(key, set);\n }\n\n _offSessionEvent(\n sessionId: string,\n event: string,\n handler: EventHandler,\n ): void {\n const key = `${sessionId}:${event}`;\n const set = this.eventHandlers.get(key);\n if (set) set.delete(handler);\n }\n\n _dispatchToSession(sessionId: string, event: string, params: unknown): void {\n const key = `${sessionId}:${event}`;\n const handlers = this.eventHandlers.get(key);\n if (handlers) for (const h of handlers) h(params);\n }\n}\n\nexport class CdpSession implements CDPSessionLike {\n constructor(\n private readonly root: CdpConnection,\n public readonly id: string,\n ) {}\n\n send<R = unknown>(method: string, params?: object): Promise<R> {\n return this.root._sendViaSession<R>(this.id, method, params);\n }\n\n on<P = unknown>(event: string, handler: (params: P) => void): void {\n this.root._onSessionEvent(this.id, event, handler as EventHandler);\n }\n\n off<P = unknown>(event: string, handler: (params: P) => void): void {\n this.root._offSessionEvent(this.id, event, handler as EventHandler);\n }\n\n async close(): Promise<void> {\n await this.root.send<void>(\"Target.detachFromTarget\", {\n sessionId: this.id,\n });\n }\n\n dispatch(event: string, params: unknown): void {\n this.root._dispatchToSession(this.id, event, params);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"cdp.js","sourceRoot":"","sources":["../../../../../lib/v3/understudy/cdp.ts"],"names":[],"mappings":"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","sourcesContent":["// lib/v3/understudy/cdp.ts\nimport WebSocket from \"ws\";\nimport type { Protocol } from \"devtools-protocol\";\nimport { STAGEHAND_VERSION } from \"../../version.js\";\nimport {\n FlowLogger,\n type FlowEvent,\n type FlowLoggerContext,\n} from \"../flowLogger.js\";\nimport {\n CdpConnectionClosedError,\n PageNotFoundError,\n} from \"../types/public/sdkErrors.js\";\n\n/**\n * CDP transport & session multiplexer\n *\n * Owns the browser WebSocket and multiplexes flattened Target sessions.\n * Tracks inflight CDP calls, routes responses to the right session, and forwards events.\n *\n * This does not interpret Page/DOM/Runtime semantics — callers own that logic.\n */\nexport interface CDPSessionLike {\n send<R = unknown>(method: string, params?: object): Promise<R>;\n on<P = unknown>(event: string, handler: (params: P) => void): void;\n off<P = unknown>(event: string, handler: (params: P) => void): void;\n close(): Promise<void>;\n readonly id: string | null;\n}\n\ntype Inflight = {\n resolve: (v: unknown) => void;\n reject: (e: Error) => void;\n sessionId?: string | null;\n method: string;\n params?: object;\n stack?: string;\n ts: number;\n flowLoggerContext?: FlowLoggerContext | null;\n cdpCallEvent?: Pick<FlowEvent, \"eventId\" | \"eventParentIds\"> | null;\n};\n\ntype EventHandler = (params: unknown) => void;\ntype SessionDispatchWaiter = {\n sessionId: string;\n method: string;\n match?: (params?: object) => boolean;\n resolve: () => void;\n reject: (error: Error) => void;\n};\n\ntype RawMessage =\n | {\n id: number;\n result?: unknown;\n error?: { code: number; message: string; data?: unknown };\n sessionId?: string;\n }\n | { method: string; params?: unknown; sessionId?: string };\n\nexport class CdpConnection implements CDPSessionLike {\n private ws: WebSocket;\n private nextId = 1;\n private inflight = new Map<number, Inflight>();\n private latestCdpCallEvent = new Map<\n string | null,\n {\n flowLoggerContext: FlowLoggerContext;\n cdpCallEvent: Pick<FlowEvent, \"eventId\" | \"eventParentIds\">;\n }\n >();\n private eventHandlers = new Map<string, Set<EventHandler>>();\n private sessions = new Map<string, CdpSession>();\n /** Maps sessionId -> targetId (1:1 mapping) */\n private sessionToTarget = new Map<string, string>();\n private sessionDispatchWaiters = new Set<SessionDispatchWaiter>();\n public readonly id: string | null = null; // root\n private transportCloseHandlers = new Set<(why: string) => void>();\n\n public flowLoggerContext?: FlowLoggerContext;\n\n public onTransportClosed(handler: (why: string) => void): void {\n this.transportCloseHandlers.add(handler);\n }\n public offTransportClosed(handler: (why: string) => void): void {\n this.transportCloseHandlers.delete(handler);\n }\n\n private emitTransportClosed(why: string) {\n for (const h of this.transportCloseHandlers) {\n try {\n h(why);\n } catch {\n //\n }\n }\n }\n\n private constructor(ws: WebSocket) {\n this.ws = ws;\n this.ws.on(\"close\", (code, reason) => {\n // Reason is a Buffer in ws; stringify defensively\n const why = `socket-close code=${code} reason=${String(reason || \"\")}`;\n this.rejectAllInflight(why);\n this.emitTransportClosed(why);\n });\n\n this.ws.on(\"error\", (err) => {\n const why = `socket-error ${err?.message ?? String(err)}`;\n this.rejectAllInflight(why);\n this.emitTransportClosed(why);\n });\n this.ws.on(\"message\", (data) => this.onMessage(data.toString()));\n }\n\n static async connect(\n wsUrl: string,\n options?: { headers?: Record<string, string> },\n ): Promise<CdpConnection> {\n // Include User-Agent header for server-side observability and version tracking\n // Merge user-provided headers, letting them override defaults\n const headers = {\n \"User-Agent\": `Stagehand/${STAGEHAND_VERSION}`,\n ...options?.headers,\n };\n const ws = new WebSocket(wsUrl, { headers });\n await new Promise<void>((resolve, reject) => {\n ws.once(\"open\", () => resolve());\n ws.once(\"error\", (e) => reject(e));\n });\n return new CdpConnection(ws);\n }\n\n async enableAutoAttach(): Promise<void> {\n await this.send(\"Target.setAutoAttach\", {\n autoAttach: true,\n flatten: true,\n waitForDebuggerOnStart: true,\n });\n await this.send(\"Target.setDiscoverTargets\", { discover: true });\n }\n\n async send<R = unknown>(method: string, params?: object): Promise<R> {\n const id = this.nextId++;\n const payload = { id, method, params };\n const stack = new Error().stack?.split(\"\\n\").slice(1, 4).join(\"\\n\");\n let flowLoggerContext: FlowLoggerContext | null = null;\n try {\n flowLoggerContext = FlowLogger.currentContext;\n } catch {\n flowLoggerContext = this.flowLoggerContext ?? null;\n }\n const cdpCallEvent = flowLoggerContext\n ? FlowLogger.logCdpCallEvent(flowLoggerContext, {\n method,\n params,\n targetId: null,\n })\n : null;\n if (flowLoggerContext && cdpCallEvent) {\n this.latestCdpCallEvent.set(null, {\n flowLoggerContext,\n cdpCallEvent,\n });\n }\n const p = new Promise<R>((resolve, reject) => {\n this.inflight.set(id, {\n resolve,\n reject,\n sessionId: null,\n method,\n params,\n stack,\n ts: Date.now(),\n flowLoggerContext,\n cdpCallEvent,\n });\n });\n // Prevent unhandledRejection if a session detaches before the caller awaits.\n void p.catch(() => {});\n this.ws.send(JSON.stringify(payload));\n return p;\n }\n\n on<P = unknown>(event: string, handler: (params: P) => void): void {\n const set = this.eventHandlers.get(event) ?? new Set<EventHandler>();\n set.add(handler as EventHandler);\n this.eventHandlers.set(event, set);\n }\n\n off<P = unknown>(event: string, handler: (params: P) => void): void {\n const set = this.eventHandlers.get(event);\n if (set) set.delete(handler as EventHandler);\n }\n\n async close(): Promise<void> {\n if (this.ws.readyState === WebSocket.CLOSED) return;\n await new Promise<void>((resolve) => {\n this.ws.once(\"close\", () => resolve());\n this.ws.close();\n });\n }\n\n private rejectAllInflight(why: string): void {\n for (const [id, entry] of this.inflight.entries()) {\n entry.reject(new CdpConnectionClosedError(why));\n this.inflight.delete(id);\n }\n this.latestCdpCallEvent.clear();\n for (const waiter of Array.from(this.sessionDispatchWaiters)) {\n waiter.reject(new CdpConnectionClosedError(why));\n }\n }\n\n getSession(sessionId: string): CdpSession | undefined {\n return this.sessions.get(sessionId);\n }\n\n waitForSessionDispatch(\n sessionId: string,\n method: string,\n match?: (params?: object) => boolean,\n ): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const waiter: SessionDispatchWaiter = {\n sessionId,\n method,\n match,\n resolve: () => {\n this.sessionDispatchWaiters.delete(waiter);\n resolve();\n },\n reject: (error: Error) => {\n this.sessionDispatchWaiters.delete(waiter);\n reject(error);\n },\n };\n this.sessionDispatchWaiters.add(waiter);\n });\n }\n\n async attachToTarget(targetId: string): Promise<CdpSession> {\n const { sessionId } = (await this.send<{ sessionId: string }>(\n \"Target.attachToTarget\",\n { targetId, flatten: true },\n )) as { sessionId: string };\n\n let session = this.sessions.get(sessionId);\n if (!session) {\n session = new CdpSession(this, sessionId);\n this.sessions.set(sessionId, session);\n }\n this.sessionToTarget.set(sessionId, targetId);\n return session;\n }\n\n async getTargets(): Promise<Protocol.Target.TargetInfo[]> {\n const res = await this.send<{\n targetInfos: Protocol.Target.TargetInfo[];\n }>(\"Target.getTargets\");\n return res.targetInfos;\n }\n\n private onMessage(json: string): void {\n const msg = JSON.parse(json) as RawMessage;\n\n if (\"id\" in msg) {\n const rec = this.inflight.get(msg.id);\n if (!rec) return;\n\n this.inflight.delete(msg.id);\n\n if (\"error\" in msg && msg.error) {\n if (rec.flowLoggerContext && rec.cdpCallEvent) {\n const targetId =\n rec.sessionId != null\n ? (this.sessionToTarget.get(rec.sessionId) ?? rec.sessionId)\n : null;\n FlowLogger.logCdpResponseEvent(\n rec.flowLoggerContext,\n rec.cdpCallEvent,\n {\n method: rec.method,\n error: `${msg.error.code} ${msg.error.message}`,\n targetId,\n },\n );\n }\n rec.reject(new Error(`${msg.error.code} ${msg.error.message}`));\n } else {\n if (rec.flowLoggerContext && rec.cdpCallEvent) {\n const targetId =\n rec.sessionId != null\n ? (this.sessionToTarget.get(rec.sessionId) ?? rec.sessionId)\n : null;\n FlowLogger.logCdpResponseEvent(\n rec.flowLoggerContext,\n rec.cdpCallEvent,\n {\n method: rec.method,\n result: (msg as { result?: unknown }).result,\n targetId,\n },\n );\n }\n rec.resolve((msg as { result?: unknown }).result);\n }\n return;\n }\n\n if (\"method\" in msg) {\n if (msg.method === \"Target.attachedToTarget\") {\n const p = (msg as { params: Protocol.Target.AttachedToTargetEvent })\n .params;\n if (!this.sessions.has(p.sessionId)) {\n this.sessions.set(p.sessionId, new CdpSession(this, p.sessionId));\n }\n this.sessionToTarget.set(p.sessionId, p.targetInfo.targetId);\n } else if (msg.method === \"Target.detachedFromTarget\") {\n const p = (msg as { params: Protocol.Target.DetachedFromTargetEvent })\n .params;\n for (const [id, entry] of this.inflight.entries()) {\n if (entry.sessionId === p.sessionId) {\n entry.reject(\n new PageNotFoundError(\n `target closed before CDP response (sessionId=${p.sessionId}, targetId=${p.targetId})`,\n ),\n );\n this.inflight.delete(id);\n }\n }\n for (const waiter of Array.from(this.sessionDispatchWaiters)) {\n if (waiter.sessionId === p.sessionId) {\n waiter.reject(\n new PageNotFoundError(\n `target closed before CDP send (sessionId=${p.sessionId}, targetId=${p.targetId})`,\n ),\n );\n }\n }\n this.sessions.delete(p.sessionId);\n this.sessionToTarget.delete(p.sessionId);\n this.latestCdpCallEvent.delete(p.sessionId);\n } else if (msg.method === \"Target.targetDestroyed\") {\n const p = (msg as { params: { targetId: string } }).params;\n // Remove any session mapping for this target\n for (const [sessionId, targetId] of this.sessionToTarget.entries()) {\n if (targetId === p.targetId) {\n this.sessionToTarget.delete(sessionId);\n this.latestCdpCallEvent.delete(sessionId);\n break;\n }\n }\n }\n\n const { method, params, sessionId } = msg;\n const latestCdpCallEvent =\n this.latestCdpCallEvent.get(sessionId ?? null) ??\n (sessionId ? this.latestCdpCallEvent.get(null) : null);\n const targetId =\n sessionId != null\n ? (this.sessionToTarget.get(sessionId) ?? sessionId)\n : null;\n\n if (latestCdpCallEvent) {\n FlowLogger.logCdpMessageEvent(\n latestCdpCallEvent.flowLoggerContext,\n latestCdpCallEvent.cdpCallEvent,\n {\n method,\n params,\n targetId,\n },\n );\n }\n\n if (sessionId) {\n const session = this.sessions.get(sessionId);\n session?.dispatch(method, params);\n\n // Forward target lifecycle events to root listeners as well.\n // Some browsers emit these via a parent session rather than the root\n // connection; fan-out keeps target tracking consistent.\n if (method.startsWith(\"Target.\")) {\n const handlers = this.eventHandlers.get(method);\n if (handlers) for (const h of handlers) h(params);\n }\n } else {\n const handlers = this.eventHandlers.get(method);\n if (handlers) for (const h of handlers) h(params);\n }\n }\n }\n\n _sendViaSession<R = unknown>(\n sessionId: string,\n method: string,\n params?: object,\n ): Promise<R> {\n const id = this.nextId++;\n const payload = { id, method, params, sessionId };\n const stack = new Error().stack?.split(\"\\n\").slice(1, 4).join(\"\\n\");\n let flowLoggerContext: FlowLoggerContext | null = null;\n try {\n flowLoggerContext = FlowLogger.currentContext;\n } catch {\n flowLoggerContext = this.flowLoggerContext ?? null;\n }\n const targetId = this.sessionToTarget.get(sessionId) ?? null;\n const cdpCallEvent = flowLoggerContext\n ? FlowLogger.logCdpCallEvent(flowLoggerContext, {\n method,\n params,\n targetId,\n })\n : null;\n if (flowLoggerContext && cdpCallEvent) {\n this.latestCdpCallEvent.set(sessionId, {\n flowLoggerContext,\n cdpCallEvent,\n });\n }\n\n const p = new Promise<R>((resolve, reject) => {\n this.inflight.set(id, {\n resolve,\n reject,\n sessionId,\n method,\n params,\n stack,\n ts: Date.now(),\n flowLoggerContext,\n cdpCallEvent,\n });\n });\n // Prevent unhandledRejection if a session detaches before the caller awaits.\n void p.catch(() => {});\n for (const waiter of Array.from(this.sessionDispatchWaiters)) {\n if (waiter.sessionId !== sessionId) continue;\n if (waiter.method !== method) continue;\n if (waiter.match && !waiter.match(params)) continue;\n waiter.resolve();\n break;\n }\n this.ws.send(JSON.stringify(payload));\n return p;\n }\n\n _onSessionEvent(\n sessionId: string,\n event: string,\n handler: EventHandler,\n ): void {\n const key = `${sessionId}:${event}`;\n const set = this.eventHandlers.get(key) ?? new Set<EventHandler>();\n set.add(handler);\n this.eventHandlers.set(key, set);\n }\n\n _offSessionEvent(\n sessionId: string,\n event: string,\n handler: EventHandler,\n ): void {\n const key = `${sessionId}:${event}`;\n const set = this.eventHandlers.get(key);\n if (set) set.delete(handler);\n }\n\n _dispatchToSession(sessionId: string, event: string, params: unknown): void {\n const key = `${sessionId}:${event}`;\n const handlers = this.eventHandlers.get(key);\n if (handlers) for (const h of handlers) h(params);\n }\n}\n\nexport class CdpSession implements CDPSessionLike {\n constructor(\n private readonly root: CdpConnection,\n public readonly id: string,\n ) {}\n\n send<R = unknown>(method: string, params?: object): Promise<R> {\n return this.root._sendViaSession<R>(this.id, method, params);\n }\n\n on<P = unknown>(event: string, handler: (params: P) => void): void {\n this.root._onSessionEvent(this.id, event, handler as EventHandler);\n }\n\n off<P = unknown>(event: string, handler: (params: P) => void): void {\n this.root._offSessionEvent(this.id, event, handler as EventHandler);\n }\n\n async close(): Promise<void> {\n await this.root.send<void>(\"Target.detachFromTarget\", {\n sessionId: this.id,\n });\n }\n\n dispatch(event: string, params: unknown): void {\n this.root._dispatchToSession(this.id, event, params);\n }\n}\n"]}
|
|
@@ -45,6 +45,7 @@ export declare class V3Context {
|
|
|
45
45
|
env?: "LOCAL" | "BROWSERBASE";
|
|
46
46
|
apiClient?: StagehandAPIClient | null;
|
|
47
47
|
localBrowserLaunchOptions?: LocalBrowserLaunchOptions | null;
|
|
48
|
+
cdpHeaders?: Record<string, string>;
|
|
48
49
|
}): Promise<V3Context>;
|
|
49
50
|
private hasTopLevelPage;
|
|
50
51
|
private ensureFirstTopLevelPage;
|
|
@@ -111,7 +111,9 @@ class V3Context {
|
|
|
111
111
|
*/
|
|
112
112
|
static async create(wsUrl, opts) {
|
|
113
113
|
const connectTask = async () => {
|
|
114
|
-
const conn = await cdp_js_1.CdpConnection.connect(wsUrl
|
|
114
|
+
const conn = await cdp_js_1.CdpConnection.connect(wsUrl, {
|
|
115
|
+
headers: opts?.cdpHeaders,
|
|
116
|
+
});
|
|
115
117
|
const ctx = new V3Context(conn, opts?.env ?? "LOCAL", opts?.apiClient ?? null, opts?.localBrowserLaunchOptions ?? null);
|
|
116
118
|
await ctx.bootstrap();
|
|
117
119
|
await ctx.ensureFirstTopLevelPage(getFirstTopLevelPageTimeoutMs());
|
|
@@ -491,77 +493,148 @@ class V3Context {
|
|
|
491
493
|
// any "must happen before first document" work.
|
|
492
494
|
await session.send("Runtime.runIfWaitingForDebugger").catch(() => { });
|
|
493
495
|
};
|
|
494
|
-
//
|
|
495
|
-
//
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
.
|
|
496
|
+
// Attach lifecycle (per target session):
|
|
497
|
+
// 1) while paused, enable domains + child auto-attach and register init scripts;
|
|
498
|
+
// 2) resume target execution;
|
|
499
|
+
// 3) build/adopt Page ownership and frame bridges.
|
|
500
|
+
// Some CDP backends defer *.enable() responses until after resume, so we
|
|
501
|
+
// cannot await those responses before resuming. Instead we:
|
|
502
|
+
// - wait for transport-level dispatch of required pre-resume commands;
|
|
503
|
+
// - then dispatch resume;
|
|
504
|
+
// - then await responses.
|
|
505
|
+
const queuePreResume = (method, params, match) => {
|
|
506
|
+
const dispatched = this.conn
|
|
507
|
+
.waitForSessionDispatch(sessionId, method, match)
|
|
508
|
+
.then(() => true)
|
|
509
|
+
.catch(() => false);
|
|
510
|
+
const response = session
|
|
511
|
+
.send(method, params)
|
|
512
|
+
.then(() => true)
|
|
513
|
+
.catch(() => false);
|
|
514
|
+
return { dispatched, response };
|
|
515
|
+
};
|
|
516
|
+
const initScriptOps = [];
|
|
517
|
+
// Pre-resume ordering matters:
|
|
518
|
+
// - enable domains;
|
|
519
|
+
// - enable child auto-attach with waitForDebuggerOnStart;
|
|
520
|
+
// - register init scripts.
|
|
521
|
+
// Commands are sent in-order on the same session before resume.
|
|
522
|
+
const corePreResumeOps = [
|
|
523
|
+
queuePreResume("Page.enable"),
|
|
524
|
+
queuePreResume("Runtime.enable"),
|
|
525
|
+
queuePreResume("Target.setAutoAttach", {
|
|
506
526
|
autoAttach: true,
|
|
507
527
|
waitForDebuggerOnStart: true,
|
|
508
528
|
flatten: true,
|
|
509
|
-
})
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
}
|
|
529
|
+
}),
|
|
530
|
+
];
|
|
531
|
+
const headerPreResumeOps = [];
|
|
532
|
+
if (this.extraHttpHeaders) {
|
|
533
|
+
const headers = { ...this.extraHttpHeaders };
|
|
534
|
+
headerPreResumeOps.push(queuePreResume("Network.enable"));
|
|
535
|
+
headerPreResumeOps.push(queuePreResume("Network.setExtraHTTPHeaders", { headers }));
|
|
536
|
+
}
|
|
537
|
+
// Send init scripts only after auto-attach has been queued.
|
|
538
|
+
if (this.initScripts.length) {
|
|
539
|
+
for (const source of this.initScripts) {
|
|
540
|
+
initScriptOps.push(queuePreResume("Page.addScriptToEvaluateOnNewDocument", {
|
|
541
|
+
source,
|
|
542
|
+
runImmediately: true,
|
|
543
|
+
}, (sentParams) => sentParams?.source ===
|
|
544
|
+
source));
|
|
524
545
|
}
|
|
525
|
-
// register piercer (shadow-DOM hook) before resume so it runs
|
|
526
|
-
// before page scripts
|
|
527
|
-
installPromises.push(session
|
|
528
|
-
.send("Page.addScriptToEvaluateOnNewDocument", {
|
|
529
|
-
source: scriptV3Content_js_1.v3ScriptContent,
|
|
530
|
-
runImmediately: true,
|
|
531
|
-
})
|
|
532
|
-
.then(() => {
|
|
533
|
-
piercerPreRegistered = true;
|
|
534
|
-
})
|
|
535
|
-
.catch(() => { }));
|
|
536
|
-
installPromises.push(resume());
|
|
537
546
|
}
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
547
|
+
const piercerPreloadOp = queuePreResume("Page.addScriptToEvaluateOnNewDocument", {
|
|
548
|
+
source: scriptV3Content_js_1.v3ScriptContent,
|
|
549
|
+
runImmediately: true,
|
|
550
|
+
}, (sentParams) => sentParams?.source ===
|
|
551
|
+
scriptV3Content_js_1.v3ScriptContent);
|
|
552
|
+
const preResumeDispatched = (await Promise.all([
|
|
553
|
+
...corePreResumeOps.map((op) => op.dispatched),
|
|
554
|
+
...headerPreResumeOps.map((op) => op.dispatched),
|
|
555
|
+
...initScriptOps.map((op) => op.dispatched),
|
|
556
|
+
piercerPreloadOp.dispatched,
|
|
557
|
+
])).every(Boolean);
|
|
558
|
+
// Dispatch resume only after pre-resume setup has actually been sent.
|
|
559
|
+
const resumeOp = queuePreResume("Runtime.runIfWaitingForDebugger");
|
|
560
|
+
const [resumedDispatched, resumedOk] = await Promise.all([
|
|
561
|
+
resumeOp.dispatched,
|
|
562
|
+
resumeOp.response,
|
|
563
|
+
]);
|
|
564
|
+
const [coreResults, headerResults, initScriptResults, piercerPreRegistered,] = await Promise.all([
|
|
565
|
+
Promise.all(corePreResumeOps.map((op) => op.response)),
|
|
566
|
+
Promise.all(headerPreResumeOps.map((op) => op.response)),
|
|
567
|
+
Promise.all(initScriptOps.map((op) => op.response)),
|
|
568
|
+
piercerPreloadOp.response,
|
|
569
|
+
]);
|
|
570
|
+
// Header propagation is independent of init-script determinism but still
|
|
571
|
+
// part of pre-resume attach setup; awaited above for ordering/lifecycle.
|
|
572
|
+
void headerResults;
|
|
573
|
+
if (!preResumeDispatched || !resumedDispatched || !resumedOk) {
|
|
574
|
+
// Short-lived child targets can detach before resume is acknowledged.
|
|
575
|
+
// Keep this noisy only for top-level pages where missing attach is fatal.
|
|
576
|
+
if (isTopLevelPage(info)) {
|
|
577
|
+
(0, logger_js_1.v3Logger)({
|
|
578
|
+
category: "ctx",
|
|
579
|
+
message: "Failed target pre-resume setup ordering",
|
|
580
|
+
level: 2,
|
|
581
|
+
auxiliary: {
|
|
582
|
+
targetId: { value: String(info.targetId), type: "string" },
|
|
583
|
+
targetType: { value: String(info.type), type: "string" },
|
|
584
|
+
preResumeDispatched: {
|
|
585
|
+
value: String(preResumeDispatched),
|
|
586
|
+
type: "string",
|
|
587
|
+
},
|
|
588
|
+
resumedDispatched: {
|
|
589
|
+
value: String(resumedDispatched),
|
|
590
|
+
type: "string",
|
|
591
|
+
},
|
|
592
|
+
resumedOk: { value: String(resumedOk), type: "string" },
|
|
593
|
+
},
|
|
594
|
+
});
|
|
545
595
|
}
|
|
596
|
+
return;
|
|
546
597
|
}
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
// CDP round-trips that delay Page.create / installFrameEventBridges and
|
|
550
|
-
// cause same-process iframe frame-events to be missed) while still falling
|
|
551
|
-
// back to the full install path when registration failed.
|
|
552
|
-
if (piercerPreRegistered) {
|
|
553
|
-
this._piercerInstalled.add(sessionId);
|
|
554
|
-
}
|
|
598
|
+
resumed = true;
|
|
599
|
+
const scriptsInstalled = coreResults.every(Boolean) && initScriptResults.every(Boolean);
|
|
555
600
|
try {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
await session
|
|
601
|
+
// Best-effort lifecycle events; do not block top-level page registration
|
|
602
|
+
// on this optional signal stream.
|
|
603
|
+
void session
|
|
560
604
|
.send("Page.setLifecycleEventsEnabled", { enabled: true })
|
|
561
605
|
.catch(() => { });
|
|
562
606
|
// Top-level handling
|
|
563
607
|
if (isTopLevelPage(info)) {
|
|
564
|
-
|
|
608
|
+
let page = null;
|
|
609
|
+
let createError;
|
|
610
|
+
// Deterministic contract: never drop a newly attached top-level target
|
|
611
|
+
// because an arbitrary local timeout fired. We wait for Page.create and
|
|
612
|
+
// let it finish regardless of CDP call latency.
|
|
613
|
+
try {
|
|
614
|
+
page = await page_js_1.Page.create(this.conn, session, info.targetId, this.apiClient, this.localBrowserLaunchOptions, this.env === "BROWSERBASE");
|
|
615
|
+
}
|
|
616
|
+
catch (error) {
|
|
617
|
+
createError = error;
|
|
618
|
+
}
|
|
619
|
+
if (!page) {
|
|
620
|
+
(0, logger_js_1.v3Logger)({
|
|
621
|
+
category: "ctx",
|
|
622
|
+
message: "Failed to create top-level Page",
|
|
623
|
+
level: 2,
|
|
624
|
+
auxiliary: {
|
|
625
|
+
targetId: { value: String(info.targetId), type: "string" },
|
|
626
|
+
targetType: { value: String(info.type), type: "string" },
|
|
627
|
+
targetUrl: { value: String(info.url ?? ""), type: "string" },
|
|
628
|
+
error: {
|
|
629
|
+
value: String(createError instanceof Error
|
|
630
|
+
? createError.message
|
|
631
|
+
: createError),
|
|
632
|
+
type: "string",
|
|
633
|
+
},
|
|
634
|
+
},
|
|
635
|
+
});
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
565
638
|
this.wireSessionToOwnerPage(sessionId, page);
|
|
566
639
|
this.pagesByTarget.set(info.targetId, page);
|
|
567
640
|
this.mainFrameToTarget.set(page.mainFrameId(), info.targetId);
|
|
@@ -576,13 +649,22 @@ class V3Context {
|
|
|
576
649
|
page.seedCurrentUrl(pendingSeedUrl ?? info.url ?? "");
|
|
577
650
|
this._pushActive(info.targetId);
|
|
578
651
|
this.installFrameEventBridges(sessionId, page);
|
|
652
|
+
if (piercerPreRegistered) {
|
|
653
|
+
this._piercerInstalled.add(sessionId);
|
|
654
|
+
}
|
|
579
655
|
// If we already installed scripts at the session level, only seed the
|
|
580
656
|
// Page's registry to avoid double-installing DOMContentLoaded handlers.
|
|
581
657
|
await this.applyInitScriptsToPage(page, {
|
|
582
658
|
seedOnly: scriptsInstalled,
|
|
583
659
|
});
|
|
660
|
+
if (!piercerPreRegistered) {
|
|
661
|
+
void this.ensurePiercer(session).catch(() => { });
|
|
662
|
+
}
|
|
584
663
|
return;
|
|
585
664
|
}
|
|
665
|
+
const piercerReady = await this.ensurePiercer(session).catch(() => false);
|
|
666
|
+
if (!piercerReady)
|
|
667
|
+
return;
|
|
586
668
|
// Child (iframe / OOPIF)
|
|
587
669
|
try {
|
|
588
670
|
const { frameTree } = await session.send("Page.getFrameTree");
|