chore: initial clean commit

This commit is contained in:
2026-02-26 13:56:21 -05:00
commit 1755075657
53 changed files with 18068 additions and 0 deletions

141
src/providers/mod.rs Normal file
View File

@@ -0,0 +1,141 @@
use async_trait::async_trait;
use anyhow::Result;
use std::sync::Arc;
use futures::stream::BoxStream;
use crate::models::UnifiedRequest;
use crate::errors::AppError;
pub mod openai;
pub mod gemini;
pub mod deepseek;
pub mod grok;
pub mod ollama;
#[async_trait]
pub trait Provider: Send + Sync {
/// Get provider name (e.g., "openai", "gemini")
fn name(&self) -> &str;
/// Check if provider supports a specific model
fn supports_model(&self, model: &str) -> bool;
/// Check if provider supports multimodal (images, etc.)
fn supports_multimodal(&self) -> bool;
/// Process a chat completion request
async fn chat_completion(
&self,
request: UnifiedRequest,
) -> Result<ProviderResponse, AppError>;
/// Process a streaming chat completion request
async fn chat_completion_stream(
&self,
request: UnifiedRequest,
) -> Result<BoxStream<'static, Result<ProviderStreamChunk, AppError>>, AppError>;
/// Estimate token count for a request (for cost calculation)
fn estimate_tokens(&self, request: &UnifiedRequest) -> Result<u32>;
/// Calculate cost based on token usage and model using the registry
fn calculate_cost(&self, model: &str, prompt_tokens: u32, completion_tokens: u32, registry: &crate::models::registry::ModelRegistry) -> f64;
}
pub struct ProviderResponse {
pub content: String,
pub reasoning_content: Option<String>,
pub prompt_tokens: u32,
pub completion_tokens: u32,
pub total_tokens: u32,
pub model: String,
}
#[derive(Debug, Clone)]
pub struct ProviderStreamChunk {
pub content: String,
pub reasoning_content: Option<String>,
pub finish_reason: Option<String>,
pub model: String,
}
#[derive(Clone)]
pub struct ProviderManager {
providers: Vec<Arc<dyn Provider>>,
}
impl ProviderManager {
pub fn new() -> Self {
Self {
providers: Vec::new(),
}
}
pub fn add_provider(&mut self, provider: Arc<dyn Provider>) {
self.providers.push(provider);
}
pub fn get_provider_for_model(&self, model: &str) -> Option<Arc<dyn Provider>> {
self.providers.iter()
.find(|p| p.supports_model(model))
.map(|p| Arc::clone(p))
}
pub fn get_provider(&self, name: &str) -> Option<Arc<dyn Provider>> {
self.providers.iter()
.find(|p| p.name() == name)
.map(|p| Arc::clone(p))
}
}
// Create placeholder provider implementations
pub mod placeholder {
use super::*;
pub struct PlaceholderProvider {
name: String,
}
impl PlaceholderProvider {
pub fn new(name: &str) -> Self {
Self { name: name.to_string() }
}
}
#[async_trait]
impl Provider for PlaceholderProvider {
fn name(&self) -> &str {
&self.name
}
fn supports_model(&self, _model: &str) -> bool {
false
}
fn supports_multimodal(&self) -> bool {
false
}
async fn chat_completion_stream(
&self,
_request: UnifiedRequest,
) -> Result<BoxStream<'static, Result<ProviderStreamChunk, AppError>>, AppError> {
Err(AppError::ProviderError("Streaming not supported for placeholder provider".to_string()))
}
async fn chat_completion(
&self,
_request: UnifiedRequest,
) -> Result<ProviderResponse, AppError> {
Err(AppError::ProviderError(format!("Provider {} not implemented", self.name)))
}
fn estimate_tokens(&self, _request: &UnifiedRequest) -> Result<u32> {
Ok(0)
}
fn calculate_cost(&self, _model: &str, _prompt_tokens: u32, _completion_tokens: u32, _registry: &crate::models::registry::ModelRegistry) -> f64 {
0.0
}
}
}