Detailed changes
@@ -6,7 +6,6 @@ mod tool_picker;
use std::{ops::Range, sync::Arc};
-use agent_settings::AgentSettings;
use anyhow::Result;
use assistant_tool::{ToolSource, ToolWorkingSet};
use cloud_llm_client::{Plan, PlanV1, PlanV2};
@@ -29,10 +28,10 @@ use project::{
agent_server_store::{AgentServerStore, CLAUDE_CODE_NAME, CODEX_NAME, GEMINI_NAME},
context_server_store::{ContextServerConfiguration, ContextServerStatus, ContextServerStore},
};
-use settings::{Settings, SettingsStore, update_settings_file};
+use settings::{SettingsStore, update_settings_file};
use ui::{
Chip, CommonAnimationExt, ContextMenu, Disclosure, Divider, DividerColor, ElevationIndex,
- Indicator, PopoverMenu, Switch, SwitchColor, SwitchField, Tooltip, WithScrollbar, prelude::*,
+ Indicator, PopoverMenu, Switch, SwitchColor, Tooltip, WithScrollbar, prelude::*,
};
use util::ResultExt as _;
use workspace::{Workspace, create_and_open_local_file};
@@ -402,101 +401,6 @@ impl AgentConfiguration {
)
}
- fn render_command_permission(&mut self, cx: &mut Context<Self>) -> impl IntoElement {
- let always_allow_tool_actions = AgentSettings::get_global(cx).always_allow_tool_actions;
- let fs = self.fs.clone();
-
- SwitchField::new(
- "always-allow-tool-actions-switch",
- Some("Allow running commands without asking for confirmation"),
- Some(
- "The agent can perform potentially destructive actions without asking for your confirmation.".into(),
- ),
- always_allow_tool_actions,
- move |state, _window, cx| {
- let allow = state == &ToggleState::Selected;
- update_settings_file(fs.clone(), cx, move |settings, _| {
- settings.agent.get_or_insert_default().set_always_allow_tool_actions(allow);
- });
- },
- )
- }
-
- fn render_single_file_review(&mut self, cx: &mut Context<Self>) -> impl IntoElement {
- let single_file_review = AgentSettings::get_global(cx).single_file_review;
- let fs = self.fs.clone();
-
- SwitchField::new(
- "single-file-review",
- Some("Enable single-file agent reviews"),
- Some("Agent edits are also displayed in single-file editors for review.".into()),
- single_file_review,
- move |state, _window, cx| {
- let allow = state == &ToggleState::Selected;
- update_settings_file(fs.clone(), cx, move |settings, _| {
- settings
- .agent
- .get_or_insert_default()
- .set_single_file_review(allow);
- });
- },
- )
- }
-
- fn render_sound_notification(&mut self, cx: &mut Context<Self>) -> impl IntoElement {
- let play_sound_when_agent_done = AgentSettings::get_global(cx).play_sound_when_agent_done;
- let fs = self.fs.clone();
-
- SwitchField::new(
- "sound-notification",
- Some("Play sound when finished generating"),
- Some(
- "Hear a notification sound when the agent is done generating changes or needs your input.".into(),
- ),
- play_sound_when_agent_done,
- move |state, _window, cx| {
- let allow = state == &ToggleState::Selected;
- update_settings_file(fs.clone(), cx, move |settings, _| {
- settings.agent.get_or_insert_default().set_play_sound_when_agent_done(allow);
- });
- },
- )
- }
-
- fn render_modifier_to_send(&mut self, cx: &mut Context<Self>) -> impl IntoElement {
- let use_modifier_to_send = AgentSettings::get_global(cx).use_modifier_to_send;
- let fs = self.fs.clone();
-
- SwitchField::new(
- "modifier-send",
- Some("Use modifier to submit a message"),
- Some(
- "Make a modifier (cmd-enter on macOS, ctrl-enter on Linux or Windows) required to send messages.".into(),
- ),
- use_modifier_to_send,
- move |state, _window, cx| {
- let allow = state == &ToggleState::Selected;
- update_settings_file(fs.clone(), cx, move |settings, _| {
- settings.agent.get_or_insert_default().set_use_modifier_to_send(allow);
- });
- },
- )
- }
-
- fn render_general_settings_section(&mut self, cx: &mut Context<Self>) -> impl IntoElement {
- v_flex()
- .p(DynamicSpacing::Base16.rems(cx))
- .pr(DynamicSpacing::Base20.rems(cx))
- .gap_2p5()
- .border_b_1()
- .border_color(cx.theme().colors().border)
- .child(Headline::new("General Settings"))
- .child(self.render_command_permission(cx))
- .child(self.render_single_file_review(cx))
- .child(self.render_sound_notification(cx))
- .child(self.render_modifier_to_send(cx))
- }
-
fn render_zed_plan_info(&self, plan: Option<Plan>, cx: &mut Context<Self>) -> impl IntoElement {
if let Some(plan) = plan {
let free_chip_bg = cx
@@ -1141,7 +1045,6 @@ impl Render for AgentConfiguration {
.track_scroll(&self.scroll_handle)
.size_full()
.overflow_y_scroll()
- .child(self.render_general_settings_section(cx))
.child(self.render_agent_servers_section(cx))
.child(self.render_context_servers_section(window, cx))
.child(self.render_provider_configuration_section(cx)),
@@ -194,7 +194,19 @@ pub enum DefaultAgentView {
TextThread,
}
-#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize, JsonSchema, MergeFrom, PartialEq)]
+#[derive(
+ Copy,
+ Clone,
+ Default,
+ Debug,
+ Serialize,
+ Deserialize,
+ JsonSchema,
+ MergeFrom,
+ PartialEq,
+ strum::VariantArray,
+ strum::VariantNames,
+)]
#[serde(rename_all = "snake_case")]
pub enum NotifyWhenAgentWaiting {
#[default]
@@ -3122,6 +3122,82 @@ pub(crate) fn settings_data() -> Vec<SettingsPage> {
metadata: None,
files: USER,
}),
+ SettingsPageItem::SectionHeader("Agent Panel"),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Agent Panel Button",
+ description: "Whether to show the agent panel button in the status bar",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(agent) = &settings_content.agent {
+ &agent.button
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content.agent.get_or_insert_default().button
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Agent Panel Dock",
+ description: "Where to dock the agent panel.",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(agent) = &settings_content.agent {
+ &agent.dock
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content.agent.get_or_insert_default().dock
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Agent Panel Default Width",
+ description: "Default width when the agent panel is docked to the left or right",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(agent) = &settings_content.agent {
+ &agent.default_width
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content.agent.get_or_insert_default().default_width
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Agent Panel Default Height",
+ description: "Default height when the agent panel is docked to the bottom",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(agent) = &settings_content.agent {
+ &agent.default_height
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .agent
+ .get_or_insert_default()
+ .default_height
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
],
},
SettingsPage {
@@ -4357,6 +4433,196 @@ pub(crate) fn settings_data() -> Vec<SettingsPage> {
metadata: None,
files: USER,
}),
+ SettingsPageItem::SectionHeader("Agent Configuration"),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Always Allow Tool Actions",
+ description: "When enabled, the agent can run potentially destructive actions without asking for your confirmation. This setting has no effect on external agents.",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(agent) = &settings_content.agent {
+ &agent.always_allow_tool_actions
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .agent
+ .get_or_insert_default()
+ .always_allow_tool_actions
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Single File Review",
+ description: "When enabled, agent edits will also be displayed in single-file buffers for review",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(agent) = &settings_content.agent {
+ &agent.single_file_review
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .agent
+ .get_or_insert_default()
+ .single_file_review
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Enable Feedback",
+ description: "Show voting thumbs up/down icon buttons for feedback on agent edits",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(agent) = &settings_content.agent {
+ &agent.enable_feedback
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .agent
+ .get_or_insert_default()
+ .enable_feedback
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Notify When Agent Waiting",
+ description: "Where to show notifications when the agent has completed its response or needs confirmation before running a tool action",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(agent) = &settings_content.agent {
+ &agent.notify_when_agent_waiting
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .agent
+ .get_or_insert_default()
+ .notify_when_agent_waiting
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Play Sound When Agent Done",
+ description: "Whether to play a sound when the agent has either completed its response, or needs user input",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(agent) = &settings_content.agent {
+ &agent.play_sound_when_agent_done
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .agent
+ .get_or_insert_default()
+ .play_sound_when_agent_done
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Expand Edit Card",
+ description: "Whether to have edit cards in the agent panel expanded, showing a preview of the diff",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(agent) = &settings_content.agent {
+ &agent.expand_edit_card
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .agent
+ .get_or_insert_default()
+ .expand_edit_card
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Expand Terminal Card",
+ description: "Whether to have terminal cards in the agent panel expanded, showing the whole command output",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(agent) = &settings_content.agent {
+ &agent.expand_terminal_card
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .agent
+ .get_or_insert_default()
+ .expand_terminal_card
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Use Modifier To Send",
+ description: "Whether to always use cmd-enter (or ctrl-enter on Linux or Windows) to send messages",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(agent) = &settings_content.agent {
+ &agent.use_modifier_to_send
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .agent
+ .get_or_insert_default()
+ .use_modifier_to_send
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
+ SettingsPageItem::SettingItem(SettingItem {
+ title: "Message Editor Min Lines",
+ description: "Minimum number of lines to display in the agent message editor",
+ field: Box::new(SettingField {
+ pick: |settings_content| {
+ if let Some(agent) = &settings_content.agent {
+ &agent.message_editor_min_lines
+ } else {
+ &None
+ }
+ },
+ pick_mut: |settings_content| {
+ &mut settings_content
+ .agent
+ .get_or_insert_default()
+ .message_editor_min_lines
+ },
+ }),
+ metadata: None,
+ files: USER,
+ }),
],
},
SettingsPage {
@@ -376,7 +376,8 @@ fn init_renderers(cx: &mut App) {
.add_basic_renderer::<settings::DisplayIn>(render_dropdown)
.add_basic_renderer::<settings::MinimapThumb>(render_dropdown)
.add_basic_renderer::<settings::MinimapThumbBorder>(render_dropdown)
- .add_basic_renderer::<settings::SteppingGranularity>(render_dropdown);
+ .add_basic_renderer::<settings::SteppingGranularity>(render_dropdown)
+ .add_basic_renderer::<settings::NotifyWhenAgentWaiting>(render_dropdown);
// .add_renderer::<ThemeSelection>(|settings_field, file, _, window, cx| {
// render_dropdown(*settings_field, file, window, cx)
// });