use crate::error::Result;
use crate::providers::{
ProviderApi, anthropic::AnthropicApi, gemini::GeminiApi, ollama::OllamaApi, openai::OpenAiApi,
};
use crate::types::{Event, ModelInfo, Provider, Response, ResponseRequest};
use std::sync::Arc;
#[derive(Clone)]
pub struct ClientConfig {
provider_kind: Provider,
provider: Arc<dyn ProviderApi>,
}
impl ClientConfig {
pub fn openai(api_key: impl Into<String>) -> Self {
let api_key = api_key.into();
Self {
provider_kind: Provider::OpenAi,
provider: Arc::new(OpenAiApi::new(
api_key,
"https://api.openai.com".to_string(),
)),
}
}
pub fn anthropic(api_key: impl Into<String>) -> Self {
let api_key = api_key.into();
Self {
provider_kind: Provider::Anthropic,
provider: Arc::new(AnthropicApi::new(
api_key,
"https://api.anthropic.com".to_string(),
)),
}
}
pub fn gemini(api_key: impl Into<String>) -> Self {
let api_key = api_key.into();
Self {
provider_kind: Provider::Gemini,
provider: Arc::new(GeminiApi::new(
api_key,
"https://generativelanguage.googleapis.com".to_string(),
)),
}
}
pub fn ollama(base_url: impl Into<String>) -> Self {
Self {
provider_kind: Provider::Ollama,
provider: Arc::new(OllamaApi::new(base_url)),
}
}
pub fn ollama_default() -> Self {
Self::ollama("http://localhost:11434".to_string())
}
}
#[derive(Clone)]
pub struct Client {
http: reqwest::Client,
cfg: ClientConfig,
}
impl Client {
pub fn new(cfg: ClientConfig) -> Self {
Self {
http: reqwest::Client::new(),
cfg,
}
}
pub fn provider(&self) -> &Provider {
&self.cfg.provider_kind
}
pub async fn send(&self, req: ResponseRequest) -> Result<Response> {
self.cfg.provider.send(&self.http, req).await
}
pub async fn stream<F>(&self, req: ResponseRequest, mut on_event: F) -> Result<Response>
where
F: FnMut(Event),
{
self.cfg
.provider
.stream(&self.http, req, &mut on_event)
.await
}
pub async fn list_models(&self) -> Result<Vec<ModelInfo>> {
self.cfg.provider.list_models(&self.http).await
}
pub fn chat(&self, model: impl Into<String>) -> crate::chat::ChatSession<'_> {
crate::chat::ChatSession::new(self, crate::chat::Chat::new(model))
}
pub fn chat_auto(&self) -> crate::chat::ChatSession<'_> {
crate::chat::ChatSession::new(self, crate::chat::Chat::new_auto())
}
pub fn chat_from(&self, chat: crate::chat::Chat) -> crate::chat::ChatSession<'_> {
crate::chat::ChatSession::new(self, chat)
}
}