Release Stagehand packages - #2798
Open
github-actions[bot] wants to merge 1 commit into
Open
Conversation
github-actions
Bot
force-pushed
the
changeset-release/main
branch
from
August 21, 2026 21:51
01a1a73 to
198d034
Compare
psyb0t
pushed a commit
to psyb0t/stagehand
that referenced
this pull request
Aug 23, 2026
…rve/extract, CLICK/HOVER/SCROLL, and CDP (browserbase#1283) # why Clarify where the execution flow goes when stagehand runs by showing more detailed logs. <img width="1443" height="529" alt="image" src="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/user-attachments/assets/1c85f91e-de94-46c3-8226-fe42d4c3e338" /> # what changed Adds a log line printed at the beginning and end of each layer's execution: 1. 🅰 Agent TASK: top-level user intent: when agent.execute('<intent here>') is called (the initial entrypoint) 2. 🆂 Stagehand STEP: any call to .act(...) .extract() or .observe() 3. 🆄 Understudy ACTION: any playwright or browser interaction api action dispatched, e.g. CLICK, HOVER, SCROLL, etc. 4. 🧠 LLM req/resp, 🅲 CDP CALL/Event: any LLM calls or CDP websocket msgs to/from the browser Log lines are written to `./.browserbase/sessions/{sessionId}/{agent,stagehand,understudy,cdp}.log` at runtime, and can be followed in a single unified screen by doing: `tail -f ./.browserbase/sessions/latest/*.log` # test plan Test by running: ```bash # (make sure `OPENAI_API_KEY` and `ANTHROPIC_API_KEY` are both set in env too) export BROWSERBASE_CONFIG_DIR=./.browserbase nano packages/core/examples/flowLoggingJourney.ts # paste in contents (it's just a basic test of the main apis) pnpm tsx packages/core/examples/flowLoggingJourney.ts & tail -f ./.browserbase/sessions/latest/* ``` `flowLoggingJourney.ts`: ```typescript import { Stagehand } from "../lib/v3"; async function run(): Promise<void> { const openaiKey = process.env.OPENAI_API_KEY; const anthropicKey = process.env.ANTHROPIC_API_KEY; if (!openaiKey || !anthropicKey) { throw new Error( "Set both OPENAI_API_KEY and ANTHROPIC_API_KEY before running this demo.", ); } const stagehand = new Stagehand({ env: "LOCAL", verbose: 2, model: { modelName: "openai/gpt-4.1-mini", apiKey: openaiKey }, localBrowserLaunchOptions: { headless: true, args: ["--window-size=1280,720"], }, disablePino: true, }); try { await stagehand.init(); const [page] = stagehand.context.pages(); await page.goto("https://example.com/", { waitUntil: "load" }); // Test standard agent path const agent = stagehand.agent({ systemPrompt: "You are a QA assistant. Keep answers short and deterministic. Finish quickly.", }); const agentResult = await agent.execute( "Glance at the Example Domain page and confirm that you see the hero text.", ); console.log("Agent result:", agentResult); // Test CUA (Computer Use Agent) path await page.goto("https://example.com/", { waitUntil: "load" }); const cuaAgent = stagehand.agent({ cua: true, model: { modelName: "anthropic/claude-sonnet-4-5-20250929", apiKey: anthropicKey, }, }); const cuaResult = await cuaAgent.execute({ instruction: "Click on the 'More information...' link on the page.", maxSteps: 3, }); console.log("CUA Agent result:", cuaResult); const observations = await stagehand.observe("Find any links on the page"); console.log("Observe result:", observations); if (observations.length > 0) { await stagehand.act(observations[0]); } else { await stagehand.act("click the link on the page"); } const extraction = await stagehand.extract( "Summarize the current page title and contents in a single sentence", ); console.log("Extraction result:", extraction); } finally { await stagehand.close({ force: true }).catch(() => {}); } } run().catch((error) => { console.error(error); process.exitCode = 1; }); ``` EXPECTED OUTPUT: ```bash 2025-12-08 12:20:26.23300 ⤑ ⤑ [🆄 #694a GOTO] ▷ Page.goto({args:[https://example.com/,{waitUntil:load}]}) 2025-12-08 12:20:26.23401 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏵ Page.navigate({url:https://example.com/}) 2025-12-08 12:20:26.26402 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏴ Page.frameStartedNavigating({frameId:8A6B…FE7B,u…rId:F41F…7B31,navigationType:differentDocument}) 2025-12-08 12:20:26.26403 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏴ Page.frameStartedLoading({frameId:8A6B…FE7B}) 2025-12-08 12:20:26.57304 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏵ Page.setLifecycleEventsEnabled({enabled:true}) 2025-12-08 12:20:26.57605 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏴ Page.frameNavigated({frame:{id:8A6B…FE7B,loaderI…tIsolated,gatedAPIFeatures:[]},type:Navigation}) 2025-12-08 12:20:26.57706 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏴ Network.policyUpdated({}) 2025-12-08 12:20:26.57807 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏴ Runtime.consoleAPICalled({type:info,args:[{type:…ptId:5,url:",lineNumber:0,columnNumber:2837}]}}) 2025-12-08 12:20:26.57908 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏴ Page.domContentEventFired({timestamp:545864.312948}) 2025-12-08 12:20:26.58009 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏴ Page.loadEventFired({timestamp:545864.313355}) 2025-12-08 12:20:26.58110 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏴ Page.frameStoppedLoading({frameId:8A6B…FE7B}) 2025-12-08 12:20:26.58311 ⤑ ⤑ [🆄 #694a GOTO] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:document.readyState,contextId:2,returnByValue:true}) 2025-12-08 12:20:26.58412 ⤑ ⤑ [🆄 #694a GOTO] ✓ GOTO completed in 0.35s 2025-12-08 12:20:26.58513 [🅰 #1d66] ▷ Agent.execute(Glance at the Example Domain page and confirm that you see the hero text.) 2025-12-08 12:20:26.59314 [🅰 #1d66] ⤑ [🧠 #21e1 LLM] gpt-4.1-mini ⏴ user: Glance at the Example Domain page and confirm that you see the hero text. +{10 tools} 2025-12-08 12:20:29.44715 [🅰 #1d66] ⤑ [🧠 #21e1 LLM] gpt-4.1-mini ↳ ꜛ688 ꜜ12 | tool call: ariaTree() 2025-12-08 12:20:29.44816 [🅰 #1d66] [🆂 #9ac4 EXTRACT] ▷ Stagehand.extract() 2025-12-08 12:20:29.45317 [🅰 #1d66] [🆂 #9ac4 EXTRACT] ⤑ [🅲 #FE7B CDP] ⏵ DOM.getDocument({depth:-1,pierce:true}) 2025-12-08 12:20:29.46018 [🅰 #1d66] [🆂 #9ac4 EXTRACT] ⤑ [🅲 #FE7B CDP] ⏵ Accessibility.getFullAXTree({frameId:8A6B…FE7B}) 2025-12-08 12:20:29.46419 [🅰 #1d66] [🆂 #9ac4 EXTRACT] ✓ EXTRACT completed in 0.02s 2025-12-08 12:20:29.46520 [🅰 #1d66] ⤑ [🧠 #03a1 LLM] gpt-4.1-mini ⏴ tool result: ariaTree(): Accessibility Tre…7] paragraph [0-18] link: Learn more +{10 tools} 2025-12-08 12:20:32.21321 [🅰 #1d66] ⤑ [🧠 #03a1 LLM] gpt-4.1-mini ↳ ꜛ806 ꜜ34 | tool call: close() 2025-12-08 12:20:32.21422 [🅰 #1d66] ✓ Agent.execute() DONE in 5.6s | 2 LLM calls ꜛ1494 ꜜ46 tokens | 6 CDP msgs 2025-12-08 12:20:32.21523 ⤑ ⤑ [🆄 #cb65 GOTO] ▷ Page.goto({args:[https://example.com/,{waitUntil:load}]}) 2025-12-08 12:20:32.21524 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏵ Page.navigate({url:https://example.com/}) 2025-12-08 12:20:32.25425 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ Page.frameStartedNavigating({frameId:8A6B…FE7B,u…rId:2130…4BDE,navigationType:differentDocument}) 2025-12-08 12:20:32.25426 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ Page.frameStartedLoading({frameId:8A6B…FE7B}) 2025-12-08 12:20:32.25727 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏵ Page.setLifecycleEventsEnabled({enabled:true}) 2025-12-08 12:20:32.25828 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ DOM.scrollableFlagUpdated({nodeId:1,isScrollable:false}) 2025-12-08 12:20:32.25929 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ Page.frameNavigated({frame:{id:8A6B…FE7B,loaderI…tIsolated,gatedAPIFeatures:[]},type:Navigation}) 2025-12-08 12:20:32.26030 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ Network.policyUpdated({}) 2025-12-08 12:20:32.26031 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ DOM.documentUpdated({}) 2025-12-08 12:20:32.26032 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ Runtime.consoleAPICalled({type:info,args:[{type:…ptId:5,url:",lineNumber:0,columnNumber:2837}]}}) 2025-12-08 12:20:32.26133 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ DOM.documentUpdated({}) 2025-12-08 12:20:32.26134 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ Page.domContentEventFired({timestamp:545869.998129}) 2025-12-08 12:20:32.26135 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ Page.loadEventFired({timestamp:545869.998762}) 2025-12-08 12:20:32.26136 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏴ Page.frameStoppedLoading({frameId:8A6B…FE7B}) 2025-12-08 12:20:32.26237 ⤑ ⤑ [🆄 #cb65 GOTO] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:document.readyState,contextId:3,returnByValue:true}) 2025-12-08 12:20:32.26338 ⤑ ⤑ [🆄 #cb65 GOTO] ✓ GOTO completed in 0.05s 2025-12-08 12:20:32.26339 [🅰 #c756] ▷ Agent.execute({instruction:Click on the More information... link on the page.,maxSteps:3}) 2025-12-08 12:20:32.26440 [🅰 #c756] ⤑ ⤑ [🅲 #FE7B CDP] ⏵ Page.addScriptToEvaluateOnNewDocument({source:(() => …ue });\n setTimeout(install, 100);\n }\n })();}) 2025-12-08 12:20:32.26441 [🅰 #c756] ⤑ ⤑ [🅲 #FE7B CDP] ⏴ Accessibility.loadComplete({root:{nodeId:23,ignored:f…ds:[24],backendDOMNodeId:23,frameId:8A6B…FE7B}}) 2025-12-08 12:20:32.26542 [🅰 #c756] ⤑ ⤑ [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:({ w: window.innerWidth,…ntextId:3,awaitPromise:true,returnByValue:true}) 2025-12-08 12:20:32.26543 [🅰 #c756] ⤑ ⤑ [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:(() => {\n const ID = __… 100);\n }\n })();,includeCommandLineAPI:false}) 2025-12-08 12:20:32.26744 [🅰 #c756] ⤑ [🧠 browserbase#2798 LLM] claude-sonnet-4-5-20250929 ⏴ Click on the More information... link on the page. 2025-12-08 12:20:36.15745 [🅰 #c756] ⤑ [🧠 browserbase#2798 LLM] claude-sonnet-4-5-20250929 ↳ ꜛ1875 ꜜ79 | Ill help you click on the More information... l tool_use:computer 2025-12-08 12:20:36.96146 [🅰 #c756] ⤑ [🆄 #f55d SCREENSHOT] ▷ Page.screenshot({args:[{fullPage:false}]}) 2025-12-08 12:20:36.96447 [🅰 #c756] ⤑ [🆄 #f55d SCREENSHOT] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:(() …ntextId:3,awaitPromise:true,returnByValue:true}) 2025-12-08 12:20:36.96648 [🅰 #c756] ⤑ [🆄 #f55d SCREENSHOT] [🅲 #FE7B CDP] ⏵ Page.captureScreenshot({format:png,fromSurface:true,captureBeyondViewport:false}) 2025-12-08 12:20:37.01149 [🅰 #c756] ⤑ [🆄 #f55d SCREENSHOT] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:(() …ntextId:3,awaitPromise:true,returnByValue:true}) 2025-12-08 12:20:37.01250 [🅰 #c756] ⤑ [🆄 #f55d SCREENSHOT] ✓ SCREENSHOT completed in 0.05s 2025-12-08 12:20:37.01251 [🅰 #c756] ⤑ [🆄 #cce8 SCREENSHOT] ▷ Page.screenshot({args:[{fullPage:false}]}) 2025-12-08 12:20:37.01352 [🅰 #c756] ⤑ [🆄 #cce8 SCREENSHOT] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:(() …ntextId:3,awaitPromise:true,returnByValue:true}) 2025-12-08 12:20:37.01453 [🅰 #c756] ⤑ [🆄 #cce8 SCREENSHOT] [🅲 #FE7B CDP] ⏵ Page.captureScreenshot({format:png,fromSurface:true,captureBeyondViewport:false}) 2025-12-08 12:20:37.04054 [🅰 #c756] ⤑ [🆄 #cce8 SCREENSHOT] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:(() …ntextId:3,awaitPromise:true,returnByValue:true}) 2025-12-08 12:20:37.04155 [🅰 #c756] ⤑ [🆄 #cce8 SCREENSHOT] ✓ SCREENSHOT completed in 0.03s 2025-12-08 12:20:37.04156 [🅰 #c756] ⤑ [🧠 #ce80 LLM] claude-sonnet-4-5-20250929 ⏴ Current URL: https://example.com/ +{15.8kb image} 2025-12-08 12:20:44.82757 [🅰 #c756] ⤑ [🧠 #ce80 LLM] claude-sonnet-4-5-20250929 ↳ ꜛ3192 ꜜ192 | I can see a pag…ith Example Domain as the head tool_use:computer 2025-12-08 12:20:45.12958 [🅰 #c756] ⤑ [🆄 #f8c3 V3CUA.SCROLL] ▷ v3CUA.scroll({target:(644, 400),args:[{type:sc…scroll_amount:3,pageUrl:https://example.com/}]}) 2025-12-08 12:20:45.12959 [🅰 #c756] ⤑ [🆄 #3fc9 SCROLL] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:typeof w…"undefined\"&&window.__v3Cursor.move(644, 400)}) 2025-12-08 12:20:45.12960 [🅰 #c756] ⤑ [🆄 #3fc9 SCROLL] ▷ Page.scroll({args:[644,400,0,300]}) 2025-12-08 12:20:45.13061 [🅰 #c756] ⤑ [🆄 #3fc9 SCROLL] [🅲 #FE7B CDP] ⏵ Input.dispatchMouseEvent({type:mouseMoved,x:644,y:400,button:none}) 2025-12-08 12:20:45.13762 [🅰 #c756] ⤑ [🆄 #3fc9 SCROLL] [🅲 #FE7B CDP] ⏵ Input.dispatchMouseEvent({type:mouseW…el,x:644,y:400,button:none,deltaX:0,deltaY:300}) 2025-12-08 12:20:45.14663 [🅰 #c756] ⤑ [🆄 #3fc9 SCROLL] ✓ SCROLL completed in 0.02s 2025-12-08 12:20:45.64764 [🅰 #c756] ⤑ [🆄 #ccb0 SCREENSHOT] ▷ Page.screenshot({args:[{fullPage:false}]}) 2025-12-08 12:20:45.64965 [🅰 #c756] ⤑ [🆄 #ccb0 SCREENSHOT] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:(() …ntextId:3,awaitPromise:true,returnByValue:true}) 2025-12-08 12:20:45.65266 [🅰 #c756] ⤑ [🆄 #ccb0 SCREENSHOT] [🅲 #FE7B CDP] ⏵ Page.captureScreenshot({format:png,fromSurface:true,captureBeyondViewport:false}) 2025-12-08 12:20:45.68567 [🅰 #c756] ⤑ [🆄 #ccb0 SCREENSHOT] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:(() …ntextId:3,awaitPromise:true,returnByValue:true}) 2025-12-08 12:20:45.68668 [🅰 #c756] ⤑ [🆄 #ccb0 SCREENSHOT] ✓ SCREENSHOT completed in 0.04s 2025-12-08 12:20:45.68769 [🅰 #c756] ⤑ [🆄 #87f4 SCREENSHOT] ▷ Page.screenshot({args:[{fullPage:false}]}) 2025-12-08 12:20:45.68770 [🅰 #c756] ⤑ [🆄 #87f4 SCREENSHOT] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:(() …ntextId:3,awaitPromise:true,returnByValue:true}) 2025-12-08 12:20:45.68971 [🅰 #c756] ⤑ [🆄 #87f4 SCREENSHOT] [🅲 #FE7B CDP] ⏵ Page.captureScreenshot({format:png,fromSurface:true,captureBeyondViewport:false}) 2025-12-08 12:20:45.71372 [🅰 #c756] ⤑ [🆄 #87f4 SCREENSHOT] [🅲 #FE7B CDP] ⏵ Runtime.evaluate({expression:(() …ntextId:3,awaitPromise:true,returnByValue:true}) 2025-12-08 12:20:45.71473 [🅰 #c756] ⤑ [🆄 #87f4 SCREENSHOT] ✓ SCREENSHOT completed in 0.03s 2025-12-08 12:20:45.71474 [🅰 #c756] ⤑ [🧠 #ed51 LLM] claude-sonnet-4-5-20250929 ⏴ Current URL: https://example.com/ +{15.8kb image} ``` --------- Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: Nick Sweeting <pirate@users.noreply.github.com> Co-authored-by: Miguel <36487034+miguelg719@users.noreply.github.com>
github-actions
Bot
force-pushed
the
changeset-release/main
branch
9 times, most recently
from
August 27, 2026 13:43
3329717 to
7f8efc6
Compare
github-actions
Bot
force-pushed
the
changeset-release/main
branch
from
August 27, 2026 13:54
7f8efc6 to
c9f01a5
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.
Releases
@browserbasehq/stagehand@4.0.3
Patch Changes
#2827
6555e81Thanks @seanmcguire12! - make browser.close() and browser.context.close() always terminate the browser regardless of keepAlive.#2790
1011177Thanks @seanmcguire12! - fail fast on browserbase.connect() when extension is not present#2818
341433aThanks @seanmcguire12! - make stagehand.close() preserve the browser and allow another Stagehand instance to attach later#2754
a21633dThanks @monadoid! - remove the redundant image type from page screenshot protocol responses.@browserbasehq/stagehand-protocol@2.0.0
Major Changes
#2827
6555e81Thanks @seanmcguire12! - make browser.close() and browser.context.close() always terminate the browser regardless of keepAlive.#2754
a21633dThanks @monadoid! - remove the redundant image type from page screenshot protocol responses.@browserbasehq/stagehand-extension@1.0.2
Patch Changes
#2827
6555e81Thanks @seanmcguire12! - make browser.close() and browser.context.close() always terminate the browser regardless of keepAlive.#2818
341433aThanks @seanmcguire12! - make stagehand.close() preserve the browser and allow another Stagehand instance to attach later#2754
a21633dThanks @monadoid! - remove the redundant image type from page screenshot protocol responses.@browserbasehq/stagehand-integrations-example-claude-code-facade@4.0.3
Patch Changes
@browserbasehq/stagehand-integrations-example-codex-facade@4.0.3
Patch Changes
@browserbasehq/stagehand-integrations@4.0.3
Patch Changes
6555e81,1011177,341433a,a21633d]:@browserbasehq/stagehand-integrations-example-eve-facade@4.0.3
Patch Changes
6555e81,1011177,341433a,a21633d]:@browserbasehq/stagehand-integrations-example-mastra-facade@4.0.3
Patch Changes
@browserbasehq/stagehand-integrations-example-pi-facade@4.0.3
Patch Changes
6555e81,1011177,341433a,a21633d]:@browserbasehq/stagehand-integrations-example-vercel-ai-facade@4.0.3
Patch Changes
@browserbasehq/stagehand-go@4.0.3
Patch Changes
#2827
6555e81Thanks @seanmcguire12! - make browser.close() and browser.context.close() always terminate the browser regardless of keepAlive.#2790
1011177Thanks @seanmcguire12! - fail fast on browserbase.connect() when extension is not present#2818
341433aThanks @seanmcguire12! - make stagehand.close() preserve the browser and allow another Stagehand instance to attach later#2754
a21633dThanks @monadoid! - remove the redundant image type from page screenshot protocol responses.@browserbasehq/stagehand-python@4.0.3
Patch Changes
#2827
6555e81Thanks @seanmcguire12! - make browser.close() and browser.context.close() always terminate the browser regardless of keepAlive.#2790
1011177Thanks @seanmcguire12! - fail fast on browserbase.connect() when extension is not present#2818
341433aThanks @seanmcguire12! - make stagehand.close() preserve the browser and allow another Stagehand instance to attach later#2754
a21633dThanks @monadoid! - remove the redundant image type from page screenshot protocol responses.