From 154b01c5fe55192d5f319c1858556f3246f49952 Mon Sep 17 00:00:00 2001 From: Finn Evers Date: Fri, 19 Sep 2025 17:05:39 +0200 Subject: [PATCH] Dismiss agent panel when `disable_ai` is toggled to `true` (#38461) Closes https://github.com/zed-industries/zed/issues/38331 This fixes an issue where we would not dismiss the panel once the user toggled the setting, leaving them in an awkward state where closing the panel would become hard. Also takes care of one more check for the `Fix with assistant` action and consolidates some of the `AgentSettings` and `DisableAiSetting` checks into one method to make the code more readable. Release Notes: - N/A --- Cargo.lock | 1 + crates/agent_settings/Cargo.toml | 1 + crates/agent_settings/src/agent_settings.rs | 5 +++ crates/agent_ui/src/agent_panel.rs | 44 ++++++++++++++++++--- crates/agent_ui/src/inline_assistant.rs | 8 ++-- crates/git_ui/src/git_panel.rs | 22 ++++------- crates/zed/src/zed/quick_action_bar.rs | 18 +++------ 7 files changed, 61 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3acfed9bd7..ed1e9bef3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -337,6 +337,7 @@ dependencies = [ "gpui", "language_model", "paths", + "project", "schemars 1.0.1", "serde", "serde_json", diff --git a/crates/agent_settings/Cargo.toml b/crates/agent_settings/Cargo.toml index 8af76053c2..a8b457a9dd 100644 --- a/crates/agent_settings/Cargo.toml +++ b/crates/agent_settings/Cargo.toml @@ -19,6 +19,7 @@ convert_case.workspace = true fs.workspace = true gpui.workspace = true language_model.workspace = true +project.workspace = true schemars.workspace = true serde.workspace = true settings.workspace = true diff --git a/crates/agent_settings/src/agent_settings.rs b/crates/agent_settings/src/agent_settings.rs index e416ce73e5..d862cacee1 100644 --- a/crates/agent_settings/src/agent_settings.rs +++ b/crates/agent_settings/src/agent_settings.rs @@ -5,6 +5,7 @@ use std::sync::Arc; use collections::IndexMap; use gpui::{App, Pixels, px}; use language_model::LanguageModel; +use project::DisableAiSettings; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use settings::{ @@ -53,6 +54,10 @@ pub struct AgentSettings { } impl AgentSettings { + pub fn enabled(&self, cx: &App) -> bool { + self.enabled && !DisableAiSettings::get_global(cx).disable_ai + } + pub fn temperature_for_model(model: &Arc, cx: &App) -> Option { let settings = Self::get_global(cx); for setting in settings.model_parameters.iter().rev() { diff --git a/crates/agent_ui/src/agent_panel.rs b/crates/agent_ui/src/agent_panel.rs index ee9ac73b2e..ba71fd84ab 100644 --- a/crates/agent_ui/src/agent_panel.rs +++ b/crates/agent_ui/src/agent_panel.rs @@ -1,4 +1,4 @@ -use std::ops::{Not, Range}; +use std::ops::Range; use std::path::Path; use std::rc::Rc; use std::sync::Arc; @@ -662,6 +662,43 @@ impl AgentPanel { ) }); + let mut old_disable_ai = false; + cx.observe_global_in::(window, move |panel, window, cx| { + let disable_ai = DisableAiSettings::get_global(cx).disable_ai; + if old_disable_ai != disable_ai { + let agent_panel_id = cx.entity_id(); + let agent_panel_visible = panel + .workspace + .update(cx, |workspace, cx| { + let agent_dock_position = panel.position(window, cx); + let agent_dock = workspace.dock_at_position(agent_dock_position); + let agent_panel_focused = agent_dock + .read(cx) + .active_panel() + .is_some_and(|panel| panel.panel_id() == agent_panel_id); + + let active_panel_visible = agent_dock + .read(cx) + .visible_panel() + .is_some_and(|panel| panel.panel_id() == agent_panel_id); + + if agent_panel_focused { + cx.dispatch_action(&ToggleFocus); + } + + active_panel_visible + }) + .unwrap_or_default(); + + if agent_panel_visible { + cx.emit(PanelEvent::Close); + } + + old_disable_ai = disable_ai; + } + }) + .detach(); + Self { active_view, workspace, @@ -674,11 +711,9 @@ impl AgentPanel { prompt_store, configuration: None, configuration_subscription: None, - inline_assist_context_store, previous_view: None, history_store: history_store.clone(), - new_thread_menu_handle: PopoverMenuHandle::default(), agent_panel_menu_handle: PopoverMenuHandle::default(), assistant_navigation_menu_handle: PopoverMenuHandle::default(), @@ -703,7 +738,6 @@ impl AgentPanel { if workspace .panel::(cx) .is_some_and(|panel| panel.read(cx).enabled(cx)) - && !DisableAiSettings::get_global(cx).disable_ai { workspace.toggle_panel_focus::(window, cx); } @@ -1499,7 +1533,7 @@ impl Panel for AgentPanel { } fn enabled(&self, cx: &App) -> bool { - DisableAiSettings::get_global(cx).disable_ai.not() && AgentSettings::get_global(cx).enabled + AgentSettings::get_global(cx).enabled(cx) } fn is_zoomed(&self, _window: &Window, _cx: &App) -> bool { diff --git a/crates/agent_ui/src/inline_assistant.rs b/crates/agent_ui/src/inline_assistant.rs index 79e092b709..98e7276dc4 100644 --- a/crates/agent_ui/src/inline_assistant.rs +++ b/crates/agent_ui/src/inline_assistant.rs @@ -144,8 +144,7 @@ impl InlineAssistant { let Some(terminal_panel) = workspace.read(cx).panel::(cx) else { return; }; - let enabled = !DisableAiSettings::get_global(cx).disable_ai - && AgentSettings::get_global(cx).enabled; + let enabled = AgentSettings::get_global(cx).enabled(cx); terminal_panel.update(cx, |terminal_panel, cx| { terminal_panel.set_assistant_enabled(enabled, cx) }); @@ -257,8 +256,7 @@ impl InlineAssistant { window: &mut Window, cx: &mut Context, ) { - let settings = AgentSettings::get_global(cx); - if !settings.enabled || DisableAiSettings::get_global(cx).disable_ai { + if !AgentSettings::get_global(cx).enabled(cx) { return; } @@ -1788,7 +1786,7 @@ impl CodeActionProvider for AssistantCodeActionProvider { _: &mut Window, cx: &mut App, ) -> Task>> { - if !AgentSettings::get_global(cx).enabled { + if !AgentSettings::get_global(cx).enabled(cx) { return Task::ready(Ok(Vec::new())); } diff --git a/crates/git_ui/src/git_panel.rs b/crates/git_ui/src/git_panel.rs index 76671eba7b..47dcc68d21 100644 --- a/crates/git_ui/src/git_panel.rs +++ b/crates/git_ui/src/git_panel.rs @@ -46,7 +46,7 @@ use panel::{ panel_icon_button, }; use project::{ - DisableAiSettings, Fs, Project, ProjectPath, + Fs, Project, ProjectPath, git_store::{GitStoreEvent, Repository, RepositoryEvent, RepositoryId}, }; use serde::{Deserialize, Serialize}; @@ -405,15 +405,11 @@ impl GitPanel { let scroll_handle = UniformListScrollHandle::new(); - let mut assistant_enabled = AgentSettings::get_global(cx).enabled; - let mut was_ai_disabled = DisableAiSettings::get_global(cx).disable_ai; + let mut was_ai_enabled = AgentSettings::get_global(cx).enabled(cx); let _settings_subscription = cx.observe_global::(move |_, cx| { - let is_ai_disabled = DisableAiSettings::get_global(cx).disable_ai; - if assistant_enabled != AgentSettings::get_global(cx).enabled - || was_ai_disabled != is_ai_disabled - { - assistant_enabled = AgentSettings::get_global(cx).enabled; - was_ai_disabled = is_ai_disabled; + let is_ai_enabled = AgentSettings::get_global(cx).enabled(cx); + if was_ai_enabled != is_ai_enabled { + was_ai_enabled = is_ai_enabled; cx.notify(); } }); @@ -1739,10 +1735,7 @@ impl GitPanel { /// Generates a commit message using an LLM. pub fn generate_commit_message(&mut self, cx: &mut Context) { - if !self.can_commit() - || DisableAiSettings::get_global(cx).disable_ai - || !agent_settings::AgentSettings::get_global(cx).enabled - { + if !self.can_commit() || !AgentSettings::get_global(cx).enabled(cx) { return; } @@ -2996,8 +2989,7 @@ impl GitPanel { &self, cx: &Context, ) -> Option { - if !agent_settings::AgentSettings::get_global(cx).enabled - || DisableAiSettings::get_global(cx).disable_ai + if !agent_settings::AgentSettings::get_global(cx).enabled(cx) || LanguageModelRegistry::read_global(cx) .commit_message_model() .is_none() diff --git a/crates/zed/src/zed/quick_action_bar.rs b/crates/zed/src/zed/quick_action_bar.rs index a6f85000e9..df1a417f58 100644 --- a/crates/zed/src/zed/quick_action_bar.rs +++ b/crates/zed/src/zed/quick_action_bar.rs @@ -15,7 +15,6 @@ use gpui::{ FocusHandle, Focusable, InteractiveElement, ParentElement, Render, Styled, Subscription, WeakEntity, Window, anchored, deferred, point, }; -use project::DisableAiSettings; use project::project_settings::DiagnosticSeverity; use search::{BufferSearchBar, buffer_search}; use settings::{Settings, SettingsStore}; @@ -48,20 +47,15 @@ impl QuickActionBar { workspace: &Workspace, cx: &mut Context, ) -> Self { - let mut was_ai_disabled = DisableAiSettings::get_global(cx).disable_ai; - let mut was_agent_enabled = AgentSettings::get_global(cx).enabled; + let mut was_agent_enabled = AgentSettings::get_global(cx).enabled(cx); let mut was_agent_button = AgentSettings::get_global(cx).button; let ai_settings_subscription = cx.observe_global::(move |_, cx| { - let is_ai_disabled = DisableAiSettings::get_global(cx).disable_ai; let agent_settings = AgentSettings::get_global(cx); + let is_agent_enabled = agent_settings.enabled(cx); - if was_ai_disabled != is_ai_disabled - || was_agent_enabled != agent_settings.enabled - || was_agent_button != agent_settings.button - { - was_ai_disabled = is_ai_disabled; - was_agent_enabled = agent_settings.enabled; + if was_agent_enabled != is_agent_enabled || was_agent_button != agent_settings.button { + was_agent_enabled = is_agent_enabled; was_agent_button = agent_settings.button; cx.notify(); } @@ -597,9 +591,7 @@ impl Render for QuickActionBar { .children(self.render_preview_button(self.workspace.clone(), cx)) .children(search_button) .when( - AgentSettings::get_global(cx).enabled - && AgentSettings::get_global(cx).button - && !DisableAiSettings::get_global(cx).disable_ai, + AgentSettings::get_global(cx).enabled(cx) && AgentSettings::get_global(cx).button, |bar| bar.child(assistant_button), ) .children(code_actions_dropdown)