From c488a18df18e6b9b222edc2a533f497d1d49e895 Mon Sep 17 00:00:00 2001 From: Sameh Khamis Date: Sun, 13 Sep 2026 22:00:14 -0700 Subject: [PATCH] fix: scope voice response parsing to its backend lifetime --- src/voice/realtimeBackend.js | 5 ++++- src/voice/realtimeBackend.test.mjs | 3 ++- src/voice/realtimeController.js | 1 - 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/voice/realtimeBackend.js b/src/voice/realtimeBackend.js index 43a76d63c..2a8af2d0d 100644 --- a/src/voice/realtimeBackend.js +++ b/src/voice/realtimeBackend.js @@ -7,9 +7,12 @@ export function createRealtimeBackend({ tokenTransport = (...args) => fetch(...args), connectionTransport = (...args) => fetch(...args), timeoutMs = 30_000, + signal: lifetime, } = {}) { const scoped = (signal) => - AbortSignal.any([signal, AbortSignal.timeout(timeoutMs)].filter(Boolean)); + AbortSignal.any( + [lifetime, signal, AbortSignal.timeout(timeoutMs)].filter(Boolean), + ); return Object.freeze({ protocol: 'openai-realtime', async requestToken({ tier = DEFAULT_VOICE_TIER, signal } = {}) { diff --git a/src/voice/realtimeBackend.test.mjs b/src/voice/realtimeBackend.test.mjs index 1cf0dcf29..1fc21da9d 100644 --- a/src/voice/realtimeBackend.test.mjs +++ b/src/voice/realtimeBackend.test.mjs @@ -89,12 +89,13 @@ test('cancellation rejects late token and SDP bodies without promoting a stopped release = resolve; }); const backend = createRealtimeBackend({ + signal: lifetime.signal, tokenTransport: async () => ({ ok: true, json: () => pending }), connectionTransport: async () => ({ ok: true, text: () => pending }), }); const result = phase === 'token' - ? backend.requestToken({ signal: lifetime.signal }) + ? backend.requestToken() : backend.negotiate({ credential: { token: 'test' }, offerSdp: 'offer', diff --git a/src/voice/realtimeController.js b/src/voice/realtimeController.js index 9e80e2806..3f1a36ee5 100644 --- a/src/voice/realtimeController.js +++ b/src/voice/realtimeController.js @@ -2598,4 +2598,3 @@ function resetVoiceVisualizerBars(bars) { bar.style.removeProperty('--audio-opacity'); } } -