fix(gateway): keep live chat assistant buffer tail truncation UTF-16 safe (#102484)

* fix(gateway): keep live chat assistant buffer tail truncation UTF-16 safe

* test(gateway): cover UTF-16 tail cap through merge path

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
wings1029
2026-07-09 15:37:50 +08:00
committed by GitHub
parent 3b418bdef6
commit e5aefd5656
2 changed files with 13 additions and 1 deletions

View File

@@ -1,3 +1,4 @@
import { sliceUtf16Safe } from "@openclaw/normalization-core/utf16-slice";
// Gateway live chat projector.
// Converts streaming assistant events into display-safe live chat text.
import { stripInternalRuntimeContext } from "../agents/internal-runtime-context.js";
@@ -36,7 +37,7 @@ function capLiveAssistantBuffer(text: string): string {
if (text.length <= MAX_LIVE_CHAT_BUFFER_CHARS) {
return text;
}
return text.slice(-MAX_LIVE_CHAT_BUFFER_CHARS);
return sliceUtf16Safe(text, -MAX_LIVE_CHAT_BUFFER_CHARS);
}
/** Merges assistant full-text and delta events into a capped live buffer. */

View File

@@ -93,4 +93,15 @@ describe("server chat stream text merge", () => {
expect(result).toHaveLength(MAX_LIVE_CHAT_BUFFER_CHARS);
expect(result.endsWith("bbbb")).toBe(true);
});
it("does not start the capped tail with the low half of a surrogate pair", () => {
const safeTail = "y".repeat(MAX_LIVE_CHAT_BUFFER_CHARS - 1);
const result = resolveMergedAssistantText({
previousText: "",
nextText: `x🚀${safeTail}`,
nextDelta: "",
});
expect(result).toBe(safeTail);
});
});