Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/fixes/18464-nvidia-missing-pricing-rows.md
Original file line number Diff line number Diff line change
@@ -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))
34 changes: 34 additions & 0 deletions src/shared/constants/pricing/inference-hosts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
Expand Down
47 changes: 47 additions & 0 deletions tests/unit/nvidia-registry-pricing-18464.test.ts
Original file line number Diff line number Diff line change
@@ -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<string>([
"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<string, Record<string, Record<string, number>>>;
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(", ")}`
);
});
Loading