fix: extract flat cached_tokens/reasoning_tokens from OpenAI-compatible usage objects (#2350)

Integrated into release/v3.8.0 — flat cached_tokens/reasoning_tokens extraction for Xiaomi MiMo and similar providers
This commit is contained in:
Tyler Ford
2026-05-17 20:11:06 -04:00
committed by GitHub
parent db8a2dc735
commit d6d585e200
3 changed files with 48 additions and 4 deletions

View File

@@ -25,10 +25,12 @@ export function extractUsageFromResponse(responseBody, provider) {
cached_tokens:
responseBody.usage.prompt_tokens_details?.cached_tokens ??
responseBody.usage.input_tokens_details?.cached_tokens ??
responseBody.usage.prompt_cache_hit_tokens,
responseBody.usage.prompt_cache_hit_tokens ??
responseBody.usage.cached_tokens,
reasoning_tokens:
responseBody.usage.completion_tokens_details?.reasoning_tokens ??
responseBody.usage.output_tokens_details?.reasoning_tokens,
responseBody.usage.output_tokens_details?.reasoning_tokens ??
responseBody.usage.reasoning_tokens,
};
}

View File

@@ -366,10 +366,12 @@ export function extractUsage(chunk) {
cached_tokens:
chunk.usage.prompt_tokens_details?.cached_tokens ??
chunk.usage.input_tokens_details?.cached_tokens ??
chunk.usage.prompt_cache_hit_tokens,
chunk.usage.prompt_cache_hit_tokens ??
chunk.usage.cached_tokens,
reasoning_tokens:
chunk.usage.completion_tokens_details?.reasoning_tokens ??
chunk.usage.output_tokens_details?.reasoning_tokens,
chunk.usage.output_tokens_details?.reasoning_tokens ??
chunk.usage.reasoning_tokens,
});
}

View File

@@ -292,3 +292,43 @@ test("extractUsage reads OpenAI streaming chunk with prompt_tokens_details", ()
assert.equal(usage.cached_tokens, 50);
assert.equal(usage.reasoning_tokens, 20);
});
// ── Flat field extraction tests (Xiaomi MiMo-style providers) ──
test("extractUsageFromResponse reads flat cached_tokens and reasoning_tokens from OpenAI-compatible usage", () => {
const usage = extractUsageFromResponse(
{
usage: {
prompt_tokens: 258,
completion_tokens: 50,
total_tokens: 308,
cached_tokens: 192,
reasoning_tokens: 49,
},
},
"xiaomi-mimo"
);
assert.deepEqual(usage, {
prompt_tokens: 258,
completion_tokens: 50,
cached_tokens: 192,
reasoning_tokens: 49,
});
});
test("extractUsage reads flat cached_tokens and reasoning_tokens from streaming chunk", () => {
const usage = extractUsage({
choices: [{ delta: {}, finish_reason: "stop" }],
usage: {
prompt_tokens: 258,
completion_tokens: 50,
total_tokens: 308,
cached_tokens: 192,
reasoning_tokens: 49,
},
});
assert.equal(usage.cached_tokens, 192);
assert.equal(usage.reasoning_tokens, 49);
});