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}
108
109impl AgentSettingsContent {
110 pub fn set_dock(&mut self, dock: DockPosition) {
111 self.dock = Some(dock);
112 }
113
114 pub fn set_model(&mut self, language_model: LanguageModelSelection) {
115 // let model = language_model.id().0.to_string();
116 // let provider = language_model.provider_id().0.to_string();
117 // self.default_model = Some(LanguageModelSelection {
118 // provider: provider.into(),
119 // model,
120 // });
121 self.default_model = Some(language_model)
122 }
123
124 pub fn set_inline_assistant_model(&mut self, provider: String, model: String) {
125 self.inline_assistant_model = Some(LanguageModelSelection {
126 provider: provider.into(),
127 model,
128 });
129 }
130
131 pub fn set_commit_message_model(&mut self, provider: String, model: String) {
132 self.commit_message_model = Some(LanguageModelSelection {
133 provider: provider.into(),
134 model,
135 });
136 }
137
138 pub fn set_thread_summary_model(&mut self, provider: String, model: String) {
139 self.thread_summary_model = Some(LanguageModelSelection {
140 provider: provider.into(),
141 model,
142 });
143 }
144
145 pub fn set_always_allow_tool_actions(&mut self, allow: bool) {
146 self.always_allow_tool_actions = Some(allow);
147 }
148
149 pub fn set_play_sound_when_agent_done(&mut self, allow: bool) {
150 self.play_sound_when_agent_done = Some(allow);
151 }
152
153 pub fn set_single_file_review(&mut self, allow: bool) {
154 self.single_file_review = Some(allow);
155 }
156
157 pub fn set_use_modifier_to_send(&mut self, always_use: bool) {
158 self.use_modifier_to_send = Some(always_use);
159 }
160
161 pub fn set_profile(&mut self, profile_id: Arc<str>) {
162 self.default_profile = Some(profile_id);
163 }
164}
165
166#[skip_serializing_none]
167#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, JsonSchema)]
168pub struct AgentProfileContent {
169 pub name: Arc<str>,
170 #[serde(default)]
171 pub tools: IndexMap<Arc<str>, bool>,
172 /// Whether all context servers are enabled by default.
173 pub enable_all_context_servers: Option<bool>,
174 #[serde(default)]
175 pub context_servers: IndexMap<Arc<str>, ContextServerPresetContent>,
176}
177
178#[skip_serializing_none]
179#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize, JsonSchema)]
180pub struct ContextServerPresetContent {
181 pub tools: IndexMap<Arc<str>, bool>,
182}
183
184#[derive(Copy, Clone, Default, Debug, PartialEq, Serialize, Deserialize, JsonSchema)]
185#[serde(rename_all = "snake_case")]
186pub enum DefaultAgentView {
187 #[default]
188 Thread,
189 TextThread,
190}
191
192#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]
193#[serde(rename_all = "snake_case")]
194pub enum NotifyWhenAgentWaiting {
195 #[default]
196 PrimaryScreen,
197 AllScreens,
198 Never,
199}
200
201#[skip_serializing_none]
202#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]
203pub struct LanguageModelSelection {
204 pub provider: LanguageModelProviderSetting,
205 pub model: String,
206}
207
208#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Default)]
209#[serde(rename_all = "snake_case")]
210pub enum CompletionMode {
211 #[default]
212 Normal,
213 #[serde(alias = "max")]
214 Burn,
215}
216
217#[skip_serializing_none]
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#[skip_serializing_none]
267#[derive(Default, PartialEq, Deserialize, Serialize, Clone, JsonSchema, Debug)]
268pub struct AllAgentServersSettings {
269 pub gemini: Option<BuiltinAgentServerSettings>,
270 pub claude: Option<BuiltinAgentServerSettings>,
271
272 /// Custom agent servers configured by the user
273 #[serde(flatten)]
274 pub custom: HashMap<SharedString, CustomAgentServerSettings>,
275}
276
277#[skip_serializing_none]
278#[derive(Default, Deserialize, Serialize, Clone, JsonSchema, Debug, PartialEq)]
279pub struct BuiltinAgentServerSettings {
280 /// Absolute path to a binary to be used when launching this agent.
281 ///
282 /// This can be used to run a specific binary without automatic downloads or searching `$PATH`.
283 #[serde(rename = "command")]
284 pub path: Option<PathBuf>,
285 /// If a binary is specified in `command`, it will be passed these arguments.
286 pub args: Option<Vec<String>>,
287 /// If a binary is specified in `command`, it will be passed these environment variables.
288 pub env: Option<HashMap<String, String>>,
289 /// Whether to skip searching `$PATH` for an agent server binary when
290 /// launching this agent.
291 ///
292 /// This has no effect if a `command` is specified. Otherwise, when this is
293 /// `false`, Zed will search `$PATH` for an agent server binary and, if one
294 /// is found, use it for threads with this agent. If no agent binary is
295 /// found on `$PATH`, Zed will automatically install and use its own binary.
296 /// When this is `true`, Zed will not search `$PATH`, and will always use
297 /// its own binary.
298 ///
299 /// Default: true
300 pub ignore_system_version: Option<bool>,
301 /// The default mode to use for this agent.
302 ///
303 /// Note: Not only all agents support modes.
304 ///
305 /// Default: None
306 pub default_mode: Option<String>,
307}
308
309#[skip_serializing_none]
310#[derive(Deserialize, Serialize, Clone, JsonSchema, Debug, PartialEq)]
311pub struct CustomAgentServerSettings {
312 #[serde(rename = "command")]
313 pub path: PathBuf,
314 #[serde(default)]
315 pub args: Vec<String>,
316 pub env: Option<HashMap<String, String>>,
317 /// The default mode to use for this agent.
318 ///
319 /// Note: Not only all agents support modes.
320 ///
321 /// Default: None
322 pub default_mode: Option<String>,
323}