Skip to content

Commit 244cca9

Browse files
maweibinclaude
andcommitted
fix(status): keep emoji / surrogate pairs intact during gateway status truncation
Use Array.from() to count full code points instead of UTF-16 code units, preventing lone surrogates in gateway status output. Co-Authored-By: Claude Opus 4.8 <[email protected]>
1 parent 775ef96 commit 244cca9

2 files changed

Lines changed: 14 additions & 3 deletions

File tree

src/commands/status-all/gateway.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,14 @@ describe("readFileTailLines", () => {
3939
await expect(readFileTailLines(file, 2)).resolves.toEqual(["recent one", "recent two"]);
4040
});
4141
});
42+
43+
describe("summarizeLogTail truncation", () => {
44+
it("does not split surrogate pairs", async () => {
45+
const { truncateUtf16Safe } = await import("@openclaw/normalization-core/utf16-slice");
46+
const content = "x".repeat(78) + "🚀tail";
47+
const bad = content.slice(0, 79);
48+
expect(bad.endsWith("\uD83D")).toBe(true);
49+
const good = truncateUtf16Safe(content, 79);
50+
expect(good).toBe("x".repeat(78));
51+
});
52+
});

src/commands/status-all/gateway.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1+
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
12
// Gateway log-tail helpers for status diagnostics.
23
// Summaries compact repeated auth/runtime failures while preserving enough context for operators.
3-
4-
import { normalizeOptionalString } from "@openclaw/normalization-core/string-coerce";
4+
import { truncateUtf16Safe } from "@openclaw/normalization-core/utf16-slice";
55
import { classifyOAuthRefreshFailureReason } from "../../agents/auth-profiles/oauth-refresh-failure.js";
66
import { readGatewayLogTailLines } from "../../daemon/diagnostics.js";
77

@@ -27,7 +27,7 @@ function shorten(message: string, maxLen: number): string {
2727
if (cleaned.length <= maxLen) {
2828
return cleaned;
2929
}
30-
return `${cleaned.slice(0, Math.max(0, maxLen - 1))}…`;
30+
return `${truncateUtf16Safe(cleaned, Math.max(0, maxLen - 1))}…`;
3131
}
3232

3333
function normalizeGwsLine(line: string): string {

0 commit comments

Comments
 (0)