Skip to content

Update stagehand template to v4 - #221

Open
dprevoznik wants to merge 2 commits into
mainfrom
hypeship/stagehand-v4
Open

Update stagehand template to v4#221
dprevoznik wants to merge 2 commits into
mainfrom
hypeship/stagehand-v4

Conversation

@dprevoznik

@dprevoznik dprevoznik commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Migrates pkg/templates/typescript/stagehand from Stagehand v3 to v4.

Why

Stagehand v4 runs as a Chrome extension next to the browser instead of driving it purely over CDP. The v3 init path (new Stagehand({ env: "LOCAL", localBrowserLaunchOptions: { cdpUrl } }) + init()) no longer exists. For a remote Kernel browser, localBrowser.connect({ cdpUrl }) alone does not work: with no extensionId it falls back to Extensions.loadUnpacked, whose path is resolved on the browser's filesystem, not the app's. The extension must be preloaded into the Kernel browser and referenced by its runtime id.

What changed

  • package.json: @browserbasehq/stagehand ^3.5.0^4.0.0; add ws and @types/ws. (zod ^4.2.0 already satisfies Stagehand v4's zod@4.4.3.)
  • index.ts:
    • Upload the Stagehand extension (shipped at dist/assets/stagehand-extension.zip inside the package) to the project once via kernel.extensions.upload, reused on later runs.
    • Create the browser with extensions: [{ name }].
    • Discover the extension's Chrome runtime id from its service worker target over CDP (Target.getTargets).
    • Connect with localBrowser.connect({ cdpUrl, extensionId }) and Stagehand.create({ browser }).
    • await browser.context.activePage() (page access is async in v4).
    • Unwrap stagehand.extract(...) via { data } (v4 primitives return { data, metadata }).
    • Close the connected browser explicitly (v4 only closes browsers it launched).
    • Read MODEL / MODEL_API_KEY from env, defaulting to openai/gpt-4.1.
  • .env.example, README.md: document MODEL / MODEL_API_KEY and the extension-based connection flow.
  • pnpm-lock.yaml: regenerated.

Testing

  • tsc --noEmit passes with the template's resolved deps (stagehand 4.0.0, @onkernel/sdk 0.23.0, zod 4.4.3, ws 8.21.3).
  • Deployed the template with kernel deploy and ran kernel invoke ts-stagehand teamsize-task --payload '{"company":"kernel"}'; it returned {"teamSize":"6"}. Deploy was run with MODEL=google/gemini-2.5-flash since that was the model key available in the test environment; the default OpenAI path is unchanged in code.

🤖 Generated with Claude Code


Note

Low Risk
Sample template and documentation only; no production service paths. Deploy env var rename may affect users still using OPENAI_API_KEY-only docs.

Overview
Migrates pkg/templates/typescript/stagehand from Stagehand v3 → v4, which no longer uses CDP-only init() and instead runs as a Chrome extension on the browser.

The sample now uploads stagehand-extension.zip to the Kernel project once, creates browsers with that extension preloaded, discovers the runtime extension id via CDP Target.getTargets, and connects with localBrowser.connect({ cdpUrl, extensionId }) plus Stagehand.create({ browser }). Automation uses async activePage(), unwraps extract results from { data }, and finally closes the connected browser and deletes the Kernel session.

Env/docs switch from OPENAI_API_KEY to MODEL / MODEL_API_KEY (with OPENAI_API_KEY fallback). @browserbasehq/stagehand is bumped to ^4.0.0; ws is added for extension discovery; lockfile is regenerated.

Reviewed by Cursor Bugbot for commit 0c321ef. Bugbot is set up for automated code reviews on this repo. Configure here.

Stagehand v4 runs as a Chrome extension next to the browser rather than
driving it purely over CDP, so the template now preloads that extension
into the Kernel browser and connects to it.

Changes to pkg/templates/typescript/stagehand:
- Bump @browserbasehq/stagehand to ^4.0.0; add ws (+ @types/ws).
- Replace `new Stagehand({ env: "LOCAL", localBrowserLaunchOptions })` +
  `init()` with `localBrowser.connect({ cdpUrl, extensionId })` +
  `Stagehand.create({ browser })`.
- Upload the Stagehand extension (shipped in the npm package) to the
  project, create the browser with `extensions: [{ name }]`, and discover
  the extension's runtime id from its service worker over CDP.
- Use `await browser.context.activePage()` (page access is async in v4)
  and unwrap `stagehand.extract(...)` via `{ data }`.
- Close the connected browser explicitly (v4 only closes browsers it
  launched).
- Read MODEL / MODEL_API_KEY from env, defaulting to openai/gpt-4.1.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@socket-security

socket-security Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​@​types/​ws@​8.18.11001007380100
Addednpm/​@​browserbasehq/​stagehand@​4.0.081100100100100
Addednpm/​ws@​8.21.39910010095100

View full report

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ca622fd. Configure here.

Comment thread pkg/templates/typescript/stagehand/index.ts
Comment thread pkg/templates/typescript/stagehand/index.ts Outdated
- discoverExtensionId: settle on an overall timeout, socket close, and
  errors, and guard JSON parsing, so a run can no longer hang past the
  timeout without reaching cleanup.
- Move browser teardown (stagehand.close, browser.close, deleteByID)
  into a finally block so a failed run no longer leaks the Kernel
  browser, matching the sibling templates.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant