fix(agents): keep tool-result context guard truncation UTF-16 safe#102466
Conversation
Replace the raw text.slice(0, cutPoint) in truncateTextToBudget with truncateUtf16Safe so oversized tool results do not emit lone surrogates when an emoji falls on the truncation boundary. Adds a regression test that places an emoji exactly at the legacy cut point and asserts the truncated output contains no lone surrogates. Co-Authored-By: Claude Opus 4.8 <[email protected]>
|
Codex review: needs real behavior proof before merge. Reviewed July 9, 2026, 2:55 AM ET / 06:55 UTC. Summary PR surface: Source +1, Tests +20. Total +21 across 2 files. Reproducibility: yes. source-level reproduction is high confidence: current main's private truncation helper can cut the PR's emoji-boundary input into a lone high surrogate. I did not run the full OpenClaw agent loop because this review was read-only. 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 UTF-16-safe context-guard fix after real behavior proof is added or a maintainer explicitly accepts the proof gap; keep the sibling truncation helper path unchanged. Do we have a high-confidence way to reproduce the issue? Yes, source-level reproduction is high confidence: current main's private truncation helper can cut the PR's emoji-boundary input into a lone high surrogate. I did not run the full OpenClaw agent loop because this review was read-only. Is this the best way to solve the issue? Yes, the proposed code is the best narrow fix: it uses the existing shared UTF-16-safe helper at the exact raw slice site and computes the notice from the actual retained prefix. The remaining issue is proof quality, not fix shape. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against b20b02a47633. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +1, Tests +20. Total +21 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
|
|
Land-ready maintainer pass complete at exact head The original UTF-16 fix was useful. I improved it by deriving the truncation notice from the actual surrogate-safe prefix (the prior version undercounted omitted code units by one when it backed up) and replacing a verbose test scanner with an exact provider-context assertion. Proof:
The focused test ran locally because fork-contributor code is not eligible for credential-hydrated Testbox execution before landing review. Exact-head fork CI supplies the broad hosted proof. No remaining proof gap. |
|
Merged via squash.
|
…penclaw#102466) * fix(agents): keep tool-result context guard truncation UTF-16 safe Replace the raw text.slice(0, cutPoint) in truncateTextToBudget with truncateUtf16Safe so oversized tool results do not emit lone surrogates when an emoji falls on the truncation boundary. Adds a regression test that places an emoji exactly at the legacy cut point and asserts the truncated output contains no lone surrogates. Co-Authored-By: Claude Opus 4.8 <[email protected]> * fix(agents): report surrogate-safe omitted count --------- Co-authored-by: chengzhichao-xydt <[email protected]> Co-authored-by: Claude Opus 4.8 <[email protected]> Co-authored-by: Peter Steinberger <[email protected]>
What Problem This Solves
truncateTextToBudgetcould split an emoji or another supplementary Unicode character when the tool-result context budget ended inside its UTF-16 surrogate pair. The resulting provider context contained a lone surrogate. The truncation notice could also undercount omitted code units if a safe boundary backed up by one.Why This Change Was Made
The context guard now truncates through the shared
truncateUtf16Safeprimitive and computes the notice from the actual retained prefix length. This keeps both the serialized text and its omitted-character count accurate without changing the existing context-budget policy.The focused regression asserts the exact provider-facing output, including the safe prefix and the corrected omitted count, and confirms the original live tool result remains unchanged.
User Impact
Oversized tool results containing emoji no longer inject malformed UTF-16 into provider replay context, and their truncation notices report the actual number of omitted UTF-16 code units.
Evidence
686f644a7c3844056f5b4327d5021986436a7180node scripts/run-vitest.mjs src/agents/embedded-agent-runner/tool-result-context-guard.test.ts— 1 file, 46 tests passed.git diff --checkpassed.0.98).Local narrow test fallback was used because fork-contributor code is not eligible for credential-hydrated Testbox execution before landing review.
AI-assisted; maintainer-reviewed.