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