From 888f687fe93f1d211eef0ab102495cca0147d3c1 Mon Sep 17 00:00:00 2001 From: Shrey Pandya Date: Thu, 17 Sep 2026 22:20:10 +0000 Subject: [PATCH 1/2] feat(pi): package native extension for pi install --- .changeset/quiet-pi-extension.md | 5 +++ justfile | 2 + packages/docs/v4/integrations/pi.mdx | 30 ++++++------- packages/integrations/pi/README.md | 53 +++++++---------------- packages/integrations/pi/package.json | 31 ++++++++++--- packages/integrations/pi/tsdown.config.ts | 12 +++++ pnpm-lock.yaml | 8 +++- scripts/release/check-changesets.test.ts | 1 + scripts/release/check-changesets.ts | 1 + scripts/release/consolidate-changelogs.ts | 4 ++ turbo.json | 7 ++- 11 files changed, 92 insertions(+), 62 deletions(-) create mode 100644 .changeset/quiet-pi-extension.md create mode 100644 packages/integrations/pi/tsdown.config.ts diff --git a/.changeset/quiet-pi-extension.md b/.changeset/quiet-pi-extension.md new file mode 100644 index 0000000000..3cfbeb6870 --- /dev/null +++ b/.changeset/quiet-pi-extension.md @@ -0,0 +1,5 @@ +--- +"@browserbasehq/pi": minor +--- + +Publish the native Pi extension as an installable Pi package, bundling the private facade implementation. diff --git a/justfile b/justfile index a69c7a116a..cd19f9e05d 100644 --- a/justfile +++ b/justfile @@ -87,6 +87,7 @@ _preview commit: _publish-typescript: pnpm --filter ./packages/sdk-ts build + pnpm exec turbo run build --filter @browserbasehq/pi pnpm exec changeset publish # Publishes a commit-addressed alpha of the TypeScript SDK (`-alpha-`) @@ -95,6 +96,7 @@ _publish-typescript: _publish-typescript-alpha: pnpm exec changeset version --snapshot pnpm --filter ./packages/sdk-ts build + pnpm exec turbo run build --filter @browserbasehq/pi pnpm exec changeset publish --tag alpha --no-git-tag # Rewrites the Python project to the commit-addressed alpha (`a0.dev`) diff --git a/packages/docs/v4/integrations/pi.mdx b/packages/docs/v4/integrations/pi.mdx index 85e0830c88..aa4e1baa3b 100644 --- a/packages/docs/v4/integrations/pi.mdx +++ b/packages/docs/v4/integrations/pi.mdx @@ -6,27 +6,24 @@ description: "Give the Pi coding agent native Stagehand browser tools registered The Pi integration gives a Pi agent native `run`, `snapshot`, and `screenshot` tools backed by one persistent Stagehand browser per Pi session. Pi ships without built-in MCP by design; extensions register tools directly, so this integration runs in process without an MCP server or bridge. The tool descriptions, runtime validators, and system prompt come from the shared facade contract, so the tools behave the same as the MCP-based integrations. -Stagehand ships this experimental integration from the repository rather than publishing it as a standalone adapter. +The extension uses Pi’s official [package format](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/packages.md). The first `@browserbasehq/pi` release must be published before the npm install below is available; use the source install below while testing an unreleased change. ## Prerequisites - Node.js 24 or newer -- pnpm 11.10.0 - A model-provider credential for Pi (`OPENAI_API_KEY` or `ANTHROPIC_API_KEY`) - A current Google Chrome installation for local browser mode ## Quickstart - + ```bash -git clone https://github.com/browserbase/stagehand.git -cd stagehand -pnpm install --frozen-lockfile -pnpm exec turbo run build \ - --filter @browserbasehq/stagehand-integrations +pi install npm:@browserbasehq/pi ``` + +Use `pi install -l npm:@browserbasehq/pi` to install only for the current project. Restart Pi after installing so it loads the extension. ```bash @@ -45,27 +42,28 @@ export BROWSERBASE_API_KEY="your-browserbase-api-key" ```bash -cd packages/integrations/pi -pnpm start "Open https://example.com and report the page title." + Two headless gotchas: print mode reads piped stdin (always redirect ` -## Install permanently +## Try the extension from source -To register the extension for every Pi session instead of loading it per invocation: +For development before the first release, build and install the package from the repository. The build bundles the private facade so installed consumers do not depend on the monorepo. ```bash +git clone https://github.com/browserbase/stagehand.git +cd stagehand +pnpm install --frozen-lockfile +pnpm exec turbo run build --filter @browserbasehq/pi pi install ./packages/integrations/pi ``` -The `pi` manifest key in the package's `package.json` points at the extension. +Use `pi list` to inspect installed packages, `pi update npm:@browserbasehq/pi` to update a published installation, and `pi remove npm:@browserbasehq/pi` to remove it. ## Configuration diff --git a/packages/integrations/pi/README.md b/packages/integrations/pi/README.md index 3f98bfb900..560ec8348d 100644 --- a/packages/integrations/pi/README.md +++ b/packages/integrations/pi/README.md @@ -1,49 +1,26 @@ -# pi + Stagehand facade (native tools) +# Stagehand for Pi -[pi](https://pi.dev) has no built-in MCP by design — extensions register tools directly. This -package is a pi extension exposing the Stagehand facade tools (`run`, `snapshot`, -`screenshot`) natively, with descriptions, validation, and agent guidance imported from -`@browserbasehq/stagehand-integrations/facade`. +Install the native extension with Pi’s package manager: -## Setup - -Use Node.js 24 or later. From the repository root, build the integrations package first: - -```bash -pnpm install -pnpm exec turbo run build --filter @browserbasehq/stagehand-integrations +```sh +pi install npm:@browserbasehq/pi +pi ``` -Export the browser credentials (Browserbase is the default and recommended backend) and a model -key pi supports: +Requires Node.js 24+, an authenticated Pi model provider, and local Chrome (or `BROWSERBASE_API_KEY` for Browserbase). The initial npm release is pending; before publishing, use the development build below. No private workspace dependency is needed by the installed package. -```bash -export BROWSERBASE_API_KEY=bb_live_... -export OPENAI_API_KEY=sk-... # or ANTHROPIC_API_KEY -``` +The extension registers `run`, `snapshot`, and `screenshot` directly through Pi’s extension API. It launches a browser on the first call, reuses it throughout the session, and closes it on shutdown. -## Run +## Develop from source -One-off, pointing pi at the extension file (no install needed; pi loads TypeScript directly and -resolves `@browserbasehq/stagehand-integrations` through the workspace): +From the Stagehand repository root: -```bash -cd packages/integrations/pi -pi -e ./extensions/stagehand.ts --no-session -p "Use your browser tools: open https://example.com, snapshot it, and report the heading citing the snapshot ID." { "@browserbasehq/stagehand-go": patch "@browserbasehq/stagehand-extension": patch "browse": patch +"@browserbasehq/pi": minor --- Release the SDKs. diff --git a/scripts/release/check-changesets.ts b/scripts/release/check-changesets.ts index 708f568177..6b1c5c1a71 100644 --- a/scripts/release/check-changesets.ts +++ b/scripts/release/check-changesets.ts @@ -10,6 +10,7 @@ const allowedPackages = new Set([ "@browserbasehq/stagehand-python", "@browserbasehq/stagehand-extension", "browse", + "@browserbasehq/pi", ]); export function validateChangeset(contents: string, file: string): void { diff --git a/scripts/release/consolidate-changelogs.ts b/scripts/release/consolidate-changelogs.ts index 346fcc1672..2bd87e006f 100644 --- a/scripts/release/consolidate-changelogs.ts +++ b/scripts/release/consolidate-changelogs.ts @@ -5,6 +5,10 @@ import { pathToFileURL } from "node:url"; const repositoryRoot = path.resolve(import.meta.dirname, "../.."); const rootChangelogPath = path.join(repositoryRoot, "CHANGELOG.md"); const packageChangelogs = [ + { + label: "Pi extension", + path: path.join(repositoryRoot, "packages/integrations/pi/CHANGELOG.md"), + }, { label: "TypeScript SDK", path: path.join(repositoryRoot, "packages/sdk-ts/CHANGELOG.md"), diff --git a/turbo.json b/turbo.json index df66097f77..7ae60679e3 100644 --- a/turbo.json +++ b/turbo.json @@ -39,6 +39,11 @@ "browse#lint": { "dependsOn": ["@browserbasehq/stagehand#build"] }, + "@browserbasehq/pi#build": { + "dependsOn": ["^build"], + "inputs": ["$TURBO_DEFAULT$", "!dist/**"], + "outputs": ["dist/**"] + }, "@browserbasehq/stagehand-integrations#build": { "dependsOn": ["^build"], "inputs": ["$TURBO_DEFAULT$", "!dist/**"], @@ -243,7 +248,7 @@ "@browserbasehq/stagehand-integrations-example-vercel-ai-facade#typecheck": { "dependsOn": ["^build"] }, - "@browserbasehq/stagehand-integrations-example-pi-facade#typecheck": { + "@browserbasehq/pi#typecheck": { "dependsOn": ["^build"] }, "@browserbasehq/stagehand-integrations-example-claude-code-facade#typecheck": { From 16e28a2ddd3c97ca0564f5f88faee489aec5a841 Mon Sep 17 00:00:00 2001 From: Shrey Pandya Date: Thu, 17 Sep 2026 22:33:02 +0000 Subject: [PATCH 2/2] fix(pi): clarify installed flow and exercise release consolidation --- packages/docs/v4/integrations/pi.mdx | 4 +- .../release/consolidate-changelogs.test.ts | 37 ++++++++++++++++++- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/packages/docs/v4/integrations/pi.mdx b/packages/docs/v4/integrations/pi.mdx index aa4e1baa3b..c9f3526f58 100644 --- a/packages/docs/v4/integrations/pi.mdx +++ b/packages/docs/v4/integrations/pi.mdx @@ -6,7 +6,7 @@ description: "Give the Pi coding agent native Stagehand browser tools registered The Pi integration gives a Pi agent native `run`, `snapshot`, and `screenshot` tools backed by one persistent Stagehand browser per Pi session. Pi ships without built-in MCP by design; extensions register tools directly, so this integration runs in process without an MCP server or bridge. The tool descriptions, runtime validators, and system prompt come from the shared facade contract, so the tools behave the same as the MCP-based integrations. -The extension uses Pi’s official [package format](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/packages.md). The first `@browserbasehq/pi` release must be published before the npm install below is available; use the source install below while testing an unreleased change. +The extension uses Pi’s official [package format](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/packages.md). Browserbase must publish the first `@browserbasehq/pi` release before you can use the npm install below; use the source install below while testing an unreleased change. ## Prerequisites @@ -48,7 +48,7 @@ pi --no-session -p "Open https://example.com and report the page title." -Two headless gotchas: print mode reads piped stdin (always redirect ` ## Try the extension from source diff --git a/scripts/release/consolidate-changelogs.test.ts b/scripts/release/consolidate-changelogs.test.ts index c50e6a0d16..7dbd715284 100644 --- a/scripts/release/consolidate-changelogs.test.ts +++ b/scripts/release/consolidate-changelogs.test.ts @@ -1,4 +1,5 @@ -import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises"; +import { execFileSync } from "node:child_process"; +import { copyFile, mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises"; import os from "node:os"; import path from "node:path"; import { describe, expect, it } from "vitest"; @@ -175,3 +176,37 @@ describe("shouldPreservePackageChangelogs", () => { expect(shouldPreservePackageChangelogs(value)).toBe(expected); }); }); + +describe("integration package release", () => { + it("consolidates the Pi extension changelog through the release entrypoint", async () => { + const directory = await mkdtemp(path.join(os.tmpdir(), "stagehand-integration-release-")); + try { + const scripts = path.join(directory, "scripts/release"); + const packagePath = path.join(directory, "packages/integrations/pi"); + await mkdir(scripts, { recursive: true }); + await mkdir(packagePath, { recursive: true }); + const scriptPath = path.join(scripts, "consolidate-changelogs.ts"); + await copyFile(new URL("./consolidate-changelogs.ts", import.meta.url), scriptPath); + await writeFile( + path.join(directory, "CHANGELOG.md"), + "# Stagehand\n\n## 4.1.0\n\nExisting release.\n", + ); + await writeFile( + path.join(packagePath, "CHANGELOG.md"), + "# Integration\n\n## 0.1.0\n\nFirst package release.\n", + ); + execFileSync(process.execPath, [scriptPath], { + env: { ...process.env, CHANGESETS_ACTION_PRESERVE_CHANGELOGS: "false" }, + }); + const result = await readFile(path.join(directory, "CHANGELOG.md"), "utf8"); + expect(result).toContain("## Pi extension 0.1.0"); + expect(result).toContain("First package release."); + expect(result).toContain("## 4.1.0\n\nExisting release."); + await expect(readFile(path.join(packagePath, "CHANGELOG.md"))).rejects.toMatchObject({ + code: "ENOENT", + }); + } finally { + await rm(directory, { recursive: true, force: true }); + } + }); +});