1use collections::{HashMap, IndexMap};
2use gpui::SharedString;
3use schemars::{JsonSchema, json_schema};
4use serde::{Deserialize, Serialize};
5use settings_macros::{MergeFrom, with_fallible_options};
6use std::{borrow::Cow, path::PathBuf, sync::Arc};
7
8use crate::DockPosition;
9
10#[with_fallible_options]
11#[derive(Clone, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom, Debug, Default)]
12pub struct AgentSettingsContent {
13 /// Whether the Agent is enabled.
14 ///
15 /// Default: true
16 pub enabled: Option<bool>,
17 /// Whether to show the agent panel button in the status bar.
18 ///
19 /// Default: true
20 pub button: Option<bool>,
21 /// Where to dock the agent panel.
22 ///
23 /// Default: right
24 pub dock: Option<DockPosition>,
25 /// Default width in pixels when the agent panel is docked to the left or right.
26 ///
27 /// Default: 640
28 #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
29 pub default_width: Option<f32>,
30 /// Default height in pixels when the agent panel is docked to the bottom.
31 ///
32 /// Default: 320
33 #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
34 pub default_height: Option<f32>,
35 /// The default model to use when creating new chats and for other features when a specific model is not specified.
36 pub default_model: Option<LanguageModelSelection>,
37 /// Model to use for the inline assistant. Defaults to default_model when not specified.
38 pub inline_assistant_model: Option<LanguageModelSelection>,
39 /// Model to use for generating git commit messages. Defaults to default_model when not specified.
40 pub commit_message_model: Option<LanguageModelSelection>,
41 /// Model to use for generating thread summaries. Defaults to default_model when not specified.
42 pub thread_summary_model: Option<LanguageModelSelection>,
43 /// Additional models with which to generate alternatives when performing inline assists.
44 pub inline_alternatives: Option<Vec<LanguageModelSelection>>,
45 /// The default profile to use in the Agent.
46 ///
47 /// Default: write
48 pub default_profile: Option<Arc<str>>,
49 /// Which view type to show by default in the agent panel.
50 ///
51 /// Default: "thread"
52 pub default_view: Option<DefaultAgentView>,
53 /// The available agent profiles.
54 pub profiles: Option<IndexMap<Arc<str>, AgentProfileContent>>,
55 /// Whenever a tool action would normally wait for your confirmation
56 /// that you allow it, always choose to allow it.
57 ///
58 /// This setting has no effect on external agents that support permission modes, such as Claude Code.
59 ///
60 /// Set `agent_servers.claude.default_mode` to `bypassPermissions`, to disable all permission requests when using Claude Code.
61 ///
62 /// Default: false
63 pub always_allow_tool_actions: Option<bool>,
64 /// Where to show a popup notification when the agent is waiting for user input.
65 ///
66 /// Default: "primary_screen"
67 pub notify_when_agent_waiting: Option<NotifyWhenAgentWaiting>,
68 /// Whether to play a sound when the agent has either completed its response, or needs user input.
69 ///
70 /// Default: false
71 pub play_sound_when_agent_done: Option<bool>,
72 /// Whether to display agent edits in single-file editors in addition to the review multibuffer pane.
73 ///
74 /// Default: true
75 pub single_file_review: Option<bool>,
76 /// Additional parameters for language model requests. When making a request
77 /// to a model, parameters will be taken from the last entry in this list
78 /// that matches the model's provider and name. In each entry, both provider
79 /// and model are optional, so that you can specify parameters for either
80 /// one.
81 ///
82 /// Default: []
83 #[serde(default)]
84 pub model_parameters: Vec<LanguageModelParameters>,
85 /// What completion mode to enable for new threads
86 ///
87 /// Default: normal
88 pub preferred_completion_mode: Option<CompletionMode>,
89 /// Whether to show thumb buttons for feedback in the agent panel.
90 ///
91 /// Default: true
92 pub enable_feedback: Option<bool>,
93 /// Whether to have edit cards in the agent panel expanded, showing a preview of the full diff.
94 ///
95 /// Default: true
96 pub expand_edit_card: Option<bool>,
97 /// Whether to have terminal cards in the agent panel expanded, showing the whole command output.
98 ///
99 /// Default: true
100 pub expand_terminal_card: Option<bool>,
101 /// Whether to always use cmd-enter (or ctrl-enter on Linux or Windows) to send messages in the agent panel.
102 ///
103 /// Default: false
104 pub use_modifier_to_send: Option<bool>,
105 /// Minimum number of lines of height the agent message editor should have.
106 ///
107 /// Default: 4
108 pub message_editor_min_lines: Option<usize>,
109}
110
111impl AgentSettingsContent {
112 pub fn set_dock(&mut self, dock: DockPosition) {
113 self.dock = Some(dock);
114 }
115
116 pub fn set_model(&mut self, language_model: LanguageModelSelection) {
117 // let model = language_model.id().0.to_string();
118 // let provider = language_model.provider_id().0.to_string();
119 // self.default_model = Some(LanguageModelSelection {
120 // provider: provider.into(),
121 // model,
122 // });
123 self.default_model = Some(language_model)
124 }
125
126 pub fn set_inline_assistant_model(&mut self, provider: String, model: String) {
127 self.inline_assistant_model = Some(LanguageModelSelection {
128 provider: provider.into(),
129 model,
130 });
131 }
132
133 pub fn set_commit_message_model(&mut self, provider: String, model: String) {
134 self.commit_message_model = Some(LanguageModelSelection {
135 provider: provider.into(),
136 model,
137 });
138 }
139
140 pub fn set_thread_summary_model(&mut self, provider: String, model: String) {
141 self.thread_summary_model = Some(LanguageModelSelection {
142 provider: provider.into(),
143 model,
144 });
145 }
146
147 pub fn set_always_allow_tool_actions(&mut self, allow: bool) {
148 self.always_allow_tool_actions = Some(allow);
149 }
150
151 pub fn set_play_sound_when_agent_done(&mut self, allow: bool) {
152 self.play_sound_when_agent_done = Some(allow);
153 }
154
155 pub fn set_single_file_review(&mut self, allow: bool) {
156 self.single_file_review = Some(allow);
157 }
158
159 pub fn set_use_modifier_to_send(&mut self, always_use: bool) {
160 self.use_modifier_to_send = Some(always_use);
161 }
162
163 pub fn set_profile(&mut self, profile_id: Arc<str>) {
164 self.default_profile = Some(profile_id);
165 }
166}
167
168#[with_fallible_options]
169#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema, MergeFrom)]
170pub struct AgentProfileContent {
171 pub name: Arc<str>,
172 #[serde(default)]
173 pub tools: IndexMap<Arc<str>, bool>,
174 /// Whether all context servers are enabled by default.
175 pub enable_all_context_servers: Option<bool>,
176 #[serde(default)]
177 pub context_servers: IndexMap<Arc<str>, ContextServerPresetContent>,
178 /// The default language model selected when using this profile.
179 pub default_model: Option<LanguageModelSelection>,
180}
181
182#[with_fallible_options]
183#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize, JsonSchema, MergeFrom)]
184pub struct ContextServerPresetContent {
185 pub tools: IndexMap<Arc<str>, bool>,
186}
187
188#[derive(Copy, Clone, Default, Debug, PartialEq, Serialize, Deserialize, JsonSchema, MergeFrom)]
189#[serde(rename_all = "snake_case")]
190pub enum DefaultAgentView {
191 #[default]
192 Thread,
193 TextThread,
194}
195
196#[derive(
197 Copy,
198 Clone,
199 Default,
200 Debug,
201 Serialize,
202 Deserialize,
203 JsonSchema,
204 MergeFrom,
205 PartialEq,
206 strum::VariantArray,
207 strum::VariantNames,
208)]
209#[serde(rename_all = "snake_case")]
210pub enum NotifyWhenAgentWaiting {
211 #[default]
212 PrimaryScreen,
213 AllScreens,
214 Never,
215}
216
217#[with_fallible_options]
218#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]
219pub struct LanguageModelSelection {
220 pub provider: LanguageModelProviderSetting,
221 pub model: String,
222}
223
224#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq, Default)]
225#[serde(rename_all = "snake_case")]
226pub enum CompletionMode {
227 #[default]
228 Normal,
229 #[serde(alias = "max")]
230 Burn,
231}
232
233#[with_fallible_options]
234#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]
235pub struct LanguageModelParameters {
236 pub provider: Option<LanguageModelProviderSetting>,
237 pub model: Option<SharedString>,
238 #[serde(serialize_with = "crate::serialize_optional_f32_with_two_decimal_places")]
239 pub temperature: Option<f32>,
240}
241
242#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, MergeFrom)]
243pub struct LanguageModelProviderSetting(pub String);
244
245impl JsonSchema for LanguageModelProviderSetting {
246 fn schema_name() -> Cow<'static, str> {
247 "LanguageModelProviderSetting".into()
248 }
249
250 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
251 // list the builtin providers as a subset so that we still auto complete them in the settings
252 json_schema!({
253 "anyOf": [
254 {
255 "type": "string",
256 "enum": [
257 "amazon-bedrock",
258 "copilot_chat",
259 "deepseek",
260 "google",
261 "lmstudio",
262 "mistral",
263 "ollama",
264 "openai",
265 "openrouter",
266 "vercel",
267 "x_ai",
268 "zed.dev"
269 ]
270 },
271 {
272 "type": "string",
273 }
274 ]
275 })
276 }
277}
278
279impl From<String> for LanguageModelProviderSetting {
280 fn from(provider: String) -> Self {
281 Self(provider)
282 }
283}
284
285impl From<&str> for LanguageModelProviderSetting {
286 fn from(provider: &str) -> Self {
287 Self(provider.to_string())
288 }
289}
290
291#[with_fallible_options]
292#[derive(Default, PartialEq, Deserialize, Serialize, Clone, JsonSchema, MergeFrom, Debug)]
293pub struct AllAgentServersSettings {
294 pub gemini: Option<BuiltinAgentServerSettings>,
295 pub claude: Option<BuiltinAgentServerSettings>,
296 pub codex: Option<BuiltinAgentServerSettings>,
297
298 /// Custom agent servers configured by the user
299 #[serde(flatten)]
300 pub custom: HashMap<SharedString, CustomAgentServerSettings>,
301}
302
303#[with_fallible_options]
304#[derive(Default, Deserialize, Serialize, Clone, JsonSchema, MergeFrom, Debug, PartialEq)]
305pub struct BuiltinAgentServerSettings {
306 /// Absolute path to a binary to be used when launching this agent.
307 ///
308 /// This can be used to run a specific binary without automatic downloads or searching `$PATH`.
309 #[serde(rename = "command")]
310 pub path: Option<PathBuf>,
311 /// If a binary is specified in `command`, it will be passed these arguments.
312 pub args: Option<Vec<String>>,
313 /// If a binary is specified in `command`, it will be passed these environment variables.
314 pub env: Option<HashMap<String, String>>,
315 /// Whether to skip searching `$PATH` for an agent server binary when
316 /// launching this agent.
317 ///
318 /// This has no effect if a `command` is specified. Otherwise, when this is
319 /// `false`, Zed will search `$PATH` for an agent server binary and, if one
320 /// is found, use it for threads with this agent. If no agent binary is
321 /// found on `$PATH`, Zed will automatically install and use its own binary.
322 /// When this is `true`, Zed will not search `$PATH`, and will always use
323 /// its own binary.
324 ///
325 /// Default: true
326 pub ignore_system_version: Option<bool>,
327 /// The default mode to use for this agent.
328 ///
329 /// Note: Not only all agents support modes.
330 ///
331 /// Default: None
332 pub default_mode: Option<String>,
333 /// The default model to use for this agent.
334 ///
335 /// This should be the model ID as reported by the agent.
336 ///
337 /// Default: None
338 pub default_model: Option<String>,
339}
340
341#[with_fallible_options]
342#[derive(Deserialize, Serialize, Clone, JsonSchema, MergeFrom, Debug, PartialEq)]
343#[serde(tag = "type", rename_all = "snake_case")]
344pub enum CustomAgentServerSettings {
345 Custom {
346 #[serde(rename = "command")]
347 path: PathBuf,
348 #[serde(default)]
349 args: Vec<String>,
350 env: Option<HashMap<String, String>>,
351 /// The default mode to use for this agent.
352 ///
353 /// Note: Not only all agents support modes.
354 ///
355 /// Default: None
356 default_mode: Option<String>,
357 /// The default model to use for this agent.
358 ///
359 /// This should be the model ID as reported by the agent.
360 ///
361 /// Default: None
362 default_model: Option<String>,
363 },
364 Extension {
365 /// The default mode to use for this agent.
366 ///
367 /// Note: Not only all agents support modes.
368 ///
369 /// Default: None
370 default_mode: Option<String>,
371 /// The default model to use for this agent.
372 ///
373 /// This should be the model ID as reported by the agent.
374 ///
375 /// Default: None
376 default_model: Option<String>,
377 },
378}