Skip to content

Commit 7b5f6d8

Browse files
committed
Fix UTF-16-safe realtime context truncation
1 parent bbd01c1 commit 7b5f6d8

2 files changed

Lines changed: 27 additions & 1 deletion

File tree

extensions/voice-call/src/realtime-agent-context.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,4 +93,29 @@ describe("buildRealtimeVoiceInstructions", () => {
9393
expect(instructions).toContain("### IDENTITY.md");
9494
expect(instructions).not.toContain("do not include");
9595
});
96+
97+
it("truncates injected context without splitting UTF-16 surrogate pairs", async () => {
98+
const agentId = `abc\uD83D\uDE80tail`;
99+
const config = createConfig({
100+
agentContext: {
101+
enabled: true,
102+
maxChars: "OpenClaw agent voice context:\n\n- Agent id: abc".length + 33,
103+
includeIdentity: false,
104+
includeWorkspaceFiles: false,
105+
files: [],
106+
},
107+
});
108+
config.agentId = agentId;
109+
110+
const instructions = await buildRealtimeVoiceInstructions({
111+
baseInstructions: "Base voice instructions.",
112+
config,
113+
coreConfig: { agents: { list: [{ id: agentId }] } } as CoreConfig,
114+
agentRuntime: createAgentRuntime(await createWorkspace()),
115+
});
116+
117+
expect(instructions).toContain("- Agent id: abc\n[truncated]");
118+
expect(instructions).not.toContain("\uD83D");
119+
expect(instructions).not.toContain("\uDE80");
120+
});
96121
});

extensions/voice-call/src/realtime-agent-context.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts";
33
import { buildRealtimeVoiceAgentConsultPolicyInstructions } from "openclaw/plugin-sdk/realtime-voice";
44
import { root } from "openclaw/plugin-sdk/security-runtime";
55
import { normalizeOptionalString as normalizeString } from "openclaw/plugin-sdk/string-coerce-runtime";
6+
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
67
import type { VoiceCallConfig } from "./config.js";
78
import type { CoreAgentDeps, CoreConfig } from "./core-bridge.js";
89

@@ -22,7 +23,7 @@ function limitText(text: string, maxChars: number): string {
2223
if (text.length <= maxChars) {
2324
return text;
2425
}
25-
return `${text.slice(0, Math.max(0, maxChars - 32)).trimEnd()}\n[truncated]`;
26+
return `${truncateUtf16Safe(text, Math.max(0, maxChars - 32)).trimEnd()}\n[truncated]`;
2627
}
2728

2829
/** Read configured workspace context files through the safe workspace root. */

0 commit comments

Comments
 (0)