1use std::time::Duration;
2
3use anyhow::Result;
4use gpui::AppContext;
5use schemars::JsonSchema;
6use serde::{Deserialize, Serialize};
7use settings::{Settings, SettingsSources};
8
9use crate::provider::{
10 anthropic::AnthropicSettings,
11 cloud::{self, ZedDotDevSettings},
12 google::GoogleSettings,
13 ollama::OllamaSettings,
14 open_ai::OpenAiSettings,
15};
16
17/// Initializes the language model settings.
18pub fn init(cx: &mut AppContext) {
19 AllLanguageModelSettings::register(cx);
20}
21
22#[derive(Default)]
23pub struct AllLanguageModelSettings {
24 pub anthropic: AnthropicSettings,
25 pub ollama: OllamaSettings,
26 pub openai: OpenAiSettings,
27 pub zed_dot_dev: ZedDotDevSettings,
28 pub google: GoogleSettings,
29}
30
31#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
32pub struct AllLanguageModelSettingsContent {
33 pub anthropic: Option<AnthropicSettingsContent>,
34 pub ollama: Option<OllamaSettingsContent>,
35 pub openai: Option<OpenAiSettingsContent>,
36 #[serde(rename = "zed.dev")]
37 pub zed_dot_dev: Option<ZedDotDevSettingsContent>,
38 pub google: Option<GoogleSettingsContent>,
39}
40
41#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
42pub struct AnthropicSettingsContent {
43 pub api_url: Option<String>,
44 pub low_speed_timeout_in_seconds: Option<u64>,
45 pub available_models: Option<Vec<anthropic::Model>>,
46}
47
48#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
49pub struct OllamaSettingsContent {
50 pub api_url: Option<String>,
51 pub low_speed_timeout_in_seconds: Option<u64>,
52}
53
54#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
55pub struct OpenAiSettingsContent {
56 pub api_url: Option<String>,
57 pub low_speed_timeout_in_seconds: Option<u64>,
58 pub available_models: Option<Vec<open_ai::Model>>,
59}
60
61#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
62pub struct GoogleSettingsContent {
63 pub api_url: Option<String>,
64 pub low_speed_timeout_in_seconds: Option<u64>,
65 pub available_models: Option<Vec<google_ai::Model>>,
66}
67
68#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
69pub struct ZedDotDevSettingsContent {
70 available_models: Option<Vec<cloud::AvailableModel>>,
71}
72
73impl settings::Settings for AllLanguageModelSettings {
74 const KEY: Option<&'static str> = Some("language_models");
75
76 type FileContent = AllLanguageModelSettingsContent;
77
78 fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
79 fn merge<T>(target: &mut T, value: Option<T>) {
80 if let Some(value) = value {
81 *target = value;
82 }
83 }
84
85 let mut settings = AllLanguageModelSettings::default();
86
87 for value in sources.defaults_and_customizations() {
88 merge(
89 &mut settings.anthropic.api_url,
90 value.anthropic.as_ref().and_then(|s| s.api_url.clone()),
91 );
92 if let Some(low_speed_timeout_in_seconds) = value
93 .anthropic
94 .as_ref()
95 .and_then(|s| s.low_speed_timeout_in_seconds)
96 {
97 settings.anthropic.low_speed_timeout =
98 Some(Duration::from_secs(low_speed_timeout_in_seconds));
99 }
100 merge(
101 &mut settings.anthropic.available_models,
102 value
103 .anthropic
104 .as_ref()
105 .and_then(|s| s.available_models.clone()),
106 );
107
108 merge(
109 &mut settings.ollama.api_url,
110 value.ollama.as_ref().and_then(|s| s.api_url.clone()),
111 );
112 if let Some(low_speed_timeout_in_seconds) = value
113 .ollama
114 .as_ref()
115 .and_then(|s| s.low_speed_timeout_in_seconds)
116 {
117 settings.ollama.low_speed_timeout =
118 Some(Duration::from_secs(low_speed_timeout_in_seconds));
119 }
120
121 merge(
122 &mut settings.openai.api_url,
123 value.openai.as_ref().and_then(|s| s.api_url.clone()),
124 );
125 if let Some(low_speed_timeout_in_seconds) = value
126 .openai
127 .as_ref()
128 .and_then(|s| s.low_speed_timeout_in_seconds)
129 {
130 settings.openai.low_speed_timeout =
131 Some(Duration::from_secs(low_speed_timeout_in_seconds));
132 }
133 merge(
134 &mut settings.openai.available_models,
135 value
136 .openai
137 .as_ref()
138 .and_then(|s| s.available_models.clone()),
139 );
140
141 merge(
142 &mut settings.zed_dot_dev.available_models,
143 value
144 .zed_dot_dev
145 .as_ref()
146 .and_then(|s| s.available_models.clone()),
147 );
148
149 merge(
150 &mut settings.google.api_url,
151 value.google.as_ref().and_then(|s| s.api_url.clone()),
152 );
153 if let Some(low_speed_timeout_in_seconds) = value
154 .google
155 .as_ref()
156 .and_then(|s| s.low_speed_timeout_in_seconds)
157 {
158 settings.google.low_speed_timeout =
159 Some(Duration::from_secs(low_speed_timeout_in_seconds));
160 }
161 merge(
162 &mut settings.google.available_models,
163 value
164 .google
165 .as_ref()
166 .and_then(|s| s.available_models.clone()),
167 );
168 }
169
170 Ok(settings)
171 }
172}