Skip to content

harness: never cut a surrogate pair when truncating tool-result previews - #150

Open
Alexsun1one wants to merge 1 commit into
exoharness:mainfrom
Alexsun1one:surrogate-safe-truncation
Open

harness: never cut a surrogate pair when truncating tool-result previews#150
Alexsun1one wants to merge 1 commit into
exoharness:mainfrom
Alexsun1one:surrogate-safe-truncation

Conversation

@Alexsun1one

Copy link
Copy Markdown
Contributor

Problem

previewText truncates tool-result previews with a plain .slice(0, TOOL_RESULT_PREVIEW_CHARS), which cuts by UTF-16 code units. When an emoji (or any astral character) straddles the 4000-char boundary, the slice keeps only the high surrogate. The lone surrogate serializes as an unpaired \ud8xx escape, and a strict JSON parser consuming the serialized event downstream rejects the whole message — one emoji at the boundary fails the entire turn.

This is a production repro, not a hypothetical: my agent signs every reply with 🚒🕵️, so its conversation history is full of surrogate pairs. A scheduled task that read that history back through a tool hit the boundary and the turn died with invalid TypeScript harness protocol message ... unexpected end of hex escape.

Fix

After slicing, drop a trailing lone high surrogate before appending the ...[truncated] marker. previewText is exported so the boundary behavior can be unit-tested.

Tests

Four cases in tools.test.ts: short text unchanged, plain truncation, an emoji straddling the boundary (fails on the old code), and a pair that fits entirely inside the boundary staying intact.

Follow-up thought

This fixes the known producer, but as akrentsel noted on Discord, the executor could also tolerate a corrupted/unparseable protocol line more gracefully than failing the turn (skip + log, or surface a structured error event). Happy to take a stab at that separately if there's interest — it touches the Rust side, so I kept it out of this PR.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant