mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-09 22:31:41 +00:00
fix(realtime): correct deferred-setup session.created modalities and reset IDs after response.done
- Convert provider's real session.created to session.updated when a synthetic one was already forwarded so clients receive the authoritative modalities derived from their session.update instead of the synthetic placeholder. - Reset current_response_id / current_output_item_id after Gemini RESPONSE_DONE so a toolCall arriving in a later frame starts a fresh response instead of reusing the completed response's ID and emitting a duplicate response.done. Co-authored-by: Yassin Kortam <yassin@berri.ai>
This commit is contained in:
parent
86ace3ef1a
commit
24af92663d
2 changed files with 17 additions and 6 deletions
|
|
@ -525,15 +525,20 @@ class RealTimeStreaming:
|
|||
else [transformed_response]
|
||||
)
|
||||
for event in events:
|
||||
event_str = json.dumps(event)
|
||||
if isinstance(event, dict) and event.get("type") == "session.created":
|
||||
if self._session_created_sent_to_client:
|
||||
# A synthetic session.created (with placeholder defaults) was
|
||||
# already forwarded to the client when we connected. The
|
||||
# provider's real session.created (e.g. emitted from Gemini
|
||||
# `setupComplete`) carries the authoritative modalities/model
|
||||
# from the client's session.update. Re-emit it as
|
||||
# `session.updated` so the client learns the corrected
|
||||
# configuration without seeing two `session.created` events.
|
||||
event = {**event, "type": "session.updated"}
|
||||
await self._maybe_send_guardrail_turn_detection_update()
|
||||
verbose_logger.debug(
|
||||
"Skipping duplicate session.created from provider stream"
|
||||
)
|
||||
continue
|
||||
self._session_created_sent_to_client = True
|
||||
else:
|
||||
self._session_created_sent_to_client = True
|
||||
event_str = json.dumps(event)
|
||||
## For audio/VAD guardrail path: forward session.created first, then inject.
|
||||
if (
|
||||
isinstance(event, dict)
|
||||
|
|
|
|||
|
|
@ -1276,6 +1276,12 @@ class GeminiRealtimeConfig(BaseRealtimeConfig):
|
|||
output_items=None,
|
||||
)
|
||||
returned_message.append(transformed_response_done_event)
|
||||
# Reset IDs so a subsequent turn (e.g. a `toolCall` arriving in
|
||||
# a later WebSocket frame after `turnComplete`) starts a fresh
|
||||
# response with its own `response.created` preamble instead of
|
||||
# reusing the just-completed response ID.
|
||||
current_output_item_id = None
|
||||
current_response_id = None
|
||||
elif (
|
||||
openai_event == OpenAIRealtimeEventTypes.RESPONSE_TEXT_DELTA
|
||||
or openai_event == OpenAIRealtimeEventTypes.RESPONSE_TEXT_DONE
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue