The Sentinel
[DONE] is not JSON. Every stream ends this way, including one that carried an error chunk.
The Usage Chunk
Setstream_options.include_usage: true and one extra chunk arrives before [DONE], with an empty choices array and a usage object:
choices[0] unconditionally fails here; check for an empty array. The usage fields match the non-streaming response.
Order
- The terminal content chunk (empty
delta, non-nullfinish_reason). - The usage chunk, only if
stream_options.include_usagewas set. data: [DONE].

