mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-26 20:35:39 -06:00
fix(nvidia): sync recommended models with featured catalog (#99242)
* fix(nvidia): refresh bundled featured models * fix(nvidia): match featured model feed exactly * fix(nvidia): remove transient feed detail * fix(nvidia): correct super context window * fix(nvidia): align auth choice expectation * fix(nvidia): hide deprecated models from selection Refresh the bundled featured catalog while retaining deprecated model metadata for exact-reference compatibility. Route NVIDIA onboarding and catalog picker surfaces through selectable-only provider builders. * fix(nvidia): simplify featured model table * fix(nvidia): restore shipped compatibility rows
This commit is contained in:
+23
-15
@@ -84,8 +84,6 @@ OpenClaw falls back to the bundled catalog and bundled default below.
|
||||
Nemotron 3 Ultra is the default NVIDIA model in OpenClaw. NVIDIA's build page for
|
||||
[`nvidia/nemotron-3-ultra-550b-a55b`](https://build.nvidia.com/nvidia/nemotron-3-ultra-550b-a55b)
|
||||
lists it as an available free endpoint with a 1M-token context specification.
|
||||
The bundled catalog records a 16,384-token max output to match NVIDIA's current
|
||||
OpenAI-compatible sample request for the hosted endpoint.
|
||||
|
||||
The bundled Ultra row sends
|
||||
`chat_template_kwargs: { enable_thinking: false, force_nonempty_content: true }`
|
||||
@@ -98,15 +96,25 @@ hosted in NVIDIA's catalog when their context, latency, or behavior fits better.
|
||||
|
||||
## Bundled fallback catalog
|
||||
|
||||
| Model ref | Name | Context | Max output | Notes |
|
||||
| ------------------------------------------ | ---------------------------- | --------- | ---------- | ---------------------------------------- |
|
||||
| `nvidia/nvidia/nemotron-3-ultra-550b-a55b` | NVIDIA Nemotron 3 Ultra 550B | 1,000,000 | 16,384 | Default |
|
||||
| `nvidia/nvidia/nemotron-3-super-120b-a12b` | NVIDIA Nemotron 3 Super 120B | 1,048,576 | 8,192 | |
|
||||
| `nvidia/moonshotai/kimi-k2.5` | Kimi K2.5 | 262,144 | 8,192 | |
|
||||
| `nvidia/minimaxai/minimax-m2.7` | Minimax M2.7 | 196,608 | 8,192 | |
|
||||
| `nvidia/z-ai/glm-5.1` | GLM 5.1 | 202,752 | 8,192 | |
|
||||
| `nvidia/minimaxai/minimax-m2.5` | MiniMax M2.5 | 196,608 | 8,192 | Deprecated; use `minimaxai/minimax-m2.7` |
|
||||
| `nvidia/z-ai/glm5` | GLM-5 | 202,752 | 8,192 | Deprecated; use `z-ai/glm-5.1` |
|
||||
The selectable bundled rows snapshot NVIDIA's featured-model catalog. Deprecated
|
||||
compatibility rows remain resolvable by exact reference but stay out of model
|
||||
pickers.
|
||||
|
||||
| Model ref | Name | Context | Max output |
|
||||
| ------------------------------------------ | --------------------- | --------- | ---------- |
|
||||
| `nvidia/nvidia/nemotron-3-ultra-550b-a55b` | Nemotron 3 Ultra 550B | 1,048,576 | 8,192 |
|
||||
| `nvidia/nvidia/nemotron-3-super-120b-a12b` | Nemotron 3 Super 120B | 1,000,000 | 8,192 |
|
||||
| `nvidia/z-ai/glm-5.2` | GLM 5.2 | 202,752 | 8,192 |
|
||||
| `nvidia/moonshotai/kimi-k2.6` | Kimi K2.6 | 262,144 | 8,192 |
|
||||
| `nvidia/minimaxai/minimax-m3` | Minimax M3 | 196,608 | 8,192 |
|
||||
| `nvidia/deepseek-ai/deepseek-v4-pro` | DeepSeek V4 Pro | 262,144 | 16,384 |
|
||||
| `nvidia/qwen/qwen3.5-397b-a17b` | Qwen3.5 397B A17B | 262,144 | 16,384 |
|
||||
|
||||
The full compatibility catalog also retains these shipped refs for existing
|
||||
configurations: `nvidia/moonshotai/kimi-k2.5`, `nvidia/z-ai/glm-5.1`,
|
||||
`nvidia/minimaxai/minimax-m2.5`, `nvidia/z-ai/glm5`, and
|
||||
`nvidia/minimaxai/minimax-m2.7`. They remain available by exact reference but
|
||||
never appear in onboarding or model pickers.
|
||||
|
||||
## Advanced configuration
|
||||
|
||||
@@ -119,10 +127,10 @@ hosted in NVIDIA's catalog when their context, latency, or behavior fits better.
|
||||
|
||||
<Accordion title="Catalog and pricing">
|
||||
OpenClaw prefers NVIDIA's public featured-model catalog when NVIDIA auth is
|
||||
configured and caches it for 24 hours. The bundled fallback catalog is static
|
||||
and keeps deprecated shipped refs for upgrade compatibility. Costs default
|
||||
to `0` in source since NVIDIA currently offers free API access for the
|
||||
listed models.
|
||||
configured and caches it for 24 hours. The bundled selectable fallback is a
|
||||
static snapshot of NVIDIA's featured-model catalog; deprecated exact-reference
|
||||
compatibility rows are hidden from model pickers. Costs default to `0` in
|
||||
source since NVIDIA currently offers free API access for the listed models.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="OpenAI-compatible endpoint">
|
||||
|
||||
@@ -209,11 +209,11 @@ describe("nvidia provider hooks", () => {
|
||||
expect(entries?.map((entry) => entry.id)).toEqual([
|
||||
"nvidia/nemotron-3-ultra-550b-a55b",
|
||||
"nvidia/nemotron-3-super-120b-a12b",
|
||||
"moonshotai/kimi-k2.5",
|
||||
"minimaxai/minimax-m2.7",
|
||||
"z-ai/glm-5.1",
|
||||
"minimaxai/minimax-m2.5",
|
||||
"z-ai/glm5",
|
||||
"z-ai/glm-5.2",
|
||||
"moonshotai/kimi-k2.6",
|
||||
"minimaxai/minimax-m3",
|
||||
"deepseek-ai/deepseek-v4-pro",
|
||||
"qwen/qwen3.5-397b-a17b",
|
||||
]);
|
||||
expect(entries?.every((entry) => entry.provider === "nvidia")).toBe(true);
|
||||
expect(ssrfRuntimeMocks.fetchWithSsrFGuard).not.toHaveBeenCalled();
|
||||
@@ -228,11 +228,11 @@ describe("nvidia provider hooks", () => {
|
||||
expect(entries?.map((entry) => entry.id)).toEqual([
|
||||
"nvidia/nemotron-3-ultra-550b-a55b",
|
||||
"nvidia/nemotron-3-super-120b-a12b",
|
||||
"moonshotai/kimi-k2.5",
|
||||
"minimaxai/minimax-m2.7",
|
||||
"z-ai/glm-5.1",
|
||||
"minimaxai/minimax-m2.5",
|
||||
"z-ai/glm5",
|
||||
"z-ai/glm-5.2",
|
||||
"moonshotai/kimi-k2.6",
|
||||
"minimaxai/minimax-m3",
|
||||
"deepseek-ai/deepseek-v4-pro",
|
||||
"qwen/qwen3.5-397b-a17b",
|
||||
]);
|
||||
expect(entries?.every((entry) => entry.provider === "nvidia")).toBe(true);
|
||||
expect(ssrfRuntimeMocks.fetchWithSsrFGuard).toHaveBeenCalledTimes(1);
|
||||
@@ -242,8 +242,8 @@ describe("nvidia provider hooks", () => {
|
||||
mockFeaturedCatalogResponse({
|
||||
"featured-models": [
|
||||
{
|
||||
model: "minimaxai/minimax-m2.7",
|
||||
"model-name": "Minimax M2.7",
|
||||
model: "minimaxai/minimax-m3",
|
||||
"model-name": "Minimax M3",
|
||||
context: 196608,
|
||||
"max-output": 8192,
|
||||
},
|
||||
@@ -253,7 +253,7 @@ describe("nvidia provider hooks", () => {
|
||||
|
||||
const entries = await provider.augmentModelCatalog?.(buildAugmentCatalogContext("nvapi-test"));
|
||||
|
||||
expect(entries?.map((entry) => entry.id)).toEqual(["minimaxai/minimax-m2.7"]);
|
||||
expect(entries?.map((entry) => entry.id)).toEqual(["minimaxai/minimax-m3"]);
|
||||
});
|
||||
|
||||
it("opts into literal provider-prefix preservation", async () => {
|
||||
@@ -280,8 +280,8 @@ describe("nvidia provider hooks", () => {
|
||||
mockFeaturedCatalogResponse({
|
||||
"featured-models": [
|
||||
{
|
||||
model: "minimaxai/minimax-m2.7",
|
||||
"model-name": "Minimax M2.7",
|
||||
model: "minimaxai/minimax-m3",
|
||||
"model-name": "Minimax M3",
|
||||
context: 196608,
|
||||
"max-output": 8192,
|
||||
},
|
||||
@@ -297,18 +297,18 @@ describe("nvidia provider hooks", () => {
|
||||
expect(staticRows?.map((entry) => `${entry.source}:${entry.provider}/${entry.model}`)).toEqual([
|
||||
"static:nvidia/nvidia/nemotron-3-ultra-550b-a55b",
|
||||
"static:nvidia/nvidia/nemotron-3-super-120b-a12b",
|
||||
"static:nvidia/moonshotai/kimi-k2.5",
|
||||
"static:nvidia/minimaxai/minimax-m2.7",
|
||||
"static:nvidia/z-ai/glm-5.1",
|
||||
"static:nvidia/minimaxai/minimax-m2.5",
|
||||
"static:nvidia/z-ai/glm5",
|
||||
"static:nvidia/z-ai/glm-5.2",
|
||||
"static:nvidia/moonshotai/kimi-k2.6",
|
||||
"static:nvidia/minimaxai/minimax-m3",
|
||||
"static:nvidia/deepseek-ai/deepseek-v4-pro",
|
||||
"static:nvidia/qwen/qwen3.5-397b-a17b",
|
||||
]);
|
||||
|
||||
await expect(catalogProvider?.liveCatalog?.(buildCatalogContext())).resolves.toEqual([]);
|
||||
|
||||
const liveRows = await catalogProvider?.liveCatalog?.(buildCatalogContext("nvapi-test"));
|
||||
expect(liveRows?.map((entry) => `${entry.source}:${entry.provider}/${entry.model}`)).toEqual([
|
||||
"live:nvidia/minimaxai/minimax-m2.7",
|
||||
"live:nvidia/minimaxai/minimax-m3",
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { defineSingleProviderPluginEntry } from "openclaw/plugin-sdk/provider-en
|
||||
import { applyNvidiaConfig, NVIDIA_DEFAULT_MODEL_REF } from "./onboard.js";
|
||||
import {
|
||||
buildLiveNvidiaProvider,
|
||||
buildNvidiaProvider,
|
||||
buildSelectableNvidiaProvider,
|
||||
buildSelectableLiveNvidiaProvider,
|
||||
} from "./provider-catalog.js";
|
||||
|
||||
@@ -22,7 +22,9 @@ async function buildNvidiaCatalogModels(ctx: {
|
||||
env: NodeJS.ProcessEnv;
|
||||
resolveProviderApiKey?: (providerId?: string) => { apiKey: string | undefined };
|
||||
}) {
|
||||
const provider = hasNvidiaApiToken(ctx) ? await buildLiveNvidiaProvider() : buildNvidiaProvider();
|
||||
const provider = hasNvidiaApiToken(ctx)
|
||||
? await buildLiveNvidiaProvider()
|
||||
: buildSelectableNvidiaProvider();
|
||||
return provider.models.map((model) => ({
|
||||
provider: PROVIDER_ID,
|
||||
id: model.id,
|
||||
@@ -57,7 +59,7 @@ export default defineSingleProviderPluginEntry({
|
||||
],
|
||||
catalog: {
|
||||
buildProvider: buildSelectableLiveNvidiaProvider,
|
||||
buildStaticProvider: buildNvidiaProvider,
|
||||
buildStaticProvider: buildSelectableNvidiaProvider,
|
||||
},
|
||||
augmentModelCatalog: buildNvidiaCatalogModels,
|
||||
wizard: {
|
||||
|
||||
@@ -18,11 +18,11 @@ describe("nvidia onboard", () => {
|
||||
expect(provider.models.map((model) => model.id)).toEqual([
|
||||
"nvidia/nemotron-3-ultra-550b-a55b",
|
||||
"nvidia/nemotron-3-super-120b-a12b",
|
||||
"moonshotai/kimi-k2.5",
|
||||
"minimaxai/minimax-m2.7",
|
||||
"z-ai/glm-5.1",
|
||||
"minimaxai/minimax-m2.5",
|
||||
"z-ai/glm5",
|
||||
"z-ai/glm-5.2",
|
||||
"moonshotai/kimi-k2.6",
|
||||
"minimaxai/minimax-m3",
|
||||
"deepseek-ai/deepseek-v4-pro",
|
||||
"qwen/qwen3.5-397b-a17b",
|
||||
]);
|
||||
// Config stores the canonical form; the picker label shows the literal
|
||||
// form via preserveLiteralProviderPrefix.
|
||||
@@ -46,11 +46,34 @@ describe("nvidia onboard", () => {
|
||||
"nvidia/custom-model",
|
||||
"nvidia/nemotron-3-ultra-550b-a55b",
|
||||
"nvidia/nemotron-3-super-120b-a12b",
|
||||
"z-ai/glm-5.2",
|
||||
"moonshotai/kimi-k2.6",
|
||||
"minimaxai/minimax-m3",
|
||||
"deepseek-ai/deepseek-v4-pro",
|
||||
"qwen/qwen3.5-397b-a17b",
|
||||
]);
|
||||
});
|
||||
|
||||
it("preserves an existing deprecated exact-reference model", () => {
|
||||
const provider = expectProviderOnboardMergedLegacyConfig({
|
||||
applyProviderConfig: applyNvidiaProviderConfig,
|
||||
providerId: "nvidia",
|
||||
providerApi: "openai-completions",
|
||||
baseUrl: "https://integrate.api.nvidia.com/v1",
|
||||
legacyApi: "openai-completions",
|
||||
legacyModelId: "moonshotai/kimi-k2.5",
|
||||
legacyModelName: "Kimi K2.5",
|
||||
});
|
||||
|
||||
expect(provider?.models.map((model) => model.id)).toEqual([
|
||||
"moonshotai/kimi-k2.5",
|
||||
"minimaxai/minimax-m2.7",
|
||||
"z-ai/glm-5.1",
|
||||
"minimaxai/minimax-m2.5",
|
||||
"z-ai/glm5",
|
||||
"nvidia/nemotron-3-ultra-550b-a55b",
|
||||
"nvidia/nemotron-3-super-120b-a12b",
|
||||
"z-ai/glm-5.2",
|
||||
"moonshotai/kimi-k2.6",
|
||||
"minimaxai/minimax-m3",
|
||||
"deepseek-ai/deepseek-v4-pro",
|
||||
"qwen/qwen3.5-397b-a17b",
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,14 +3,14 @@ import {
|
||||
createDefaultModelsPresetAppliers,
|
||||
type OpenClawConfig,
|
||||
} from "openclaw/plugin-sdk/provider-onboard";
|
||||
import { buildNvidiaProvider, NVIDIA_DEFAULT_MODEL_ID } from "./provider-catalog.js";
|
||||
import { buildSelectableNvidiaProvider, NVIDIA_DEFAULT_MODEL_ID } from "./provider-catalog.js";
|
||||
|
||||
export const NVIDIA_DEFAULT_MODEL_REF = NVIDIA_DEFAULT_MODEL_ID;
|
||||
|
||||
const nvidiaPresetAppliers = createDefaultModelsPresetAppliers({
|
||||
primaryModelRef: NVIDIA_DEFAULT_MODEL_REF,
|
||||
resolveParams: (_cfg: OpenClawConfig) => {
|
||||
const defaultProvider = buildNvidiaProvider();
|
||||
const defaultProvider = buildSelectableNvidiaProvider();
|
||||
return {
|
||||
providerId: "nvidia",
|
||||
api: defaultProvider.api ?? "openai-completions",
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
"models": [
|
||||
{
|
||||
"id": "nvidia/nemotron-3-ultra-550b-a55b",
|
||||
"name": "NVIDIA Nemotron 3 Ultra 550B",
|
||||
"name": "Nemotron 3 Ultra 550B",
|
||||
"input": ["text"],
|
||||
"contextWindow": 1000000,
|
||||
"maxTokens": 16384,
|
||||
"contextWindow": 1048576,
|
||||
"maxTokens": 8192,
|
||||
"cost": {
|
||||
"input": 0,
|
||||
"output": 0,
|
||||
@@ -44,9 +44,9 @@
|
||||
},
|
||||
{
|
||||
"id": "nvidia/nemotron-3-super-120b-a12b",
|
||||
"name": "NVIDIA Nemotron 3 Super 120B",
|
||||
"name": "Nemotron 3 Super 120B",
|
||||
"input": ["text"],
|
||||
"contextWindow": 1048576,
|
||||
"contextWindow": 1000000,
|
||||
"maxTokens": 8192,
|
||||
"cost": {
|
||||
"input": 0,
|
||||
@@ -58,6 +58,86 @@
|
||||
"requiresStringContent": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "z-ai/glm-5.2",
|
||||
"name": "GLM 5.2",
|
||||
"input": ["text"],
|
||||
"contextWindow": 202752,
|
||||
"maxTokens": 8192,
|
||||
"cost": {
|
||||
"input": 0,
|
||||
"output": 0,
|
||||
"cacheRead": 0,
|
||||
"cacheWrite": 0
|
||||
},
|
||||
"compat": {
|
||||
"requiresStringContent": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "moonshotai/kimi-k2.6",
|
||||
"name": "Kimi K2.6",
|
||||
"input": ["text"],
|
||||
"contextWindow": 262144,
|
||||
"maxTokens": 8192,
|
||||
"cost": {
|
||||
"input": 0,
|
||||
"output": 0,
|
||||
"cacheRead": 0,
|
||||
"cacheWrite": 0
|
||||
},
|
||||
"compat": {
|
||||
"requiresStringContent": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "minimaxai/minimax-m3",
|
||||
"name": "Minimax M3",
|
||||
"input": ["text"],
|
||||
"contextWindow": 196608,
|
||||
"maxTokens": 8192,
|
||||
"cost": {
|
||||
"input": 0,
|
||||
"output": 0,
|
||||
"cacheRead": 0,
|
||||
"cacheWrite": 0
|
||||
},
|
||||
"compat": {
|
||||
"requiresStringContent": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "deepseek-ai/deepseek-v4-pro",
|
||||
"name": "DeepSeek V4 Pro",
|
||||
"input": ["text"],
|
||||
"contextWindow": 262144,
|
||||
"maxTokens": 16384,
|
||||
"cost": {
|
||||
"input": 0,
|
||||
"output": 0,
|
||||
"cacheRead": 0,
|
||||
"cacheWrite": 0
|
||||
},
|
||||
"compat": {
|
||||
"requiresStringContent": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "qwen/qwen3.5-397b-a17b",
|
||||
"name": "Qwen3.5 397B A17B",
|
||||
"input": ["text"],
|
||||
"contextWindow": 262144,
|
||||
"maxTokens": 16384,
|
||||
"cost": {
|
||||
"input": 0,
|
||||
"output": 0,
|
||||
"cacheRead": 0,
|
||||
"cacheWrite": 0
|
||||
},
|
||||
"compat": {
|
||||
"requiresStringContent": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "moonshotai/kimi-k2.5",
|
||||
"name": "Kimi K2.5",
|
||||
@@ -72,23 +152,10 @@
|
||||
},
|
||||
"compat": {
|
||||
"requiresStringContent": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "minimaxai/minimax-m2.7",
|
||||
"name": "Minimax M2.7",
|
||||
"input": ["text"],
|
||||
"contextWindow": 196608,
|
||||
"maxTokens": 8192,
|
||||
"cost": {
|
||||
"input": 0,
|
||||
"output": 0,
|
||||
"cacheRead": 0,
|
||||
"cacheWrite": 0
|
||||
},
|
||||
"compat": {
|
||||
"requiresStringContent": true
|
||||
}
|
||||
"status": "deprecated",
|
||||
"statusReason": "Still available by exact reference; use moonshotai/kimi-k2.6 for new NVIDIA setups.",
|
||||
"replacedBy": "moonshotai/kimi-k2.6"
|
||||
},
|
||||
{
|
||||
"id": "z-ai/glm-5.1",
|
||||
@@ -104,7 +171,10 @@
|
||||
},
|
||||
"compat": {
|
||||
"requiresStringContent": true
|
||||
}
|
||||
},
|
||||
"status": "deprecated",
|
||||
"statusReason": "Still available by exact reference; use z-ai/glm-5.2 for new NVIDIA setups.",
|
||||
"replacedBy": "z-ai/glm-5.2"
|
||||
},
|
||||
{
|
||||
"id": "minimaxai/minimax-m2.5",
|
||||
@@ -122,8 +192,8 @@
|
||||
"requiresStringContent": true
|
||||
},
|
||||
"status": "deprecated",
|
||||
"statusReason": "Shipped compatibility row; use minimaxai/minimax-m2.7 for new NVIDIA setups.",
|
||||
"replacedBy": "minimaxai/minimax-m2.7"
|
||||
"statusReason": "Still available by exact reference; use minimaxai/minimax-m3 for new NVIDIA setups.",
|
||||
"replacedBy": "minimaxai/minimax-m3"
|
||||
},
|
||||
{
|
||||
"id": "z-ai/glm5",
|
||||
@@ -141,8 +211,27 @@
|
||||
"requiresStringContent": true
|
||||
},
|
||||
"status": "deprecated",
|
||||
"statusReason": "Shipped compatibility row; use z-ai/glm-5.1 for new NVIDIA setups.",
|
||||
"replacedBy": "z-ai/glm-5.1"
|
||||
"statusReason": "Still available by exact reference; use z-ai/glm-5.2 for new NVIDIA setups.",
|
||||
"replacedBy": "z-ai/glm-5.2"
|
||||
},
|
||||
{
|
||||
"id": "minimaxai/minimax-m2.7",
|
||||
"name": "Minimax M2.7",
|
||||
"input": ["text"],
|
||||
"contextWindow": 196608,
|
||||
"maxTokens": 8192,
|
||||
"cost": {
|
||||
"input": 0,
|
||||
"output": 0,
|
||||
"cacheRead": 0,
|
||||
"cacheWrite": 0
|
||||
},
|
||||
"compat": {
|
||||
"requiresStringContent": true
|
||||
},
|
||||
"status": "deprecated",
|
||||
"statusReason": "Still available by exact reference; use minimaxai/minimax-m3 for new NVIDIA setups.",
|
||||
"replacedBy": "minimaxai/minimax-m3"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,13 +1,88 @@
|
||||
// Nvidia tests cover provider catalog plugin behavior.
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import manifest from "./openclaw.plugin.json" with { type: "json" };
|
||||
import {
|
||||
buildLiveNvidiaProvider,
|
||||
buildNvidiaProvider,
|
||||
buildSelectableNvidiaProvider,
|
||||
buildSelectableLiveNvidiaProvider,
|
||||
clearNvidiaFeaturedModelCacheForTests,
|
||||
NVIDIA_FEATURED_MODELS_URL,
|
||||
} from "./provider-catalog.js";
|
||||
|
||||
const EXPECTED_FEATURED_MODELS = [
|
||||
{
|
||||
id: "nvidia/nemotron-3-ultra-550b-a55b",
|
||||
name: "Nemotron 3 Ultra 550B",
|
||||
contextWindow: 1_048_576,
|
||||
maxTokens: 8_192,
|
||||
},
|
||||
{
|
||||
id: "nvidia/nemotron-3-super-120b-a12b",
|
||||
name: "Nemotron 3 Super 120B",
|
||||
contextWindow: 1_000_000,
|
||||
maxTokens: 8_192,
|
||||
},
|
||||
{ id: "z-ai/glm-5.2", name: "GLM 5.2", contextWindow: 202_752, maxTokens: 8_192 },
|
||||
{
|
||||
id: "moonshotai/kimi-k2.6",
|
||||
name: "Kimi K2.6",
|
||||
contextWindow: 262_144,
|
||||
maxTokens: 8_192,
|
||||
},
|
||||
{
|
||||
id: "minimaxai/minimax-m3",
|
||||
name: "Minimax M3",
|
||||
contextWindow: 196_608,
|
||||
maxTokens: 8_192,
|
||||
},
|
||||
{
|
||||
id: "deepseek-ai/deepseek-v4-pro",
|
||||
name: "DeepSeek V4 Pro",
|
||||
contextWindow: 262_144,
|
||||
maxTokens: 16_384,
|
||||
},
|
||||
{
|
||||
id: "qwen/qwen3.5-397b-a17b",
|
||||
name: "Qwen3.5 397B A17B",
|
||||
contextWindow: 262_144,
|
||||
maxTokens: 16_384,
|
||||
},
|
||||
] as const;
|
||||
|
||||
const EXPECTED_DEPRECATED_MODELS = [
|
||||
{
|
||||
id: "moonshotai/kimi-k2.5",
|
||||
name: "Kimi K2.5",
|
||||
contextWindow: 262_144,
|
||||
maxTokens: 8_192,
|
||||
},
|
||||
{
|
||||
id: "z-ai/glm-5.1",
|
||||
name: "GLM 5.1",
|
||||
contextWindow: 202_752,
|
||||
maxTokens: 8_192,
|
||||
},
|
||||
{
|
||||
id: "minimaxai/minimax-m2.5",
|
||||
name: "MiniMax M2.5",
|
||||
contextWindow: 196_608,
|
||||
maxTokens: 8_192,
|
||||
},
|
||||
{ id: "z-ai/glm5", name: "GLM-5", contextWindow: 202_752, maxTokens: 8_192 },
|
||||
{
|
||||
id: "minimaxai/minimax-m2.7",
|
||||
name: "Minimax M2.7",
|
||||
contextWindow: 196_608,
|
||||
maxTokens: 8_192,
|
||||
},
|
||||
] as const;
|
||||
|
||||
const EXPECTED_BUNDLED_MODELS = [
|
||||
...EXPECTED_FEATURED_MODELS,
|
||||
...EXPECTED_DEPRECATED_MODELS,
|
||||
] as const;
|
||||
|
||||
const ssrfRuntimeMocks = vi.hoisted(() => ({
|
||||
fetchWithSsrFGuard: vi.fn(),
|
||||
ssrfPolicyFromHttpBaseUrlAllowedHostname: vi.fn((baseUrl: string) => ({
|
||||
@@ -41,21 +116,20 @@ describe("nvidia provider catalog", () => {
|
||||
expect(provider.baseUrl).toBe("https://integrate.api.nvidia.com/v1");
|
||||
expect(provider.api).toBe("openai-completions");
|
||||
expect(provider.apiKey).toBe("NVIDIA_API_KEY");
|
||||
expect(provider.models.map((model) => model.id)).toEqual([
|
||||
"nvidia/nemotron-3-ultra-550b-a55b",
|
||||
"nvidia/nemotron-3-super-120b-a12b",
|
||||
"moonshotai/kimi-k2.5",
|
||||
"minimaxai/minimax-m2.7",
|
||||
"z-ai/glm-5.1",
|
||||
"minimaxai/minimax-m2.5",
|
||||
"z-ai/glm5",
|
||||
]);
|
||||
expect(
|
||||
provider.models.map(({ id, name, contextWindow, maxTokens }) => ({
|
||||
id,
|
||||
name,
|
||||
contextWindow,
|
||||
maxTokens,
|
||||
})),
|
||||
).toEqual(EXPECTED_BUNDLED_MODELS);
|
||||
expect(provider.models.filter((model) => model.compat?.requiresStringContent !== true)).toEqual(
|
||||
[],
|
||||
);
|
||||
expect(provider.models[0]).toMatchObject({
|
||||
contextWindow: 1_000_000,
|
||||
maxTokens: 16_384,
|
||||
contextWindow: 1_048_576,
|
||||
maxTokens: 8_192,
|
||||
params: {
|
||||
chat_template_kwargs: {
|
||||
enable_thinking: false,
|
||||
@@ -65,16 +139,35 @@ describe("nvidia provider catalog", () => {
|
||||
});
|
||||
expect(provider.models[1]).toMatchObject({
|
||||
id: "nvidia/nemotron-3-super-120b-a12b",
|
||||
contextWindow: 1_048_576,
|
||||
contextWindow: 1_000_000,
|
||||
});
|
||||
expect(
|
||||
manifest.modelCatalog.providers.nvidia.models
|
||||
.filter((model) => "status" in model && model.status === "deprecated")
|
||||
.map((model) => ({ id: model.id, replacedBy: model.replacedBy })),
|
||||
).toEqual([
|
||||
{ id: "moonshotai/kimi-k2.5", replacedBy: "moonshotai/kimi-k2.6" },
|
||||
{ id: "z-ai/glm-5.1", replacedBy: "z-ai/glm-5.2" },
|
||||
{ id: "minimaxai/minimax-m2.5", replacedBy: "minimaxai/minimax-m3" },
|
||||
{ id: "z-ai/glm5", replacedBy: "z-ai/glm-5.2" },
|
||||
{ id: "minimaxai/minimax-m2.7", replacedBy: "minimaxai/minimax-m3" },
|
||||
]);
|
||||
});
|
||||
|
||||
it("keeps deprecated exact-reference rows out of the selectable catalog", () => {
|
||||
const provider = buildSelectableNvidiaProvider();
|
||||
|
||||
expect(provider.models.map((model) => model.id)).toEqual(
|
||||
EXPECTED_FEATURED_MODELS.map((model) => model.id),
|
||||
);
|
||||
});
|
||||
|
||||
it("promotes ranked models from NVIDIA's featured catalog", async () => {
|
||||
const release = mockFeaturedCatalogResponse({
|
||||
"featured-models": [
|
||||
{
|
||||
model: "z-ai/glm-5.1",
|
||||
"model-name": "GLM 5.1",
|
||||
model: "z-ai/glm-5.2",
|
||||
"model-name": "GLM 5.2",
|
||||
context: 202752,
|
||||
"max-output": 8192,
|
||||
},
|
||||
@@ -90,11 +183,11 @@ describe("nvidia provider catalog", () => {
|
||||
const provider = await buildLiveNvidiaProvider();
|
||||
|
||||
expect(provider.models.map((model) => model.id)).toEqual([
|
||||
"z-ai/glm-5.1",
|
||||
"z-ai/glm-5.2",
|
||||
"nvidia/nemotron-3-super-120b-a12b",
|
||||
]);
|
||||
expect(provider.models[0]).toMatchObject({
|
||||
name: "GLM 5.1",
|
||||
name: "GLM 5.2",
|
||||
contextWindow: 202752,
|
||||
maxTokens: 8192,
|
||||
compat: { requiresStringContent: true },
|
||||
@@ -117,22 +210,8 @@ describe("nvidia provider catalog", () => {
|
||||
|
||||
const provider = await buildLiveNvidiaProvider();
|
||||
|
||||
expect(provider.models.map((model) => model.id)).toEqual([
|
||||
"nvidia/nemotron-3-ultra-550b-a55b",
|
||||
"nvidia/nemotron-3-super-120b-a12b",
|
||||
"moonshotai/kimi-k2.5",
|
||||
"minimaxai/minimax-m2.7",
|
||||
"z-ai/glm-5.1",
|
||||
"minimaxai/minimax-m2.5",
|
||||
"z-ai/glm5",
|
||||
]);
|
||||
});
|
||||
|
||||
it("retains shipped NVIDIA model refs as bundled fallback compatibility rows", () => {
|
||||
const provider = buildNvidiaProvider();
|
||||
|
||||
expect(provider.models.map((model) => model.id)).toEqual(
|
||||
expect.arrayContaining(["minimaxai/minimax-m2.5", "z-ai/glm5"]),
|
||||
EXPECTED_FEATURED_MODELS.map((model) => model.id),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -140,8 +219,8 @@ describe("nvidia provider catalog", () => {
|
||||
mockFeaturedCatalogResponse({
|
||||
"featured-models": [
|
||||
{
|
||||
model: "z-ai/glm-5.1",
|
||||
"model-name": "GLM 5.1",
|
||||
model: "z-ai/glm-5.2",
|
||||
"model-name": "GLM 5.2",
|
||||
context: 202752,
|
||||
"max-output": 8192,
|
||||
},
|
||||
@@ -157,11 +236,75 @@ describe("nvidia provider catalog", () => {
|
||||
const provider = await buildSelectableLiveNvidiaProvider();
|
||||
|
||||
expect(provider.models.map((model) => model.id)).toEqual([
|
||||
"z-ai/glm-5.1",
|
||||
"z-ai/glm-5.2",
|
||||
"nvidia/nemotron-3-super-120b-a12b",
|
||||
]);
|
||||
});
|
||||
|
||||
it("keeps every deprecated exact-reference row out of live catalogs", async () => {
|
||||
mockFeaturedCatalogResponse({
|
||||
"featured-models": [
|
||||
{
|
||||
model: "minimaxai/minimax-m3",
|
||||
"model-name": "Minimax M3",
|
||||
context: 196608,
|
||||
"max-output": 8192,
|
||||
},
|
||||
...EXPECTED_DEPRECATED_MODELS.map((model) => ({
|
||||
model: model.id,
|
||||
"model-name": model.name,
|
||||
context: model.contextWindow,
|
||||
"max-output": model.maxTokens,
|
||||
})),
|
||||
],
|
||||
});
|
||||
|
||||
const live = await buildLiveNvidiaProvider();
|
||||
const selectableLive = await buildSelectableLiveNvidiaProvider();
|
||||
|
||||
expect(live.models.map((model) => model.id)).toEqual(["minimaxai/minimax-m3"]);
|
||||
expect(selectableLive.models.map((model) => model.id)).toEqual(["minimaxai/minimax-m3"]);
|
||||
});
|
||||
|
||||
it("maps current featured feed metadata for MiniMax, DeepSeek, and Qwen", async () => {
|
||||
mockFeaturedCatalogResponse({
|
||||
"featured-models": [
|
||||
{
|
||||
model: "minimaxai/minimax-m3",
|
||||
"model-name": "Minimax M3",
|
||||
context: 196608,
|
||||
"max-output": 8192,
|
||||
},
|
||||
{
|
||||
model: "deepseek-ai/deepseek-v4-pro",
|
||||
"model-name": "DeepSeek V4 Pro",
|
||||
context: 262144,
|
||||
"max-output": 16384,
|
||||
},
|
||||
{
|
||||
model: "qwen/qwen3.5-397b-a17b",
|
||||
"model-name": "Qwen3.5 397B A17B",
|
||||
context: 262144,
|
||||
"max-output": 16384,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
const provider = await buildLiveNvidiaProvider();
|
||||
|
||||
expect(
|
||||
provider.models.map(({ id, contextWindow, maxTokens }) => ({
|
||||
id,
|
||||
contextWindow,
|
||||
maxTokens,
|
||||
})),
|
||||
).toEqual([
|
||||
{ id: "minimaxai/minimax-m3", contextWindow: 196_608, maxTokens: 8_192 },
|
||||
{ id: "deepseek-ai/deepseek-v4-pro", contextWindow: 262_144, maxTokens: 16_384 },
|
||||
{ id: "qwen/qwen3.5-397b-a17b", contextWindow: 262_144, maxTokens: 16_384 },
|
||||
]);
|
||||
});
|
||||
|
||||
it("returns no selectable live rows when the featured catalog is unavailable", async () => {
|
||||
mockFeaturedCatalogResponse({ error: "unavailable" }, 503);
|
||||
|
||||
@@ -180,8 +323,8 @@ describe("nvidia provider catalog", () => {
|
||||
"max-output": 1000,
|
||||
},
|
||||
{
|
||||
model: "minimaxai/minimax-m2.7",
|
||||
"model-name": "Minimax M2.7",
|
||||
model: "minimaxai/minimax-m3",
|
||||
"model-name": "Minimax M3",
|
||||
context: 196608,
|
||||
"max-output": 8192,
|
||||
},
|
||||
@@ -196,15 +339,15 @@ describe("nvidia provider catalog", () => {
|
||||
|
||||
const provider = await buildLiveNvidiaProvider();
|
||||
|
||||
expect(provider.models.map((model) => model.id)).toEqual(["minimaxai/minimax-m2.7"]);
|
||||
expect(provider.models.map((model) => model.id)).toEqual(["minimaxai/minimax-m3"]);
|
||||
});
|
||||
|
||||
it("caches the featured catalog for repeated provider builds", async () => {
|
||||
mockFeaturedCatalogResponse({
|
||||
"featured-models": [
|
||||
{
|
||||
model: "minimaxai/minimax-m2.7",
|
||||
"model-name": "Minimax M2.7",
|
||||
model: "minimaxai/minimax-m3",
|
||||
"model-name": "Minimax M3",
|
||||
context: 196608,
|
||||
"max-output": 8192,
|
||||
},
|
||||
@@ -222,8 +365,8 @@ describe("nvidia provider catalog", () => {
|
||||
mockFeaturedCatalogResponse({
|
||||
"featured-models": [
|
||||
{
|
||||
model: "minimaxai/minimax-m2.7",
|
||||
"model-name": "Minimax M2.7",
|
||||
model: "minimaxai/minimax-m3",
|
||||
"model-name": "Minimax M3",
|
||||
context: 196608,
|
||||
"max-output": 8192,
|
||||
},
|
||||
@@ -232,8 +375,8 @@ describe("nvidia provider catalog", () => {
|
||||
mockFeaturedCatalogResponse({
|
||||
"featured-models": [
|
||||
{
|
||||
model: "z-ai/glm-5.1",
|
||||
"model-name": "GLM 5.1",
|
||||
model: "z-ai/glm-5.2",
|
||||
"model-name": "GLM 5.2",
|
||||
context: 202752,
|
||||
"max-output": 8192,
|
||||
},
|
||||
@@ -243,8 +386,8 @@ describe("nvidia provider catalog", () => {
|
||||
const first = await buildLiveNvidiaProvider();
|
||||
const second = await buildLiveNvidiaProvider();
|
||||
|
||||
expect(first.models.map((model) => model.id)).toEqual(["minimaxai/minimax-m2.7"]);
|
||||
expect(second.models.map((model) => model.id)).toEqual(["z-ai/glm-5.1"]);
|
||||
expect(first.models.map((model) => model.id)).toEqual(["minimaxai/minimax-m3"]);
|
||||
expect(second.models.map((model) => model.id)).toEqual(["z-ai/glm-5.2"]);
|
||||
expect(ssrfRuntimeMocks.fetchWithSsrFGuard).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
@@ -262,8 +405,8 @@ describe("nvidia provider catalog", () => {
|
||||
mockFeaturedCatalogResponse({
|
||||
"featured-models": [
|
||||
{
|
||||
model: "z-ai/glm-5.1",
|
||||
"model-name": "GLM 5.1",
|
||||
model: "z-ai/glm-5.2",
|
||||
"model-name": "GLM 5.2",
|
||||
context: 202752,
|
||||
"max-output": 8192,
|
||||
},
|
||||
@@ -273,16 +416,10 @@ describe("nvidia provider catalog", () => {
|
||||
const first = await buildLiveNvidiaProvider();
|
||||
const second = await buildLiveNvidiaProvider();
|
||||
|
||||
expect(first.models.map((model) => model.id)).toEqual([
|
||||
"nvidia/nemotron-3-ultra-550b-a55b",
|
||||
"nvidia/nemotron-3-super-120b-a12b",
|
||||
"moonshotai/kimi-k2.5",
|
||||
"minimaxai/minimax-m2.7",
|
||||
"z-ai/glm-5.1",
|
||||
"minimaxai/minimax-m2.5",
|
||||
"z-ai/glm5",
|
||||
]);
|
||||
expect(second.models.map((model) => model.id)).toEqual(["z-ai/glm-5.1"]);
|
||||
expect(first.models.map((model) => model.id)).toEqual(
|
||||
EXPECTED_FEATURED_MODELS.map((model) => model.id),
|
||||
);
|
||||
expect(second.models.map((model) => model.id)).toEqual(["z-ai/glm-5.2"]);
|
||||
expect(ssrfRuntimeMocks.fetchWithSsrFGuard).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
@@ -292,8 +429,8 @@ describe("nvidia provider catalog", () => {
|
||||
{
|
||||
model: "nemotron-3-ultra-550b-a55b",
|
||||
"model-name": "Nemotron 3 Ultra 550B",
|
||||
context: 1000000,
|
||||
"max-output": 16384,
|
||||
context: 1048576,
|
||||
"max-output": 8192,
|
||||
},
|
||||
{
|
||||
model: "minimaxai/minimax-m2.7",
|
||||
@@ -306,14 +443,11 @@ describe("nvidia provider catalog", () => {
|
||||
|
||||
const provider = await buildLiveNvidiaProvider();
|
||||
|
||||
expect(provider.models.map((model) => model.id)).toEqual([
|
||||
"nvidia/nemotron-3-ultra-550b-a55b",
|
||||
"minimaxai/minimax-m2.7",
|
||||
]);
|
||||
expect(provider.models.map((model) => model.id)).toEqual(["nvidia/nemotron-3-ultra-550b-a55b"]);
|
||||
expect(provider.models[0]).toMatchObject({
|
||||
name: "Nemotron 3 Ultra 550B",
|
||||
contextWindow: 1_000_000,
|
||||
maxTokens: 16_384,
|
||||
contextWindow: 1_048_576,
|
||||
maxTokens: 8_192,
|
||||
params: {
|
||||
chat_template_kwargs: {
|
||||
enable_thinking: false,
|
||||
|
||||
@@ -39,6 +39,11 @@ const NVIDIA_ULTRA_DEFAULT_PARAMS = {
|
||||
force_nonempty_content: true,
|
||||
},
|
||||
} as const;
|
||||
const DEPRECATED_NVIDIA_MODEL_IDS = new Set<string>(
|
||||
manifest.modelCatalog.providers.nvidia.models
|
||||
.filter((model) => "status" in model && model.status === "deprecated")
|
||||
.map((model) => model.id),
|
||||
);
|
||||
|
||||
type NvidiaFeaturedModel = {
|
||||
model: string;
|
||||
@@ -79,20 +84,28 @@ export function buildNvidiaProvider(): ModelProviderConfig {
|
||||
};
|
||||
}
|
||||
|
||||
export async function buildLiveNvidiaProvider(): Promise<ModelProviderConfig> {
|
||||
export function buildSelectableNvidiaProvider(): ModelProviderConfig {
|
||||
const provider = buildNvidiaProvider();
|
||||
return {
|
||||
...provider,
|
||||
models: filterSelectableNvidiaModels(provider.models ?? []),
|
||||
};
|
||||
}
|
||||
|
||||
export async function buildLiveNvidiaProvider(): Promise<ModelProviderConfig> {
|
||||
const provider = buildSelectableNvidiaProvider();
|
||||
const featuredModels = await loadNvidiaFeaturedModels();
|
||||
if (!featuredModels || featuredModels.length === 0) {
|
||||
return provider;
|
||||
}
|
||||
return {
|
||||
...provider,
|
||||
models: applyNvidiaModelDefaults(featuredModels),
|
||||
models: applyNvidiaModelDefaults(filterSelectableNvidiaModels(featuredModels)),
|
||||
};
|
||||
}
|
||||
|
||||
export async function buildSelectableLiveNvidiaProvider(): Promise<ModelProviderConfig> {
|
||||
const provider = buildNvidiaProvider();
|
||||
const provider = buildSelectableNvidiaProvider();
|
||||
const featuredModels = await loadNvidiaFeaturedModels();
|
||||
if (!featuredModels || featuredModels.length === 0) {
|
||||
return {
|
||||
@@ -102,7 +115,7 @@ export async function buildSelectableLiveNvidiaProvider(): Promise<ModelProvider
|
||||
}
|
||||
return {
|
||||
...provider,
|
||||
models: applyNvidiaModelDefaults(featuredModels),
|
||||
models: applyNvidiaModelDefaults(filterSelectableNvidiaModels(featuredModels)),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -166,6 +179,10 @@ function applyNvidiaModelDefaults(models: ModelDefinitionConfig[]): ModelDefinit
|
||||
);
|
||||
}
|
||||
|
||||
function filterSelectableNvidiaModels(models: ModelDefinitionConfig[]): ModelDefinitionConfig[] {
|
||||
return models.filter((model) => !DEPRECATED_NVIDIA_MODEL_IDS.has(model.id));
|
||||
}
|
||||
|
||||
function parseNvidiaFeaturedModel(row: unknown): ModelDefinitionConfig | null {
|
||||
if (!row || typeof row !== "object") {
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user