open_ai: Fix parsing stream usage chunks with null prompt cache tokens (#62983)

# Objective

Some OpenAI-compatible models end a stream with a usage-only chunk
(`"choices": []`) where the cache token fields are `null`. Such as, the
`deepseek-v4-flash` model in `OpenCode Go` provider.

Zed chokes on it and kills the whole turn:

```text
ERROR [open_ai] Failed to parse OpenAI response into ResponseStreamResult: `data did not match any variant of untagged enum ResponseStreamResult`
Response: `{"id":"chatcmpl-xxx","object":"chat.completion.chunk","created":1787286372,"model":"deepseek-v4-flash","choices":[],"usage":{"prompt_tokens":12191,"completion_tokens":95,"total_tokens":12286,"prompt_tokens_details":{"cached_tokens":0,"cache_write_tokens":null}}}`
ERROR [agent::thread] Turn execution failed: data did not match any variant of untagged enum ResponseStreamResult
```

## Solution

`PromptTokensDetails` stored these as `u64` with `#[serde(default)]`,
which handles a missing field but not `null`. Switched them to
`Option<u64>` so `null` parses to `None`, and updated the one consumer
(`OpenAiEventMapper::map_event`) to `.and_then(...).unwrap_or(0)`.
Behavior is unchanged.

## Testing

- Added a regression test using the failing `null` chunk.
- `cargo test -p open_ai` — 78 tests + doc-test pass.
- `./script/clippy -p open_ai` — clean.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content adheres to Zed's UI standards (UX/UI and icon
guidelines)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

---

Release Notes:

- Fixed a crash when an OpenAI-compatible model sends a usage-only
stream chunk with null cache token fields.
693140abacEnoch committed on 8/25/2026, 9:33:45 AM· committed by GitHubparent91ebd50
2 files changedLine totals unavailable