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