Skip to content

feat(evals): add AI-enabled V4 code surface#2378

Open
shrey150 wants to merge 4 commits into
shrey/stg-2664-v4-code-deterministicfrom
shrey/stg-2662-v4-code-ai
Open

feat(evals): add AI-enabled V4 code surface#2378
shrey150 wants to merge 4 commits into
shrey/stg-2664-v4-code-deterministicfrom
shrey/stg-2662-v4-code-ai

Conversation

@shrey150

@shrey150 shrey150 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add v4_code as the AI-enabled companion to v4_code_deterministic
  • carry the selected Claude Code harness model and provider credential through the typed child-process initialization protocol
  • expose positional page.act(instruction), page.observe(instruction), and page.extract(instruction, schema) methods only in AI mode, with z available for extraction schemas
  • preserve the deterministic mode's model-free facade and the existing timeout, JSON-safe result, logging, and process-tree cleanup behavior

This is the second draft in a stack and is based on the deterministic local V4 code surface. Both modes use the same extension-backed local browser runtime; the added AI methods are the intentional experimental variable.

Linear: https://linear.app/browserbase/issue/STG-2662/add-ai-enabled-v4-code-mode-to-stagehand-evals

E2E Test Matrix

Command / flow Observed output Confidence / sufficiency
Real extension-backed controller flow using extract, observe, and act extract returned the page heading, observe returned an available action, and act successfully navigated to the requested destination; the recorded Chrome process was gone after cleanup. Directly proves all three AI methods, schema injection, model initialization, extension communication, and cleanup without depending on harness tool selection.
VERIFIER_DISABLE_TRUNCATION=1 node packages/evals/dist/cli/cli.js run b:webtailbench --harness claude_code --tool v4_code --startup tool_launch_local --env local --model anthropic/claude-sonnet-5 --trials 1 --concurrency 1 --filter ids=recreation.gov_question_answering_26 --success outcome with STAGEHAND_V4_SDK_PATH=<local V4 SDK entry> Claude Code invoked the V4 AI surface, including page.act, completed the live browser task, and the outcome verifier accepted the result; cleanup left no V4 bridge or Chrome process. End-to-end proof of CLI planning, selected-model propagation, local startup, extension handshake, AI-assisted execution, verification, and cleanup for one smoke task. It is not a statistical benchmark.
The same live task using --tool v4_code_deterministic The deterministic surface also completed the task and the outcome verifier accepted the result; cleanup left no V4 bridge or Chrome process. Confirms the shared AI-mode refactor did not regress the deterministic end-to-end path.
pnpm exec turbo run build:esm build:cli --filter=@browserbasehq/stagehand-evals --force Exact local ESM and bundled CLI builds completed successfully with the cache bypassed. Proves the source under review builds through both eval distribution paths.
pnpm --filter @browserbasehq/stagehand-evals exec vitest run 54 test files and 433 tests passed. Covers adapter selection, model normalization, mode-discriminated IPC, facade behavior, lifecycle edges, and the existing eval suite.
pnpm --filter @browserbasehq/stagehand-evals lint Prettier, ESLint, and TypeScript typecheck passed. Static validation supporting the live smokes above.

Release

No changeset: this is private eval scaffolding and does not change the published Stagehand package runtime.


Summary by cubic

Adds v4_code, a Stagehand V4 surface that runs with a selected model, alongside v4_code_deterministic. The Claude Code harness now passes typed init IPC with mode and model, validates model identifiers and credentials, injects z (Zod), and exposes stagehand.act/observe/extract in AI mode while keeping the page/context facades deterministic and unchanged. Addresses Linear STG-2662.

  • New Features

    • Support v4_code (model-enabled) and v4_code_deterministic in LOCAL tool_launch_local; bench harness forwards --model.
    • Resolve and validate model config from --model: normalize names, infer provider when omitted, reject unsupported providers, require provider API keys, and add Anthropic anthropic-dangerous-direct-browser-access.
    • Controller/bridge/runtime carry mode and model; Stagehand constructor receives model only in model-enabled runs; typed init IPC enforces this.
    • Snippet API: page/context facades remain deterministic; AI-only methods moved to a stagehand facade (stagehand.act/observe/extract(schema)), with z available for schemas; deterministic mode rejects model config.
    • Internals/RPC stay hidden; timeouts, JSON-safe results, logging, and cleanup preserved; tests updated for model normalization, typed IPC, and the new stagehand-scoped methods.
  • Migration

    • Use --tool v4_code --startup tool_launch_local --env local --model <provider/model>, e.g. anthropic/claude-sonnet-5.
    • Set provider API key env: ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEY/GOOGLE_GENERATIVE_AI_API_KEY/GOOGLE_API_KEY, GROQ_API_KEY, CEREBRAS_API_KEY.
    • Ensure STAGEHAND_V4_SDK_PATH points to the local V4 SDK.

Written for commit c53abd7. Summary will update on new commits.

Review in cubic

@changeset-bot

changeset-bot Bot commented Jul 22, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: c53abd7

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

@shrey150
shrey150 marked this pull request as ready for review July 22, 2026 18:13
@shrey150
shrey150 force-pushed the shrey/stg-2662-v4-code-ai branch from 8440835 to f919f92 Compare July 22, 2026 18:16

@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 and verified against the latest diff

Confidence score: 3/5

  • In packages/evals/core/contracts/tool.ts, adding toolSurface: "v4_code" to ToolSurface lets core callers pass a value the core registry cannot initialize, which can cause runtime init failures for otherwise valid-looking configs; remove this harness-only surface from the core contract (or add a matching core registry implementation) before merging.
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/evals/core/contracts/tool.ts">

<violation number="1" location="packages/evals/core/contracts/tool.ts:23">
P2: Core callers can now pass `toolSurface: "v4_code"` as a valid contract value, but initialization immediately fails because the core registry has no implementation. Keep this harness-only surface out of `ToolSurface`, or register/support it in the core path.</violation>
</file>

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

Re-trigger cubic

| "understudy_code"
| "playwright_code"
| "cdp_code"
| "v4_code"

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.

P2: Core callers can now pass toolSurface: "v4_code" as a valid contract value, but initialization immediately fails because the core registry has no implementation. Keep this harness-only surface out of ToolSurface, or register/support it in the core path.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/evals/core/contracts/tool.ts, line 23:

<comment>Core callers can now pass `toolSurface: "v4_code"` as a valid contract value, but initialization immediately fails because the core registry has no implementation. Keep this harness-only surface out of `ToolSurface`, or register/support it in the core path.</comment>

<file context>
@@ -20,6 +20,7 @@ export type ToolSurface =
   | "understudy_code"
   | "playwright_code"
   | "cdp_code"
+  | "v4_code"
   | "v4_code_deterministic"
   | "playwright_mcp"
</file context>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The shared ToolSurface type is intentionally the selection contract across core and external harnesses. listCoreTools()/getCoreTool() define the core-only subset, while resolveClaudeCodeToolSurface() owns this external-harness dispatch. Keeping v4_code in the shared union is required for typed harness rows and does not register it as a core tool.

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.

The parent comment was too broad here: ToolSurface is intentionally shared, and v4_code is not registered as a core tool because listCoreTools()/getCoreTool() and resolveClaudeCodeToolSurface() split those responsibilities. The issue is the core registry boundary, not the shared union itself.

Comment thread packages/evals/framework/v4CodeConfig.ts
Comment thread packages/evals/framework/v4CodeConfig.ts Outdated
Comment thread packages/evals/framework/v4CodeConfig.ts
@shrey150
shrey150 force-pushed the shrey/stg-2662-v4-code-ai branch from fafeac6 to f70ac5c Compare July 22, 2026 19:25
@shrey150
shrey150 force-pushed the shrey/stg-2662-v4-code-ai branch from f70ac5c to 3643ee2 Compare July 22, 2026 20:47
Comment thread packages/evals/tests/framework/v4CodeRuntime.test.ts Outdated

@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 3 files (changes from recent commits).

Confidence score: 3/5

  • In packages/evals/framework/claudeCodeToolAdapter.ts, the MCP tool description is now out of sync with the prompt (it still references page.act/extract/observe and misses stagehand), which can steer Claude toward invalid tool calls and reduce eval reliability; align the tool description/schema with the injected MCP format to de-risk run behavior.
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/evals/framework/claudeCodeToolAdapter.ts">

<violation number="1" location="packages/evals/framework/claudeCodeToolAdapter.ts:1383">
P2: AI runs receive contradictory tool guidance: the MCP tool still says `page.act/extract/observe` exist and omits `stagehand` from scope. Update that tool description/schema alongside this prompt so Claude uses the injected `stagehand` facade rather than failing calls on `page`.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

"The context facade supports pages, newPage, activePage, setActivePage, clipboard, addInitScript, setExtraHTTPHeaders, domain policy, and cookie methods. context.close is intentionally unavailable because the harness owns cleanup.",
"AI methods act, extract, and observe are intentionally omitted from the provided facade. Stagehand internals and RPC objects are also omitted. This is an API-surface distinction, not a hostile-code security sandbox.",
mode === "ai"
? "AI methods belong to the stagehand facade: await stagehand.act(instruction, options?), await stagehand.observe(instruction?, options?), and await stagehand.extract(instruction, schema, options?). Build extraction schemas with z, for example: await stagehand.extract('Extract the heading', z.object({ heading: z.string() })). To target a non-active page, pass its facade in options, for example { page }."

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.

P2: AI runs receive contradictory tool guidance: the MCP tool still says page.act/extract/observe exist and omits stagehand from scope. Update that tool description/schema alongside this prompt so Claude uses the injected stagehand facade rather than failing calls on page.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/evals/framework/claudeCodeToolAdapter.ts, line 1383:

<comment>AI runs receive contradictory tool guidance: the MCP tool still says `page.act/extract/observe` exist and omits `stagehand` from scope. Update that tool description/schema alongside this prompt so Claude uses the injected `stagehand` facade rather than failing calls on `page`.</comment>

<file context>
@@ -1374,14 +1374,14 @@ function buildV4CodePromptInstructions(
     mode === "ai"
-      ? "AI methods use the exact positional signatures await page.act(instruction), await page.observe(instruction), and await page.extract(instruction, schema). Build extraction schemas with z, for example: await page.extract('Extract the heading', z.object({ heading: z.string() }))."
-      : "AI methods act, extract, and observe are intentionally omitted from the provided facade. No model or AI provider credential is configured in this mode.",
+      ? "AI methods belong to the stagehand facade: await stagehand.act(instruction, options?), await stagehand.observe(instruction?, options?), and await stagehand.extract(instruction, schema, options?). Build extraction schemas with z, for example: await stagehand.extract('Extract the heading', z.object({ heading: z.string() })). To target a non-active page, pass its facade in options, for example { page }."
+      : "The stagehand facade, z, and AI methods act, extract, and observe are intentionally omitted. No model or AI provider credential is configured in this mode.",
     "Stagehand internals and RPC objects are omitted. This is an API-surface distinction, not a hostile-code security sandbox.",
</file context>

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