fix(openai): drop ?model= on native /realtime STT URL to avoid invalid_model#1767
Open
tsushanth wants to merge 1 commit into
Open
fix(openai): drop ?model= on native /realtime STT URL to avoid invalid_model#1767tsushanth wants to merge 1 commit into
tsushanth wants to merge 1 commit into
Conversation
…d_model OpenAI's native wss://api.openai.com/.../realtime endpoint now treats a ?model= query param on the WebSocket upgrade URL as selecting a conversation session, and rejects the subsequent transcription-mode session.update with error.invalid_request_error.invalid_model (close 4000). Every transcription model (gpt-4o-mini-transcribe, gpt-4o-transcribe, whisper-1) currently fails this way against the native endpoint, so realtime STT through this plugin produces zero transcripts. The ?model= upgrade-URL convention exists for OpenAI-compatible proxies (LiteLLM, Cloudflare AI Gateway, etc.) that route at the HTTP upgrade without parsing the first JSON frame — see livekit#1467. Drop the param only when the host is api.openai.com; non-OpenAI hosts still receive the model on the URL so proxy routing keeps working. The model is conveyed to OpenAI via session.update → audio.input.transcription.model instead. Updates the corresponding URL builder test and adds a second test for the explicit-OpenAI-baseURL path. Closes livekit#1756
🦋 Changeset detectedLatest commit: 0c547bc The changes in this PR will be included in the next version bump. This PR includes changesets to release 35 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Realtime STT through the OpenAI plugin currently fails on every transcription model when connecting directly to
wss://api.openai.com/.../realtime:{"type":"error","error":{"type":"invalid_request_error","code":"invalid_model", "message":"Model \"gpt-4o-mini-transcribe\" is not supported in transcription mode."}}…followed by
close 4000 reason=invalid_request_error.invalid_model. So withuseRealtime: true(the default for realtime-capable models), the plugin produces zero transcripts against the native endpoint.Root cause
buildRealtimeSttUrlappends?model=…to the WebSocket upgrade URL. As of 2026-06, OpenAI's native/realtimeendpoint treats a?model=query param as selecting a conversation session; the subsequent transcription-modesession.updateis then rejected for any transcription model.Verified directly against
wss://api.openai.com/v1/realtime?intent=transcription:&model=...: identicalsession.update→session.updated, and audio streams transcribe correctly (deltas + completed events)&model=...:invalid_modelfor every model tried (gpt-4o-mini-transcribe,gpt-4o-transcribe,whisper-1)The model is conveyed in the documented place for transcription sessions —
session.update → audio.input.transcription.model— so the URL param is redundant for OpenAI direct.Why not just delete
?model=?The param was added in #1467 specifically for OpenAI-compatible proxies (LiteLLM, Cloudflare AI Gateway, etc.) that route WebSocket connections at the HTTP upgrade and need to know the model before any JSON frame arrives. Deleting it across the board would regress those proxy users for STT.
Fix
Skip the model param only when the host is
api.openai.com. Non-OpenAI proxy users still receive the model on the URL so routing keeps working.url.searchParams.set('intent', 'transcription'); - url.searchParams.set('model', model); + if (url.hostname !== 'api.openai.com') { + url.searchParams.set('model', model); + } return url.toString();Updated the JSDoc to reflect the new endpoint behaviour, updated the existing URL builder test that asserted
modelwas present on the native endpoint, and added a second test covering an explicitbaseURLthat still points atapi.openai.com.Test plan
pnpm vitest run plugins/openai/src/stt.test.ts— 12 passed, 1 skipped (the pre-existing integration test gated onOPENAI_API_KEY)pnpm build:agents+pnpm build:plugins— cleanpnpm lint— no new warnings on touched filespnpm format:check— clean?model=on the upgrade URL —https://gateway.example.com/v1,http://gateway.example.com/v1, andwss://gateway.example.com/v1/realtimetest cases all still assertmodelis setCloses #1756