use std::pin::Pin;
use async_trait::async_trait;
use futures::Stream;
use crate::ir::{ChatRequest, ChatResponse, StreamEvent};
#[derive(Debug, thiserror::Error)]
pub enum AdapterError {
#[error("backend request failed: {0}")]
BackendError(String),
#[error("protocol translation error: {0}")]
TranslationError(String),
#[error("stream error: {0}")]
StreamError(String),
#[error("feature not supported: {feature} (provider: {provider})")]
UnsupportedFeature { provider: String, feature: String },
}
#[async_trait]
pub trait Adapter: Send + Sync {
fn provider_name(&self) -> &str;
fn supports_model(&self, model: &str) -> bool;
async fn chat(&self, request: &ChatRequest) -> Result<ChatResponse, AdapterError>;
async fn chat_stream(
&self,
request: &ChatRequest,
) -> Result<Pin<Box<dyn Stream<Item = Result<StreamEvent, AdapterError>> + Send>>, AdapterError>;
}
#[async_trait]
impl<T: Adapter + ?Sized> Adapter for Box<T> {
fn provider_name(&self) -> &str {
(**self).provider_name()
}
fn supports_model(&self, model: &str) -> bool {
(**self).supports_model(model)
}
async fn chat(&self, request: &ChatRequest) -> Result<ChatResponse, AdapterError> {
(**self).chat(request).await
}
async fn chat_stream(
&self,
request: &ChatRequest,
) -> Result<Pin<Box<dyn Stream<Item = Result<StreamEvent, AdapterError>> + Send>>, AdapterError>
{
(**self).chat_stream(request).await
}
}