Skip to content

feat(integrations): pi harness example (native facade tools) - #2718

Merged
miguelg719 merged 2 commits into
mainfrom
miguel/harness-pi
Aug 14, 2026
Merged

feat(integrations): pi harness example (native facade tools)#2718
miguelg719 merged 2 commits into
mainfrom
miguel/harness-pi

Conversation

@miguelg719

@miguelg719 miguelg719 commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

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 with pi -e): the three facade tools registered with descriptions, runtime validators, and FACADE_AGENT_INSTRUCTIONS imported from @browserbasehq/stagehand-integrations/facade; TypeBox param schemas; lazy browser launch on first tool call, closed on session_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 native pi tools so pi can use the canonical facade without MCP. Also fixes shutdown to close the browser even if a launch is still pending.

  • Registers the three tools with canonical descriptions; validates params via TypeBox and re-validates with contract schemas at execution; forwards FACADE_AGENT_INSTRUCTIONS on run (from @browserbasehq/stagehand-integrations/facade).
  • Launches the browser lazily on first tool call (Browserbase or local per env); on session_shutdown waits for any in-flight launch and then closes Stagehand and the browser. Returns screenshots as native image content.
  • Security: model-authored JS runs in the Stagehand extension service worker; Browserbase is the recommended isolation boundary; only STAGEHAND_*/BROWSERBASE_* envs configure the browser; pi model credentials never reach the browser session.
  • Tests assert only the canonical tools register, descriptions match, guidelines pass through, and no browser launches at registration.
  • Package @browserbasehq/stagehand-integrations-example-pi-facade includes a pi manifest and is installable via pi, or loadable with pi -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.

Review in cubic

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.
@changeset-bot

changeset-bot Bot commented Aug 14, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 8b01a10

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@changeset-bot

changeset-bot Bot commented Aug 14, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: c162148

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@socket-security

socket-security Bot commented Aug 14, 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/​@​earendil-works/​pi-coding-agent@​0.84.26710010097100
Addednpm/​typebox@​1.3.71001009996100

View full report

@socket-security

socket-security Bot commented Aug 14, 2026

Copy link
Copy Markdown

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.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm highlight.js is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: pnpm-lock.yamlnpm/@earendil-works/pi-coding-agent@0.84.2npm/highlight.js@10.7.3

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/highlight.js@10.7.3. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

3 issues found across 9 files

Confidence score: 3/5

  • In packages/integrations/pi/extensions/stagehand.ts, the screenshotParameters TypeBox schema currently permits floating-point quality values, 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, setting engines.node to >=24 is 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 plain pnpm install can produce lockfile drift and non-reproducible installs for readers, increasing setup variability when testing the integration — switch the docs command to pnpm 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
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread packages/integrations/pi/extensions/stagehand.ts
Comment thread packages/integrations/pi/README.md
Comment thread packages/integrations/pi/package.json
Comment thread packages/integrations/pi/extensions/stagehand.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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 in tests/extension.test.ts that simulates shutdown during an in-flight resourcesPromise.
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;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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>

@miguelg719
miguelg719 merged commit 0740acf into main Aug 14, 2026
49 checks passed
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.

2 participants