[fix]: support <frame> elements in XPath frame detection#1697
Merged
seanmcguire12 merged 3 commits intomainfrom Feb 22, 2026
Merged
[fix]: support <frame> elements in XPath frame detection#1697seanmcguire12 merged 3 commits intomainfrom
seanmcguire12 merged 3 commits intomainfrom
Conversation
🦋 Changeset detectedLatest commit: 4d09b02 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Contributor
There was a problem hiding this comment.
No issues found across 3 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Architecture diagram
sequenceDiagram
participant Agent as Stagehand Agent
participant DL as DeepLocator
participant FS as focusSelectors (Utils)
participant Browser as Browser/DOM Context
Note over Agent,Browser: Cross-Frame Element Resolution Flow
Agent->>DL: act/observe(selector/xpath)
DL->>FS: parseXPathToSteps(xpath)
FS-->>DL: Array of Steps (e.g. html, frameset, frame[4], body)
loop For each XPath Step
DL->>DL: CHANGED: Match step name against shared IFRAME_STEP_RE
alt Step matches /^i?frame(?:\[\d+])?$/i
Note over DL: NEW: Now matches legacy <frame> <br/>in addition to <iframe>
DL->>Browser: Resolve FrameLocator for boundary
Browser-->>DL: New Frame Context
else Step is standard element (e.g. div, frameset, body)
DL->>Browser: Continue path resolution in current context
end
end
alt Element Found
DL-->>Agent: Return ElementHandle
else Frame Detection Failed (Old behavior for <frame>)
DL-->>Agent: Throw StagehandInvalidArgumentError
end
Contributor
Greptile SummaryFixed frame detection regex to support legacy
Confidence Score: 5/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[XPath with frame elements] --> B[parseXPathToSteps]
B --> C{For each step}
C --> D[Extract name by removing index]
D --> E{Test with IFRAME_STEP_RE}
E -->|Matches iframe or iframe N| F[Detected as frame boundary]
E -->|Matches frame or frame N - NEW| F
E -->|Does not match frameset or other| G[Regular element]
F --> H[Navigate into child frame]
G --> J[Add to current frame buffer]
H --> K[Continue parsing in child frame]
J --> K
Last reviewed commit: 80d56e3 |
3d50339 to
c33f3c5
Compare
IFRAME_STEP_RE only matched "iframe" steps, causing act() to fail on legacy <frameset> pages where observe() returns XPaths with "frame[N]". Changed regex to /^i?frame(?:\[\d+])?$/i and consolidated the duplicate constant into a single shared export. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
c33f3c5 to
4d09b02
Compare
seanmcguire12
approved these changes
Feb 22, 2026
Kylejeong2
approved these changes
Feb 22, 2026
This was referenced Feb 22, 2026
Merged
miguelg719
pushed a commit
that referenced
this pull request
Feb 24, 2026
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## @browserbasehq/stagehand@3.1.0 ### Minor Changes - [#1681](#1681) [`e3db9aa`](e3db9aa) Thanks [@tkattkat](https://github.com/tkattkat)! - Add cookie management APIs: `context.addCookies()`, `context.clearCookies()`, & `context.cookies()` - [#1672](#1672) [`b65756e`](b65756e) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add boolean keepAlive parameter to allow for configuring whether the browser should be closed when stagehand.close() is called. - [#1708](#1708) [`176d420`](176d420) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add context.setExtraHTTPHeaders() - [#1611](#1611) [`8a3c066`](8a3c066) Thanks [@monadoid](https://github.com/monadoid)! - Using `mode` enum instead of old `cua` boolean in openapi spec ### Patch Changes - [#1683](#1683) [`7584f3e`](7584f3e) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - fix: include shadow DOM in .count() & .nth() & support xpath predicates - [#1644](#1644) [`1e1c9c1`](1e1c9c1) Thanks [@monadoid](https://github.com/monadoid)! - Fix unhandled CDP detaches by returning the original sendCDP promise - [#1729](#1729) [`6bef890`](6bef890) Thanks [@shrey150](https://github.com/shrey150)! - fix: support Claude 4.6 (Opus and Sonnet) in CUA mode by using the correct `computer_20251124` tool version and `computer-use-2025-11-24` beta header - [#1647](#1647) [`ffd4b33`](ffd4b33) Thanks [@tkattkat](https://github.com/tkattkat)! - Fix [Agent] - Address bug causing issues with continuing a conversation from past messages in dom mode - [#1614](#1614) [`677bff5`](677bff5) Thanks [@miguelg719](https://github.com/miguelg719)! - Enforce <number>-<number> regex validation on act/observe for elementId - [#1580](#1580) [`65ff464`](65ff464) Thanks [@tkattkat](https://github.com/tkattkat)! - Add unified variables support across act and agent with a single VariableValue type - [#1666](#1666) [`101bcf2`](101bcf2) Thanks [@Kylejeong2](https://github.com/Kylejeong2)! - add support for codex models - [#1728](#1728) [`0a94301`](0a94301) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - handle potential race condition on `.close()` when using the Stagehand API - [#1664](#1664) [`b27c04d`](b27c04d) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - fixes issue with context.addInitScript() where scripts were not being applied to out of process iframes (OOPIFs), and popup pages with same process iframes (SPIFs) - [#1632](#1632) [`afbd08b`](afbd08b) Thanks [@pirate](https://github.com/pirate)! - Remove automatic `.env` loading via `dotenv`. If your app relies on `.env` files, install `dotenv` and load it explicitly in your code: ```ts import dotenv from "dotenv"; dotenv.config({ path: ".env" }); ``` - [#1624](#1624) [`0e8d569`](0e8d569) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - fix issue where screenshot masks were not being applied to dialog elements - [#1596](#1596) [`ff0f979`](ff0f979) Thanks [@tkattkat](https://github.com/tkattkat)! - Update usage/metrics handling in agent - [#1631](#1631) [`2d89d2b`](2d89d2b) Thanks [@miguelg719](https://github.com/miguelg719)! - Add right and middle click support to act and observe - [#1697](#1697) [`aac9a19`](aac9a19) Thanks [@shrey150](https://github.com/shrey150)! - fix: support `<frame>` elements in XPath frame boundary detection so `act()` works on legacy `<frameset>` pages - [#1692](#1692) [`06de50f`](06de50f) Thanks [@shrey150](https://github.com/shrey150)! - fix: skip piercer injection for chrome-extension:// and other non-HTML targets - [#1613](#1613) [`aa4d981`](aa4d981) Thanks [@miguelg719](https://github.com/miguelg719)! - SupportedUnderstudyAction Enum validation for 'method' on act/observe inference - [#1652](#1652) [`18b1e3b`](18b1e3b) Thanks [@miguelg719](https://github.com/miguelg719)! - Add support for gemini 3 flash and pro in hybrid/cua agent - [#1706](#1706) [`957d82b`](957d82b) Thanks [@chrisreadsf](https://github.com/chrisreadsf)! - Add GLM to prompt-based JSON fallback for models without native structured output support - [#1633](#1633) [`22e371a`](22e371a) Thanks [@tkattkat](https://github.com/tkattkat)! - Add warning when incorrect models are used with agents hybrid mode - [#1673](#1673) [`d29b91f`](d29b91f) Thanks [@miguelg719](https://github.com/miguelg719)! - Add multi-region support for Stagehand API with region-specific endpoints - [#1695](#1695) [`7b4f817`](7b4f817) Thanks [@tkattkat](https://github.com/tkattkat)! - Fix: zod bug when pinning zod to v3 and using structured output in agent - [#1609](#1609) [`3f9ca4d`](3f9ca4d) Thanks [@miguelg719](https://github.com/miguelg719)! - Add SupportedUnderstudyActions to observe system prompt - [#1581](#1581) [`49ead1e`](49ead1e) Thanks [@sameelarif](https://github.com/sameelarif)! - **Server-side caching is now available.** When running `env: "BROWSERBASE"`, Stagehand automatically caches `act()`, `extract()`, and `observe()` results server-side — repeated calls with the same inputs return instantly without consuming LLM tokens. Caching is enabled by default and can be disabled via `serverCache: false` on the Stagehand instance or per individual call. Check out the [browserbase blog](https://www.browserbase.com/blog/stagehand-caching) for more details. - [#1642](#1642) [`3673369`](3673369) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - fix issue where scripts added via context.addInitScripts() were not being injected into new pages that were opened via popups (eg, clicking a link that opens a new page) and/or calling context.newPage(url) - [#1735](#1735) [`c465e87`](c465e87) Thanks [@monadoid](https://github.com/monadoid)! - Supports request header authentication with connectToMCPServer - [#1705](#1705) [`ae533e4`](ae533e4) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - include error cause in UnderstudyCommandException - [#1636](#1636) [`ea33052`](ea33052) Thanks [@miguelg719](https://github.com/miguelg719)! - Include executionModel on the AgentConfigSchema - [#1679](#1679) [`5764ede`](5764ede) Thanks [@shrey150](https://github.com/shrey150)! - fix issue where locator.count() was not working with xpaths that have attribute predicates - [#1646](#1646) [`f09b184`](f09b184) Thanks [@miguelg719](https://github.com/miguelg719)! - Add user-agent to CDP connections - [#1637](#1637) [`a7d29de`](a7d29de) Thanks [@miguelg719](https://github.com/miguelg719)! - Improve error and warning message for legacy model format - [#1685](#1685) [`d334399`](d334399) Thanks [@tkattkat](https://github.com/tkattkat)! - Bump ai sdk & google provider version - [#1662](#1662) [`44416da`](44416da) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - fix issue where locator.fill() was not working on elements that require direct value setting - [#1612](#1612) [`bdd8b4e`](bdd8b4e) Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - fix issue where screenshot mask was only being applied to the first element that the locator resolved to. masks now apply to all matching elements. ## @browserbasehq/stagehand-server@3.6.0 ### Minor Changes - [#1611](#1611) [`8a3c066`](8a3c066) Thanks [@monadoid](https://github.com/monadoid)! - Using `mode` enum instead of old `cua` boolean in openapi spec ### Patch Changes - [#1604](#1604) [`4753078`](4753078) Thanks [@miguelg719](https://github.com/miguelg719)! - Enable bedrock - [#1636](#1636) [`ea33052`](ea33052) Thanks [@miguelg719](https://github.com/miguelg719)! - Include executionModel on the AgentConfigSchema - [#1602](#1602) [`22a0502`](22a0502) Thanks [@miguelg719](https://github.com/miguelg719)! - Include vertex as a supported provider - Updated dependencies \[[`7584f3e`](7584f3e), [`1e1c9c1`](1e1c9c1), [`6bef890`](6bef890), [`ffd4b33`](ffd4b33), [`677bff5`](677bff5), [`65ff464`](65ff464), [`101bcf2`](101bcf2), [`0a94301`](0a94301), [`b27c04d`](b27c04d), [`afbd08b`](afbd08b), [`e3db9aa`](e3db9aa), [`0e8d569`](0e8d569), [`ff0f979`](ff0f979), [`2d89d2b`](2d89d2b), [`aac9a19`](aac9a19), [`06de50f`](06de50f), [`aa4d981`](aa4d981), [`18b1e3b`](18b1e3b), [`957d82b`](957d82b), [`b65756e`](b65756e), [`22e371a`](22e371a), [`d29b91f`](d29b91f), [`7b4f817`](7b4f817), [`176d420`](176d420), [`3f9ca4d`](3f9ca4d), [`8a3c066`](8a3c066), [`49ead1e`](49ead1e), [`3673369`](3673369), [`c465e87`](c465e87), [`ae533e4`](ae533e4), [`ea33052`](ea33052), [`5764ede`](5764ede), [`f09b184`](f09b184), [`a7d29de`](a7d29de), [`d334399`](d334399), [`44416da`](44416da), [`bdd8b4e`](bdd8b4e)]: - @browserbasehq/stagehand@3.1.0 ## @browserbasehq/stagehand-evals@1.1.8 ### Patch Changes - Updated dependencies \[[`7584f3e`](7584f3e), [`1e1c9c1`](1e1c9c1), [`6bef890`](6bef890), [`ffd4b33`](ffd4b33), [`677bff5`](677bff5), [`65ff464`](65ff464), [`101bcf2`](101bcf2), [`0a94301`](0a94301), [`b27c04d`](b27c04d), [`afbd08b`](afbd08b), [`e3db9aa`](e3db9aa), [`0e8d569`](0e8d569), [`ff0f979`](ff0f979), [`2d89d2b`](2d89d2b), [`aac9a19`](aac9a19), [`06de50f`](06de50f), [`aa4d981`](aa4d981), [`18b1e3b`](18b1e3b), [`957d82b`](957d82b), [`b65756e`](b65756e), [`22e371a`](22e371a), [`d29b91f`](d29b91f), [`7b4f817`](7b4f817), [`176d420`](176d420), [`3f9ca4d`](3f9ca4d), [`8a3c066`](8a3c066), [`49ead1e`](49ead1e), [`3673369`](3673369), [`c465e87`](c465e87), [`ae533e4`](ae533e4), [`ea33052`](ea33052), [`5764ede`](5764ede), [`f09b184`](f09b184), [`a7d29de`](a7d29de), [`d334399`](d334399), [`44416da`](44416da), [`bdd8b4e`](bdd8b4e)]: - @browserbasehq/stagehand@3.1.0 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
IFRAME_STEP_REregex only matchediframesteps, causingact()to fail on legacy<frameset>pages whereobserve()returns XPaths containingframe[N](e.g./html[1]/frameset[1]/frame[4]/html[1]/body[1]/...)/^iframe(?:\[\d+])?$/ito/^i?frame(?:\[\d+])?$/iso both<iframe>and<frame>are recognized as frame boundariesIFRAME_STEP_REconstant (was defined in bothdeepLocator.tsandfocusSelectors.ts) into a single shared exportTest plan
frame,frame[4],FRAME— all pass with fixsnapshot-focus-selectors-utils.test.tscovering:iframe,iframe[N],frame,frame[N](case-insensitive)frameset,frameset[N],div,body,htmlframesetis not false-positive detected as a frame boundary🤖 Generated with Claude Code
Summary by cubic
Adds support for in XPath frame boundary detection so navigation works on legacy pages. iframe and frame steps are treated as frame boundaries.
Bug Fixes
Refactors
Written for commit 4d09b02. Summary will update on new commits. Review in cubic