use crate::adapter::adapters::ollama::OllamaAdapter;
use crate::adapter::adapters::openai_resp::OpenAIRespAdapter;
use crate::adapter::adapters::together::TogetherAdapter;
use crate::adapter::adapters::zai::ZaiAdapter;
use crate::adapter::aliyun::AliyunAdapter;
use crate::adapter::anthropic::AnthropicAdapter;
use crate::adapter::bigmodel::BigModelAdapter;
use crate::adapter::cohere::CohereAdapter;
use crate::adapter::deepseek::DeepSeekAdapter;
use crate::adapter::fireworks::FireworksAdapter;
use crate::adapter::gemini::GeminiAdapter;
use crate::adapter::groq::GroqAdapter;
use crate::adapter::mimo::MimoAdapter;
use crate::adapter::nebius::NebiusAdapter;
use crate::adapter::openai::OpenAIAdapter;
use crate::adapter::xai::XaiAdapter;
use crate::adapter::{Adapter as _, zai};
use crate::{ModelName, Result};
use derive_more::Display;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, Display, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub enum AdapterKind {
OpenAI,
OpenAIResp,
Gemini,
Anthropic,
Fireworks,
Together,
Groq,
Mimo,
Nebius,
Xai,
DeepSeek,
Zai,
BigModel,
Aliyun,
Cohere,
Ollama,
}
impl AdapterKind {
pub fn as_str(&self) -> &'static str {
match self {
AdapterKind::OpenAI => "OpenAI",
AdapterKind::OpenAIResp => "OpenAIResp",
AdapterKind::Gemini => "Gemini",
AdapterKind::Anthropic => "Anthropic",
AdapterKind::Fireworks => "Fireworks",
AdapterKind::Together => "Together",
AdapterKind::Groq => "Groq",
AdapterKind::Mimo => "Mimo",
AdapterKind::Nebius => "Nebius",
AdapterKind::Xai => "xAi",
AdapterKind::DeepSeek => "DeepSeek",
AdapterKind::Zai => "Zai",
AdapterKind::BigModel => "BigModel",
AdapterKind::Aliyun => "Aliyun",
AdapterKind::Cohere => "Cohere",
AdapterKind::Ollama => "Ollama",
}
}
pub fn as_lower_str(&self) -> &'static str {
match self {
AdapterKind::OpenAI => "openai",
AdapterKind::OpenAIResp => "openai_resp",
AdapterKind::Gemini => "gemini",
AdapterKind::Anthropic => "anthropic",
AdapterKind::Fireworks => "fireworks",
AdapterKind::Together => "together",
AdapterKind::Groq => "groq",
AdapterKind::Mimo => "mimo",
AdapterKind::Nebius => "nebius",
AdapterKind::Xai => "xai",
AdapterKind::DeepSeek => "deepseek",
AdapterKind::Zai => "zai",
AdapterKind::BigModel => "bigmodel",
AdapterKind::Aliyun => "aliyun",
AdapterKind::Cohere => "cohere",
AdapterKind::Ollama => "ollama",
}
}
pub fn from_lower_str(name: &str) -> Option<Self> {
match name {
"openai" => Some(AdapterKind::OpenAI),
"openai_resp" => Some(AdapterKind::OpenAIResp),
"gemini" => Some(AdapterKind::Gemini),
"anthropic" => Some(AdapterKind::Anthropic),
"fireworks" => Some(AdapterKind::Fireworks),
"together" => Some(AdapterKind::Together),
"groq" => Some(AdapterKind::Groq),
"mimo" => Some(AdapterKind::Mimo),
"nebius" => Some(AdapterKind::Nebius),
"xai" => Some(AdapterKind::Xai),
"deepseek" => Some(AdapterKind::DeepSeek),
"zai" => Some(AdapterKind::Zai),
"bigmodel" => Some(AdapterKind::BigModel),
"aliyun" => Some(AdapterKind::Aliyun),
"cohere" => Some(AdapterKind::Cohere),
"ollama" => Some(AdapterKind::Ollama),
_ => None,
}
}
}
impl AdapterKind {
pub fn default_key_env_name(&self) -> Option<&'static str> {
match self {
AdapterKind::OpenAI => OpenAIAdapter::DEFAULT_API_KEY_ENV_NAME,
AdapterKind::OpenAIResp => OpenAIRespAdapter::DEFAULT_API_KEY_ENV_NAME,
AdapterKind::Gemini => GeminiAdapter::DEFAULT_API_KEY_ENV_NAME,
AdapterKind::Anthropic => AnthropicAdapter::DEFAULT_API_KEY_ENV_NAME,
AdapterKind::Fireworks => FireworksAdapter::DEFAULT_API_KEY_ENV_NAME,
AdapterKind::Together => TogetherAdapter::DEFAULT_API_KEY_ENV_NAME,
AdapterKind::Groq => GroqAdapter::DEFAULT_API_KEY_ENV_NAME,
AdapterKind::Mimo => MimoAdapter::DEFAULT_API_KEY_ENV_NAME,
AdapterKind::Nebius => NebiusAdapter::DEFAULT_API_KEY_ENV_NAME,
AdapterKind::Xai => XaiAdapter::DEFAULT_API_KEY_ENV_NAME,
AdapterKind::DeepSeek => DeepSeekAdapter::DEFAULT_API_KEY_ENV_NAME,
AdapterKind::Zai => ZaiAdapter::DEFAULT_API_KEY_ENV_NAME,
AdapterKind::BigModel => BigModelAdapter::DEFAULT_API_KEY_ENV_NAME,
AdapterKind::Aliyun => AliyunAdapter::DEFAULT_API_KEY_ENV_NAME,
AdapterKind::Cohere => CohereAdapter::DEFAULT_API_KEY_ENV_NAME,
AdapterKind::Ollama => OllamaAdapter::DEFAULT_API_KEY_ENV_NAME,
}
}
}
impl AdapterKind {
pub fn from_model(model: &str) -> Result<Self> {
if let Some(adapter) = Self::from_model_namespace(model) {
return Ok(adapter);
};
if model.starts_with("o3")
|| model.starts_with("o4")
|| model.starts_with("o1")
|| model.starts_with("chatgpt")
|| model.starts_with("codex")
|| (model.starts_with("gpt") && !model.starts_with("gpt-oss"))
|| model.starts_with("text-embedding")
{
if model.starts_with("gpt") && (model.contains("codex") || model.contains("pro")) {
Ok(Self::OpenAIResp)
} else {
Ok(Self::OpenAI)
}
} else if model.starts_with("gemini") {
Ok(Self::Gemini)
} else if model.starts_with("claude") {
Ok(Self::Anthropic)
} else if model.contains("fireworks") {
Ok(Self::Fireworks)
} else if model.starts_with("mimo-") {
Ok(Self::Mimo)
} else if model.starts_with("command") || model.starts_with("embed-") {
Ok(Self::Cohere)
} else if model.starts_with("grok") {
Ok(Self::Xai)
} else if model.starts_with("glm") {
Ok(Self::Zai)
} else if model.starts_with("deepseek-chat") || model.starts_with("deepseek-reasoner") {
Ok(Self::DeepSeek)
}
else {
Ok(Self::Ollama)
}
}
}
impl AdapterKind {
fn from_model_namespace(model: &str) -> Option<Self> {
let (namespace, _) = ModelName::split_as_namespace_and_name(model);
let namespace = namespace?;
if let Some(adapter) = Self::from_lower_str(namespace) {
Some(adapter)
}
else if namespace == zai::ZAI_CODING_NAMESPACE {
Some(Self::Zai)
}
else {
None
}
}
}