fix(usage): strict validation for xAI exact provider-reported cost (#6856)

extractUsageFromResponse() and normalizeUsage() used Number(x)
coercion for cost_in_usd_ticks, which silently turned null/""
into 0 -- accepted downstream as a valid $0 exact cost instead of
falling back to the token-based estimate. Both call sites now
require typeof === "number" && Number.isFinite && >= 0.

Rebased onto current release/v3.8.47 tip (already carries #6711)
and trimmed to just the incremental validation fix + 2 regression
tests, replacing the stale-base diff that re-added the whole
already-merged feature.

Co-authored-by: KooshaPari <koosha@phenotype.io>
Co-authored-by: diegosouzapw <8016841+diegosouzapw@users.noreply.github.com>
This commit is contained in:
KooshaPari
2026-07-11 22:04:20 -07:00
committed by GitHub
parent 3164eafbd1
commit 37ea7aab2c
4 changed files with 40 additions and 4 deletions

View File

@@ -0,0 +1 @@
- **fix(usage):** xAI's exact provider-reported `cost_in_usd_ticks` no longer silently accepts `null`/`""`/negative values as a valid `$0` exact cost — `extractUsageFromResponse()` (`open-sse/handlers/usageExtractor.ts`) and `normalizeUsage()` (`open-sse/utils/usageTracking.ts`) now require `typeof value === "number" && Number.isFinite(value) && value >= 0` instead of coercing with `Number(x)`, so a malformed exact cost correctly falls back to the token-based estimate instead of masking it with a bogus `$0`. Regression guard: `tests/unit/xai-exact-cost-2453.test.ts` (rejects null/empty/negative exact costs on both call sites). ([#6856](https://github.com/diegosouzapw/OmniRoute/pull/6856) — thanks @KooshaPari)

View File

@@ -35,8 +35,10 @@ export function extractUsageFromResponse(responseBody, provider) {
// @ryanngit). Only set the key when present so non-xAI OpenAI-shaped usage
// (Codex, DeepSeek, etc.) is unaffected. Ticks → USD conversion happens in
// costCalculator.ts, not here.
...(Number.isFinite(Number(responseBody.usage.cost_in_usd_ticks))
? { cost_in_usd_ticks: Number(responseBody.usage.cost_in_usd_ticks) }
...(typeof responseBody.usage.cost_in_usd_ticks === "number" &&
Number.isFinite(responseBody.usage.cost_in_usd_ticks) &&
responseBody.usage.cost_in_usd_ticks >= 0
? { cost_in_usd_ticks: responseBody.usage.cost_in_usd_ticks }
: {}),
};
}

View File

@@ -253,7 +253,7 @@ export function filterUsageForFormat(usage, targetFormat) {
export function normalizeUsage(usage) {
if (!usage || typeof usage !== "object" || Array.isArray(usage)) return null;
const normalized = {};
const normalized: Record<string, number> = {};
const assignNumber = (key, value) => {
if (value === undefined || value === null) return;
const numeric = Number(value);
@@ -271,7 +271,14 @@ export function normalizeUsage(usage) {
assignNumber("reasoning_tokens", usage?.reasoning_tokens);
// xAI's exact provider-reported cost (port of decolua/9router#2453, capability A —
// @ryanngit). Ticks → USD conversion happens in costCalculator.ts, not here.
assignNumber("cost_in_usd_ticks", usage?.cost_in_usd_ticks);
const exactCostTicks = usage?.cost_in_usd_ticks;
if (
typeof exactCostTicks === "number" &&
Number.isFinite(exactCostTicks) &&
exactCostTicks >= 0
) {
normalized.cost_in_usd_ticks = exactCostTicks;
}
if (Object.keys(normalized).length === 0) return null;
return normalized;

View File

@@ -91,6 +91,32 @@ test("normalizeUsage: drops a non-finite cost_in_usd_ticks", () => {
assert.equal(normalized.cost_in_usd_ticks, undefined);
});
test("normalizeUsage: rejects null, empty, and negative exact costs", () => {
for (const value of [null, "", -1]) {
const normalized = normalizeUsage({ prompt_tokens: 10, cost_in_usd_ticks: value });
assert.equal(normalized.cost_in_usd_ticks, undefined, `unexpected exact cost for ${value}`);
}
});
test("extractUsageFromResponse: rejects malformed exact cost values", () => {
for (const value of [null, "", -1]) {
const usage = extractUsageFromResponse(
{
usage: {
prompt_tokens: 12,
completion_tokens: 8,
cost_in_usd_ticks: value,
},
},
"xai"
);
assert.ok(
!("cost_in_usd_ticks" in usage),
`must not add cost_in_usd_ticks for malformed value ${value}`
);
}
});
test("extractUsageFromResponse: xAI OpenAI-shaped usage carries cost_in_usd_ticks through", () => {
const usage = extractUsageFromResponse(
{