settings.rs

  1use std::sync::Arc;
  2
  3use anyhow::Result;
  4use collections::HashMap;
  5use gpui::App;
  6use schemars::JsonSchema;
  7use serde::{Deserialize, Serialize};
  8use settings::{Settings, SettingsKey, SettingsSources, SettingsUi};
  9
 10use crate::provider::{
 11    self,
 12    anthropic::AnthropicSettings,
 13    bedrock::AmazonBedrockSettings,
 14    cloud::{self, ZedDotDevSettings},
 15    deepseek::DeepSeekSettings,
 16    google::GoogleSettings,
 17    lmstudio::LmStudioSettings,
 18    mistral::MistralSettings,
 19    ollama::OllamaSettings,
 20    open_ai::OpenAiSettings,
 21    open_ai_compatible::OpenAiCompatibleSettings,
 22    open_router::OpenRouterSettings,
 23    vercel::VercelSettings,
 24    x_ai::XAiSettings,
 25};
 26
 27/// Initializes the language model settings.
 28pub fn init_settings(cx: &mut App) {
 29    AllLanguageModelSettings::register(cx);
 30}
 31
 32#[derive(Default)]
 33pub struct AllLanguageModelSettings {
 34    pub anthropic: AnthropicSettings,
 35    pub bedrock: AmazonBedrockSettings,
 36    pub deepseek: DeepSeekSettings,
 37    pub google: GoogleSettings,
 38    pub lmstudio: LmStudioSettings,
 39    pub mistral: MistralSettings,
 40    pub ollama: OllamaSettings,
 41    pub open_router: OpenRouterSettings,
 42    pub openai: OpenAiSettings,
 43    pub openai_compatible: HashMap<Arc<str>, OpenAiCompatibleSettings>,
 44    pub vercel: VercelSettings,
 45    pub x_ai: XAiSettings,
 46    pub zed_dot_dev: ZedDotDevSettings,
 47}
 48
 49#[derive(
 50    Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema, SettingsUi, SettingsKey,
 51)]
 52#[settings_key(key = "language_models")]
 53pub struct AllLanguageModelSettingsContent {
 54    pub anthropic: Option<AnthropicSettingsContent>,
 55    pub bedrock: Option<AmazonBedrockSettingsContent>,
 56    pub deepseek: Option<DeepseekSettingsContent>,
 57    pub google: Option<GoogleSettingsContent>,
 58    pub lmstudio: Option<LmStudioSettingsContent>,
 59    pub mistral: Option<MistralSettingsContent>,
 60    pub ollama: Option<OllamaSettingsContent>,
 61    pub open_router: Option<OpenRouterSettingsContent>,
 62    pub openai: Option<OpenAiSettingsContent>,
 63    pub openai_compatible: Option<HashMap<Arc<str>, OpenAiCompatibleSettingsContent>>,
 64    pub vercel: Option<VercelSettingsContent>,
 65    pub x_ai: Option<XAiSettingsContent>,
 66    #[serde(rename = "zed.dev")]
 67    pub zed_dot_dev: Option<ZedDotDevSettingsContent>,
 68}
 69
 70#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
 71pub struct AnthropicSettingsContent {
 72    pub api_url: Option<String>,
 73    pub available_models: Option<Vec<provider::anthropic::AvailableModel>>,
 74}
 75
 76#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
 77pub struct AmazonBedrockSettingsContent {
 78    available_models: Option<Vec<provider::bedrock::AvailableModel>>,
 79    endpoint_url: Option<String>,
 80    region: Option<String>,
 81    profile: Option<String>,
 82    authentication_method: Option<provider::bedrock::BedrockAuthMethod>,
 83}
 84
 85#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
 86pub struct OllamaSettingsContent {
 87    pub api_url: Option<String>,
 88    pub available_models: Option<Vec<provider::ollama::AvailableModel>>,
 89}
 90
 91#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
 92pub struct LmStudioSettingsContent {
 93    pub api_url: Option<String>,
 94    pub available_models: Option<Vec<provider::lmstudio::AvailableModel>>,
 95}
 96
 97#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
 98pub struct DeepseekSettingsContent {
 99    pub api_url: Option<String>,
100    pub available_models: Option<Vec<provider::deepseek::AvailableModel>>,
101}
102
103#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
104pub struct MistralSettingsContent {
105    pub api_url: Option<String>,
106    pub available_models: Option<Vec<provider::mistral::AvailableModel>>,
107}
108
109#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
110pub struct OpenAiSettingsContent {
111    pub api_url: Option<String>,
112    pub available_models: Option<Vec<provider::open_ai::AvailableModel>>,
113}
114
115#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
116pub struct OpenAiCompatibleSettingsContent {
117    pub api_url: String,
118    pub available_models: Vec<provider::open_ai_compatible::AvailableModel>,
119}
120
121#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
122pub struct VercelSettingsContent {
123    pub api_url: Option<String>,
124    pub available_models: Option<Vec<provider::vercel::AvailableModel>>,
125}
126
127#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
128pub struct GoogleSettingsContent {
129    pub api_url: Option<String>,
130    pub available_models: Option<Vec<provider::google::AvailableModel>>,
131}
132
133#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
134pub struct XAiSettingsContent {
135    pub api_url: Option<String>,
136    pub available_models: Option<Vec<provider::x_ai::AvailableModel>>,
137}
138
139#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
140pub struct ZedDotDevSettingsContent {
141    available_models: Option<Vec<cloud::AvailableModel>>,
142}
143
144#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
145pub struct OpenRouterSettingsContent {
146    pub api_url: Option<String>,
147    pub available_models: Option<Vec<provider::open_router::AvailableModel>>,
148}
149
150impl settings::Settings for AllLanguageModelSettings {
151    const PRESERVED_KEYS: Option<&'static [&'static str]> = Some(&["version"]);
152
153    type FileContent = AllLanguageModelSettingsContent;
154
155    fn load(sources: SettingsSources<Self::FileContent>, _: &mut App) -> Result<Self> {
156        fn merge<T>(target: &mut T, value: Option<T>) {
157            if let Some(value) = value {
158                *target = value;
159            }
160        }
161
162        let mut settings = AllLanguageModelSettings::default();
163
164        for value in sources.defaults_and_customizations() {
165            // Anthropic
166            let anthropic = value.anthropic.clone();
167            merge(
168                &mut settings.anthropic.api_url,
169                anthropic.as_ref().and_then(|s| s.api_url.clone()),
170            );
171            merge(
172                &mut settings.anthropic.available_models,
173                anthropic.as_ref().and_then(|s| s.available_models.clone()),
174            );
175
176            // Bedrock
177            let bedrock = value.bedrock.clone();
178            merge(
179                &mut settings.bedrock.profile_name,
180                bedrock.as_ref().map(|s| s.profile.clone()),
181            );
182            merge(
183                &mut settings.bedrock.authentication_method,
184                bedrock.as_ref().map(|s| s.authentication_method.clone()),
185            );
186            merge(
187                &mut settings.bedrock.region,
188                bedrock.as_ref().map(|s| s.region.clone()),
189            );
190            merge(
191                &mut settings.bedrock.endpoint,
192                bedrock.as_ref().map(|s| s.endpoint_url.clone()),
193            );
194
195            // Ollama
196            let ollama = value.ollama.clone();
197
198            merge(
199                &mut settings.ollama.api_url,
200                value.ollama.as_ref().and_then(|s| s.api_url.clone()),
201            );
202            merge(
203                &mut settings.ollama.available_models,
204                ollama.as_ref().and_then(|s| s.available_models.clone()),
205            );
206
207            // LM Studio
208            let lmstudio = value.lmstudio.clone();
209
210            merge(
211                &mut settings.lmstudio.api_url,
212                value.lmstudio.as_ref().and_then(|s| s.api_url.clone()),
213            );
214            merge(
215                &mut settings.lmstudio.available_models,
216                lmstudio.as_ref().and_then(|s| s.available_models.clone()),
217            );
218
219            // DeepSeek
220            let deepseek = value.deepseek.clone();
221
222            merge(
223                &mut settings.deepseek.api_url,
224                value.deepseek.as_ref().and_then(|s| s.api_url.clone()),
225            );
226            merge(
227                &mut settings.deepseek.available_models,
228                deepseek.as_ref().and_then(|s| s.available_models.clone()),
229            );
230
231            // OpenAI
232            let openai = value.openai.clone();
233            merge(
234                &mut settings.openai.api_url,
235                openai.as_ref().and_then(|s| s.api_url.clone()),
236            );
237            merge(
238                &mut settings.openai.available_models,
239                openai.as_ref().and_then(|s| s.available_models.clone()),
240            );
241
242            // OpenAI Compatible
243            if let Some(openai_compatible) = value.openai_compatible.clone() {
244                for (id, openai_compatible_settings) in openai_compatible {
245                    settings.openai_compatible.insert(
246                        id,
247                        OpenAiCompatibleSettings {
248                            api_url: openai_compatible_settings.api_url,
249                            available_models: openai_compatible_settings.available_models,
250                        },
251                    );
252                }
253            }
254
255            // Vercel
256            let vercel = value.vercel.clone();
257            merge(
258                &mut settings.vercel.api_url,
259                vercel.as_ref().and_then(|s| s.api_url.clone()),
260            );
261            merge(
262                &mut settings.vercel.available_models,
263                vercel.as_ref().and_then(|s| s.available_models.clone()),
264            );
265
266            // XAI
267            let x_ai = value.x_ai.clone();
268            merge(
269                &mut settings.x_ai.api_url,
270                x_ai.as_ref().and_then(|s| s.api_url.clone()),
271            );
272            merge(
273                &mut settings.x_ai.available_models,
274                x_ai.as_ref().and_then(|s| s.available_models.clone()),
275            );
276
277            // ZedDotDev
278            merge(
279                &mut settings.zed_dot_dev.available_models,
280                value
281                    .zed_dot_dev
282                    .as_ref()
283                    .and_then(|s| s.available_models.clone()),
284            );
285            merge(
286                &mut settings.google.api_url,
287                value.google.as_ref().and_then(|s| s.api_url.clone()),
288            );
289            merge(
290                &mut settings.google.available_models,
291                value
292                    .google
293                    .as_ref()
294                    .and_then(|s| s.available_models.clone()),
295            );
296
297            // Mistral
298            let mistral = value.mistral.clone();
299            merge(
300                &mut settings.mistral.api_url,
301                mistral.as_ref().and_then(|s| s.api_url.clone()),
302            );
303            merge(
304                &mut settings.mistral.available_models,
305                mistral.as_ref().and_then(|s| s.available_models.clone()),
306            );
307
308            // OpenRouter
309            let open_router = value.open_router.clone();
310            merge(
311                &mut settings.open_router.api_url,
312                open_router.as_ref().and_then(|s| s.api_url.clone()),
313            );
314            merge(
315                &mut settings.open_router.available_models,
316                open_router
317                    .as_ref()
318                    .and_then(|s| s.available_models.clone()),
319            );
320        }
321
322        Ok(settings)
323    }
324
325    fn import_from_vscode(_vscode: &settings::VsCodeSettings, _current: &mut Self::FileContent) {}
326}