diff --git a/changelog.d/fixes/18464-nvidia-missing-pricing-rows.md b/changelog.d/fixes/18464-nvidia-missing-pricing-rows.md new file mode 100644 index 000000000000..5a4dfaba1f67 --- /dev/null +++ b/changelog.d/fixes/18464-nvidia-missing-pricing-rows.md @@ -0,0 +1 @@ +- **fix(pricing):** add zero-price rows for the seven NVIDIA catalog models that had none (`meta/muse-glimmer-30b`, `poolside/laguna-xs-2.1`, `google/gemma-4-31b-it`, `google/diffusiongemma-26b-a4b-it`, `nvidia/nemotron-3-ultra-550b-a55b`, `nvidia/nemotron-3.5-lightning-30b-a3b`, `nvidia/nemotron-3-nano-omni-30b-a3b-reasoning`). They run on NVIDIA's free hosted endpoint, which has no per-token price listed, but without a row their usage was unpriced and an API key with a USD limit failed closed after one request ([#18464](https://github.com/diegosouzapw/OmniRoute/issues/18464)) diff --git a/src/shared/constants/pricing/inference-hosts.ts b/src/shared/constants/pricing/inference-hosts.ts index 97a0673baf81..4815a98b2c84 100644 --- a/src/shared/constants/pricing/inference-hosts.ts +++ b/src/shared/constants/pricing/inference-hosts.ts @@ -380,6 +380,40 @@ export const DEFAULT_PRICING_INFERENCE = { "nvidia/gpt-oss-120b": { input: 0, output: 0, cached: 0, reasoning: 0, cache_creation: 0 }, "openai/gpt-oss-120b": { input: 0, output: 0, cached: 0, reasoning: 0, cache_creation: 0 }, "gpt-oss-120b": { input: 0, output: 0, cached: 0, reasoning: 0, cache_creation: 0 }, + // #18464: NVIDIA hosted free endpoints. build.nvidia.com rate limits them and lists no + // per-token price, so they are priced at zero. Without a row, usage is unpriced and + // USD-limited API keys fail closed (#12341) after one request. + "meta/muse-glimmer-30b": { input: 0, output: 0, cached: 0, reasoning: 0, cache_creation: 0 }, + "poolside/laguna-xs-2.1": { input: 0, output: 0, cached: 0, reasoning: 0, cache_creation: 0 }, + "google/gemma-4-31b-it": { input: 0, output: 0, cached: 0, reasoning: 0, cache_creation: 0 }, + "google/diffusiongemma-26b-a4b-it": { + input: 0, + output: 0, + cached: 0, + reasoning: 0, + cache_creation: 0, + }, + "nvidia/nemotron-3-ultra-550b-a55b": { + input: 0, + output: 0, + cached: 0, + reasoning: 0, + cache_creation: 0, + }, + "nvidia/nemotron-3.5-lightning-30b-a3b": { + input: 0, + output: 0, + cached: 0, + reasoning: 0, + cache_creation: 0, + }, + "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning": { + input: 0, + output: 0, + cached: 0, + reasoning: 0, + cache_creation: 0, + }, }, nebius: { "openai/gpt-oss-120b": { input: 0, output: 0, cached: 0, reasoning: 0, cache_creation: 0 }, diff --git a/tests/unit/nvidia-registry-pricing-18464.test.ts b/tests/unit/nvidia-registry-pricing-18464.test.ts new file mode 100644 index 000000000000..797ced7ee1a9 --- /dev/null +++ b/tests/unit/nvidia-registry-pricing-18464.test.ts @@ -0,0 +1,47 @@ +import test from "node:test"; +import assert from "node:assert/strict"; + +import { nvidiaProvider } from "../../open-sse/config/providers/registry/nvidia/index.ts"; +import { calculateCostDetailed } from "../../src/lib/usage/costCalculator.ts"; +import { getDefaultPricing } from "../../src/shared/constants/pricing.ts"; + +// #18464: every NVIDIA registry model runs on NVIDIA's free hosted endpoint, which is +// rate limited and has no per-token price listed. A registry model without a pricing row is +// reported unpriced, and an API key with a USD limit then fails closed (#12341) +// after a single request to it. +// +// Ids that the fix for #18418 handles instead of this one. It removes the +// first three from the registry, because NVIDIA retired them (410 end of life), and +// adds the zero row for the fourth. Once that fix is merged, this list can be emptied. +const HANDLED_BY_18418 = new Set([ + "moonshotai/kimi-k3", + "deepseek-ai/deepseek-v4-pro-0813", + "deepseek-ai/deepseek-v4-flash-0731", + "nvidia/nemotron-3.5-super-vl-120b-a12b", +]); + +const ZERO_ROW = { input: 0, output: 0, cached: 0, reasoning: 0, cache_creation: 0 }; + +const checkedIds = nvidiaProvider.models + .map((model) => model.id) + .filter((id) => !HANDLED_BY_18418.has(id)); + +test("every NVIDIA registry model has a zero-price pricing row (#18464, #12341)", async () => { + const pricing = getDefaultPricing() as Record>>; + assert.ok(checkedIds.length > 0, "the nvidia registry walk must check at least one model"); + const unpriced: string[] = []; + for (const id of checkedIds) { + const result = await calculateCostDetailed("nvidia", id, { input: 1000, output: 1000 }); + if (!result.priced) { + unpriced.push(id); + continue; + } + assert.equal(result.costUsd, 0, `nvidia/${id} is a free endpoint and must cost 0`); + assert.deepEqual(pricing.nvidia?.[id], ZERO_ROW, `nvidia/${id} needs an all zero row`); + } + assert.deepEqual( + unpriced, + [], + `NVIDIA registry models without a pricing row: ${unpriced.join(", ")}` + ); +});