diff --git a/ui/src/lib/session-display.test.ts b/ui/src/lib/session-display.test.ts index 923138fb4fd6..55c4895da137 100644 --- a/ui/src/lib/session-display.test.ts +++ b/ui/src/lib/session-display.test.ts @@ -26,6 +26,12 @@ describe("resolveSessionDisplayName", () => { expect(resolveSessionDisplayName("agent:main:imessage:direct:+4912")).toBe("iMessage · +4912"); }); + it("does not split UTF-16 surrogate pairs when shortening peer ids", () => { + expect(resolveSessionDisplayName("agent:main:telegram:direct:12345😀67890")).toBe( + "Telegram · …67890", + ); + }); + it("falls back to a friendly name for dashboard sessions instead of the uuid key", () => { expect( resolveSessionDisplayName("agent:main:dashboard:0f9d5c1e-6d0f-4c9a-9d84-1c2f3a4b5c6d"), diff --git a/ui/src/lib/session-display.ts b/ui/src/lib/session-display.ts index 58d8dbe8b36c..4d57bd824da6 100644 --- a/ui/src/lib/session-display.ts +++ b/ui/src/lib/session-display.ts @@ -1,4 +1,5 @@ // Control UI module implements session display behavior. +import { sliceUtf16Safe } from "@openclaw/normalization-core/utf16-slice"; import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "./string-coerce.ts"; const CHANNEL_LABELS: Record = { @@ -18,7 +19,7 @@ const KNOWN_CHANNEL_KEYS = Object.keys(CHANNEL_LABELS); /** Raw peer ids stay out of the sidebar; keep a short recognizable tail only. */ function shortenPeerId(identifier: string): string { const trimmed = identifier.trim(); - return trimmed.length <= 10 ? trimmed : `…${trimmed.slice(-6)}`; + return trimmed.length <= 10 ? trimmed : `…${sliceUtf16Safe(trimmed, -6)}`; } // Long hex/uuid runs inside keys and node ids are machine ids, not names;