fix(openai): pass response_id in ResponseCancelEvent on interrupt - #7255
fix(openai): pass response_id in ResponseCancelEvent on interrupt#7255rrfunde wants to merge 5 commits into
Conversation
RealtimeSession.interrupt() sent ResponseCancelEvent(type="response.cancel") without specifying response_id. Under OpenAI Realtime API semantics, a cancel without response_id is a no-op when multiple responses are in flight. Track response_id on _ResponseGeneration and forward it in interrupt() when available, falling back to cancel-all if absent. Fixes livekit#5564
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6723825f38
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ResponseCancelEvent( | ||
| type="response.cancel", | ||
| response_id=self._current_generation.response_id, | ||
| ) |
There was a problem hiding this comment.
Preserve the legacy Azure cancellation schema
When the session uses legacy Azure mode (is_azure with an api_version, such as the documented 2024-10-01-preview configuration), _run_ws serializes this event unchanged, but that beta response.cancel schema does not support response_id. Azure therefore rejects normal interrupts after response.created instead of stopping the response. Keep emitting the bare cancel event for legacy Azure sessions and include the ID only for the GA protocol.
Useful? React with 👍 / 👎.
|
Fixed: Preserved bare |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9e2e3e411f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| self.send_event( | ||
| ResponseCancelEvent( | ||
| type="response.cancel", | ||
| response_id=self._current_generation.response_id, | ||
| ) |
There was a problem hiding this comment.
Keep targeted cancellation off the xAI subclass
When this session is used through livekit.plugins.xai.realtime.RealtimeSession, _opts.is_azure is false and interrupt() delegates here via super().interrupt(), so every active xAI response now receives response.cancel with response_id. The xAI v1 Realtime protocol uses the legacy bare cancellation event—the xAI-specific _discard_say() path accordingly still emits one without an ID—so the endpoint rejects this targeted form and normal barge-ins no longer stop speaking responses. Gate the new field to providers that support it, rather than excluding only legacy Azure.
Useful? React with 👍 / 👎.
|
Fixed: Added |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c1494749f9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if model is not None and getattr(model, "_provider_label", None) != "OpenAI Realtime API": | ||
| return False |
There was a problem hiding this comment.
Enable targeted cancellation for OpenAI inference sessions
When using InferenceRealtimeModel("openai/gpt-realtime", ...), the model sets _provider_label to "LiveKit Inference Realtime" in inference_realtime_model.py:146, so this label check always disables targeted cancellation even though that class routes the OpenAI-compatible protocol and explicitly clears the Azure flags. Consequently, an interrupt with multiple responses in flight still sends the bare response.cancel that this change is intended to replace, allowing the OpenAI-backed generation to continue; distinguish the routed provider/model capability from the diagnostic label.
Useful? React with 👍 / 👎.
… while disabling for xAI
|
Addressed review feedback:
|
Summary
RealtimeSession.interrupt()in the OpenAI Realtime plugin was emitting:without specifying
response_id. Under OpenAI Realtime API semantics, a cancel event withoutresponse_idis a no-op when multiple responses are in flight.This PR:
response_idon_ResponseGenerationfromResponseCreatedEvent.response.id.RealtimeSession.interrupt()to passresponse_id=self._current_generation.response_idwhen available, cleanly cancelling the targeted in-flight response, while falling back to a general cancel if absent.Fixes #5564
Testing
test_interrupt_includes_response_id_from_current_generationintests/test_realtime/test_openai_realtime_model.py.uv run pytest tests/test_realtime/test_openai_realtime_model.pypassed (26 tests).uv run pytest tests/test_realtime_interrupt_cancels_generation.pypassed (6 tests).uv run ruff checkpassed.