



















@@ -58,6 +58,7 @@ const DISCORD_REALTIME_FALLBACK_TEXT = "I hit an error while checking that. Plea
5858const DISCORD_REALTIME_PENDING_SPEAKER_CONTEXT_LIMIT = 32;
5959const DISCORD_REALTIME_RECENT_AGENT_PROXY_CONSULT_LIMIT = 16;
6060const DISCORD_REALTIME_RECENT_AGENT_PROXY_CONSULT_TTL_MS = 15_000;
61+const DISCORD_REALTIME_IGNORED_WAKE_NAME_CONTEXT_TTL_MS = 10_000;
6162const DISCORD_REALTIME_LOG_PREVIEW_CHARS = 500;
6263const DISCORD_REALTIME_DEFAULT_MIN_BARGE_IN_AUDIO_END_MS = 250;
6364const DISCORD_REALTIME_FORCED_CONSULT_FALLBACK_DELAY_MS = 200;
@@ -140,6 +141,11 @@ type RecentAgentProxyConsultContext = {
140141result?: RecentAgentProxyConsultResult;
141142};
142143144+type RecentIgnoredWakeNameSpeakerContext = {
145+context: DiscordRealtimeSpeakerContext;
146+createdAt: number;
147+};
148+143149function formatRealtimeLogPreview(text: string): string {
144150const oneLine = text.replace(/\s+/g, " ").trim();
145151if (oneLine.length <= DISCORD_REALTIME_LOG_PREVIEW_CHARS) {
@@ -636,6 +642,7 @@ export class DiscordRealtimeVoiceSession implements VoiceRealtimeSession {
636642private wakeNames: string[] = [];
637643private pendingAgentProxyConsultContexts: PendingAgentProxyConsultContext[] = [];
638644private recentAgentProxyConsultContexts: RecentAgentProxyConsultContext[] = [];
645+private recentIgnoredWakeNameSpeakerContext: RecentIgnoredWakeNameSpeakerContext | undefined;
639646private readonly pendingSpeakerTurns: PendingSpeakerTurn[] = [];
640647private outputAudioTimestampMs = 0;
641648private outputAudioDiscordBytes = 0;
@@ -832,6 +839,7 @@ export class DiscordRealtimeVoiceSession implements VoiceRealtimeSession {
832839this.clearForcedConsultTimers();
833840this.pendingAgentProxyConsultContexts = [];
834841this.recentAgentProxyConsultContexts = [];
842+this.recentIgnoredWakeNameSpeakerContext = undefined;
835843this.pendingSpeakerTurns.length = 0;
836844this.queuedExactSpeechMessages = [];
837845this.exactSpeechResponseActive = false;
@@ -1424,10 +1432,10 @@ export class DiscordRealtimeVoiceSession implements VoiceRealtimeSession {
14241432this.recordMeetingNotesUtterance(trimmed, meetingNotesTurn);
14251433const wakeNameResult = this.resolveWakeNameTranscript(trimmed);
14261434if (!wakeNameResult.allowed) {
1435+this.rememberIgnoredWakeNameSpeakerContext(this.consumePendingSpeakerContext());
14271436logger.info(
14281437`discord voice: realtime wake-name gate ignored transcript chars=${trimmed.length} voiceSession=${this.params.entry.voiceSessionKey} agent=${this.params.entry.route.agentId} wakeNames=${this.wakeNames.join(",") || "none"}`,
14291438);
1430-this.consumePendingSpeakerContext();
14311439return;
14321440}
14331441const acceptedText = wakeNameResult.text || trimmed;
@@ -1540,14 +1548,18 @@ export class DiscordRealtimeVoiceSession implements VoiceRealtimeSession {
15401548if (!question) {
15411549return undefined;
15421550}
1543-const context = this.consumePendingSpeakerContext();
15441551const skipReason = classifySkippableForcedAgentProxyTranscript(question);
15451552if (skipReason) {
1553+const context = this.consumePendingSpeakerContext();
15461554logger.info(
15471555`discord voice: realtime forced agent consult skipped reason=${skipReason} chars=${question.length} speaker=${context?.speakerLabel ?? "unknown"} transcript=${formatRealtimeLogPreview(question)}`,
15481556);
15491557return undefined;
15501558}
1559+let context = this.consumePendingSpeakerContext();
1560+if (!context) {
1561+context = this.consumeRecentIgnoredWakeNameSpeakerContext();
1562+}
15511563if (!context) {
15521564const recent = this.findRecentAgentProxyConsultContext(question);
15531565if (recent) {
@@ -1681,6 +1693,30 @@ export class DiscordRealtimeVoiceSession implements VoiceRealtimeSession {
16811693return turn?.context;
16821694}
168316951696+private rememberIgnoredWakeNameSpeakerContext(
1697+context: DiscordRealtimeSpeakerContext | undefined,
1698+): void {
1699+if (!context) {
1700+return;
1701+}
1702+this.recentIgnoredWakeNameSpeakerContext = {
1703+ context,
1704+createdAt: Date.now(),
1705+};
1706+}
1707+1708+private consumeRecentIgnoredWakeNameSpeakerContext(): DiscordRealtimeSpeakerContext | undefined {
1709+const recent = this.recentIgnoredWakeNameSpeakerContext;
1710+this.recentIgnoredWakeNameSpeakerContext = undefined;
1711+if (
1712+!recent ||
1713+Date.now() - recent.createdAt > DISCORD_REALTIME_IGNORED_WAKE_NAME_CONTEXT_TTL_MS
1714+) {
1715+return undefined;
1716+}
1717+return recent.context;
1718+}
1719+16841720private peekPendingSpeakerTurn(): PendingSpeakerTurn | undefined {
16851721this.prunePendingSpeakerTurns();
16861722this.expireClosedSpeakerTurnsBeforeLaterAudio();
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。