fix(talk): use truncateUtf16Safe for LLM-prompt-facing text truncation#102477
Conversation
fast-context-runtime.ts normalizeSnippet and heartbeat-events-filter.ts buildExecEventPrompt used raw .slice(0, N), which can produce lone surrogates when truncation boundaries cross emoji surrogate pairs.
|
Codex review: needs real behavior proof before merge. Reviewed July 9, 2026, 3:32 AM ET / 07:32 UTC. Summary PR surface: Source +1, Tests +40. Total +41 across 2 files. Reproducibility: yes. for source-level reproduction: current main still uses raw UTF-16 Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land the narrow Talk fast-context helper substitution after the contributor adds corrected redacted terminal or live output that calls the actual prompt path; keep the heartbeat fix from #102483 on main. Do we have a high-confidence way to reproduce the issue? Yes for source-level reproduction: current main still uses raw UTF-16 Is this the best way to solve the issue? Yes for the code shape: using the existing AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against c3d567db95d0. Label changesLabel justifications:
Evidence reviewedPR surface: Source +1, Tests +40. Total +41 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
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
Land-ready at exact head Review improvements:
Proof:
No known proof gaps. |
|
Merged via squash.
|
Replace unsafe .slice() with truncateUtf16Safe to avoid splitting emoji surrogate pairs when truncating memory/session snippets for realtime voice prompts. This fixes the same issue as PR openclaw#102477 but in the fast-context runtime path.
Replace raw .slice(0, maxLength) with truncateUtf16Safe to prevent emoji surrogate pair truncation issues in assistant identity values. The coerceIdentityValue function is used to truncate assistant name, avatar, and emoji values. When these values contain emoji at the truncation boundary, the old implementation could produce lone surrogates (invalid UTF-16 text). This fix follows the same pattern as PR openclaw#102477 which addressed similar issues in talk/fast-context-runtime.ts and infra/heartbeat-events-filter.ts.
Replace raw .slice(0, maxLength) with truncateUtf16Safe to prevent emoji surrogate pair truncation issues in assistant identity values. The coerceIdentityValue function is used to truncate assistant name, avatar, and emoji values. When these values contain emoji at the truncation boundary, the old implementation could produce lone surrogates (invalid UTF-16 text). This fix follows the same pattern as PR openclaw#102477 which addressed similar issues in talk/fast-context-runtime.ts and infra/heartbeat-events-filter.ts.
Replace raw .slice(0, maxLength) with truncateUtf16Safe to prevent emoji surrogate pair truncation issues in assistant identity values. The coerceIdentityValue function is used to truncate assistant name, avatar, and emoji values. When these values contain emoji at the truncation boundary, the old implementation could produce lone surrogates (invalid UTF-16 text). This fix follows the same pattern as PR openclaw#102477 which addressed similar issues in talk/fast-context-runtime.ts and infra/heartbeat-events-filter.ts.
Replace raw .slice(0, maxLength) with truncateUtf16Safe to prevent emoji surrogate pair truncation issues in assistant identity values. The coerceIdentityValue function is used to truncate assistant name, avatar, and emoji values. When these values contain emoji at the truncation boundary, the old implementation could produce lone surrogates (invalid UTF-16 text). This fix follows the same pattern as PR openclaw#102477 which addressed similar issues in talk/fast-context-runtime.ts and infra/heartbeat-events-filter.ts.
Replace raw .slice(0, maxLength) with truncateUtf16Safe to prevent emoji surrogate pair truncation issues in assistant identity values. The coerceIdentityValue function is used to truncate assistant name, avatar, and emoji values. When these values contain emoji at the truncation boundary, the old implementation could produce lone surrogates (invalid UTF-16 text). This fix follows the same pattern as PR openclaw#102477 which addressed similar issues in talk/fast-context-runtime.ts and infra/heartbeat-events-filter.ts.
openclaw#102477) * fix(talk): use truncateUtf16Safe for snippet text truncation fast-context-runtime.ts normalizeSnippet and heartbeat-events-filter.ts buildExecEventPrompt used raw .slice(0, N), which can produce lone surrogates when truncation boundaries cross emoji surrogate pairs. * test(talk): cover UTF-16 snippet boundary --------- Co-authored-by: hailory <[email protected]> Co-authored-by: Peter Steinberger <[email protected]> Co-authored-by: Peter Steinberger <[email protected]>
What Problem This Solves
Two LLM-prompt-facing text truncation sites use raw UTF-16
.slice(0, N), which can produce lone surrogates when truncation boundaries cross emoji surrogate pairs.Why This Change Was Made
Replace raw
slicewith the canonicaltruncateUtf16Safehelper:src/talk/fast-context-runtime.ts—normalizeSnippettruncates memory snippets at 700 chars for realtime response promptssrc/infra/heartbeat-events-filter.ts—buildExecEventPrompttruncates command output at 8000 chars for LLM promptsUser Impact
None for typical text. Memory snippets or command output that happen to contain emoji at the truncation boundary may previously have produced malformed text in the LLM prompt.
Real Behavior Proof
slice(0, N)produces lone surrogate0xDE80;truncateUtf16Safedrops the preceding high surrogate and produces valid text.