synaps_cli/runtime/openai/catalog/
groq.rs1use serde::Deserialize;
4
5use super::{CatalogModel, CatalogProviderKind, CatalogSource, ReasoningSupport};
6
7#[derive(Debug, Deserialize)]
8struct GroqModelsResponse {
9 data: Vec<GroqModelItem>,
10}
11
12#[derive(Debug, Deserialize)]
13struct GroqModelItem {
14 id: String,
15 #[serde(default = "default_true")]
16 active: bool,
17 #[serde(default)]
18 context_window: Option<u64>,
19 #[serde(default)]
20 owned_by: Option<String>,
21}
22
23fn default_true() -> bool { true }
24
25pub fn infer_groq_reasoning(model_id: &str) -> ReasoningSupport {
26 let id = model_id.to_ascii_lowercase();
27 if id.starts_with("openai/gpt-oss-") || id.starts_with("qwen/qwen3-") || id.starts_with("groq/compound") {
28 ReasoningSupport::GroqReasoning
29 } else {
30 ReasoningSupport::None
31 }
32}
33
34pub fn parse_groq_catalog_models(body: &str) -> Result<Vec<CatalogModel>, serde_json::Error> {
35 let resp: GroqModelsResponse = serde_json::from_str(body)?;
36 Ok(resp
37 .data
38 .into_iter()
39 .filter(|item| item.active)
40 .filter_map(|item| {
41 let mut m = CatalogModel::new("groq", "Groq", item.id)?;
42 m.provider_kind = CatalogProviderKind::Groq;
43 m.label = item.owned_by.as_ref().map(|owner| format!("{} — {}", m.id, owner));
44 m.context_tokens = item.context_window;
45 m.reasoning = infer_groq_reasoning(&m.id);
46 m.source = CatalogSource::Live;
47 Some(m)
48 })
49 .collect())
50}