Add App core struct with event-handling and initialization logic for TUI.
This commit is contained in:
105
crates/owlen-core/src/provider.rs
Normal file
105
crates/owlen-core/src/provider.rs
Normal file
@@ -0,0 +1,105 @@
|
||||
//! Provider trait and related types
|
||||
|
||||
use crate::{types::*, Result};
|
||||
use futures::Stream;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
|
||||
/// A stream of chat responses
|
||||
pub type ChatStream = Pin<Box<dyn Stream<Item = Result<ChatResponse>> + Send>>;
|
||||
|
||||
/// Trait for LLM providers (Ollama, OpenAI, Anthropic, etc.)
|
||||
#[async_trait::async_trait]
|
||||
pub trait Provider: Send + Sync {
|
||||
/// Get the name of this provider
|
||||
fn name(&self) -> &str;
|
||||
|
||||
/// List available models from this provider
|
||||
async fn list_models(&self) -> Result<Vec<ModelInfo>>;
|
||||
|
||||
/// Send a chat completion request
|
||||
async fn chat(&self, request: ChatRequest) -> Result<ChatResponse>;
|
||||
|
||||
/// Send a streaming chat completion request
|
||||
async fn chat_stream(&self, request: ChatRequest) -> Result<ChatStream>;
|
||||
|
||||
/// Check if the provider is available/healthy
|
||||
async fn health_check(&self) -> Result<()>;
|
||||
|
||||
/// Get provider-specific configuration schema
|
||||
fn config_schema(&self) -> serde_json::Value {
|
||||
serde_json::json!({})
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration for a provider
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub struct ProviderConfig {
|
||||
/// Provider type identifier
|
||||
pub provider_type: String,
|
||||
/// Base URL for API calls
|
||||
pub base_url: Option<String>,
|
||||
/// API key or token
|
||||
pub api_key: Option<String>,
|
||||
/// Additional provider-specific configuration
|
||||
#[serde(flatten)]
|
||||
pub extra: std::collections::HashMap<String, serde_json::Value>,
|
||||
}
|
||||
|
||||
/// A registry of providers
|
||||
pub struct ProviderRegistry {
|
||||
providers: std::collections::HashMap<String, Arc<dyn Provider>>,
|
||||
}
|
||||
|
||||
impl ProviderRegistry {
|
||||
/// Create a new provider registry
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
providers: std::collections::HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Register a provider
|
||||
pub fn register<P: Provider + 'static>(&mut self, provider: P) {
|
||||
self.register_arc(Arc::new(provider));
|
||||
}
|
||||
|
||||
/// Register an already wrapped provider
|
||||
pub fn register_arc(&mut self, provider: Arc<dyn Provider>) {
|
||||
let name = provider.name().to_string();
|
||||
self.providers.insert(name, provider);
|
||||
}
|
||||
|
||||
/// Get a provider by name
|
||||
pub fn get(&self, name: &str) -> Option<Arc<dyn Provider>> {
|
||||
self.providers.get(name).cloned()
|
||||
}
|
||||
|
||||
/// List all registered provider names
|
||||
pub fn list_providers(&self) -> Vec<String> {
|
||||
self.providers.keys().cloned().collect()
|
||||
}
|
||||
|
||||
/// Get all models from all providers
|
||||
pub async fn list_all_models(&self) -> Result<Vec<ModelInfo>> {
|
||||
let mut all_models = Vec::new();
|
||||
|
||||
for provider in self.providers.values() {
|
||||
match provider.list_models().await {
|
||||
Ok(mut models) => all_models.append(&mut models),
|
||||
Err(e) => {
|
||||
// Log error but continue with other providers
|
||||
eprintln!("Failed to get models from {}: {}", provider.name(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(all_models)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ProviderRegistry {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user