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