use async_trait::async_trait;
use serde::{Deserialize, Serialize};
pub mod completion;
pub mod message;
#[cfg(feature = "mock")]
pub mod mock;
#[cfg(all(unix, feature = "remote"))]
pub mod remote;
pub use completion::{
CompletionError, CompletionRequest, ErrorClass, FinalResponse, ModelStream, StreamChunk,
ToolCallDeltaContent, ToolDefinition, Usage,
};
pub use message::{
AssistantContent, Image, ImageMediaType, ImageSource, Message, Reasoning, ReasoningContent,
Text, ToolCall, ToolFunction, ToolResult, ToolResultContent, UserContent,
};
type BoxError = Box<dyn std::error::Error + Send + Sync>;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ModelEntry {
pub model_id: String,
pub display_name: String,
pub context_window: usize,
pub max_output_tokens: Option<u64>,
#[serde(default)]
pub supports_image_input: bool,
}
#[async_trait]
pub trait ModelProvider: Send + Sync {
async fn list_models(&self) -> Result<Vec<ModelEntry>, BoxError>;
async fn invoke_model(
&self,
model_id: &str,
request: CompletionRequest,
) -> Result<ModelStream, CompletionError>;
}
#[async_trait]
pub trait CompletionModel: Send + Sync {
async fn stream(&self, request: CompletionRequest) -> Result<ModelStream, CompletionError>;
}
pub struct SingleModelProvider<M> {
entry: ModelEntry,
model: M,
}
impl<M: CompletionModel> SingleModelProvider<M> {
pub fn new(entry: ModelEntry, model: M) -> Self {
Self { entry, model }
}
}
#[async_trait]
impl<M: CompletionModel> ModelProvider for SingleModelProvider<M> {
async fn list_models(&self) -> Result<Vec<ModelEntry>, BoxError> {
Ok(vec![self.entry.clone()])
}
async fn invoke_model(
&self,
_model_id: &str,
request: CompletionRequest,
) -> Result<ModelStream, CompletionError> {
self.model.stream(request).await
}
}