1use collections::{HashMap, IndexMap};
2use gpui::SharedString;
3use schemars::{JsonSchema, json_schema};
4use serde::{Deserialize, Serialize};
5use std::{borrow::Cow, path::PathBuf, sync::Arc};
6
7use crate::DockPosition;
8
9#[derive(Clone, PartialEq, Serialize, Deserialize, JsonSchema, Debug, Default)]
10pub struct AgentSettingsContent {
11 /// Whether the Agent is enabled.
12 ///
13 /// Default: true
14 pub enabled: Option<bool>,
15 /// Whether to show the agent panel button in the status bar.
16 ///
17 /// Default: true
18 pub button: Option<bool>,
19 /// Where to dock the agent panel.
20 ///
21 /// Default: right
22 pub dock: Option<DockPosition>,
23 /// Default width in pixels when the agent panel is docked to the left or right.
24 ///
25 /// Default: 640
26 pub default_width: Option<f32>,
27 /// Default height in pixels when the agent panel is docked to the bottom.
28 ///
29 /// Default: 320
30 pub default_height: Option<f32>,
31 /// The default model to use when creating new chats and for other features when a specific model is not specified.
32 pub default_model: Option<LanguageModelSelection>,
33 /// Model to use for the inline assistant. Defaults to default_model when not specified.
34 pub inline_assistant_model: Option<LanguageModelSelection>,
35 /// Model to use for generating git commit messages. Defaults to default_model when not specified.
36 pub commit_message_model: Option<LanguageModelSelection>,
37 /// Model to use for generating thread summaries. Defaults to default_model when not specified.
38 pub thread_summary_model: Option<LanguageModelSelection>,
39 /// Additional models with which to generate alternatives when performing inline assists.
40 pub inline_alternatives: Option<Vec<LanguageModelSelection>>,
41 /// The default profile to use in the Agent.
42 ///
43 /// Default: write
44 pub default_profile: Option<Arc<str>>,
45 /// Which view type to show by default in the agent panel.
46 ///
47 /// Default: "thread"
48 pub default_view: Option<DefaultAgentView>,
49 /// The available agent profiles.
50 pub profiles: Option<IndexMap<Arc<str>, AgentProfileContent>>,
51 /// Whenever a tool action would normally wait for your confirmation
52 /// that you allow it, always choose to allow it.
53 ///
54 /// This setting has no effect on external agents that support permission modes, such as Claude Code.
55 ///
56 /// Set `agent_servers.claude.default_mode` to `bypassPermissions`, to disable all permission requests when using Claude Code.
57 ///
58 /// Default: false
59 pub always_allow_tool_actions: Option<bool>,
60 /// Where to show a popup notification when the agent is waiting for user input.
61 ///
62 /// Default: "primary_screen"
63 pub notify_when_agent_waiting: Option<NotifyWhenAgentWaiting>,
64 /// Whether to play a sound when the agent has either completed its response, or needs user input.
65 ///
66 /// Default: false
67 pub play_sound_when_agent_done: Option<bool>,
68 /// Whether to stream edits from the agent as they are received.
69 ///
70 /// Default: false
71 pub stream_edits: 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}
106
107impl AgentSettingsContent {
108 pub fn set_dock(&mut self, dock: DockPosition) {
109 self.dock = Some(dock);
110 }
111
112 pub fn set_model(&mut self, language_model: LanguageModelSelection) {
113 // let model = language_model.id().0.to_string();
114 // let provider = language_model.provider_id().0.to_string();
115 // self.default_model = Some(LanguageModelSelection {
116 // provider: provider.into(),
117 // model,
118 // });
119 self.default_model = Some(language_model)
120 }
121
122 pub fn set_inline_assistant_model(&mut self, provider: String, model: String) {
123 self.inline_assistant_model = Some(LanguageModelSelection {
124 provider: provider.into(),
125 model,
126 });
127 }
128
129 pub fn set_commit_message_model(&mut self, provider: String, model: String) {
130 self.commit_message_model = Some(LanguageModelSelection {
131 provider: provider.into(),
132 model,
133 });
134 }
135
136 pub fn set_thread_summary_model(&mut self, provider: String, model: String) {
137 self.thread_summary_model = Some(LanguageModelSelection {
138 provider: provider.into(),
139 model,
140 });
141 }
142
143 pub fn set_always_allow_tool_actions(&mut self, allow: bool) {
144 self.always_allow_tool_actions = Some(allow);
145 }
146
147 pub fn set_play_sound_when_agent_done(&mut self, allow: bool) {
148 self.play_sound_when_agent_done = Some(allow);
149 }
150
151 pub fn set_single_file_review(&mut self, allow: bool) {
152 self.single_file_review = Some(allow);
153 }
154
155 pub fn set_use_modifier_to_send(&mut self, always_use: bool) {
156 self.use_modifier_to_send = Some(always_use);
157 }
158
159 pub fn set_profile(&mut self, profile_id: Arc<str>) {
160 self.default_profile = Some(profile_id);
161 }
162}
163#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
164pub struct AgentProfileContent {
165 pub name: Arc<str>,
166 #[serde(default)]
167 pub tools: IndexMap<Arc<str>, bool>,
168 /// Whether all context servers are enabled by default.
169 pub enable_all_context_servers: Option<bool>,
170 #[serde(default)]
171 pub context_servers: IndexMap<Arc<str>, ContextServerPresetContent>,
172}
173
174#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize, JsonSchema)]
175pub struct ContextServerPresetContent {
176 pub tools: IndexMap<Arc<str>, bool>,
177}
178
179#[derive(Copy, Clone, Default, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
180#[serde(rename_all = "snake_case")]
181pub enum DefaultAgentView {
182 #[default]
183 Thread,
184 TextThread,
185}
186
187#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]
188#[serde(rename_all = "snake_case")]
189pub enum NotifyWhenAgentWaiting {
190 #[default]
191 PrimaryScreen,
192 AllScreens,
193 Never,
194}
195
196#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]
197pub struct LanguageModelSelection {
198 pub provider: LanguageModelProviderSetting,
199 pub model: String,
200}
201
202#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Default)]
203#[serde(rename_all = "snake_case")]
204pub enum CompletionMode {
205 #[default]
206 Normal,
207 #[serde(alias = "max")]
208 Burn,
209}
210
211#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]
212pub struct LanguageModelParameters {
213 pub provider: Option<LanguageModelProviderSetting>,
214 pub model: Option<SharedString>,
215 pub temperature: Option<f32>,
216}
217
218#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
219pub struct LanguageModelProviderSetting(pub String);
220
221impl JsonSchema for LanguageModelProviderSetting {
222 fn schema_name() -> Cow<'static, str> {
223 "LanguageModelProviderSetting".into()
224 }
225
226 fn json_schema(_: &mut schemars::SchemaGenerator) -> schemars::Schema {
227 json_schema!({
228 "enum": [
229 "amazon-bedrock",
230 "anthropic",
231 "copilot_chat",
232 "deepseek",
233 "google",
234 "lmstudio",
235 "mistral",
236 "ollama",
237 "openai",
238 "openrouter",
239 "vercel",
240 "x_ai",
241 "zed.dev"
242 ]
243 })
244 }
245}
246
247impl From<String> for LanguageModelProviderSetting {
248 fn from(provider: String) -> Self {
249 Self(provider)
250 }
251}
252
253impl From<&str> for LanguageModelProviderSetting {
254 fn from(provider: &str) -> Self {
255 Self(provider.to_string())
256 }
257}
258
259#[derive(Default, PartialEq, Deserialize, Serialize, Clone, JsonSchema, Debug)]
260pub struct AllAgentServersSettings {
261 pub gemini: Option<BuiltinAgentServerSettings>,
262 pub claude: Option<BuiltinAgentServerSettings>,
263
264 /// Custom agent servers configured by the user
265 #[serde(flatten)]
266 pub custom: HashMap<SharedString, CustomAgentServerSettings>,
267}
268
269#[derive(Default, Deserialize, Serialize, Clone, JsonSchema, Debug, PartialEq)]
270pub struct BuiltinAgentServerSettings {
271 /// Absolute path to a binary to be used when launching this agent.
272 ///
273 /// This can be used to run a specific binary without automatic downloads or searching `$PATH`.
274 #[serde(rename = "command")]
275 pub path: Option<PathBuf>,
276 /// If a binary is specified in `command`, it will be passed these arguments.
277 pub args: Option<Vec<String>>,
278 /// If a binary is specified in `command`, it will be passed these environment variables.
279 pub env: Option<HashMap<String, String>>,
280 /// Whether to skip searching `$PATH` for an agent server binary when
281 /// launching this agent.
282 ///
283 /// This has no effect if a `command` is specified. Otherwise, when this is
284 /// `false`, Zed will search `$PATH` for an agent server binary and, if one
285 /// is found, use it for threads with this agent. If no agent binary is
286 /// found on `$PATH`, Zed will automatically install and use its own binary.
287 /// When this is `true`, Zed will not search `$PATH`, and will always use
288 /// its own binary.
289 ///
290 /// Default: true
291 pub ignore_system_version: Option<bool>,
292 /// The default mode to use for this agent.
293 ///
294 /// Note: Not only all agents support modes.
295 ///
296 /// Default: None
297 pub default_mode: Option<String>,
298}
299
300#[derive(Deserialize, Serialize, Clone, JsonSchema, Debug, PartialEq)]
301pub struct CustomAgentServerSettings {
302 #[serde(rename = "command")]
303 pub path: PathBuf,
304 #[serde(default)]
305 pub args: Vec<String>,
306 pub env: Option<HashMap<String, String>>,
307 /// The default mode to use for this agent.
308 ///
309 /// Note: Not only all agents support modes.
310 ///
311 /// Default: None
312 pub default_mode: Option<String>,
313}