From 27ca05a70759d8c2e78b2e4c0bc08aa526640ed2 Mon Sep 17 00:00:00 2001 From: Yassin Kortam Date: Tue, 25 Aug 2026 13:01:51 -0700 Subject: [PATCH] fix(ui): read reasoning tokens from Responses API output_tokens_details (#37952) --- .../src/components/llm_calls/responses_api.test.tsx | 12 ++++++++++++ .../src/components/llm_calls/responses_api.tsx | 6 ++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/ui/litellm-dashboard/src/components/llm_calls/responses_api.test.tsx b/ui/litellm-dashboard/src/components/llm_calls/responses_api.test.tsx index 065eaaf3632..033813397fc 100644 --- a/ui/litellm-dashboard/src/components/llm_calls/responses_api.test.tsx +++ b/ui/litellm-dashboard/src/components/llm_calls/responses_api.test.tsx @@ -400,4 +400,16 @@ describe("responses_api prompt cache usage", () => { expect(usageData).not.toHaveProperty("cacheCreationTokens"); expect(usageData.promptTokens).toBe(5000); }); + + it("surfaces reasoning tokens from Responses-shape output_tokens_details", async () => { + await expect(captureUsage({ output_tokens_details: { reasoning_tokens: 42 } })).resolves.toMatchObject({ + reasoningTokens: 42, + }); + }); + + it("falls back to completion_tokens_details reasoning tokens when output_tokens_details is absent", async () => { + await expect(captureUsage({ completion_tokens_details: { reasoning_tokens: 17 } })).resolves.toMatchObject({ + reasoningTokens: 17, + }); + }); }); diff --git a/ui/litellm-dashboard/src/components/llm_calls/responses_api.tsx b/ui/litellm-dashboard/src/components/llm_calls/responses_api.tsx index 94e8cb46765..8d71a4e29a8 100644 --- a/ui/litellm-dashboard/src/components/llm_calls/responses_api.tsx +++ b/ui/litellm-dashboard/src/components/llm_calls/responses_api.tsx @@ -295,8 +295,10 @@ export async function makeOpenAIResponsesRequest( }; // Add reasoning tokens if available - if (usage.completion_tokens_details?.reasoning_tokens) { - usageData.reasoningTokens = usage.completion_tokens_details.reasoning_tokens; + const reasoningTokens = + usage.output_tokens_details?.reasoning_tokens ?? usage.completion_tokens_details?.reasoning_tokens; + if (reasoningTokens) { + usageData.reasoningTokens = reasoningTokens; } if (usage.cost !== undefined && usage.cost !== null) {