diff --git a/docs/providers/nvidia.md b/docs/providers/nvidia.md index 592535ea4c80..d40b23e4b8ab 100644 --- a/docs/providers/nvidia.md +++ b/docs/providers/nvidia.md @@ -70,10 +70,11 @@ When an NVIDIA API key is configured, setup and model-selection paths fetch NVIDIA's public featured-model catalog from `https://assets.ngc.nvidia.com/products/api-catalog/featured-models.json` and cache the result for 24 hours (first 32 entries, imported as free text-input -rows). New featured models from build.nvidia.com therefore appear in setup and -model-selection surfaces without waiting for an OpenClaw release. When the -live feed is available, the first returned model is the preselected option -during NVIDIA setup. +rows). New or republished featured models from build.nvidia.com therefore appear +in setup and model-selection surfaces after the cache refreshes, without waiting +for an OpenClaw release. A fresh NVIDIA catalog overrides bundled retirement +metadata. When the live feed is available, its first model is preselected during +NVIDIA setup. The fetch uses a fixed HTTPS host policy for `assets.ngc.nvidia.com`. If no NVIDIA API key is configured, or if the feed is unavailable or malformed, @@ -97,8 +98,8 @@ hosted in NVIDIA's catalog when their context, latency, or behavior fits better. ## Bundled fallback catalog The selectable bundled rows snapshot NVIDIA's featured-model catalog. Deprecated -compatibility rows remain resolvable by exact reference but stay out of model -pickers. +compatibility rows keep existing exact model references recognizable but stay +out of model pickers. | Model ref | Name | Context | Max output | | ------------------------------------------ | --------------------- | --------- | ---------- | @@ -108,12 +109,14 @@ pickers. | `nvidia/moonshotai/kimi-k2.6` | Kimi K2.6 | 262,144 | 65,536 | | `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 | 32,768 | The full compatibility catalog also retains these shipped refs for existing -configurations: `nvidia/moonshotai/kimi-k2.5`, `nvidia/z-ai/glm-5.1`, -`nvidia/z-ai/glm5`, and `nvidia/minimaxai/minimax-m2.7`. They remain available -by exact reference but never appear in onboarding or model pickers. +configurations and migration: `nvidia/qwen/qwen3.5-397b-a17b`, +`nvidia/moonshotai/kimi-k2.5`, `nvidia/z-ai/glm-5.1`, `nvidia/z-ai/glm5`, and +`nvidia/minimaxai/minimax-m2.7`. These references stay hidden from bundled and +offline model pickers unless NVIDIA republishes them in its featured catalog. +NVIDIA has retired the Qwen endpoint, so requests using its model reference no +longer work. Migrate existing Qwen configurations to an active model. ## Advanced configuration @@ -128,8 +131,9 @@ by exact reference but never appear in onboarding or model pickers. OpenClaw prefers NVIDIA's public featured-model catalog when NVIDIA auth is 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. + compatibility rows stay hidden from that fallback. Fresh featured rows can + restore models that NVIDIA has republished. Costs default to `0` in source + since NVIDIA currently offers free API access for the listed models. diff --git a/extensions/nvidia/index.test.ts b/extensions/nvidia/index.test.ts index ac85e35b9a34..9465b5bf0039 100644 --- a/extensions/nvidia/index.test.ts +++ b/extensions/nvidia/index.test.ts @@ -213,7 +213,6 @@ describe("nvidia provider hooks", () => { "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(); @@ -232,13 +231,12 @@ describe("nvidia provider hooks", () => { "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); }); - it("surfaces live featured NVIDIA models via augmentModelCatalog", async () => { + it("surfaces republished NVIDIA featured models via augmentModelCatalog", async () => { mockFeaturedCatalogResponse({ "featured-models": [ { @@ -247,13 +245,22 @@ describe("nvidia provider hooks", () => { context: 196608, "max-output": 8192, }, + { + model: "qwen/qwen3.5-397b-a17b", + "model-name": "Qwen3.5 397B A17B", + context: 262144, + "max-output": 32768, + }, ], }); const provider = await registerNvidiaProvider(); const entries = await provider.augmentModelCatalog?.(buildAugmentCatalogContext("nvapi-test")); - expect(entries?.map((entry) => entry.id)).toEqual(["minimaxai/minimax-m3"]); + expect(entries?.map((entry) => entry.id)).toEqual([ + "minimaxai/minimax-m3", + "qwen/qwen3.5-397b-a17b", + ]); }); it("opts into literal provider-prefix preservation", async () => { @@ -285,6 +292,12 @@ describe("nvidia provider hooks", () => { context: 196608, "max-output": 8192, }, + { + model: "qwen/qwen3.5-397b-a17b", + "model-name": "Qwen3.5 397B A17B", + context: 262144, + "max-output": 32768, + }, ], }); const { registeredModelCatalogProviders } = registerNvidiaPluginApi(); @@ -301,7 +314,6 @@ describe("nvidia provider hooks", () => { "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([]); @@ -309,6 +321,7 @@ describe("nvidia provider hooks", () => { const liveRows = await catalogProvider?.liveCatalog?.(buildCatalogContext("nvapi-test")); expect(liveRows?.map((entry) => `${entry.source}:${entry.provider}/${entry.model}`)).toEqual([ "live:nvidia/minimaxai/minimax-m3", + "live:nvidia/qwen/qwen3.5-397b-a17b", ]); }); diff --git a/extensions/nvidia/onboard.test.ts b/extensions/nvidia/onboard.test.ts index 91e03b8eb9e2..505867af7909 100644 --- a/extensions/nvidia/onboard.test.ts +++ b/extensions/nvidia/onboard.test.ts @@ -22,7 +22,6 @@ describe("nvidia onboard", () => { "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. @@ -50,30 +49,31 @@ describe("nvidia onboard", () => { "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", () => { + it.each([ + { id: "minimaxai/minimax-m2.7", name: "MiniMax M2.7" }, + { id: "qwen/qwen3.5-397b-a17b", name: "Qwen3.5 397B A17B" }, + ])("preserves an existing deprecated exact-reference model: $id", ({ id, name }) => { const provider = expectProviderOnboardMergedLegacyConfig({ applyProviderConfig: applyNvidiaProviderConfig, providerId: "nvidia", providerApi: "openai-completions", baseUrl: "https://integrate.api.nvidia.com/v1", legacyApi: "openai-completions", - legacyModelId: "minimaxai/minimax-m2.7", - legacyModelName: "MiniMax M2.7", + legacyModelId: id, + legacyModelName: name, }); expect(provider?.models.map((model) => model.id)).toEqual([ - "minimaxai/minimax-m2.7", + id, "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", ]); }); }); diff --git a/extensions/nvidia/openclaw.plugin.json b/extensions/nvidia/openclaw.plugin.json index 0b0ca54c0dd8..a6cd33017e9a 100644 --- a/extensions/nvidia/openclaw.plugin.json +++ b/extensions/nvidia/openclaw.plugin.json @@ -5,18 +5,12 @@ "onStartup": false }, "enabledByDefault": true, - "providers": [ - "nvidia" - ], + "providers": ["nvidia"], "providerEndpoints": [ { "endpointClass": "nvidia-native", - "hosts": [ - "integrate.api.nvidia.com" - ], - "baseUrls": [ - "https://integrate.api.nvidia.com/v1" - ] + "hosts": ["integrate.api.nvidia.com"], + "baseUrls": ["https://integrate.api.nvidia.com/v1"] } ], "modelIdNormalization": { @@ -35,9 +29,7 @@ { "id": "nvidia/nemotron-3-ultra-550b-a55b", "name": "Nemotron 3 Ultra 550B", - "input": [ - "text" - ], + "input": ["text"], "reasoning": true, "contextWindow": 1048576, "maxTokens": 8192, @@ -54,9 +46,7 @@ { "id": "nvidia/nemotron-3-super-120b-a12b", "name": "Nemotron 3 Super 120B", - "input": [ - "text" - ], + "input": ["text"], "reasoning": true, "contextWindow": 1000000, "maxTokens": 8192, @@ -73,9 +63,7 @@ { "id": "z-ai/glm-5.2", "name": "GLM 5.2", - "input": [ - "text" - ], + "input": ["text"], "reasoning": true, "contextWindow": 202752, "maxTokens": 8192, @@ -93,10 +81,7 @@ { "id": "moonshotai/kimi-k2.6", "name": "Kimi K2.6", - "input": [ - "text", - "image" - ], + "input": ["text", "image"], "reasoning": true, "contextWindow": 262144, "maxTokens": 65536, @@ -113,10 +98,7 @@ { "id": "minimaxai/minimax-m3", "name": "Minimax M3", - "input": [ - "text", - "image" - ], + "input": ["text", "image"], "reasoning": true, "contextWindow": 196608, "maxTokens": 8192, @@ -133,9 +115,7 @@ { "id": "deepseek-ai/deepseek-v4-pro", "name": "DeepSeek V4 Pro", - "input": [ - "text" - ], + "input": ["text"], "reasoning": true, "contextWindow": 262144, "maxTokens": 16384, @@ -153,10 +133,7 @@ { "id": "qwen/qwen3.5-397b-a17b", "name": "Qwen3.5 397B A17B", - "input": [ - "text", - "image" - ], + "input": ["text", "image"], "reasoning": true, "contextWindow": 262144, "maxTokens": 32768, @@ -168,15 +145,14 @@ }, "compat": { "requiresStringContent": true - } + }, + "status": "deprecated", + "statusReason": "NVIDIA retired this model and no longer lists it in its model catalog." }, { "id": "moonshotai/kimi-k2.5", "name": "Kimi K2.5", - "input": [ - "text", - "image" - ], + "input": ["text", "image"], "reasoning": true, "contextWindow": 262144, "maxTokens": 32768, @@ -196,9 +172,7 @@ { "id": "z-ai/glm-5.1", "name": "GLM 5.1", - "input": [ - "text" - ], + "input": ["text"], "contextWindow": 202752, "maxTokens": 8192, "cost": { @@ -218,9 +192,7 @@ { "id": "z-ai/glm5", "name": "GLM-5", - "input": [ - "text" - ], + "input": ["text"], "contextWindow": 202752, "maxTokens": 8192, "cost": { @@ -239,9 +211,7 @@ { "id": "minimaxai/minimax-m2.7", "name": "Minimax M2.7", - "input": [ - "text" - ], + "input": ["text"], "reasoning": true, "contextWindow": 204800, "maxTokens": 16384, @@ -269,9 +239,7 @@ "providers": [ { "id": "nvidia", - "envVars": [ - "NVIDIA_API_KEY" - ] + "envVars": ["NVIDIA_API_KEY"] } ] }, diff --git a/extensions/nvidia/provider-catalog.test.ts b/extensions/nvidia/provider-catalog.test.ts index 5def98f8cf50..39ab1c0104a6 100644 --- a/extensions/nvidia/provider-catalog.test.ts +++ b/extensions/nvidia/provider-catalog.test.ts @@ -44,15 +44,15 @@ const EXPECTED_FEATURED_MODELS = [ contextWindow: 262_144, maxTokens: 16_384, }, +] as const; + +const EXPECTED_DEPRECATED_MODELS = [ { id: "qwen/qwen3.5-397b-a17b", name: "Qwen3.5 397B A17B", contextWindow: 262_144, maxTokens: 32_768, }, -] as const; - -const EXPECTED_DEPRECATED_MODELS = [ { id: "moonshotai/kimi-k2.5", name: "Kimi K2.5", @@ -152,11 +152,6 @@ describe("nvidia provider catalog", () => { reasoning: true, }, { id: "deepseek-ai/deepseek-v4-pro", input: ["text"], reasoning: true }, - { - id: "qwen/qwen3.5-397b-a17b", - input: ["text", "image"], - reasoning: true, - }, ]); expect(provider.models[0]).toMatchObject({ contextWindow: 1_048_576, @@ -175,8 +170,11 @@ describe("nvidia provider catalog", () => { expect( manifest.modelCatalog.providers.nvidia.models .filter((model) => "status" in model && model.status === "deprecated") - .map((model) => ({ id: model.id, replacedBy: model.replacedBy })), + .map((model) => + "replacedBy" in model ? { id: model.id, replacedBy: model.replacedBy } : { id: model.id }, + ), ).toEqual([ + { id: "qwen/qwen3.5-397b-a17b" }, { id: "moonshotai/kimi-k2.5", replacedBy: "moonshotai/kimi-k2.6" }, { id: "z-ai/glm-5.1", replacedBy: "z-ai/glm-5.2" }, { id: "z-ai/glm5", replacedBy: "z-ai/glm-5.2" }, @@ -283,7 +281,7 @@ describe("nvidia provider catalog", () => { ]); }); - it("keeps every deprecated exact-reference row out of live catalogs", async () => { + it("restores bundled legacy models when NVIDIA republishes them in its featured catalog", async () => { mockFeaturedCatalogResponse({ "featured-models": [ { @@ -303,12 +301,16 @@ describe("nvidia provider catalog", () => { const live = await buildLiveNvidiaProvider(); const selectableLive = await buildSelectableLiveNvidiaProvider(); + const republishedIds = [ + "minimaxai/minimax-m3", + ...EXPECTED_DEPRECATED_MODELS.map((model) => model.id), + ]; - expect(live.models.map((model) => model.id)).toEqual(["minimaxai/minimax-m3"]); - expect(selectableLive.models.map((model) => model.id)).toEqual(["minimaxai/minimax-m3"]); + expect(live.models.map((model) => model.id)).toEqual(republishedIds); + expect(selectableLive.models.map((model) => model.id)).toEqual(republishedIds); }); - it("maps current featured feed metadata for MiniMax, DeepSeek, and Qwen", async () => { + it("maps a republished Qwen model from NVIDIA's current featured catalog", async () => { mockFeaturedCatalogResponse({ "featured-models": [ { @@ -485,7 +487,10 @@ describe("nvidia provider catalog", () => { const provider = await buildLiveNvidiaProvider(); - expect(provider.models.map((model) => model.id)).toEqual(["nvidia/nemotron-3-ultra-550b-a55b"]); + expect(provider.models.map((model) => model.id)).toEqual([ + "nvidia/nemotron-3-ultra-550b-a55b", + "minimaxai/minimax-m2.7", + ]); expect(provider.models[0]).toMatchObject({ name: "Nemotron 3 Ultra 550B", contextWindow: 1_048_576, diff --git a/extensions/nvidia/provider-catalog.ts b/extensions/nvidia/provider-catalog.ts index ba65bd88ee3c..5ab8df75a142 100644 --- a/extensions/nvidia/provider-catalog.ts +++ b/extensions/nvidia/provider-catalog.ts @@ -97,7 +97,7 @@ export async function buildLiveNvidiaProvider(): Promise { } return { ...provider, - models: applyNvidiaModelDefaults(filterSelectableNvidiaModels(featuredModels)), + models: applyNvidiaModelDefaults(featuredModels), }; } @@ -112,7 +112,7 @@ export async function buildSelectableLiveNvidiaProvider(): Promise