mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-17 12:42:21 +03:00
fix(usage): read Gemini usageMetadata out of the antigravity response envelope (#10430)
* fix(usage): read Gemini usageMetadata out of the antigravity response envelope
Port decolua/9router#59d858b: antigravity/gemini-cli wrap non-streaming
payloads in { response: {...} }, so extractUsageFromResponse only saw the
top-level usageMetadata and every non-streaming antigravity request logged
zero usage (IN 0 | OUT 0) and zeroed usage-dashboard rows. Top-level
metadata keeps priority; OpenAI/Claude branches untouched.
* chore(changelog): fragment for #10430 antigravity usage envelope
* ci: re-run dast-smoke (Build CLI bundle runner timeout flake)
---------
Co-authored-by: Rouzbeh <rqzbeh@users.noreply.github.com>
This commit is contained in:
1
changelog.d/fixes/10430-antigravity-usage-envelope.md
Normal file
1
changelog.d/fixes/10430-antigravity-usage-envelope.md
Normal file
@@ -0,0 +1 @@
|
||||
- **fix(usage):** read Gemini `usageMetadata` out of the antigravity `{ response: {...} }` envelope so non-streaming requests log real token usage instead of `IN 0 | OUT 0` (port of decolua/9router#59d858b) ([#10430](https://github.com/diegosouzapw/OmniRoute/pull/10430)) — thanks @rqzbeh
|
||||
@@ -93,14 +93,17 @@ export function extractUsageFromResponse(responseBody, provider) {
|
||||
};
|
||||
}
|
||||
|
||||
// Gemini format
|
||||
if (responseBody.usageMetadata && typeof responseBody.usageMetadata === "object") {
|
||||
// Gemini format. Antigravity / gemini-cli wrap the payload in
|
||||
// { response: { ... } } — read the envelope so non-streaming requests do
|
||||
// not silently log zero usage (port of decolua/9router#59d858b).
|
||||
const usageMetadata = responseBody.usageMetadata || responseBody.response?.usageMetadata;
|
||||
if (usageMetadata && typeof usageMetadata === "object") {
|
||||
// Gemini reports thoughts outside candidates. Fold them into completion so
|
||||
// every provider keeps reasoning as a subset of completion tokens.
|
||||
const thoughts = responseBody.usageMetadata.thoughtsTokenCount || 0;
|
||||
const thoughts = usageMetadata.thoughtsTokenCount || 0;
|
||||
return {
|
||||
prompt_tokens: responseBody.usageMetadata.promptTokenCount || 0,
|
||||
completion_tokens: (responseBody.usageMetadata.candidatesTokenCount || 0) + thoughts,
|
||||
prompt_tokens: usageMetadata.promptTokenCount || 0,
|
||||
completion_tokens: (usageMetadata.candidatesTokenCount || 0) + thoughts,
|
||||
reasoning_tokens: thoughts,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -232,6 +232,46 @@ test("extractUsageFromResponse reads Gemini usageMetadata and thinking tokens",
|
||||
});
|
||||
});
|
||||
|
||||
test("extractUsageFromResponse reads Gemini usageMetadata from the antigravity response envelope", () => {
|
||||
// Antigravity / gemini-cli wrap non-streaming payloads in { response: {...} }
|
||||
// (port of decolua/9router#59d858b — previously logged zero usage).
|
||||
const usage = extractUsageFromResponse(
|
||||
{
|
||||
response: {
|
||||
usageMetadata: {
|
||||
promptTokenCount: 42,
|
||||
candidatesTokenCount: 13,
|
||||
thoughtsTokenCount: 4,
|
||||
cachedContentTokenCount: 7,
|
||||
},
|
||||
},
|
||||
},
|
||||
"antigravity"
|
||||
);
|
||||
|
||||
assert.deepEqual(usage, {
|
||||
prompt_tokens: 42,
|
||||
completion_tokens: 17,
|
||||
reasoning_tokens: 4,
|
||||
});
|
||||
});
|
||||
|
||||
test("extractUsageFromResponse prefers top-level usageMetadata over the envelope", () => {
|
||||
const usage = extractUsageFromResponse(
|
||||
{
|
||||
usageMetadata: { promptTokenCount: 1, candidatesTokenCount: 2 },
|
||||
response: { usageMetadata: { promptTokenCount: 99, candidatesTokenCount: 99 } },
|
||||
},
|
||||
"gemini"
|
||||
);
|
||||
|
||||
assert.deepEqual(usage, {
|
||||
prompt_tokens: 1,
|
||||
completion_tokens: 2,
|
||||
reasoning_tokens: 0,
|
||||
});
|
||||
});
|
||||
|
||||
test("extractUsageFromResponse returns null when usage is missing", () => {
|
||||
const usage = extractUsageFromResponse(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user