fix(export): prevent broken emoji in HTML tool call previews#104054
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 19, 2026, 4:47 AM ET / 08:47 UTC. Summary PR surface: Source +5, Tests +92. Total +97 across 2 files. Reproducibility: yes. from source inspection: the production export template slices preview strings at UTF-16 code-unit boundaries, so an emoji placed across the boundary leaves an unpaired surrogate; the reported production export and Chromium proof show the corrected path. Review metrics: none identified. Stored data model Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Merge the focused local canonical-equivalent helper and regression coverage through the exact-head automerge gates, preserving existing preview limits and ellipsis behavior. Do we have a high-confidence way to reproduce the issue? Yes from source inspection: the production export template slices preview strings at UTF-16 code-unit boundaries, so an emoji placed across the boundary leaves an unpaired surrogate; the reported production export and Chromium proof show the corrected path. Is this the best way to solve the issue? Yes. A small local helper that matches the canonical UTF-16 boundary algorithm is the narrowest maintainable fix because the standalone browser asset cannot directly import the TypeScript helper. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 2e8b042f9fba. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +5, Tests +92. Total +97 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (11 earlier review cycles; latest 8 shown)
|
|
A/B verified locally against base SHA. Ran vitest with the PR's test file against the PR's fix (B) and against the base's fix (A). Result: CLEAN A/B The new test |
d7205d8 to
4b72ae3
Compare
|
@clawsweeper automerge |
|
🦞🧹
Draft PRs stay fix-only until GitHub marks them ready for review. Pause with Automerge progress:
Re-review progress:
|
|
@clawsweeper automerge |
|
@clawsweeper automerge |
|
@clawsweeper automerge |
|
@clawsweeper automerge Retry the exact current head 4b72ae3 after ClawSweeper main merged openclaw/clawsweeper#670, #671, and #672. Keep the existing fail-closed validation boundaries and use the production automerge path. |
|
@clawsweeper automerge Retry the exact current head 4b72ae3 after openclaw/clawsweeper#679 merged. Use the production direct-behind path, preserve exact-head/check/review gates, and do not rewrite the contributor branch solely for base drift. |
|
@clawsweeper re-review Refresh the exact-head verdict after openclaw/clawsweeper#679 landed. Automerge is already enabled; preserve the current head and let the trusted exact-head verdict resume the production direct-behind path. |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
🦞✅ Source: Why human review is needed: What the maintainer can do as a next step: I added |
|
@clawsweeper automerge Resume the exact current head after openclaw/clawsweeper#680 landed. |
|
@clawsweeper approve |
|
@clawsweeper automerge |
|
@clawsweeper automerge Resume the exact current head after openclaw/clawsweeper#702 merged. If the protected merge gate reports the head behind base, route it through the existing cloud rebase repair lane; preserve all exact-head review, CAS, immutable-ledger, and merge safety gates. |
|
Merged via squash.
|
Additional instructions
MUST: Keep Allow edits from maintainers enabled for this PR so maintainers
can help update the branch when needed.
What Problem This Solves
Fixes an issue where users exporting a session to HTML could see a broken replacement glyph in compact tool-call previews when a bash command or serialized tool argument was truncated through an emoji.
The corrupted preview was written into the standalone HTML artifact, so it remained visible when the export was saved or shared.
Why This Change Was Made
The standalone viewer truncated compact sidebar strings at raw UTF-16 code-unit boundaries. The change uses one surrogate-safe helper for the 50-code-unit assistant bash preview, the 40-code-unit generic argument preview, and the shared sidebar truncation path used by persisted
bashExecutionrecords. It preserves the existing limits and ellipsis behavior while dropping a boundary surrogate half instead of emitting invalid text.This is a root-cause, display-layer fix. It does not alter the stored transcript, embedded session data, full tool-call rendering, model input, schema, configuration, or wire format.
User Impact
Exported HTML transcripts now show stable compact tool labels when long commands or arguments contain emoji at a truncation boundary. Existing ASCII previews and their length limits remain unchanged.
Evidence
After resolving the current-main conflict, the complete export template test file passes:
Fresh end-to-end proof used the built production
/export-sessioncommand handler with an isolated canonical SQLite session store and five transcript entries. It wrote a 362,241-byte standalone HTML file inside the agent workspace, opened it in Chromium, and asserted the rendered sidebar labels:A 764,811-byte full-page screenshot was captured during the same browser run. Additional fresh checks passed:
node scripts/run-oxlint.mjson the two changed filesgit diff --checkon the two changed filespnpm build, including the export HTML asset copy step