chasm_cli/providers/
mod.rs1#[allow(dead_code)]
30pub mod cloud;
31pub mod config;
32pub mod cursor;
33#[allow(dead_code)]
34pub mod discovery;
35pub mod ollama;
36pub mod openai_compat;
37#[allow(dead_code)]
38pub mod session_format;
39
40#[allow(unused_imports)]
41pub use cloud::{CloudConversation, CloudMessage, CloudProvider, FetchOptions};
42pub use config::ProviderType;
43#[allow(unused_imports)]
44pub use config::{CsmConfig, ProviderConfig};
45#[allow(unused_imports)]
46pub use discovery::discover_all_providers;
47#[allow(unused_imports)]
48pub use session_format::{GenericMessage, GenericSession};
49
50use crate::models::ChatSession;
51use anyhow::Result;
52use std::path::PathBuf;
53
54pub trait ChatProvider: Send + Sync {
56 fn provider_type(&self) -> ProviderType;
58
59 fn name(&self) -> &str;
61
62 fn is_available(&self) -> bool;
64
65 fn sessions_path(&self) -> Option<PathBuf>;
67
68 fn list_sessions(&self) -> Result<Vec<ChatSession>>;
70
71 fn import_session(&self, session_id: &str) -> Result<ChatSession>;
73
74 #[allow(dead_code)]
76 fn export_session(&self, session: &ChatSession) -> Result<()>;
77
78 fn list_models(&self) -> Result<Vec<String>> {
80 Ok(Vec::new())
82 }
83}
84
85pub struct ProviderRegistry {
87 providers: Vec<Box<dyn ChatProvider>>,
88}
89
90impl ProviderRegistry {
91 pub fn new() -> Self {
93 let mut registry = Self {
94 providers: Vec::new(),
95 };
96 registry.discover_providers();
97 registry
98 }
99
100 fn discover_providers(&mut self) {
102 if let Some(provider) = cursor::CursorProvider::discover() {
104 self.providers.push(Box::new(provider));
105 }
106
107 if let Some(provider) = ollama::OllamaProvider::discover() {
109 self.providers.push(Box::new(provider));
110 }
111
112 for provider in openai_compat::discover_openai_compatible_providers() {
114 self.providers.push(Box::new(provider));
115 }
116 }
117
118 pub fn providers(&self) -> &[Box<dyn ChatProvider>] {
120 &self.providers
121 }
122
123 pub fn available_providers(&self) -> Vec<&dyn ChatProvider> {
125 self.providers
126 .iter()
127 .filter(|p| p.is_available())
128 .map(|p| p.as_ref())
129 .collect()
130 }
131
132 pub fn get_provider(&self, provider_type: ProviderType) -> Option<&dyn ChatProvider> {
134 self.providers
135 .iter()
136 .find(|p| p.provider_type() == provider_type)
137 .map(|p| p.as_ref())
138 }
139
140 #[allow(dead_code)]
142 pub fn list_all_sessions(&self) -> Result<Vec<(ProviderType, ChatSession)>> {
143 let mut all_sessions = Vec::new();
144
145 for provider in &self.providers {
146 if provider.is_available() {
147 if let Ok(sessions) = provider.list_sessions() {
148 for session in sessions {
149 all_sessions.push((provider.provider_type(), session));
150 }
151 }
152 }
153 }
154
155 Ok(all_sessions)
156 }
157}
158
159impl Default for ProviderRegistry {
160 fn default() -> Self {
161 Self::new()
162 }
163}