synaps_cli/runtime/openai/catalog/
nvidia.rs1use serde::Deserialize;
4
5use super::{CatalogModel, CatalogProviderKind, CatalogSource, ReasoningSupport};
6
7#[derive(Debug, Deserialize)]
8struct NvidiaModelsResponse {
9 data: Vec<NvidiaModelItem>,
10}
11
12#[derive(Debug, Deserialize)]
13struct NvidiaModelItem {
14 id: String,
15 #[serde(default)]
16 owned_by: Option<String>,
17}
18
19fn infer_nvidia_context_tokens(model_id: &str) -> Option<u64> {
20 let id = model_id.to_ascii_lowercase();
21 if id.contains("kimi-k2-thinking") { Some(256_000) }
22 else if id.contains("nemotron-ultra")
23 || id.contains("nemotron-super")
24 || id.contains("qwen3-next")
25 || id.contains("deepseek-v3.1")
26 || id.contains("llama-3.1-405b")
27 || id.contains("llama-3.2-90b-vision")
28 || id.contains("mistral-large-2")
29 { Some(128_000) }
30 else { None }
31}
32
33pub fn infer_nvidia_reasoning(model_id: &str) -> ReasoningSupport {
34 let id = model_id.to_ascii_lowercase();
35 if id.contains("thinking")
36 || id.contains("cosmos-reason")
37 || id.contains("nemotron-ultra")
38 || id.contains("nemotron-super")
39 || id.contains("mistral-nemotron")
40 || id.contains("magistral")
41 || id.contains("deepseek-v4")
42 || id.contains("kimi")
43 || id.contains("reasoning")
44 {
45 ReasoningSupport::NvidiaInlineThinking
46 } else {
47 ReasoningSupport::None
48 }
49}
50
51pub fn parse_nvidia_catalog_models(body: &str) -> Result<Vec<CatalogModel>, serde_json::Error> {
52 let resp: NvidiaModelsResponse = serde_json::from_str(body)?;
53 let mut seen = std::collections::BTreeSet::new();
54 Ok(resp
55 .data
56 .into_iter()
57 .filter_map(|item| {
58 let id = item.id;
59 if id.trim().is_empty() || !seen.insert(id.clone()) {
60 return None;
61 }
62 let mut m = CatalogModel::new("nvidia", "NVIDIA NIM", id)?;
63 m.provider_kind = CatalogProviderKind::NvidiaNim;
64 m.label = item.owned_by.as_ref().map(|owner| format!("{} — {}", m.id, owner));
65 m.context_tokens = infer_nvidia_context_tokens(&m.id);
66 m.reasoning = infer_nvidia_reasoning(&m.id);
67 m.source = if m.context_tokens.is_some() || m.reasoning != ReasoningSupport::None {
68 CatalogSource::Inferred
69 } else {
70 CatalogSource::Live
71 };
72 Some(m)
73 })
74 .collect())
75}