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 open-sse/config/freeModelCatalog.data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ export const FREE_MODEL_BUDGETS: FreeModelBudget[] = [
{ provider: "nscale", modelId: "meta-llama/Llama-4-Scout-17B-16E-Instruct", displayName: "meta-llama/Llama-4-Scout-17B-16E-Instruct", monthlyTokens: 0, creditTokens: 5000000, freeType: "one-time-initial", poolKey: "nscale", tos: "caution" },
{ provider: "nscale", modelId: "meta-llama/Llama-3.3-70B-Instruct", displayName: "meta-llama/Llama-3.3-70B-Instruct", monthlyTokens: 0, creditTokens: 5000000, freeType: "one-time-initial", poolKey: "nscale", tos: "caution" },
{ provider: "nvidia", modelId: "z-ai/glm-5.1", displayName: "GLM 5.1", monthlyTokens: 0, creditTokens: 0, freeType: "one-time-initial", poolKey: "nvidia", tos: "caution" },
{ provider: "nvidia", modelId: "z-ai/glm-5.2", displayName: "GLM 5.2", monthlyTokens: 0, creditTokens: 0, freeType: "one-time-initial", poolKey: "nvidia", tos: "caution" },
{ provider: "nvidia", modelId: "minimaxai/minimax-m2.7", displayName: "MiniMax M2.7", monthlyTokens: 0, creditTokens: 0, freeType: "one-time-initial", poolKey: "nvidia", tos: "caution" },
{ provider: "nvidia", modelId: "google/gemma-4-31b-it", displayName: "Gemma 4 31B", monthlyTokens: 0, creditTokens: 0, freeType: "one-time-initial", poolKey: "nvidia", tos: "caution" },
{ provider: "nvidia", modelId: "mistralai/mistral-small-4-119b-2603", displayName: "Mistral Small 4 2603", monthlyTokens: 0, creditTokens: 0, freeType: "one-time-initial", poolKey: "nvidia", tos: "caution" },
Expand Down
18 changes: 18 additions & 0 deletions open-sse/config/nvidiaHostedModels.snapshot.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[
"deepseek-ai/deepseek-v4-pro",
"google/gemma-4-31b-it",
"minimaxai/minimax-m2.7",
"mistralai/devstral-2-123b-instruct-2512",
"mistralai/mistral-large-3-675b-instruct-2512",
"mistralai/mistral-small-4-119b-2603",
"nvidia/nemotron-3-super-120b-a12b",
"openai/gpt-oss-120b",
"openai/gpt-oss-20b",
"poolside/laguna-xs-2.1",
"qwen/qwen3.5-122b-a10b",
"qwen/qwen3.5-397b-a17b",
"stepfun-ai/step-3.5-flash",
"thinkingmachines/inkling",
"z-ai/glm-5.1",
"z-ai/glm-5.2"
]
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@
"check:openapi-security-tiers": "node scripts/check/check-openapi-security-tiers.mjs",
"check:provider-consistency": "bun scripts/check/check-provider-consistency.ts",
"check:provider-assets": "node scripts/check/check-provider-assets.mjs",
"check:nvidia-catalog-drift": "node --import tsx/esm scripts/check/check-nvidia-catalog-drift.ts",
"check:fetch-targets": "node scripts/check/check-fetch-targets.mjs",
"check:openapi-routes": "node scripts/check/check-openapi-routes.mjs",
"check:api-docs-refs": "node scripts/check/check-api-docs-refs.mjs",
Expand Down
108 changes: 108 additions & 0 deletions scripts/check/check-nvidia-catalog-drift.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { FREE_MODEL_BUDGETS } from "../../open-sse/config/freeModelCatalog.data.ts";
import reviewedLiveIds from "../../open-sse/config/nvidiaHostedModels.snapshot.json" with { type: "json" };

const NVIDIA_MODELS_URL = "https://integrate.api.nvidia.com/v1/models";

export interface NvidiaCatalogDrift {
liveCount: number;
reviewedLiveCount: number;
documentedFreeCount: number;
newLiveIds: string[];
removedLiveIds: string[];
documentedMissingUpstreamIds: string[];
}

function normalizeIds(ids: Iterable<string>): Set<string> {
return new Set(
[...ids].filter((id) => typeof id === "string" && id.trim().length > 0).map((id) => id.trim())
);
}

export function computeNvidiaCatalogDrift(
liveIdsInput: Iterable<string>,
reviewedLiveIdsInput: Iterable<string>,
documentedFreeIdsInput: Iterable<string>
): NvidiaCatalogDrift {
const liveIds = normalizeIds(liveIdsInput);
const reviewedIds = normalizeIds(reviewedLiveIdsInput);
const documentedFreeIds = normalizeIds(documentedFreeIdsInput);
return {
liveCount: liveIds.size,
reviewedLiveCount: reviewedIds.size,
documentedFreeCount: documentedFreeIds.size,
newLiveIds: [...liveIds].filter((id) => !reviewedIds.has(id)).sort(),
removedLiveIds: [...reviewedIds].filter((id) => !liveIds.has(id)).sort(),
documentedMissingUpstreamIds: [...documentedFreeIds].filter((id) => !liveIds.has(id)).sort(),
};
}

function printIds(label: string, ids: string[]): void {
console.log(`${label} (${ids.length})`);
for (const id of ids) console.log(` - ${id}`);
}

async function main(): Promise<void> {
const apiKey = process.env.NVIDIA_API_KEY?.trim();
if (!apiKey) {
console.error("NVIDIA_API_KEY is required to query the live NVIDIA NIM model catalog.");
process.exitCode = 2;
return;
}

let liveIds: string[] = [];
try {
const response = await fetch(NVIDIA_MODELS_URL, {
headers: { Authorization: `Bearer ${apiKey}`, Accept: "application/json" },
signal: AbortSignal.timeout(30_000),
});
if (!response.ok) {
console.error(`NVIDIA model catalog returned HTTP ${response.status}.`);
process.exitCode = 2;
return;
}

const body = (await response.json()) as { data?: Array<{ id?: unknown }> } | null;
liveIds = (body && Array.isArray(body.data) ? body.data : [])
.map((model) => model?.id)
.filter((id): id is string => typeof id === "string");
} catch (error) {
console.error(
"Failed to fetch or parse NVIDIA model catalog:",
error instanceof Error ? error.message : error
);
process.exitCode = 2;
return;
}
const documentedFreeIds = FREE_MODEL_BUDGETS.filter((model) => model.provider === "nvidia").map(
(model) => model.modelId
);
const drift = computeNvidiaCatalogDrift(liveIds, reviewedLiveIds, documentedFreeIds);
Comment thread
JxnLexn marked this conversation as resolved.
Resolved

console.log(
`NVIDIA catalog: ${drift.liveCount} live model(s), ${drift.reviewedLiveCount} reviewed live model(s), ${drift.documentedFreeCount} documented free/trial model(s).`
);
printIds("New live models requiring metadata review", drift.newLiveIds);
printIds("Reviewed models removed from the live catalog", drift.removedLiveIds);
printIds(
"Documented free models missing from the live catalog",
drift.documentedMissingUpstreamIds
);

if (
drift.newLiveIds.length ||
drift.removedLiveIds.length ||
drift.documentedMissingUpstreamIds.length
) {
console.warn(
"Catalog drift requires review. Availability alone does not prove that a model is free; verify NVIDIA's model page before updating FREE_MODEL_BUDGETS."
);
if (process.argv.includes("--strict")) process.exitCode = 1;
} else {
console.log("No NVIDIA catalog drift detected.");
}
}

const isDirectExecution = process.argv[1]?.endsWith("check-nvidia-catalog-drift.ts");
if (isDirectExecution) {
await main();
}
4 changes: 4 additions & 0 deletions tests/unit/free-models.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ test("isFreeModel: a model id listed in the free catalog for that provider is fr
assert.equal(isFreeModel(sample.provider, { id: sample.modelId }), true);
});

test("isFreeModel: NVIDIA GLM 5.2 is included in the reviewed trial catalog", () => {
assert.equal(isFreeModel("nvidia", { id: "z-ai/glm-5.2" }), true);
});

test("selectModelsForImport: passthrough when importFreeOnly is false", () => {
const models = [
{ id: "a:free" },
Expand Down
28 changes: 28 additions & 0 deletions tests/unit/nvidia-catalog-drift.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { test } from "node:test";
import assert from "node:assert/strict";
import { computeNvidiaCatalogDrift } from "../../scripts/check/check-nvidia-catalog-drift.ts";

test("NVIDIA catalog drift separates new live ids from removed documented ids", () => {
assert.deepEqual(
computeNvidiaCatalogDrift(
["z-ai/glm-5.2", "openai/gpt-oss-120b", "new/model", "new/model"],
["z-ai/glm-5.2", "openai/gpt-oss-120b", "removed/model"],
["z-ai/glm-5.2", "openai/gpt-oss-120b", "retired/model"]
),
{
liveCount: 3,
reviewedLiveCount: 3,
documentedFreeCount: 3,
newLiveIds: ["new/model"],
removedLiveIds: ["removed/model"],
documentedMissingUpstreamIds: ["retired/model"],
}
);
});

test("NVIDIA catalog drift is empty when live and documented ids match", () => {
const drift = computeNvidiaCatalogDrift(["b", "a"], ["a", "b"], ["a"]);
assert.deepEqual(drift.newLiveIds, []);
assert.deepEqual(drift.removedLiveIds, []);
assert.deepEqual(drift.documentedMissingUpstreamIds, []);
});
Loading