Add NVIDIA NIM platform (provider 11)

The 14th registry row: id "nvidia", NVIDIA_API_KEY > auth.json "nvidia"
scope, https://integrate.api.nvidia.com/v1 with KIGI_NVIDIA_BASE_URL
override, Bearer, ChatCompletions, enrichment-backed metadata
(models_dev_id nvidia — the quirk matrix's earlier 'absent' claim was
wrong; models.dev has 84 nvidia models), restrict_to_enriched=true (the
NIM listing mixes chat/embedding/rerank/vision/image; keep the 45
tool-calling chat models). Slashed org/model ids
(nvidia/meta/llama-3.3-70b-instruct) round-trip via the first-slash split;
the native id rides the wire.

NIM exposes raw vLLM behavior and stream_options support varies per model
(some strict vLLM backends 4xx on it), so chat_compat=StrictOpenAi strips
stream_options — streaming works across the whole fleet, usage falls back
to estimation. Snapshot reasoning models carry no effort menus, so kigi
sends no reasoning_effort (which an unsupported strict validator would
400 on). Review: no defects. Logged note: a key lacking the org 'Public
API Endpoints' permission passes /models validation but 403s on chat
(user-fixable edge case).
This commit is contained in:
2026-07-21 14:31:25 -04:00
parent f825132983
commit 9ee40b13d0
4 changed files with 149 additions and 9 deletions
+39 -2
View File
@@ -531,6 +531,38 @@ const CEREBRAS_SPEC: PlatformSpec = PlatformSpec {
restrict_to_enriched: false,
};
/// Base-URL override for NVIDIA NIM (dev/test escape hatch).
pub const NVIDIA_BASE_URL_ENV: &str = "KIGI_NVIDIA_BASE_URL";
const NVIDIA_SPEC: PlatformSpec = PlatformSpec {
id: "nvidia",
display_name: "NVIDIA NIM",
base_url: BaseUrlSource::EnvOr {
env: NVIDIA_BASE_URL_ENV,
default: "https://integrate.api.nvidia.com/v1",
},
uses_oauth: false,
allowed_model_prefixes: None,
api_key_envs: &["NVIDIA_API_KEY"],
vendor: "NVIDIA",
console_host: Some("build.nvidia.com"),
login_label: Some("NVIDIA NIM (API key)"),
models_dev_id: Some("nvidia"),
wire_serves_metadata: false,
wire_api: PlatformWireApi::ChatCompletions,
listing: ListingDialect::OpenAi,
// NIM exposes raw vLLM behavior; stream_options support varies per model
// and some 4xx on it, so strip it (StrictOpenAi) to keep streaming
// working across the fleet.
chat_compat: PlatformChatCompat::StrictOpenAi,
key_header: PlatformKeyHeader::Bearer,
key_validation_path: None,
strip_listing_id_prefix: None,
// The listing mixes chat/embedding/rerank/vision/image models; keep
// tool-calling enrichment-known chat models only.
restrict_to_enriched: true,
};
/// The platform registry. Platforms are compiled-in spec rows; there is no
/// dynamic provider registration (PRD F2).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
@@ -561,12 +593,14 @@ pub enum PlatformId {
Together,
/// Cerebras platform API (API key, OpenAI-compatible ChatCompletions).
Cerebras,
/// NVIDIA NIM platform API (API key, OpenAI-compatible ChatCompletions).
Nvidia,
}
impl PlatformId {
/// All platforms, in catalog precedence order: the subscription channel
/// first so "default model = first list item" favors it when present.
pub const ALL: [PlatformId; 13] = [
pub const ALL: [PlatformId; 14] = [
Self::KimiCode,
Self::MoonshotCn,
Self::MoonshotAi,
@@ -580,6 +614,7 @@ impl PlatformId {
Self::OpenRouter,
Self::Together,
Self::Cerebras,
Self::Nvidia,
];
/// The registry row backing this platform (single source of per-platform
@@ -599,6 +634,7 @@ impl PlatformId {
Self::OpenRouter => &OPENROUTER_SPEC,
Self::Together => &TOGETHER_SPEC,
Self::Cerebras => &CEREBRAS_SPEC,
Self::Nvidia => &NVIDIA_SPEC,
}
}
@@ -1350,9 +1386,10 @@ mod tests {
PlatformId::OpenRouter => 10,
PlatformId::Together => 11,
PlatformId::Cerebras => 12,
PlatformId::Nvidia => 13,
}
}
const VARIANT_COUNT: usize = 13; // update together with `ordinal`
const VARIANT_COUNT: usize = 14; // update together with `ordinal`
let mut seen: Vec<usize> = PlatformId::ALL.iter().map(|&p| ordinal(p)).collect();
seen.sort_unstable();
seen.dedup();