#[allow(dead_code)]
pub mod cloud;
pub mod config;
pub mod continuedev;
pub mod cursor;
#[allow(dead_code)]
pub mod discovery;
pub mod ollama;
pub mod openai_compat;
#[allow(dead_code)]
pub mod session_format;
#[allow(unused_imports)]
pub use cloud::{CloudConversation, CloudMessage, CloudProvider, FetchOptions};
pub use config::ProviderType;
#[allow(unused_imports)]
pub use config::{CsmConfig, ProviderConfig};
#[allow(unused_imports)]
pub use discovery::discover_all_providers;
#[allow(unused_imports)]
pub use session_format::{GenericMessage, GenericSession};
use crate::models::ChatSession;
use anyhow::Result;
use std::path::PathBuf;
pub trait ChatProvider: Send + Sync {
fn provider_type(&self) -> ProviderType;
fn name(&self) -> &str;
fn is_available(&self) -> bool;
fn sessions_path(&self) -> Option<PathBuf>;
fn list_sessions(&self) -> Result<Vec<ChatSession>>;
fn import_session(&self, session_id: &str) -> Result<ChatSession>;
#[allow(dead_code)]
fn export_session(&self, session: &ChatSession) -> Result<()>;
}
pub struct ProviderRegistry {
providers: Vec<Box<dyn ChatProvider>>,
}
impl ProviderRegistry {
pub fn new() -> Self {
let mut registry = Self {
providers: Vec::new(),
};
registry.discover_providers();
registry
}
fn discover_providers(&mut self) {
if let Some(provider) = cursor::CursorProvider::discover() {
self.providers.push(Box::new(provider));
}
if let Some(provider) = ollama::OllamaProvider::discover() {
self.providers.push(Box::new(provider));
}
for provider in openai_compat::discover_openai_compatible_providers() {
self.providers.push(Box::new(provider));
}
}
pub fn providers(&self) -> &[Box<dyn ChatProvider>] {
&self.providers
}
pub fn available_providers(&self) -> Vec<&dyn ChatProvider> {
self.providers
.iter()
.filter(|p| p.is_available())
.map(|p| p.as_ref())
.collect()
}
pub fn get_provider(&self, provider_type: ProviderType) -> Option<&dyn ChatProvider> {
self.providers
.iter()
.find(|p| p.provider_type() == provider_type)
.map(|p| p.as_ref())
}
#[allow(dead_code)]
pub fn list_all_sessions(&self) -> Result<Vec<(ProviderType, ChatSession)>> {
let mut all_sessions = Vec::new();
for provider in &self.providers {
if provider.is_available() {
if let Ok(sessions) = provider.list_sessions() {
for session in sessions {
all_sessions.push((provider.provider_type(), session));
}
}
}
}
Ok(all_sessions)
}
}
impl Default for ProviderRegistry {
fn default() -> Self {
Self::new()
}
}