Don't construct an agent panel when disable_ai is set (#39689)

Follow-up to #39649, possible fix for #39669

This implements an alternate strategy for showing/hiding the agent panel
in response to `disable_ai`. We don't load the panel at all if AI is
disabled at startup, and when the value of `disable_ai` changes, we load
the panel or destroy it as needed.

Release Notes:

- N/A
This commit is contained in:
Cole Miller
2025-10-07 12:48:37 -04:00
committed by GitHub
parent f9a2724a8b
commit d04ac864b8
3 changed files with 64 additions and 61 deletions
+3 -47
View File
@@ -48,12 +48,12 @@ use editor::{Anchor, AnchorRangeExt as _, Editor, EditorEvent, MultiBuffer};
use fs::Fs;
use gpui::{
Action, AnyElement, App, AsyncWindowContext, Corner, DismissEvent, Entity, EventEmitter,
ExternalPaths, FocusHandle, Focusable, KeyContext, Pixels, ReadGlobal as _, Subscription, Task,
UpdateGlobal, WeakEntity, prelude::*,
ExternalPaths, FocusHandle, Focusable, KeyContext, Pixels, Subscription, Task, UpdateGlobal,
WeakEntity, prelude::*,
};
use language::LanguageRegistry;
use language_model::{ConfigurationError, LanguageModelRegistry};
use project::{DisableAiSettings, Project, ProjectPath, Worktree};
use project::{Project, ProjectPath, Worktree};
use prompt_store::{PromptBuilder, PromptStore, UserPromptId};
use rules_library::{RulesLibrary, open_rules_library};
use search::{BufferSearchBar, buffer_search};
@@ -520,13 +520,6 @@ impl AgentPanel {
)
});
if SettingsStore::global(cx)
.get::<DisableAiSettings>(None)
.disable_ai
{
return panel;
}
panel.as_mut(cx).loading = true;
if let Some(serialized_panel) = serialized_panel {
panel.update(cx, |panel, cx| {
@@ -678,43 +671,6 @@ impl AgentPanel {
)
});
let mut old_disable_ai = false;
cx.observe_global_in::<SettingsStore>(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,
+13
View File
@@ -1748,6 +1748,19 @@ impl Workspace {
});
}
pub fn remove_panel<T: Panel>(
&mut self,
panel: &Entity<T>,
window: &mut Window,
cx: &mut Context<Self>,
) {
for dock in [&self.left_dock, &self.bottom_dock, &self.right_dock] {
dock.update(cx, |dock, cx| {
dock.remove_panel(panel, window, cx);
})
}
}
pub fn status_bar(&self) -> &Entity<StatusBar> {
&self.status_bar
}
+48 -14
View File
@@ -46,7 +46,7 @@ use paths::{
local_debug_file_relative_path, local_settings_file_relative_path,
local_tasks_file_relative_path,
};
use project::{DirectoryLister, ProjectItem};
use project::{DirectoryLister, DisableAiSettings, ProjectItem};
use project_panel::ProjectPanel;
use prompt_store::PromptBuilder;
use quick_action_bar::QuickActionBar;
@@ -604,21 +604,55 @@ fn initialize_panels(
workspace.add_panel(debug_panel, window, cx);
})?;
let is_assistant2_enabled = !cfg!(test);
let agent_panel = if is_assistant2_enabled {
let agent_panel =
agent_ui::AgentPanel::load(workspace_handle.clone(), prompt_builder, cx.clone())
.await?;
fn setup_or_teardown_agent_panel(
workspace: &mut Workspace,
prompt_builder: Arc<PromptBuilder>,
window: &mut Window,
cx: &mut Context<Workspace>,
) -> Task<anyhow::Result<()>> {
let disable_ai = SettingsStore::global(cx)
.get::<DisableAiSettings>(None)
.disable_ai
|| cfg!(test);
let existing_panel = workspace.panel::<agent_ui::AgentPanel>(cx);
match (disable_ai, existing_panel) {
(false, None) => cx.spawn_in(window, async move |workspace, cx| {
let panel =
agent_ui::AgentPanel::load(workspace.clone(), prompt_builder, cx.clone())
.await?;
workspace.update_in(cx, |workspace, window, cx| {
let disable_ai = SettingsStore::global(cx)
.get::<DisableAiSettings>(None)
.disable_ai;
let have_panel = workspace.panel::<agent_ui::AgentPanel>(cx).is_some();
if !disable_ai && !have_panel {
workspace.add_panel(panel, window, cx);
}
})
}),
(true, Some(existing_panel)) => {
workspace.remove_panel::<agent_ui::AgentPanel>(&existing_panel, window, cx);
Task::ready(Ok(()))
}
_ => Task::ready(Ok(())),
}
}
Some(agent_panel)
} else {
None
};
workspace_handle
.update_in(cx, |workspace, window, cx| {
setup_or_teardown_agent_panel(workspace, prompt_builder.clone(), window, cx)
})?
.await?;
workspace_handle.update_in(cx, |workspace, window, cx| {
if let Some(agent_panel) = agent_panel {
workspace.add_panel(agent_panel, window, cx);
}
cx.observe_global_in::<SettingsStore>(window, {
let prompt_builder = prompt_builder.clone();
move |workspace, window, cx| {
setup_or_teardown_agent_panel(workspace, prompt_builder.clone(), window, cx)
.detach_and_log_err(cx);
}
})
.detach();
// Register the actions that are shared between `assistant` and `assistant2`.
//
@@ -626,7 +660,7 @@ fn initialize_panels(
// functions so that we only register the actions once.
//
// Once we ship `assistant2` we can push this back down into `agent::agent_panel::init`.
if is_assistant2_enabled {
if !cfg!(test) {
<dyn AgentPanelDelegate>::set_global(
Arc::new(agent_ui::ConcreteAssistantPanelDelegate),
cx,