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