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