Skip to content

fix(core): add goto variable substitution parity#2054

Open
BABTUNA wants to merge 2 commits intobrowserbase:mainfrom
BABTUNA:fix/goto-variable-substitution
Open

fix(core): add goto variable substitution parity#2054
BABTUNA wants to merge 2 commits intobrowserbase:mainfrom
BABTUNA:fix/goto-variable-substitution

Conversation

@BABTUNA
Copy link
Copy Markdown
Contributor

@BABTUNA BABTUNA commented Apr 26, 2026

why
goto did not substitute %variableName% tokens in either live execution or AgentCache replay.

That created parity drift with keys (which already supports variable substitution in live + replay) and caused variable-driven navigation steps to replay incorrectly.

Closes #2053.

what changed

  • goto tool now resolves %variable% tokens before calling page.goto(...).
  • goto tool replay recording still stores the original tokenized URL.
  • createAgentTools now wires variables into gotoTool.
  • AgentCache replay now resolves %variable% tokens for cached goto steps.

tests

  • Added packages/core/tests/unit/goto-tool-variables.test.ts
    • verifies live goto substitution + tokenized replay recording.
  • Extended packages/core/tests/unit/cache-llm-resolution.test.ts
    • verifies cached goto replay applies substitutions.

validation run

  • npm.cmd exec prettier -- --write on touched files
  • npm.cmd exec eslint -- on touched files
  • node node_modules/vitest/vitest.mjs run --config .tmp-vitest-unit-config.mjs (targeting the two updated unit tests)

Summary by cubic

Fixes goto variable substitution: %var% tokens now resolve in live runs and AgentCache replays, matching keys behavior, and adds expectNavigation, expectPopup, and expectDownload to the v4 click API. Closes #2053.

  • Bug Fixes

    • goto resolves %variable% before page.goto(...) and during AgentCache replay; replays keep the tokenized URL.
    • createAgentTools now passes variables into goto.
  • New Features

    • POST /v4/page/click accepts expectNavigation, expectPopup, and expectDownload; OpenAPI and schema updated.
    • Added unit and integration tests for variable substitution and click options.

Written for commit a24cb0a. Summary will update on new commits. Review in cubic

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 26, 2026

⚠️ No Changeset found

Latest commit: a24cb0a

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

@github-actions
Copy link
Copy Markdown
Contributor

This PR is from an external contributor and must be approved by a stagehand team member with write access before CI can run.
Approving the latest commit mirrors it into an internal PR owned by the approver.
If new commits are pushed later, the internal PR stays open but is marked stale until someone approves the latest external commit and refreshes it.

@github-actions github-actions Bot added external-contributor Tracks PRs mirrored from external contributor forks. external-contributor:awaiting-approval Waiting for a stagehand team member to approve the latest external commit. labels Apr 26, 2026
Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

1 issue found across 8 files

Confidence score: 2/5

  • There is a high-confidence security risk in packages/core/lib/v3/agent/tools/goto.ts: raw page.goto errors can include resolved URLs after variable substitution, which may expose secret values in error messages.
  • Because this is a concrete, user-impacting secret-leak path (severity 8/10, confidence 8/10), merge risk is elevated even though only one issue was identified.
  • Pay close attention to packages/core/lib/v3/agent/tools/goto.ts - ensure exceptions are sanitized/redacted so resolved URL variables and secrets are not returned in error text.
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/core/lib/v3/agent/tools/goto.ts">

<violation number="1" location="packages/core/lib/v3/agent/tools/goto.ts:33">
P1: Custom agent: **Exception and error message sanitization**

goto now substitutes variable values into URL, then returns raw page.goto error messages that can include the resolved URL and leak secret variable values.</violation>
</file>
Architecture diagram
sequenceDiagram
    participant Agent as Agent / LLM
    participant Tool as gotoTool
    participant Vars as Variable Utility
    participant Page as Playwright/Page
    participant Cache as AgentCache

    Note over Agent, Cache: Live Execution Flow

    Agent->>Tool: execute({ url: "https://%env%/home" })
    
    Tool->>Vars: NEW: substituteVariables(url, variables)
    Vars-->>Tool: "https://prod.com/home"
    
    Tool->>Page: CHANGED: goto("https://prod.com/home")
    
    Tool->>Cache: CHANGED: recordAgentReplayStep({ url: "https://%env%/home" })
    Note right of Tool: Stores original template for portability

    Note over Agent, Cache: Replay Execution Flow (AgentCache)

    Cache->>Cache: Retrieve cached step
    
    alt step.type == "goto"
        Cache->>Vars: NEW: substituteVariables(step.url, variables)
        Vars-->>Cache: "https://prod.com/home"
        
        Cache->>Page: CHANGED: goto("https://prod.com/home")
    end

    Note over Agent, Page: V4 API Additions (Non-Agent)
    
    participant API as V4 Click API
    API->>Page: NEW: click(selector, { expectNavigation, expectPopup, expectDownload })
Loading

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

const resolvedUrl = substituteVariables(url, variables);
const page = await v3.context.awaitActivePage();
await page.goto(url, { waitUntil: "load" });
await page.goto(resolvedUrl, { waitUntil: "load" });
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Apr 26, 2026

Choose a reason for hiding this comment

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

P1: Custom agent: Exception and error message sanitization

goto now substitutes variable values into URL, then returns raw page.goto error messages that can include the resolved URL and leak secret variable values.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/core/lib/v3/agent/tools/goto.ts, line 33:

<comment>goto now substitutes variable values into URL, then returns raw page.goto error messages that can include the resolved URL and leak secret variable values.</comment>

<file context>
@@ -21,12 +28,14 @@ export const gotoTool = (v3: V3) =>
+        const resolvedUrl = substituteVariables(url, variables);
         const page = await v3.context.awaitActivePage();
-        await page.goto(url, { waitUntil: "load" });
+        await page.goto(resolvedUrl, { waitUntil: "load" });
         v3.recordAgentReplayStep({ type: "goto", url, waitUntil: "load" });
         return { success: true, url };
</file context>
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external-contributor:awaiting-approval Waiting for a stagehand team member to approve the latest external commit. external-contributor Tracks PRs mirrored from external contributor forks.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

core(cache): apply %variables% substitution to goto tool + replay

1 participant