Files
windmill/backend/windmill-ai
hugocasa 2b58df57fc feat(ai): extract prompt cache token usage from OpenAI and Azure providers (#10214)
* feat(ai): extract prompt cache token usage from OpenAI and Azure providers

Parse the nested cache token details OpenAI returns and thread them into
TokenUsage, matching the Anthropic and Bedrock providers.

- sse.rs: add OpenAIPromptTokensDetails / OpenAIInputTokensDetails and the
  optional prompt_tokens_details / input_tokens_details fields.
- other.rs (Chat Completions) and openai.rs (Responses): populate
  cache_read via .with_cache(cached_tokens, None).

OpenAI's prompt_tokens/input_tokens already include cached tokens (cached is
a subset), so total/prompt are unchanged; cache_read is recorded separately
for reporting. For the same reason the frontend token-usage conversions are
left as-is (adding cached would double-count); optional cache fields and a
clarifying comment are added to prevent a future incorrect Anthropic-style fix.

Fixes WIN-2207

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(ai): pin OpenAI/Azure cache-token deserialization paths

Add regression tests deserializing the real Chat Completions and Responses
usage payloads, guarding the prompt_tokens_details.cached_tokens /
input_tokens_details.cached_tokens paths against a silent rename.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(ai): extract to_token_usage() and test the cache mapping

Address review nit: move the usage->TokenUsage conversion into
OpenAIChatUsage::to_token_usage / OpenAIResponsesUsage::to_token_usage so
the providers call one method and the tests exercise the real mapping.
Tests now assert cache_read is populated while input/total are unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 18:47:25 +02:00
..