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