mod anthropic;
mod gemini;
mod openai;
mod openai_compatible;
mod retry;
use async_trait::async_trait;
use tokio::sync::mpsc;
use crate::core::models::{Choice, Message, Tool};
use crate::error::Result;
#[derive(Debug)]
pub enum LlmChunk {
Text(String),
Thinking(String),
}
#[async_trait]
pub trait LlmClient: Send + Sync {
async fn send(&self, messages: &[Message], tools: &[Tool]) -> Result<Choice>;
async fn send_streaming(
&self,
messages: &[Message],
tools: &[Tool],
chunk_tx: mpsc::UnboundedSender<LlmChunk>,
) -> Result<Choice> {
let choice = self.send(messages, tools).await?;
if let Some(ref content) = choice.message.content {
let _ = chunk_tx.send(LlmChunk::Text(content.clone()));
}
Ok(choice)
}
}
pub use anthropic::AnthropicClient;
pub use gemini::GeminiClient;
pub use openai::OpenAiClient;
pub use openai_compatible::OpenAiCompatibleClient;
pub use retry::RetryClient;