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