Repository navigation
fix(server): html_preview no longer splits an emoji in a long console line - #29844
Conversation
… line Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — The change avoids splitting an emoji when truncating long HTML-preview console messages. Existing output limits and browser behavior remain unchanged, keeping the impact narrowly confined to console-text formatting. You can add or adjust custom eligibility rules. Learn more. |
|
No actionable comments were generated in the recent review. Walkthrough
Merge Risk:
|
|
Note Written by Verified in a real dev environmentverified as-is at ran
both servers used Not verifiednative desktop and ios/android clients, macos/windows hosts, other providers, and remote/relay connections were not exercised on this linux vm. the worker's three browser-gated tests were skipped because |


Problem
html_previewreturns the page's console messages to the agent and cuts each one at 500 characters. The cut counts UTF-16 units, so when an emoji sits across character 500, the message keeps only the first half of it: a lone high surrogate. The MCP result then carries that half as a\ud83descape, and strict JSON parsers reject the whole tool response. Rustserde_json, which Codex's and Grok's MCP clients use, fails withunexpected end of hex escape.So if a page logs a long line with emoji in it, such as
console.log(JSON.stringify(data))on a dashboard, the agent's preview call can fail. The agent loses the screenshot and contentHeight, not only the log line.Change
When the last kept unit is a high surrogate, the cut steps back one unit. This is the same guard that #29600 adds to
McpHttpServer.cutTextforpreview_snapshot, and that #29168 and #29633 use for their own cuts. Messages under the cap, and cuts that don't split a pair, come out the same as before.Scope and approval
Very small, focused fix for an obvious bug, so no prior issue: one cut site, 5 non-test lines, using a pattern this repo already uses. Overlap search: the earlier surrogate PRs (#29158, #29163, #29168, #29563, #29572, #29600, #29633, #29647, #29653, #29830) each fix a different cut site. #29600 covers
preview_snapshot, which is the server browser, not thehtml_previewheadless renderer. Open PRs that touchheadlessChrome.ts(#25276, #26570) do not change this line.Verification
HtmlRender.test.ts(the only preview flow that runs in CI) fails withAssertionError: expected false to be trueonisWellFormed().vp test run src/htmlRender/HtmlRender.test.ts, 8 passed and 3 skipped (the real-browser cases needT3CODE_TEST_HEADLESS_SHELL).console.log("x" + "😀".repeat(300))comes back with length 501, ends in"\ude00\ud83d…"and is not well-formed. With the fix it is well-formed.serde_json1.0.154from_stron the JSON-RPC result that main produces givesERR unexpected end of hex escape.vp run check:changed: all pass (format, lint, knip, typecheck, tests).html_preview.Reviewed with sol-loop: 1 round with GPT-6.1 Sol on high. Sol verdict: approved.
Created with Claude Opus 5.5 in Claude Code (T3 Code).
🤖 Generated with Claude Code