Repository navigation
[feat]: add extension archive getter - #3267
Conversation
🦋 Changeset detectedLatest commit: 6769580 The changes in this PR will be included in the next version bump. This PR includes changesets to release 23 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
There was a problem hiding this comment.
All reported issues were addressed across 10 files
Architecture diagram
sequenceDiagram
participant TS as TypeScript SDK
participant Py as Python SDK
participant Go as Go SDK
participant Assets as Extension Assets Module
participant FS as File System
participant Zip as ZIP Archive
Note over TS,Go: Public API for extension archive retrieval
TS->>TS: getExtensionArchive()
TS->>FS: readFile(STAGEHAND_EXTENSION_ARCHIVE_PATH)
FS-->>TS: Buffer (ZIP bytes)
TS-->>TS: Return Buffer
Py->>Py: get_extension_archive()
Py->>Assets: build_extension_archive()
Assets->>FS: Read extension source files
FS-->>Assets: File contents
Assets->>Zip: Create in-memory ZIP
Zip-->>Assets: ZIP bytes
Assets-->>Py: bytes
Py-->>Py: Return bytes
Go->>Go: ExtensionArchive()
Go->>Assets: extensionassets.Archive()
Assets->>Assets: Return copy of embedded archive
Assets-->>Go: []byte (ZIP)
Go-->>Go: Return []byte
Note over TS,Go: Consumers can save, upload, or extract to dir
Reply with feedback, questions, or to request a fix.
View guided diff | Turn on auto-fix | Re-trigger cubic
| Save or upload the bytes directly, or extract them to a directory for | ||
| Chrome's Load unpacked option. No browser session is required. | ||
| """ | ||
| return build_extension_archive() |
There was a problem hiding this comment.
nit: TS and Go return the prebuilt stagehand-extension.zip, but Python re-zips _extension/ on every call. The extracted contents should match, but the zip bytes and hashes won't match across SDKs, so anyone checksumming or deduping uploads by hash will be surprised. Could the Python package ship the same prebuilt zip and have this read it, the same way TS reads dist/assets/stagehand-extension.zip? That would also skip rebuilding the archive on each call.
This PR was opened by the [Changesets release](https://github.com/changesets/action) 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.3.0 ### Minor Changes - [#3267](#3267) [`cb9a1d1`](cb9a1d1) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add extension archive getter - [#3253](#3253) [`6bf4146`](6bf4146) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add optional `extensionCdpUrl` to `localBrowser.connect` to allow configuring the in-browser CDP url - [#3263](#3263) [`ecb2a6b`](ecb2a6b) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add `headers` to `localBrowser.connect` so CDP gateways can be authenticated without credentials in the URL - [#3183](#3183) [`901eb27`](901eb27) Thanks [@supremeboxlogos](https://github.com/supremeboxlogos)! - Add `page.waitForFunction()` to wait until a predicate in the page returns a truthy value. ### Patch Changes - [#3229](#3229) [`c6b6f27`](c6b6f27) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - skip caching for request bodies larger than 25 MB. - [#3198](#3198) [`10418f9`](10418f9) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - enable WebMCP by default for local chromium versions newer than 157 - [#3210](#3210) [`1c40ba7`](1c40ba7) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Require client transport for Browserbase Model Gateway and cache requests. - [#3209](#3209) [`17de6ea`](17de6ea) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Route Browserbase Model Gateway and cache requests through the connected SDK. ## @browserbasehq/eve@0.2.2 ### Patch Changes - Updated dependencies [[`c6b6f27`](c6b6f27), [`cb9a1d1`](cb9a1d1), [`10418f9`](10418f9), [`1c40ba7`](1c40ba7), [`17de6ea`](17de6ea), [`6bf4146`](6bf4146), [`ecb2a6b`](ecb2a6b), [`901eb27`](901eb27)]: - @browserbasehq/stagehand@4.3.0 ## @browserbasehq/stagehand-protocol@3.0.0 ### Major Changes - [#3210](#3210) [`1c40ba7`](1c40ba7) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Require client transport for Browserbase Model Gateway and cache requests. ### Minor Changes - [#3208](#3208) [`4a7c637`](4a7c637) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Support routing Browserbase Model Gateway and cache requests through the connected SDK. - [#3183](#3183) [`901eb27`](901eb27) Thanks [@supremeboxlogos](https://github.com/supremeboxlogos)! - Add the `page.wait_for_function` method. ## @browserbasehq/stagehand-extension@1.2.0 ### Minor Changes - [#3208](#3208) [`4a7c637`](4a7c637) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Support routing Browserbase Model Gateway and cache requests through the connected SDK. - [#3183](#3183) [`901eb27`](901eb27) Thanks [@supremeboxlogos](https://github.com/supremeboxlogos)! - Add the `page.wait_for_function` method. ### Patch Changes - [#3229](#3229) [`c6b6f27`](c6b6f27) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - skip caching for request bodies larger than 25 MB. - [#3257](#3257) [`113ad81`](113ad81) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - honour a changed extension CDP WS URL when creating a new Stagehand instance after closing the previous one - [#3210](#3210) [`1c40ba7`](1c40ba7) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Require client transport for Browserbase Model Gateway and cache requests. ## @browserbasehq/stagehand-go@4.3.0 ### Minor Changes - [#3267](#3267) [`cb9a1d1`](cb9a1d1) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add extension archive getter - [#3265](#3265) [`a31e2da`](a31e2da) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add `Headers` to `LocalBrowserConnectOptions` so CDP gateways can be authenticated without credentials in the URL - [#3254](#3254) [`9eac212`](9eac212) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add optional `ExtensionCDPURL` to `LocalBrowserConnectOptions` to allow configuring the in-browser CDP url. - [#3183](#3183) [`901eb27`](901eb27) Thanks [@supremeboxlogos](https://github.com/supremeboxlogos)! - Add `Page.WaitForFunction` to wait until a predicate in the page returns a truthy value. ### Patch Changes - [#3229](#3229) [`c6b6f27`](c6b6f27) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - skip caching for request bodies larger than 25 MB. - [#3198](#3198) [`10418f9`](10418f9) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - enable WebMCP by default for local chromium versions newer than 157 - [#3210](#3210) [`1c40ba7`](1c40ba7) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Require client transport for Browserbase Model Gateway and cache requests. - [#3209](#3209) [`17de6ea`](17de6ea) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Route Browserbase Model Gateway and cache requests through the connected SDK. ## @browserbasehq/stagehand-python@4.3.0 ### Minor Changes - [#3260](#3260) [`2859fd5`](2859fd5) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add `headers` to `local_browser.connect` so CDP gateways can be authenticated without credentials in the URL - [#3267](#3267) [`cb9a1d1`](cb9a1d1) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add extension archive getter - [#3252](#3252) [`21e0363`](21e0363) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add `extension_cdp_url` to `local_browser.connect` for clients that reach Chrome through a proxy the extension cannot use - [#3183](#3183) [`901eb27`](901eb27) Thanks [@supremeboxlogos](https://github.com/supremeboxlogos)! - Add `page.wait_for_function()` to wait until a predicate in the page returns a truthy value. ### Patch Changes - [#3229](#3229) [`c6b6f27`](c6b6f27) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - skip caching for request bodies larger than 25 MB. - [#3198](#3198) [`10418f9`](10418f9) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - enable WebMCP by default for local chromium versions newer than 157 - [#3210](#3210) [`1c40ba7`](1c40ba7) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Require client transport for Browserbase Model Gateway and cache requests. - [#3209](#3209) [`17de6ea`](17de6ea) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Route Browserbase Model Gateway and cache requests through the connected SDK. ## @browserbasehq/stagehand-examples@0.0.3 ### Patch Changes - Updated dependencies [[`c6b6f27`](c6b6f27), [`cb9a1d1`](cb9a1d1), [`10418f9`](10418f9), [`1c40ba7`](1c40ba7), [`17de6ea`](17de6ea), [`6bf4146`](6bf4146), [`ecb2a6b`](ecb2a6b), [`901eb27`](901eb27)]: - @browserbasehq/stagehand@4.3.0 - @browserbasehq/stagehand-integrations@4.0.6 ## @browserbasehq/stagehand-integrations-claude-agent-sdk@4.0.5 ### Patch Changes - Updated dependencies []: - @browserbasehq/stagehand-integrations@4.0.6 ## @browserbasehq/stagehand-integrations-example-claude-code-facade@4.0.6 ### Patch Changes - Updated dependencies []: - @browserbasehq/stagehand-integrations@4.0.6 - @browserbasehq/stagehand-integrations-claude-agent-sdk@4.0.5 ## @browserbasehq/stagehand-integrations-claude-cua-sdk@4.0.4 ### Patch Changes - Updated dependencies [[`c6b6f27`](c6b6f27), [`cb9a1d1`](cb9a1d1), [`10418f9`](10418f9), [`1c40ba7`](1c40ba7), [`17de6ea`](17de6ea), [`6bf4146`](6bf4146), [`ecb2a6b`](ecb2a6b), [`901eb27`](901eb27)]: - @browserbasehq/stagehand@4.3.0 - @browserbasehq/stagehand-integrations@4.0.6 ## @browserbasehq/stagehand-integrations-example-codex-facade@4.0.6 ### Patch Changes - Updated dependencies []: - @browserbasehq/stagehand-integrations@4.0.6 - @browserbasehq/stagehand-integrations-codex-sdk@4.0.5 ## @browserbasehq/stagehand-integrations-codex-sdk@4.0.5 ### Patch Changes - Updated dependencies []: - @browserbasehq/stagehand-integrations@4.0.6 ## @browserbasehq/stagehand-integrations@4.0.6 ### Patch Changes - Updated dependencies [[`c6b6f27`](c6b6f27), [`cb9a1d1`](cb9a1d1), [`10418f9`](10418f9), [`1c40ba7`](1c40ba7), [`17de6ea`](17de6ea), [`6bf4146`](6bf4146), [`ecb2a6b`](ecb2a6b), [`901eb27`](901eb27)]: - @browserbasehq/stagehand@4.3.0 ## @browserbasehq/stagehand-integrations-example-cursor-facade@4.0.4 ### Patch Changes - Updated dependencies []: - @browserbasehq/stagehand-integrations@4.0.6 - @browserbasehq/stagehand-integrations-cursor-sdk@4.0.5 ## @browserbasehq/stagehand-integrations-cursor-sdk@4.0.5 ### Patch Changes - Updated dependencies []: - @browserbasehq/stagehand-integrations@4.0.6 ## @browserbasehq/stagehand-integrations-deepagents-sdk@4.0.5 ### Patch Changes - Updated dependencies []: - @browserbasehq/stagehand-integrations@4.0.6 ## @browserbasehq/stagehand-integrations-eve-sdk@4.0.5 ### Patch Changes - Updated dependencies []: - @browserbasehq/stagehand-integrations@4.0.6 ## @browserbasehq/stagehand-integrations-fx-sdk@4.0.5 ### Patch Changes - Updated dependencies []: - @browserbasehq/stagehand-integrations@4.0.6 ## @browserbasehq/stagehand-integrations-gemini-cua-sdk@4.0.4 ### Patch Changes - Updated dependencies [[`c6b6f27`](c6b6f27), [`cb9a1d1`](cb9a1d1), [`10418f9`](10418f9), [`1c40ba7`](1c40ba7), [`17de6ea`](17de6ea), [`6bf4146`](6bf4146), [`ecb2a6b`](ecb2a6b), [`901eb27`](901eb27)]: - @browserbasehq/stagehand@4.3.0 - @browserbasehq/stagehand-integrations@4.0.6 ## @browserbasehq/stagehand-integrations-example-mastra-facade@4.0.6 ### Patch Changes - Updated dependencies []: - @browserbasehq/stagehand-integrations@4.0.6 ## @browserbasehq/stagehand-integrations-mastra-sdk@4.0.5 ### Patch Changes - Updated dependencies []: - @browserbasehq/stagehand-integrations@4.0.6 ## @browserbasehq/stagehand-integrations-example-pi-facade@4.0.6 ### Patch Changes - Updated dependencies [[`c6b6f27`](c6b6f27), [`cb9a1d1`](cb9a1d1), [`10418f9`](10418f9), [`1c40ba7`](1c40ba7), [`17de6ea`](17de6ea), [`6bf4146`](6bf4146), [`ecb2a6b`](ecb2a6b), [`901eb27`](901eb27)]: - @browserbasehq/stagehand@4.3.0 - @browserbasehq/stagehand-integrations@4.0.6 ## @browserbasehq/stagehand-integrations-pi-sdk@4.0.5 ### Patch Changes - Updated dependencies []: - @browserbasehq/stagehand-integrations@4.0.6 ## @browserbasehq/stagehand-integrations-example-vercel-ai-facade@4.0.6 ### Patch Changes - Updated dependencies []: - @browserbasehq/stagehand-integrations@4.0.6 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
) Upload the bundled Stagehand extension directly without requiring a file path. Uses getExtensionArchive() from @browserbasehq/stagehand and passes the bytes via toFile() to the Browserbase API. # why # what changed # test plan <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Adds a `--stagehand` flag to `browse cloud extensions upload` so the bundled Stagehand extension can be uploaded without a file path; the archive bytes come from `getExtensionArchive()` and are sent to the Browserbase API without writing a temp file. - The `file` argument is now optional; you must provide either a file path or `--stagehand`. - Passing both `--stagehand` and a file path errors out. <sup>Written for commit 3e27ee2. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/browserbase/stagehand/pull/3289?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="View guided diff" src="https://www.cubic.dev/buttons/review-in-cubic-light.svg"></picture></a> <a href="https://www.cubic.dev/action/auto-fix/pr/browserbase/stagehand/3289?returnTo=https%3A%2F%2Fgithub.com%2Fbrowserbase%2Fstagehand%2Fpull%2F3289&source=description" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-light.svg"><img alt="Turn on auto-fix" src="https://www.cubic.dev/buttons/turn-on-auto-fix-light.svg"></picture></a> <!-- End of auto-generated description by cubic. --> <!-- CURSOR_AGENT_PR_BODY_BEGIN --> # why Sean added a public `getExtensionArchive()` helper to the Stagehand SDK (`packages/sdk-ts/src/extensionAssets.ts`, #3267) so users can get the bundled extension ZIP without reaching into `node_modules/@browserbasehq/stagehand/dist/assets/stagehand-extension.zip`—a path that may change across releases. He asked for the CLI and docs to use it. The existing `browse cloud extensions upload <file>` command only accepts a filesystem path, so users had to pass that brittle internal path directly. This adds a `--stagehand` flag that handles the export and upload in one step. # what changed - Add `--stagehand` boolean flag to `browse cloud extensions upload` - With `--stagehand`: call `getExtensionArchive()` from `@browserbasehq/stagehand` to get the `Uint8Array`, wrap it with the Browserbase SDK's `toFile(bytes, "stagehand-extension.zip", { type: "application/zip" })`, and pass that to `client.extensions.create()`. No temp file is written. - Make the `file` positional arg optional (was required) - Validation: `--stagehand` and `file` are mutually exclusive; providing both exits 1 with `"Cannot specify both --stagehand and a file path."`. Providing neither exits 1 with `"Provide a file path or use --stagehand to upload the Stagehand extension."` - Existing `<file>` path behavior unchanged—still uses `resolveUploadableFile()` to stream from disk - Output unchanged: prints the JSON response from `extensions.create` (includes `id`) - Update command description and examples in help - Add Browse patch changeset - Add 3 tests in `packages/cli/tests/cli-cloud-contract.test.ts`: - `extensions upload --stagehand uploads the bundled Stagehand extension`: verifies multipart POST to `/v1/extensions` with `filename="stagehand-extension.zip"` - `extensions upload rejects both --stagehand and a file path`: verifies exit 1 and error message - `extensions upload requires --stagehand or a file path`: verifies exit 1 and error message when neither provided **Before:** ```bash browse cloud extensions upload node_modules/@browserbasehq/stagehand/dist/assets/stagehand-extension.zip ``` **After:** ```bash browse cloud extensions upload --stagehand ``` # test plan - [x] 505 CLI tests pass (38 test files), including the 3 new tests - [x] `pnpm format:check` passes - [x] `pnpm eslint` passes - [x] `pnpm turbo run build --filter=browse` succeeds (TypeScript compiles, oclif manifest generates) --- PR 1 of 2. #3275 is stacked on this and updates the user-facing instructions (functions init, deployment docs, CLI skill) to use `--stagehand`. <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Adds a `--stagehand` flag to `browse cloud extensions upload` so the bundled Stagehand extension can be uploaded without a file path. - The `file` argument is now optional; you must provide either a file path or `--stagehand`. - Passing both `--stagehand` and a file path errors out. <sup>Written for commit 81444f9. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/browserbase/stagehand/pull/3289?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="View guided diff" src="https://www.cubic.dev/buttons/review-in-cubic-light.svg"></picture></a> <a href="https://www.cubic.dev/action/auto-fix/pr/browserbase/stagehand/3289?returnTo=https%3A%2F%2Fgithub.com%2Fbrowserbase%2Fstagehand%2Fpull%2F3289&source=description" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/turn-on-auto-fix-light.svg"><img alt="Turn on auto-fix" src="https://www.cubic.dev/buttons/turn-on-auto-fix-light.svg"></picture></a> <!-- End of auto-generated description by cubic. --> <!-- CURSOR_AGENT_PR_BODY_END --> <div><a href="https://cursor.com/agents/bc-036e53ad-deeb-5484-9f72-e4ced49d81e3?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a> <a href="https://cursor.com/background-agent?bcId=bc-036e53ad-deeb-5484-9f72-e4ced49d81e3&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a> </div> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com>
why
what changed
added an extension archive getter in all three SDKs:
test plan
Summary by cubic
Adds a public getter for the bundled Stagehand extension archive across all three SDKs, so users no longer need to reach into internal file paths.
getExtensionArchive()returns aUint8Array; Python:get_extension_archive()returnsbytes; Go:ExtensionArchive()returns[]byte.Written for commit 6769580. Summary will update on new commits.