Skip to content

Fix malformed snapshot Unicode - #2345

Merged
monadoid merged 3 commits into
mainfrom
STG-2500
Jul 9, 2026
Merged

monadoid merged 3 commits into
mainfrom
STG-2500

Conversation

@monadoid

@monadoid monadoid commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

why

BYOK/direct provider calls reject when page snapshot text we passed in contained malformed UTF-16. I

what changed

Normalize captured accessibility snapshot strings with toWellFormed() at the snapshot boundary and add unit/integration coverage for lone-surrogate page text.

test plan

Red/greened the new unit and local SDK observe regressions, and the focused unicode-well-formed integration test.


Summary by cubic

Fixes malformed Unicode in accessibility snapshots by normalizing text with String.prototype.toWellFormed() at capture and during frame merge, so both local SDK and provider prompts always get well-formed UTF-16. Adds tests that confirm lone surrogates are repaired to U+FFFD in prompts.

  • Bug Fixes

    • Normalize outline strings during capture and frame merge; per-frame and combined trees are well-formed before prompting.
    • Add integration test asserting U+FFFD appears in the model prompt and a unit test verifying combined tree repair.
  • Dependencies

    • Add changeset to publish a patch for @browserbasehq/stagehand.

Written for commit 143ac0e. Summary will update on new commits.

Review in cubic

@changeset-bot

changeset-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 143ac0e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@browserbasehq/stagehand Patch
@browserbasehq/stagehand-evals Patch
@browserbasehq/stagehand-server-v3 Patch

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

@monadoid
monadoid marked this pull request as ready for review July 9, 2026 20:58

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

Review completed against the latest diff

Confidence score: 5/5

  • Safe to merge after the addressed issues were fixed.

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

Re-trigger cubic

Comment thread packages/core/lib/v3/understudy/a11y/snapshot/capture.ts
@monadoid
monadoid merged commit 21826c7 into main Jul 9, 2026
250 checks passed
seanmcguire12 pushed a commit that referenced this pull request Jul 13, 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.7.0

### Minor Changes

- [#2283](#2283)
[`871ca7e`](871ca7e)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add
`context.setDomainPolicy({ allowedDomains: ["allowed.domain"] })` which
allows users to define a set of domains that are accessible to stagehand

- [#2274](#2274)
[`f31980f`](f31980f)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add
`context.setDomainPolicy({blockedDomains: ["some.domain"]})` which
allows users to define a list of domains that will be blocked by
stagehand

### Patch Changes

- [#2305](#2305)
[`cd1daad`](cd1daad)
Thanks [@shrey150](https://github.com/shrey150)! - Remove the noisy AI
SDK "system message in messages" warning logged on every hybrid/DOM
`agent.execute()` call.

- [#2328](#2328)
[`d287ff4`](d287ff4)
Thanks [@miguelg719](https://github.com/miguelg719)! - Allow modelName
"auto" in the constructor and per-primitive model overrides when running
through the Stagehand API

- [#2294](#2294)
[`3938590`](3938590)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! -
automatically close popups that violate user defined domain policy

- [#2298](#2298)
[`892701a`](892701a)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Fix CUA
`keypress` actions to press key combinations as a single chord.

- [#2345](#2345)
[`21826c7`](21826c7)
Thanks [@monadoid](https://github.com/monadoid)! - Repair malformed
UTF-16 snapshot text before it reaches model prompts.

- [#2306](#2306)
[`8dcef1b`](8dcef1b)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Use the
screenshot provider's declared media type when sending CUA image
payloads. The `setScreenshotProvider` callback now returns
`ScreenshotProviderResult` (`{ base64, mediaType }`) instead of a bare
base64 string.

- [#2273](#2273)
[`93a23d3`](93a23d3)
Thanks [@miguelg719](https://github.com/miguelg719)! - Add support for
the new `google/gemini-3.5-flash` computer-use tools model

- [#2278](#2278)
[`022d68f`](022d68f)
Thanks [@shrey150](https://github.com/shrey150)! - Fix `TypeError:
Converting circular structure to JSON` when creating an agent with MCP
`integrations` that include a `Client` instance (e.g. a local/stdio
server from `connectToMCPServer`). The agent-creation log serialized the
raw `integrations` array, and a live MCP `Client` is circular. It now
logs a safe descriptor (URL strings kept, client instances summarized)
so `agent({ integrations: [client] })` works.

- [#2288](#2288)
[`bb5ffa6`](bb5ffa6)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - clean up
cdp session event handlers on target detach

## @browserbasehq/stagehand-evals@2.0.4

### Patch Changes

- Updated dependencies
\[[`cd1daad`](cd1daad),
[`d287ff4`](d287ff4),
[`3938590`](3938590),
[`892701a`](892701a),
[`21826c7`](21826c7),
[`8dcef1b`](8dcef1b),
[`93a23d3`](93a23d3),
[`871ca7e`](871ca7e),
[`022d68f`](022d68f),
[`bb5ffa6`](bb5ffa6),
[`f31980f`](f31980f)]:
    -   @browserbasehq/stagehand@3.7.0

## @browserbasehq/stagehand-server-v3@3.7.2

### Patch Changes

- Updated dependencies
\[[`cd1daad`](cd1daad),
[`d287ff4`](d287ff4),
[`3938590`](3938590),
[`892701a`](892701a),
[`21826c7`](21826c7),
[`8dcef1b`](8dcef1b),
[`93a23d3`](93a23d3),
[`871ca7e`](871ca7e),
[`022d68f`](022d68f),
[`bb5ffa6`](bb5ffa6),
[`f31980f`](f31980f)]:
    -   @browserbasehq/stagehand@3.7.0

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
felipeofdev-ai pushed a commit to felipeofdev-ai/stagehand that referenced this pull request Aug 4, 2026
# why

BYOK/direct provider calls reject when page snapshot text we passed in
contained malformed UTF-16. I

# what changed

Normalize captured accessibility snapshot strings with `toWellFormed()`
at the snapshot boundary and add unit/integration coverage for
lone-surrogate page text.

# test plan

Red/greened the new unit and local SDK observe regressions, and the
focused `unicode-well-formed` integration test.


<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Fixes malformed Unicode in accessibility snapshots by normalizing text
with `String.prototype.toWellFormed()` at capture and during frame
merge, so both local SDK and provider prompts always get well-formed
UTF-16. Adds tests that confirm lone surrogates are repaired to U+FFFD
in prompts.

- **Bug Fixes**
- Normalize outline strings during capture and frame merge; per-frame
and combined trees are well-formed before prompting.
- Add integration test asserting U+FFFD appears in the model prompt and
a unit test verifying combined tree repair.

- **Dependencies**
  - Add changeset to publish a patch for `@browserbasehq/stagehand`.

<sup>Written for commit 143ac0e.
Summary will update on new commits.</sup>

<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2345?utm_source=github"
target="_blank" rel="noopener noreferrer"
data-no-image-dialog="true"><picture><source
media="(prefers-color-scheme: dark)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source
media="(prefers-color-scheme: light)"
srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img
alt="Review in cubic"
src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a>

<!-- End of auto-generated description by cubic. -->

---------
felipeofdev-ai pushed a commit to felipeofdev-ai/stagehand that referenced this pull request Aug 4, 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.7.0

### Minor Changes

- [browserbase#2283](browserbase#2283)
[`871ca7e`](browserbase@871ca7e)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add
`context.setDomainPolicy({ allowedDomains: ["allowed.domain"] })` which
allows users to define a set of domains that are accessible to stagehand

- [browserbase#2274](browserbase#2274)
[`f31980f`](browserbase@f31980f)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - add
`context.setDomainPolicy({blockedDomains: ["some.domain"]})` which
allows users to define a list of domains that will be blocked by
stagehand

### Patch Changes

- [browserbase#2305](browserbase#2305)
[`cd1daad`](browserbase@cd1daad)
Thanks [@shrey150](https://github.com/shrey150)! - Remove the noisy AI
SDK "system message in messages" warning logged on every hybrid/DOM
`agent.execute()` call.

- [browserbase#2328](browserbase#2328)
[`d287ff4`](browserbase@d287ff4)
Thanks [@miguelg719](https://github.com/miguelg719)! - Allow modelName
"auto" in the constructor and per-primitive model overrides when running
through the Stagehand API

- [browserbase#2294](browserbase#2294)
[`3938590`](browserbase@3938590)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! -
automatically close popups that violate user defined domain policy

- [browserbase#2298](browserbase#2298)
[`892701a`](browserbase@892701a)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Fix CUA
`keypress` actions to press key combinations as a single chord.

- [browserbase#2345](browserbase#2345)
[`21826c7`](browserbase@21826c7)
Thanks [@monadoid](https://github.com/monadoid)! - Repair malformed
UTF-16 snapshot text before it reaches model prompts.

- [browserbase#2306](browserbase#2306)
[`8dcef1b`](browserbase@8dcef1b)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - Use the
screenshot provider's declared media type when sending CUA image
payloads. The `setScreenshotProvider` callback now returns
`ScreenshotProviderResult` (`{ base64, mediaType }`) instead of a bare
base64 string.

- [browserbase#2273](browserbase#2273)
[`93a23d3`](browserbase@93a23d3)
Thanks [@miguelg719](https://github.com/miguelg719)! - Add support for
the new `google/gemini-3.5-flash` computer-use tools model

- [browserbase#2278](browserbase#2278)
[`022d68f`](browserbase@022d68f)
Thanks [@shrey150](https://github.com/shrey150)! - Fix `TypeError:
Converting circular structure to JSON` when creating an agent with MCP
`integrations` that include a `Client` instance (e.g. a local/stdio
server from `connectToMCPServer`). The agent-creation log serialized the
raw `integrations` array, and a live MCP `Client` is circular. It now
logs a safe descriptor (URL strings kept, client instances summarized)
so `agent({ integrations: [client] })` works.

- [browserbase#2288](browserbase#2288)
[`bb5ffa6`](browserbase@bb5ffa6)
Thanks [@seanmcguire12](https://github.com/seanmcguire12)! - clean up
cdp session event handlers on target detach

## @browserbasehq/stagehand-evals@2.0.4

### Patch Changes

- Updated dependencies
\[[`cd1daad`](browserbase@cd1daad),
[`d287ff4`](browserbase@d287ff4),
[`3938590`](browserbase@3938590),
[`892701a`](browserbase@892701a),
[`21826c7`](browserbase@21826c7),
[`8dcef1b`](browserbase@8dcef1b),
[`93a23d3`](browserbase@93a23d3),
[`871ca7e`](browserbase@871ca7e),
[`022d68f`](browserbase@022d68f),
[`bb5ffa6`](browserbase@bb5ffa6),
[`f31980f`](browserbase@f31980f)]:
    -   @browserbasehq/stagehand@3.7.0

## @browserbasehq/stagehand-server-v3@3.7.2

### Patch Changes

- Updated dependencies
\[[`cd1daad`](browserbase@cd1daad),
[`d287ff4`](browserbase@d287ff4),
[`3938590`](browserbase@3938590),
[`892701a`](browserbase@892701a),
[`21826c7`](browserbase@21826c7),
[`8dcef1b`](browserbase@8dcef1b),
[`93a23d3`](browserbase@93a23d3),
[`871ca7e`](browserbase@871ca7e),
[`022d68f`](browserbase@022d68f),
[`bb5ffa6`](browserbase@bb5ffa6),
[`f31980f`](browserbase@f31980f)]:
    -   @browserbasehq/stagehand@3.7.0
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