Picks the usage payload out of an OpenAI-protocol response.done frame, tolerating the two
layouts the compatible providers actually send on the wire:
OpenAI (gpt-realtime): populated response.usage; no top-level usage.
xAI (Grok Voice): populated TOP-LEVEL usage; response.usage present but {}.
Nested wins whenever it carries real numbers, so OpenAI's behavior is unchanged and xAI is
picked up as a fallback. If xAI later populates the nested slot, this keeps working untouched —
hence prefer-and-fall-back rather than switching outright.
The empty-object check is the entire point. Callers used to read only response.usage and
guard with if (!usage) return. For xAI that value is {} — which is TRUTHY — so the guard
never fired: a usage event was emitted with input_tokens/output_tokensundefined, those
clamped to 0 downstream, an all-zero delta was dropped, and the session's tokens were never
recorded at all (NULL on AIPromptRun) instead of failing loudly. Shared here so the
client-direct and server-bridged paths cannot drift apart on it again.
Picks the usage payload out of an OpenAI-protocol
response.doneframe, tolerating the two layouts the compatible providers actually send on the wire:gpt-realtime): populatedresponse.usage; no top-levelusage.usage;response.usagepresent but{}.Nested wins whenever it carries real numbers, so OpenAI's behavior is unchanged and xAI is picked up as a fallback. If xAI later populates the nested slot, this keeps working untouched — hence prefer-and-fall-back rather than switching outright.
The empty-object check is the entire point. Callers used to read only
response.usageand guard withif (!usage) return. For xAI that value is{}— which is TRUTHY — so the guard never fired: a usage event was emitted withinput_tokens/output_tokensundefined, those clamped to0downstream, an all-zero delta was dropped, and the session's tokens were never recorded at all (NULL onAIPromptRun) instead of failing loudly. Shared here so the client-direct and server-bridged paths cannot drift apart on it again.