Skip to main content

adk_model/
provider.rs

1use std::fmt::{Display, Formatter};
2use std::str::FromStr;
3
4/// Canonical provider identifiers and metadata shared across ADK crates.
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
6pub enum ModelProvider {
7    Gemini,
8    Openai,
9    Anthropic,
10    Deepseek,
11    Groq,
12    Ollama,
13}
14
15impl ModelProvider {
16    /// All providers in UI/display order.
17    pub const ALL: [Self; 6] =
18        [Self::Gemini, Self::Openai, Self::Anthropic, Self::Deepseek, Self::Groq, Self::Ollama];
19
20    /// Return all providers in a stable order.
21    pub const fn all() -> &'static [Self] {
22        &Self::ALL
23    }
24
25    /// Machine identifier used in CLIs and configs.
26    pub const fn as_str(self) -> &'static str {
27        match self {
28            Self::Gemini => "gemini",
29            Self::Openai => "openai",
30            Self::Anthropic => "anthropic",
31            Self::Deepseek => "deepseek",
32            Self::Groq => "groq",
33            Self::Ollama => "ollama",
34        }
35    }
36
37    /// Default model for the provider.
38    pub const fn default_model(self) -> &'static str {
39        match self {
40            Self::Gemini => "gemini-3.1-flash-lite-preview",
41            Self::Openai => "gpt-5-mini",
42            Self::Anthropic => "claude-sonnet-4-5-20250929",
43            Self::Deepseek => "deepseek-chat",
44            Self::Groq => "llama-3.3-70b-versatile",
45            Self::Ollama => "qwen3.5",
46        }
47    }
48
49    /// Primary environment variable used for the provider API key.
50    pub const fn env_var(self) -> &'static str {
51        match self {
52            Self::Gemini => "GOOGLE_API_KEY",
53            Self::Openai => "OPENAI_API_KEY",
54            Self::Anthropic => "ANTHROPIC_API_KEY",
55            Self::Deepseek => "DEEPSEEK_API_KEY",
56            Self::Groq => "GROQ_API_KEY",
57            Self::Ollama => "",
58        }
59    }
60
61    /// Alternate environment variable used for the provider API key.
62    pub const fn alt_env_var(self) -> Option<&'static str> {
63        match self {
64            Self::Gemini => Some("GEMINI_API_KEY"),
65            _ => None,
66        }
67    }
68
69    /// Whether the provider requires an API key.
70    pub const fn requires_key(self) -> bool {
71        !matches!(self, Self::Ollama)
72    }
73
74    /// Display name for interactive prompts and help text.
75    pub const fn display_name(self) -> &'static str {
76        match self {
77            Self::Gemini => "Gemini (Google)",
78            Self::Openai => "OpenAI",
79            Self::Anthropic => "Anthropic (Claude)",
80            Self::Deepseek => "DeepSeek",
81            Self::Groq => "Groq",
82            Self::Ollama => "Ollama (local, no key needed)",
83        }
84    }
85}
86
87impl Display for ModelProvider {
88    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
89        f.write_str(self.as_str())
90    }
91}
92
93impl FromStr for ModelProvider {
94    type Err = String;
95
96    fn from_str(value: &str) -> Result<Self, Self::Err> {
97        match value {
98            "gemini" => Ok(Self::Gemini),
99            "openai" => Ok(Self::Openai),
100            "anthropic" => Ok(Self::Anthropic),
101            "deepseek" => Ok(Self::Deepseek),
102            "groq" => Ok(Self::Groq),
103            "ollama" => Ok(Self::Ollama),
104            other => Err(format!("unsupported provider: {other}")),
105        }
106    }
107}
108
109#[cfg(test)]
110mod tests {
111    use super::ModelProvider;
112    use std::str::FromStr;
113
114    #[test]
115    fn provider_roundtrips_from_machine_name() {
116        for provider in ModelProvider::all() {
117            let parsed = ModelProvider::from_str(provider.as_str()).expect("provider should parse");
118            assert_eq!(*provider, parsed);
119        }
120    }
121}