fix(discord): count retained speech bytes

This commit is contained in:
Vincent Koc
2026-08-04 22:27:43 +08:00
parent 193317fd68
commit c238564d27
2 changed files with 13 additions and 8 deletions
@@ -4117,7 +4117,7 @@ describe("DiscordVoiceManager", () => {
expectUserMessageIncludes("third answer");
});
it("terminates realtime voice when retained exact speech exceeds the character budget", async () => {
it("terminates realtime voice when retained Unicode speech exceeds the byte budget", async () => {
const client = createClient();
client.fetchChannel.mockImplementation(async (channelId: string) => {
const guildId = channelId === "2001" ? "g2" : "g1";
@@ -4138,7 +4138,9 @@ describe("DiscordVoiceManager", () => {
const connection = (entry as unknown as { connection: { destroy: ReturnType<typeof vi.fn> } })
.connection;
const bridgeParams = lastRealtimeBridgeParams();
const accepted = "a".repeat(32 * 1024);
const accepted = "😀".repeat(8 * 1024);
expect(accepted.length).toBe(16 * 1024);
expect(Buffer.byteLength(accepted, "utf8")).toBe(32 * 1024);
await manager.join({ guildId: "g2", channelId: "2001" });
const siblingRealtime = getSessionEntry(manager, "g2").realtime as unknown as {
+9 -6
View File
@@ -90,7 +90,7 @@ const DISCORD_REALTIME_DUPLICATE_ERROR_SUPPRESS_MS = 60_000;
const DISCORD_REALTIME_CONTROL_SPEECH_DEDUPE_MS = 5_000;
const DISCORD_REALTIME_OUTPUT_PLAYBACK_WATCHDOG_MARGIN_MS = 1_500;
const DISCORD_REALTIME_MAX_RETAINED_EXACT_SPEECH_MESSAGES = 32;
const DISCORD_REALTIME_MAX_RETAINED_EXACT_SPEECH_CHARS = 32 * 1024;
const DISCORD_REALTIME_MAX_RETAINED_EXACT_SPEECH_BYTES = 32 * 1024;
const DISCORD_REALTIME_CANCELLATION_RACE_DETAIL = "Cancellation failed: no active response found";
const DISCORD_REALTIME_WAKE_ACKS = ["Yeah.", "Mm-hmm.", "Got it.", "One sec."];
const discordRealtimeTalkPayload = () => ({});
@@ -999,12 +999,15 @@ export class DiscordRealtimeVoiceSession implements VoiceRealtimeSession {
}
const retainedMessages =
this.queuedExactSpeechMessages.length + (this.activeExactSpeechMessage ? 1 : 0);
const retainedChars =
this.queuedExactSpeechMessages.reduce((total, message) => total + message.length, 0) +
(this.activeExactSpeechMessage?.length ?? 0);
const retainedBytes =
this.queuedExactSpeechMessages.reduce(
(total, message) => total + Buffer.byteLength(message, "utf8"),
0,
) + Buffer.byteLength(this.activeExactSpeechMessage ?? "", "utf8");
const incomingBytes = Buffer.byteLength(text, "utf8");
if (
retainedMessages >= DISCORD_REALTIME_MAX_RETAINED_EXACT_SPEECH_MESSAGES ||
retainedChars + text.length > DISCORD_REALTIME_MAX_RETAINED_EXACT_SPEECH_CHARS
retainedBytes + incomingBytes > DISCORD_REALTIME_MAX_RETAINED_EXACT_SPEECH_BYTES
) {
// Completed speech cannot be silently dropped. Overflow terminally retires
// this session before late provider or playback events can drain stale work.
@@ -1019,7 +1022,7 @@ export class DiscordRealtimeVoiceSession implements VoiceRealtimeSession {
this.clearOutputAudio("exact-speech-overflow");
this.params.onTerminalError(
new Error(
`Discord realtime exact speech overflow: retained=${retainedMessages} retainedChars=${retainedChars} incomingChars=${text.length}`,
`Discord realtime exact speech overflow: retained=${retainedMessages} retainedBytes=${retainedBytes} incomingBytes=${incomingBytes}`,
),
);
return;