Skip to content

fix(xai): match id-less delete acks to the oldest pending delete - #7122

Draft
Speediing wants to merge 2 commits into
livekit:mainfrom
Speediing:cursor/xai-realtime-session-update-rca-8e60
Draft

fix(xai): match id-less delete acks to the oldest pending delete#7122
Speediing wants to merge 2 commits into
livekit:mainfrom
Speediing:cursor/xai-realtime-session-update-rca-8e60

Conversation

@Speediing

@Speediing Speediing commented Sep 4, 2026

Copy link
Copy Markdown

Summary

xAI's realtime API acknowledges conversation.item.delete with an empty item_id. The plugin mapped that ack to the first pending delete future, which can already be a settled (rejected) one. The real delete then sat until update_chat_ctx's 5s timeout, which looks like a mid-session hang.

This PR matches an id-less delete ack to the oldest unsettled pending delete instead.

Changes

  • Skip settled futures when pairing an empty-item_id delete ack
  • Unit test covering the rejected-then-real-delete ordering
  • Notes below on related xAI realtime behavior (not fixed here)

Test plan

  • Unit test in tests/test_realtime/test_xai_realtime_model.py
  • Live: mid-session tools/update_chat_ctx under load with xAI realtime

Related findings (no code change)

These came up while digging the hang. Separate from the delete-ack bug:

  1. $ref in tool schemas — Both OpenAI and xAI plugins forward $ref/$defs as-is. A live probe against xAI accepted a mid-session tools update with nested $ref and still produced a response. Field reports that stripping $ref helps may be conflating this with the update_chat_ctx timeout above.

  2. Long-lived sessions — OpenAI realtime defaults max_session_duration to 20 minutes (websocket recycle). xAI defaults it to None. Callers can set max_session_duration=20*60 today; changing the xAI default is a possible follow-up.

  3. Context / item IDs — xAI often omits item_id / previous_item_id on conversation item events, so the plugin has to guess. Wrong guesses desync the mirror. Needs better IDs from xAI (see also xAI realtime: an interruption desyncs the local chat context, then every later item is dropped (unrecoverable) #6391). This PR only fixes one wrong-guess path on delete acks.

cursoragent and others added 2 commits September 4, 2026 22:06
xAI acknowledges conversation.item.delete with item_id "". The plugin maps
that ack to the first future in _item_delete_future, which can be one the
server already rejected by event id, so the ack removes the wrong item from
the mirror and the real delete waits out update_chat_ctx's 5s timeout.

Co-authored-by: Jason Wiker <jason.wiker@gmail.com>
xAI's conversation.item.deleted carries item_id "". The shim picked the
first key of _item_delete_future, but a delete the server rejected by event
id is already settled and still sits there until update_chat_ctx's finally.
The ack then removed the wrong item from the remote mirror and left the real
delete pending until the 5s update_chat_ctx timeout. Skip settled futures.

Co-authored-by: Jason Wiker <jason.wiker@gmail.com>
@Speediing Speediing changed the title fix(xai): match id-less delete acks to the oldest pending delete; RCA for Zillow Grok Voice reports fix(xai): match id-less delete acks to the oldest pending delete; RCA for xAI realtime session issues Sep 4, 2026
@Speediing Speediing changed the title fix(xai): match id-less delete acks to the oldest pending delete; RCA for xAI realtime session issues fix(xai): match id-less delete acks to the oldest pending delete Sep 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants