use super::macros::adapter_kind_str_maps;
use crate::adapter::Adapter as _;
use crate::adapter::adapters;
use crate::adapter::adapters::baidu::BAIDU_CODING_ANTHROPIC_NAMESPACE;
use crate::adapter::adapters::baidu::BAIDU_CODING_OPENAI_NAMESPACE;
use crate::adapter::adapters::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,
Aihubmix,
Kimi,
Mimo,
Moonshot,
Nebius,
Xai,
DeepSeek,
Zai,
BigModel,
Aliyun,
Baidu,
Cohere,
Ollama,
OllamaCloud,
Omlx,
Vertex,
GithubCopilot,
OpenCodeGo,
BedrockApi,
#[cfg(feature = "bedrock-sigv4")]
BedrockSigv4,
OpenRouter,
MiniMax,
#[display("genai_{_0}")]
Custom(u8),
}
adapter_kind_str_maps! {
OpenAI => "OpenAI", "openai", adapters::all_adapters::OpenAIAdapter;
OpenAIResp => "OpenAIResp", "openai_resp", adapters::all_adapters::OpenAIRespAdapter;
Gemini => "Gemini", "gemini", adapters::all_adapters::GeminiAdapter;
Anthropic => "Anthropic", "anthropic", adapters::all_adapters::AnthropicAdapter;
Fireworks => "Fireworks", "fireworks", adapters::all_adapters::FireworksAdapter;
Together => "Together", "together", adapters::all_adapters::TogetherAdapter;
Groq => "Groq", "groq", adapters::all_adapters::GroqAdapter;
Aihubmix => "Aihubmix", "aihubmix", adapters::all_adapters::AihubmixAdapter;
Kimi => "Kimi", "kimi", adapters::all_adapters::KimiAdapter;
Mimo => "Mimo", "mimo", adapters::all_adapters::MimoAdapter;
Moonshot => "Moonshot", "moonshot", adapters::all_adapters::MoonshotAdapter;
Nebius => "Nebius", "nebius", adapters::all_adapters::NebiusAdapter;
Xai => "Xai", "xai", adapters::all_adapters::XaiAdapter;
DeepSeek => "DeepSeek", "deepseek", adapters::all_adapters::DeepSeekAdapter;
Zai => "Zai", "zai", adapters::all_adapters::ZaiAdapter;
BigModel => "BigModel", "bigmodel", adapters::all_adapters::BigModelAdapter;
Aliyun => "Aliyun", "aliyun", adapters::all_adapters::AliyunAdapter;
Baidu => "Baidu", "baidu", adapters::all_adapters::BaiduAdapter;
Cohere => "Cohere", "cohere", adapters::all_adapters::CohereAdapter;
Ollama => "Ollama", "ollama", adapters::all_adapters::OllamaAdapter;
OllamaCloud => "OllamaCloud", "ollama_cloud", adapters::all_adapters::OllamaCloudAdapter;
Omlx => "Omlx", "omlx", adapters::all_adapters::OmlxAdapter;
Vertex => "Vertex", "vertex", adapters::all_adapters::VertexAdapter;
GithubCopilot => "GithubCopilot", "github_copilot", adapters::all_adapters::GithubCopilotAdapter;
OpenCodeGo => "OpenCodeGo", "opencode_go", adapters::all_adapters::OpenCodeGoAdapter;
BedrockApi => "BedrockApi", "bedrock_api", adapters::all_adapters::BedrockApiAdapter;
OpenRouter => "OpenRouter", "open_router", adapters::all_adapters::OpenRouterAdapter;
MiniMax => "MiniMax", "minimax", adapters::all_adapters::MiniMaxAdapter;
}
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-5")
|| (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("kimi-") {
Ok(Self::Kimi)
} 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-") {
Ok(Self::DeepSeek)
} else if model.starts_with("moonshot-") {
Ok(Self::Moonshot)
} else if model.starts_with("MiniMax-") || model.starts_with("minimax-") {
Ok(Self::MiniMax)
} else if model.starts_with("omlx-") {
Ok(Self::Omlx)
}
else {
Ok(Self::Ollama)
}
}
}
impl AdapterKind {
pub(crate) 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 if namespace == BAIDU_CODING_OPENAI_NAMESPACE || namespace == BAIDU_CODING_ANTHROPIC_NAMESPACE {
Some(Self::Baidu)
}
else {
None
}
}
}