fix(ci): restore guardrail injection on duplicate session.created and cast realtime delta event

- Re-enable the one-time guardrail turn_detection update on duplicate
  session.created. `_maybe_send_guardrail_turn_detection_update` is
  already idempotent via `_guardrail_turn_detection_update_sent`, so
  the previous guard was unnecessary and broke the deferred-setup path
  where the synthetic session.created is emitted by llm_http_handler
  outside this loop (no prior chance to inject).

- Cast the response.function_call_arguments.delta dict appended to
  `returned_message: List[OpenAIRealtimeEvents]` so mypy is satisfied.
This commit is contained in:
mateo-berri 2026-05-23 01:52:45 +00:00
parent a27e6bcae9
commit d3490859a4
No known key found for this signature in database
2 changed files with 21 additions and 20 deletions

View file

@ -533,7 +533,6 @@ class RealTimeStreaming:
is_session_created_event = (
isinstance(event, dict) and event.get("type") == "session.created"
)
is_first_session_created_event = False
if is_session_created_event:
if self._session_created_sent_to_client:
# A synthetic session.created (with placeholder defaults) was
@ -546,17 +545,16 @@ class RealTimeStreaming:
event = {**event, "type": "session.updated"}
else:
self._session_created_sent_to_client = True
is_first_session_created_event = True
event_str = json.dumps(event)
## For audio/VAD guardrail path: forward the first session.created
## first, then inject the guardrail turn-detection update. Skip
## this path for duplicate session.created events that we just
## retyped to `session.updated` above — the guardrail injection
## was already handled on the original session.created.
if (
is_first_session_created_event
and self._has_audio_transcription_guardrails()
):
## For audio/VAD guardrail path: forward the (possibly retyped)
## session.created first, then invoke the one-time guardrail
## turn-detection update. ``_maybe_send_guardrail_turn_detection_update``
## is idempotent (gated by ``_guardrail_turn_detection_update_sent``),
## so duplicate session.created events — including those emitted
## after a synthetic session.created from ``llm_http_handler`` in
## deferred-setup mode — still get a single chance to inject the
## update if a prior attempt was dropped by the provider transform.
if is_session_created_event and self._has_audio_transcription_guardrails():
self.store_message(event_str)
await self.websocket.send_text(event_str)
await self._maybe_send_guardrail_turn_detection_update()

View file

@ -1418,15 +1418,18 @@ class GeminiRealtimeConfig(BaseRealtimeConfig):
# clients accumulate ``delta.delta`` and rely on at least
# one delta before ``.done``.
returned_message.append(
{
"type": "response.function_call_arguments.delta",
"event_id": f"event_{uuid.uuid4()}",
"response_id": current_response_id,
"item_id": item_id,
"output_index": idx,
"call_id": tool_call["call_id"],
"delta": tool_call["arguments"],
}
cast(
OpenAIRealtimeEvents,
{
"type": "response.function_call_arguments.delta",
"event_id": f"event_{uuid.uuid4()}",
"response_id": current_response_id,
"item_id": item_id,
"output_index": idx,
"call_id": tool_call["call_id"],
"delta": tool_call["arguments"],
},
)
)
# response.function_call_arguments.done
returned_message.append(tool_call)