The realtime health check always built the Azure websocket URL with the
default beta protocol, so GA-only transcription models such as
azure/gpt-realtime-whisper got probed at /openai/realtime and were
rejected with HTTP 400 on every /health run, while real calls through
the proxy resolved the GA path via intent=transcription and worked.
The probe now resolves the protocol the way the real call path does:
an explicit realtime_protocol (argument, deployment litellm_params, or
LITELLM_AZURE_REALTIME_PROTOCOL) wins, transcription-only models fall
back to GA with intent=transcription, and everything else keeps beta.
Transcription-only detection reads both mode and supported_endpoints
from get_model_info because a live proxy overwrites the catalog mode
with the operator's deployment model_info (mode: realtime) during
router registration, while supported_endpoints survives it.
get_model_info now propagates supported_endpoints from the cost map;
it declared the field but never populated it.
Vertex AI Live accepts a speechConfig on setup for native-audio models, so
stripping it silently discarded the voice a client asked for. Confirmed against
a live BidiGenerateContent session on gemini-live-2.5-flash-native-audio and on
gemini-live-2.5-flash-preview-native-audio-09-2025: both return setupComplete
with speechConfig present.
The strip stays in place for Google AI Studio, which was never verified to
accept it, via an overridable predicate matching the existing
_include_function_response_id pattern. The responseModalities TEXT to AUDIO
coercion is unchanged, since Vertex does reject TEXT on these models.
Creating a search tool through the UI only wrote the row; the router was updated
solely by the add_deployment job, so the tool was unusable for up to
PROXY_CONFIG_RELOAD_INTERVAL_SECONDS (30s by default) even on the worker that
served the write. Tools declared in config.yaml load straight into the router at
startup, which is why they never showed the delay.
The create, update and delete endpoints now refresh the router inline, matching
what the MCP server endpoints already do. The refresh is best-effort: the row is
already committed, so a failure must not surface as a 500 and push the caller
into a retry that creates duplicates.
Two related gaps go with it. _init_search_tools_in_db skipped the router update
whenever the merged list came back empty, so deleting the last search tool left
it live in memory forever. And in store_model_in_db-off deployments the
add_deployment job is never scheduled, so DB-backed search tools never reached
the router at all; that branch now loads them at startup and keeps them fresh on
its own interval, the same way MCP servers already do.
The badges flagged UI that shipped a while ago, so they no longer tell
anyone anything. Dropped all four render sites: the Settings and Admin
Settings items in the left nav, the UI Settings tab in the admin panel,
and the Submitted MCPs tab.
The NewBadge component stays so the next genuinely new surface can use
it again. BetaBadge and the "hide new badges" account toggle are
untouched, since that toggle still gates BetaBadge.