feat(integrations): pi harness example (native facade tools) - #2718
Conversation
c162148 to
a0af817
Compare
pi ships without built-in MCP by design; this pi package registers the three facade tools natively — descriptions, validators, and agent guidance imported from @browserbasehq/stagehand-integrations/facade, TypeBox param schemas, lazy browser on first tool call, closed on session_shutdown, screenshots as image content. Smoke-verified on Browserbase via pi 0.84.2.
a0af817 to
af3c038
Compare
|
|
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Warning Review the following alerts detected in dependencies. According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.
|
There was a problem hiding this comment.
3 issues found across 9 files
Confidence score: 3/5
- In
packages/integrations/pi/extensions/stagehand.ts, thescreenshotParametersTypeBox schema currently permits floating-pointqualityvalues, which can violate the intended contract and cause inconsistent screenshot behavior or downstream validation failures — enforce integer-only quality (0–100) in the schema. - In
packages/integrations/pi/package.json, settingengines.nodeto>=24is stricter than the repo baseline and may block users in otherwise supported environments from installing or running this integration — align it with the project’s stated Node minimum unless there is a documented hard requirement. - In
packages/integrations/pi/README.md, using plainpnpm installcan produce lockfile drift and non-reproducible installs for readers, increasing setup variability when testing the integration — switch the docs command topnpm install --frozen-lockfile.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/integrations/pi/README.md">
<violation number="1" location="packages/integrations/pi/README.md:13">
P2: `pnpm install` here allows lockfile drift and non-reproducible setup for the integration example. Use `--frozen-lockfile` so readers install exactly the committed dependency graph.
(Based on your team's feedback about freezing pnpm integration installs.) .</violation>
</file>
<file name="packages/integrations/pi/package.json">
<violation number="1" location="packages/integrations/pi/package.json:31">
P2: This package now requires Node `>=24`, which is stricter than the repo’s stated `>=22.18.0` baseline and can block users on otherwise supported environments. Align `engines.node` with the project baseline unless this extension has a verified Node 24-only runtime requirement.</violation>
</file>
<file name="packages/integrations/pi/extensions/stagehand.ts">
<violation number="1" location="packages/integrations/pi/extensions/stagehand.ts:59">
P2: Custom agent flagged.
The TypeBox wire schema `screenshotParameters` does not enforce instruction 8c277b79 for screenshot quality. `Type.Number({ minimum: 0, maximum: 100 })` allows float values instead of requiring integers, and `type` is an unbounded optional string rather than requiring `"jpeg"` whenever `quality` is supplied. Change `quality` to `Type.Integer({ minimum: 0, maximum: 100 })` and add a conditional or union schema that requires `type: "jpeg"` when `quality` is present.</violation>
</file>
Architecture diagram
sequenceDiagram
participant User as User
participant PI as pi Agent (pi-coding-agent)
participant Ext as Stagehand Extension
participant Contract as @browserbasehq/stagehand-integrations/facade
participant Stagehand as Stagehand Runtime
participant BB as Browserbase (or Local)
Note over User,BB: pi extension: native facade tools (no MCP)
User->>PI: pi -e ./extensions/stagehand.ts -p "instruction"
PI->>Ext: Load extension & register tools
rect rgb(240, 248, 255)
Note over Ext,Contract: Registration (no browser launch)
Ext->>Contract: Import tool descriptions, schemas, FACADE_AGENT_INSTRUCTIONS
Ext->>PI: registerTool(run, snapshot, screenshot)
end
PI-->>User: Session ready, tools available
loop Per user instruction (model-driven)
PI->>Ext: execute(run, params)
Ext->>Contract: CodeModeRunInputSchema.parse(params) - validate & enforce semantics
alt First tool call
Ext->>Ext: facadeTools() - lazy init
Ext->>Ext: stagehandFacadeConfigFromEnv() - read STAGEHAND_*/BROWSERBASE_* env
alt Browserbase backend
Ext->>BB: browserbase.launch()
BB-->>Ext: browser instance
else Local backend
Ext->>BB: localBrowser.launch()
end
Ext->>Stagehand: Stagehand.create({ browser, ...config })
Stagehand-->>Ext: stagehand + StagehandFacadeTools
end
alt Run with code
Ext->>Stagehand: tools.run(input.code)
Stagehand->>BB: Execute JS workflow (service worker context)
BB-->>Stagehand: Result
Stagehand-->>Ext: Execution result
else Run with actions
Ext->>Stagehand: tools.runActions(input.actions)
Stagehand-->>Ext: Actions result
end
Ext-->>PI: AgentToolResult (text JSON content)
PI-->>User: Tool result (model reads)
PI->>Ext: execute(snapshot, params)
Ext->>Contract: SnapshotInputSchema.parse(params)
Ext->>Ext: facadeTools() - reuse existing resources
Ext->>Stagehand: tools.snapshot(input)
Stagehand->>BB: Snapshot page state
BB-->>Stagehand: Page tree
Stagehand-->>Ext: Snapshot tree
Ext-->>PI: AgentToolResult (text content)
PI->>Ext: execute(screenshot, params)
Ext->>Contract: ScreenshotInputSchema.parse(params)
Ext->>Ext: facadeTools() - reuse existing resources
Ext->>Stagehand: tools.screenshot(input)
Stagehand->>BB: Capture screenshot
BB-->>Stagehand: Image data
Stagehand-->>Ext: Screenshot
Ext-->>PI: AgentToolResult (native image content)
PI-->>User: Screenshot rendered for model
end
User->>PI: session shutdown / close session
PI->>Ext: session_shutdown event
Ext->>Ext: closeResources()
Ext->>Stagehand: stagehand.close()
Ext->>BB: browser.close()
BB-->>Ext: Closed
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Confidence score: 5/5
- In
packages/integrations/pi/extensions/stagehand.ts, the shutdown/pending-launch race fix is untested, so regressions in async teardown/startup ordering could slip through and cause intermittent resource leaks or flaky extension lifecycle behavior—add a focused unit test intests/extension.test.tsthat simulates shutdown during an in-flightresourcesPromise.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/integrations/pi/extensions/stagehand.ts">
<violation number="1" location="packages/integrations/pi/extensions/stagehand.ts:97">
P3: The shutdown-vs-pending-launch race this change fixes (await the in-flight `resourcesPromise` before reading `resources`) has no unit test coverage. The existing `tests/extension.test.ts` only verifies tool registration and that no browser launches at registration; it never exercises `closeResources`. Add a focused test that initiates a launch, triggers `closeResources` mid-launch, and asserts the produced browser is closed (and one for the launch-rejection path).</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| async function closeResources(): Promise<void> { | ||
| // A shutdown can race a still-pending launch; wait for it so the browser | ||
| // it produces is closed rather than leaked. | ||
| const pending = resourcesPromise; |
There was a problem hiding this comment.
P3: The shutdown-vs-pending-launch race this change fixes (await the in-flight resourcesPromise before reading resources) has no unit test coverage. The existing tests/extension.test.ts only verifies tool registration and that no browser launches at registration; it never exercises closeResources. Add a focused test that initiates a launch, triggers closeResources mid-launch, and asserts the produced browser is closed (and one for the launch-rejection path).
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/integrations/pi/extensions/stagehand.ts, line 97:
<comment>The shutdown-vs-pending-launch race this change fixes (await the in-flight `resourcesPromise` before reading `resources`) has no unit test coverage. The existing `tests/extension.test.ts` only verifies tool registration and that no browser launches at registration; it never exercises `closeResources`. Add a focused test that initiates a launch, triggers `closeResources` mid-launch, and asserts the produced browser is closed (and one for the launch-rejection path).</comment>
<file context>
@@ -92,6 +92,10 @@ export default function stagehandExtension(pi: ExtensionAPI) {
async function closeResources(): Promise<void> {
+ // A shutdown can race a still-pending launch; wait for it so the browser
+ // it produces is closed rather than leaked.
+ const pending = resourcesPromise;
+ if (pending) await pending.catch(() => undefined);
const current = resources;
</file context>
pi ships without built-in MCP by design, so this is a native pi extension (pi-package manifest, installable via
pi install, loadable one-off withpi -e): the three facade tools registered with descriptions, runtime validators, andFACADE_AGENT_INSTRUCTIONSimported from@browserbasehq/stagehand-integrations/facade; TypeBox param schemas; lazy browser launch on first tool call, closed onsession_shutdown; screenshots as native image content. Contract drift test + turbo typecheck entry.One-line run after
pnpm install+ core build:pnpm --filter @browserbasehq/stagehand-integrations-example-pi-facade start "your instruction"Verified: Browserbase smoke via pi 0.84.2 — "The page heading is 'Example Domain' [0-19]".
Summary by cubic
Exposes Stagehand’s facade tools (
run,snapshot,screenshot) as nativepitools sopican use the canonical facade without MCP. Also fixes shutdown to close the browser even if a launch is still pending.FACADE_AGENT_INSTRUCTIONSonrun(from@browserbasehq/stagehand-integrations/facade).session_shutdownwaits for any in-flight launch and then closes Stagehand and the browser. Returns screenshots as native image content.STAGEHAND_*/BROWSERBASE_*envs configure the browser;pimodel credentials never reach the browser session.@browserbasehq/stagehand-integrations-example-pi-facadeincludes apimanifest and is installable viapi, or loadable withpi -e. Requires Node 24+,pi>= 0.84.2, Browserbase credentials, and a supported model API key.Written for commit 8b01a10. Summary will update on new commits.