fix(cost): carry grounding counters through the Responses usage bridge

A realtime session's usage is rebuilt from its own response.done event, so a counter
that does not survive the round trip is invisible to the cost path. Both directions
copied a fixed allow-list, which meant a grounded Gemini Live session reported its
query on the Usage object and then lost it before anything could bill it.

Gemini reads the grounding counters off the input token details while Anthropic reads
its own server_tool_use field, so carrying these two cannot move an Anthropic bill.
Absent counters stay absent, so no provider starts paying a fee it did not incur.

(cherry picked from commit ffd6c723e2a65dfff1860a913c34e41bc72ff11f)
(cherry picked from commit 1590822f6893c57086b72965963d23f4f367b424)
This commit is contained in:
Marty Sullivan 2026-09-07 22:12:46 -04:00
parent 9580b89bb1
commit 6d71e3385b
2 changed files with 14 additions and 0 deletions

View file

@ -2667,6 +2667,14 @@ class LiteLLMCompletionResponsesConfig:
if hasattr(prompt_details, "audio_tokens") and prompt_details.audio_tokens is not None:
input_details_dict["audio_tokens"] = prompt_details.audio_tokens
# The cost path reads the grounding counters off the input details, and a realtime
# session's usage is rebuilt from its own response.done, so dropping them here bills
# no per-query grounding fee at all.
for counter in ("web_search_requests", "google_maps_grounding_requests"):
counter_value = getattr(prompt_details, counter, None)
if counter_value is not None:
input_details_dict[counter] = counter_value
cache_write_tokens = getattr(prompt_details, "cache_write_tokens", None) or getattr(
prompt_details, "cache_creation_tokens", None
)

View file

@ -1137,6 +1137,12 @@ class ResponseAPILoggingUtils:
text_tokens=getattr(response_api_usage.input_tokens_details, "text_tokens", None),
image_tokens=getattr(response_api_usage.input_tokens_details, "image_tokens", None),
cache_write_tokens=getattr(response_api_usage.input_tokens_details, "cache_write_tokens", None),
web_search_requests=getattr(
response_api_usage.input_tokens_details, "web_search_requests", None
),
google_maps_grounding_requests=getattr(
response_api_usage.input_tokens_details, "google_maps_grounding_requests", None
),
)
completion_tokens_details: CompletionTokensDetailsWrapper | None = None
output_tokens_details: Final[OutputTokensDetails | None] = getattr(