fix (tui): sanitize binary-heavy history text before render

This commit is contained in:
Vignesh Natarajan
2026-02-14 18:29:12 -08:00
parent 914b9d1e79
commit 750a7146e4
3 changed files with 81 additions and 9 deletions

View File

@@ -4,6 +4,7 @@ import {
extractTextFromMessage,
extractThinkingFromMessage,
isCommandMessage,
sanitizeRenderableText,
} from "./tui-formatters.js";
describe("extractTextFromMessage", () => {
@@ -58,6 +59,24 @@ describe("extractTextFromMessage", () => {
expect(text).toBe("[thinking]\nponder\n\nhello");
});
it("sanitizes ANSI and control chars from string content", () => {
const text = extractTextFromMessage({
role: "assistant",
content: "Hello\x1b[31m red\x1b[0m\x00world",
});
expect(text).toBe("Hello redworld");
});
it("redacts heavily corrupted binary-like lines", () => {
const text = extractTextFromMessage({
role: "assistant",
content: [{ type: "text", text: "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>" }],
});
expect(text).toBe("[binary data omitted]");
});
});
describe("extractThinkingFromMessage", () => {
@@ -106,3 +125,13 @@ describe("isCommandMessage", () => {
expect(isCommandMessage({})).toBe(false);
});
});
describe("sanitizeRenderableText", () => {
it("breaks very long unbroken tokens to avoid overflow", () => {
const input = "a".repeat(140);
const sanitized = sanitizeRenderableText(input);
const longestSegment = Math.max(...sanitized.split(/\s+/).map((segment) => segment.length));
expect(longestSegment).toBeLessThanOrEqual(64);
});
});