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::{
10 provider::{
11 anthropic::AnthropicSettings, cloud::ZedDotDevSettings, ollama::OllamaSettings,
12 open_ai::OpenAiSettings,
13 },
14 CloudModel,
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}
29
30#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
31pub struct AllLanguageModelSettingsContent {
32 pub anthropic: Option<AnthropicSettingsContent>,
33 pub ollama: Option<OllamaSettingsContent>,
34 pub openai: Option<OpenAiSettingsContent>,
35 #[serde(rename = "zed.dev")]
36 pub zed_dot_dev: Option<ZedDotDevSettingsContent>,
37}
38
39#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
40pub struct AnthropicSettingsContent {
41 pub api_url: Option<String>,
42 pub low_speed_timeout_in_seconds: Option<u64>,
43 pub available_models: Option<Vec<anthropic::Model>>,
44}
45
46#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
47pub struct OllamaSettingsContent {
48 pub api_url: Option<String>,
49 pub low_speed_timeout_in_seconds: Option<u64>,
50}
51
52#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
53pub struct OpenAiSettingsContent {
54 pub api_url: Option<String>,
55 pub low_speed_timeout_in_seconds: Option<u64>,
56 pub available_models: Option<Vec<open_ai::Model>>,
57}
58
59#[derive(Default, Clone, Debug, Serialize, Deserialize, PartialEq, JsonSchema)]
60pub struct ZedDotDevSettingsContent {
61 available_models: Option<Vec<CloudModel>>,
62}
63
64impl settings::Settings for AllLanguageModelSettings {
65 const KEY: Option<&'static str> = Some("language_models");
66
67 type FileContent = AllLanguageModelSettingsContent;
68
69 fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
70 fn merge<T>(target: &mut T, value: Option<T>) {
71 if let Some(value) = value {
72 *target = value;
73 }
74 }
75
76 let mut settings = AllLanguageModelSettings::default();
77
78 for value in sources.defaults_and_customizations() {
79 merge(
80 &mut settings.anthropic.api_url,
81 value.anthropic.as_ref().and_then(|s| s.api_url.clone()),
82 );
83 if let Some(low_speed_timeout_in_seconds) = value
84 .anthropic
85 .as_ref()
86 .and_then(|s| s.low_speed_timeout_in_seconds)
87 {
88 settings.anthropic.low_speed_timeout =
89 Some(Duration::from_secs(low_speed_timeout_in_seconds));
90 }
91 merge(
92 &mut settings.anthropic.available_models,
93 value
94 .anthropic
95 .as_ref()
96 .and_then(|s| s.available_models.clone()),
97 );
98
99 merge(
100 &mut settings.ollama.api_url,
101 value.ollama.as_ref().and_then(|s| s.api_url.clone()),
102 );
103 if let Some(low_speed_timeout_in_seconds) = value
104 .ollama
105 .as_ref()
106 .and_then(|s| s.low_speed_timeout_in_seconds)
107 {
108 settings.ollama.low_speed_timeout =
109 Some(Duration::from_secs(low_speed_timeout_in_seconds));
110 }
111
112 merge(
113 &mut settings.openai.api_url,
114 value.openai.as_ref().and_then(|s| s.api_url.clone()),
115 );
116 if let Some(low_speed_timeout_in_seconds) = value
117 .openai
118 .as_ref()
119 .and_then(|s| s.low_speed_timeout_in_seconds)
120 {
121 settings.openai.low_speed_timeout =
122 Some(Duration::from_secs(low_speed_timeout_in_seconds));
123 }
124 merge(
125 &mut settings.openai.available_models,
126 value
127 .openai
128 .as_ref()
129 .and_then(|s| s.available_models.clone()),
130 );
131
132 merge(
133 &mut settings.zed_dot_dev.available_models,
134 value
135 .zed_dot_dev
136 .as_ref()
137 .and_then(|s| s.available_models.clone()),
138 );
139 }
140
141 Ok(settings)
142 }
143}