diff --git a/src/beta/realtime/internal-base.ts b/src/beta/realtime/internal-base.ts index 2323b9c37..8de57838e 100644 --- a/src/beta/realtime/internal-base.ts +++ b/src/beta/realtime/internal-base.ts @@ -197,6 +197,11 @@ export function buildRealtimeURL( } url.protocol = 'wss'; + if (!azure) { + url.searchParams.delete('model'); + url.searchParams.delete('intent'); + url.searchParams.delete('call_id'); + } // Sideband control connections attach to an existing call via `call_id`. if (azure) { if (hasCallID) { diff --git a/src/realtime/internal-base.ts b/src/realtime/internal-base.ts index 9e69dde4d..4738ab83e 100644 --- a/src/realtime/internal-base.ts +++ b/src/realtime/internal-base.ts @@ -299,6 +299,9 @@ export function buildRealtimeURL( url.search = ''; } else { url.pathname += url.pathname.endsWith('/') ? 'realtime' : '/realtime'; + url.searchParams.delete('model'); + url.searchParams.delete('intent'); + url.searchParams.delete('call_id'); } url.hash = ''; diff --git a/tests/realtime-wire-lifecycle.test.ts b/tests/realtime-wire-lifecycle.test.ts index 56f1b75ac..4a6665852 100644 --- a/tests/realtime-wire-lifecycle.test.ts +++ b/tests/realtime-wire-lifecycle.test.ts @@ -69,6 +69,59 @@ afterAll(async () => { await stopped; }); +describe.each([StableWS, StableNative])('GA Realtime target selection (%s)', (Realtime) => { + test.each([ + { target: { model: 'chosen-model' }, selected: ['model', 'chosen-model'] }, + { target: { intent: 'transcription' }, selected: ['intent', 'transcription'] }, + { target: { callID: 'call_test_+/&' }, selected: ['call_id', 'call_test_+/&'] }, + ] satisfies { target: RealtimeConnectionConfig; selected: string[] }[])( + 'replaces stale base URL targets with $selected', + async ({ target, selected }) => { + const incoming = once(peers, 'connection'); + const client = new OpenAI({ + baseURL: `${baseURL}?model=old&model=other&intent=old&call_id=old&tenant=one`, + apiKey: 'ek_synthetic_wire', + }); + const realtime = new Realtime({ ...target, options: settings.options }, client); + const opened = rawEvent(realtime.socket, 'open'); + try { + const [, request] = await incoming; + await opened; + const url = new URL(request.url, baseURL); + expect([...url.searchParams]).toEqual([['tenant', 'one'], selected]); + } finally { + const closed = rawEvent(realtime.socket, 'close'); + realtime.close(); + await closed; + } + }, + ); +}); + +describe.each([BetaWS, BetaNative])('beta Realtime target selection (%s)', (Realtime) => { + test.each([ + { target: { model: 'chosen-model' }, selected: ['model', 'chosen-model'] }, + { target: { callID: 'call_test_+/&' }, selected: ['call_id', 'call_test_+/&'] }, + ])('replaces stale base URL targets with $selected', async ({ target, selected }) => { + const incoming = once(peers, 'connection'); + const client = new OpenAI({ + baseURL: `${baseURL}?model=old&model=other&intent=old&call_id=old&call_id=other&tenant=one`, + apiKey: 'ek_synthetic_wire', + }); + const realtime = new Realtime({ ...target, options: settings.options }, client); + const opened = rawEvent(realtime.socket, 'open'); + try { + const [, request] = await incoming; + await opened; + expect([...new URL(request.url, baseURL).searchParams]).toEqual([['tenant', 'one'], selected]); + } finally { + const closed = rawEvent(realtime.socket, 'close'); + realtime.close(); + await closed; + } + }); +}); + describe.each([ { label: 'GA ws', Realtime: StableWS, native: false, beta: false }, { label: 'beta ws', Realtime: BetaWS, native: false, beta: true },