From abf20945e70d685be6f3a1cac0f8b131762a8beb Mon Sep 17 00:00:00 2001 From: felixlaga Date: Sat, 7 Nov 2026 17:23:53 +0900 Subject: [PATCH] fix(grok): long command titles no longer end in a broken character Grok tool calls with a generic title fall back to the command, cut to 77 characters. When that cut lands inside an emoji, the row title keeps half of a surrogate pair and shows a replacement character before the "...". The cut now moves back one unit when it would split a pair, like the other title truncations in the repo. Co-Authored-By: Claude Opus 5.5 --- .../provider-grok/src/server/xaiAcpExtension.test.ts | 12 ++++++++++++ packages/provider-grok/src/server/xaiAcpExtension.ts | 5 ++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/provider-grok/src/server/xaiAcpExtension.test.ts b/packages/provider-grok/src/server/xaiAcpExtension.test.ts index 6b9cbf1ed30c6..a74078733d5df 100644 --- a/packages/provider-grok/src/server/xaiAcpExtension.test.ts +++ b/packages/provider-grok/src/server/xaiAcpExtension.test.ts @@ -458,6 +458,18 @@ describe("XAiAcpExtension", () => { const normalized = normalizeXAiAcpToolCallState(toolCall); expect(normalized.status).toBe("completed"); expect(normalized.title).toBe("for i in 1 2; do echo STREAM_$i; done; echo STREAM_DONE"); + expect( + normalizeXAiAcpToolCallState({ + ...toolCall, + data: { + ...toolCall.data, + rawOutput: { + ...toolCall.data.rawOutput, + command: `git commit -m "${"x".repeat(61)}🎉 ship it"`, + }, + }, + }).title, + ).toBe(`git commit -m "${"x".repeat(61)}...`); expect( normalizeXAiAcpToolCallState({ ...toolCall, diff --git a/packages/provider-grok/src/server/xaiAcpExtension.ts b/packages/provider-grok/src/server/xaiAcpExtension.ts index fe356d0ec0483..022dd327b55bb 100644 --- a/packages/provider-grok/src/server/xaiAcpExtension.ts +++ b/packages/provider-grok/src/server/xaiAcpExtension.ts @@ -549,7 +549,10 @@ function resolveXAiAcpToolTitle(toolCall: AcpToolCallState): string | undefined nonEmptyString(rawInput?.command) ?? nonEmptyString(unknownRecord(toolCall.data.rawOutput)?.command); if (command !== undefined) { - return command.length > 80 ? `${command.slice(0, 77)}...` : command; + if (command.length <= 80) return command; + const splitsPair = + /[\uD800-\uDBFF]/.test(command.charAt(76)) && /[\uDC00-\uDFFF]/.test(command.charAt(77)); + return `${command.slice(0, splitsPair ? 76 : 77)}...`; } return nonEmptyString(toolCall.title); }