use crate::error::AppError;
use async_trait::async_trait;
use axum::{
body::{Body, Bytes},
http::{HeaderMap, Response},
};
use tracing::error;
#[async_trait]
pub trait Provider: Send + Sync {
fn base_url(&self) -> String;
fn name(&self) -> &str;
fn transform_path(&self, path: &str) -> String {
path.to_string()
}
fn process_headers(&self, headers: &HeaderMap) -> Result<HeaderMap, AppError>;
async fn prepare_request_body(&self, body: Bytes) -> Result<Bytes, AppError> {
Ok(body)
}
async fn process_response(&self, response: Response<Body>) -> Result<Response<Body>, AppError> {
Ok(response)
}
async fn sign_request(
&self,
method: &str,
url: &str,
headers: &HeaderMap,
body: &[u8],
) -> Result<HeaderMap, AppError> {
Ok(headers.clone())
}
async fn before_request(&self, headers: &HeaderMap, body: &Bytes) -> Result<(), AppError> {
Ok(())
}
fn requires_signing(&self) -> bool {
false
}
fn get_signing_credentials(&self, _headers: &HeaderMap) -> Option<(String, String, String)> {
None
}
fn get_signing_host(&self) -> String {
self.base_url()
.replace("https://", "")
.replace("http://", "")
}
}
pub mod anthropic;
pub mod bedrock;
pub mod fireworks;
pub mod groq;
pub mod openai;
pub mod together;
pub use anthropic::AnthropicProvider;
pub use bedrock::BedrockProvider;
pub use fireworks::FireworksProvider;
pub use groq::GroqProvider;
pub use openai::OpenAIProvider;
pub use together::TogetherProvider;
pub fn create_provider(provider_name: &str) -> Result<Box<dyn Provider>, AppError> {
match provider_name.to_lowercase().as_str() {
"openai" => Ok(Box::new(OpenAIProvider::new())),
"anthropic" => Ok(Box::new(AnthropicProvider::new())),
"groq" => Ok(Box::new(GroqProvider::new())),
"fireworks" => Ok(Box::new(FireworksProvider::new())),
"together" => Ok(Box::new(TogetherProvider::new())),
"bedrock" => Ok(Box::new(BedrockProvider::new())),
unknown => {
error!("Attempted to use unsupported provider: {}", unknown);
Err(AppError::UnsupportedProvider)
}
}
}