sidebar: Remove agent panel terminal feature flag (#56678)

Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments
- [x] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

Release Notes:

- Add the ability to create Terminal Threads in the Sidebar and Agent
Panel.
This commit is contained in:
Ben Brandt 2026-05-13 23:21:52 +02:00 committed by GitHub
parent 7d8fe38b56
commit a7f037d94b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 6 additions and 98 deletions

View file

@ -60,7 +60,6 @@ use collections::HashMap;
use editor::{Editor, MultiBuffer};
use extension::ExtensionEvents;
use extension_host::ExtensionStore;
use feature_flags::{AgentPanelTerminalFeatureFlag, FeatureFlagAppExt as _};
use fs::Fs;
use gpui::{
Action, Anchor, Animation, AnimationExt, AnyElement, App, AsyncWindowContext, ClipboardItem,
@ -1488,9 +1487,6 @@ impl AgentPanel {
window: &mut Window,
cx: &mut Context<Self>,
) {
if !cx.has_flag::<AgentPanelTerminalFeatureFlag>() {
return;
}
let working_directory = self.terminal_working_directory(workspace, cx);
self.spawn_terminal(TerminalId::new(), working_directory, true, window, cx);
}
@ -1505,13 +1501,9 @@ impl AgentPanel {
.unwrap_or_else(|| self.default_terminal_working_directory(cx))
}
pub fn supports_terminal(&self, cx: &App) -> bool {
cx.has_flag::<AgentPanelTerminalFeatureFlag>()
&& self.project.read(cx).supports_terminal(cx)
}
pub fn should_create_terminal_for_new_entry(&self, cx: &App) -> bool {
self.last_created_entry_kind == AgentPanelEntryKind::Terminal && self.supports_terminal(cx)
self.last_created_entry_kind == AgentPanelEntryKind::Terminal
&& self.project.read(cx).supports_terminal(cx)
}
fn set_last_created_entry_kind(
@ -1570,9 +1562,6 @@ impl AgentPanel {
window: &mut Window,
cx: &mut Context<Self>,
) {
if !cx.has_flag::<AgentPanelTerminalFeatureFlag>() {
return;
}
let terminal_entity = terminal_view.read(cx).terminal().clone();
let view_subscription = cx.subscribe(
&terminal_view,
@ -1634,9 +1623,6 @@ impl AgentPanel {
window: &mut Window,
cx: &mut Context<Self>,
) {
if !cx.has_flag::<AgentPanelTerminalFeatureFlag>() {
return;
}
let Some(terminal) = self.terminals.get_mut(&terminal_id) else {
return;
};
@ -2359,10 +2345,6 @@ impl AgentPanel {
}
pub fn terminals(&self, cx: &App) -> Vec<AgentPanelTerminalInfo> {
if !cx.has_flag::<AgentPanelTerminalFeatureFlag>() {
return Vec::new();
}
self.terminals
.iter()
.map(|(id, terminal)| AgentPanelTerminalInfo {
@ -4170,7 +4152,7 @@ impl AgentPanel {
let focus_handle = self.focus_handle(cx);
let supports_terminal = self.supports_terminal(cx);
let supports_terminal = self.project.read(cx).supports_terminal(cx);
let showing_terminal = matches!(self.visible_surface(), VisibleSurface::Terminal(_));
let (selected_agent_custom_icon, selected_agent_label) = if showing_terminal {
@ -5088,10 +5070,6 @@ impl AgentPanel {
window: &mut Window,
cx: &mut Context<Self>,
) -> Result<TerminalId> {
if !cx.has_flag::<AgentPanelTerminalFeatureFlag>() {
anyhow::bail!("agent-panel-terminal feature flag must be enabled");
}
let terminal_id = TerminalId::new();
let settings = TerminalSettings::get_global(cx).clone();
let path_style = self.project.read(cx).path_style(cx);
@ -6460,12 +6438,8 @@ mod tests {
#[gpui::test]
async fn test_terminal_entry_kind_controls_new_entry(cx: &mut TestAppContext) {
let (panel, mut cx) = setup_panel(cx).await;
cx.update(|_, cx| {
cx.update_flags(true, vec!["agent-panel-terminal".to_string()]);
});
panel.read_with(&cx, |panel, cx| {
assert!(panel.supports_terminal(cx));
assert!(panel.project.read(cx).supports_terminal(cx));
assert!(!panel.should_create_terminal_for_new_entry(cx));
});
@ -6500,10 +6474,6 @@ mod tests {
#[gpui::test]
async fn test_terminal_title_omits_placeholder_title(cx: &mut TestAppContext) {
let (panel, mut cx) = setup_panel(cx).await;
cx.update(|_, cx| {
cx.update_flags(true, vec!["agent-panel-terminal".to_string()]);
});
let terminal_id = panel
.update_in(&mut cx, |panel, window, cx| {
panel.insert_test_terminal("", true, window, cx)
@ -6571,10 +6541,6 @@ mod tests {
cx: &mut TestAppContext,
) {
let (workspace, panel, mut cx) = setup_workspace_panel(cx).await;
cx.update(|_, cx| {
cx.update_flags(true, vec!["agent-panel-terminal".to_string()]);
});
panel
.update_in(&mut cx, |panel, window, cx| {
panel.insert_test_terminal("Dev Server", false, window, cx)
@ -6606,10 +6572,6 @@ mod tests {
#[gpui::test]
async fn test_terminal_title_editor_is_created_only_while_editing(cx: &mut TestAppContext) {
let (panel, mut cx) = setup_panel(cx).await;
cx.update(|_, cx| {
cx.update_flags(true, vec!["agent-panel-terminal".to_string()]);
});
let terminal_id = panel
.update_in(&mut cx, |panel, window, cx| {
panel.insert_test_terminal("Dev Server", true, window, cx)
@ -6674,10 +6636,6 @@ mod tests {
cx: &mut TestAppContext,
) {
let (panel, mut cx) = setup_panel(cx).await;
cx.update(|_, cx| {
cx.update_flags(true, vec!["agent-panel-terminal".to_string()]);
});
let terminal_id = panel
.update_in(&mut cx, |panel, window, cx| {
panel.insert_test_terminal("Initial Custom Title", true, window, cx)
@ -6763,10 +6721,6 @@ mod tests {
#[gpui::test]
async fn test_terminal_bell_marks_and_activation_clears_notification(cx: &mut TestAppContext) {
let (panel, mut cx) = setup_panel(cx).await;
cx.update(|_, cx| {
cx.update_flags(true, vec!["agent-panel-terminal".to_string()]);
});
let first_terminal_id = panel
.update_in(&mut cx, |panel, window, cx| {
panel.insert_test_terminal("Build", true, window, cx)

View file

@ -35,14 +35,6 @@ impl FeatureFlag for AgentSharingFeatureFlag {
}
register_feature_flag!(AgentSharingFeatureFlag);
pub struct AgentPanelTerminalFeatureFlag;
impl FeatureFlag for AgentPanelTerminalFeatureFlag {
const NAME: &'static str = "agent-panel-terminal";
type Value = PresenceFlag;
}
register_feature_flag!(AgentPanelTerminalFeatureFlag);
pub struct DiffReviewFeatureFlag;
impl FeatureFlag for DiffReviewFeatureFlag {

View file

@ -21,8 +21,7 @@ use agent_ui::{
use chrono::{DateTime, Utc};
use editor::Editor;
use feature_flags::{
AgentPanelTerminalFeatureFlag, AgentThreadWorktreeLabel, AgentThreadWorktreeLabelFlag,
FeatureFlag, FeatureFlagAppExt as _, FeatureFlagViewExt as _,
AgentThreadWorktreeLabel, AgentThreadWorktreeLabelFlag, FeatureFlag, FeatureFlagAppExt as _,
};
use gpui::{
Action as _, AnyElement, App, ClickEvent, Context, DismissEvent, Entity, EntityId, FocusHandle,
@ -621,17 +620,6 @@ impl Sidebar {
.detach();
AgentThreadWorktreeLabelFlag::watch(cx);
cx.observe_flag::<AgentPanelTerminalFeatureFlag, _>(
window,
|enabled, this, _window, cx| {
if !*enabled && matches!(this.active_entry, Some(ActiveEntry::Terminal { .. })) {
this.active_entry = None;
}
this.sync_active_entry_from_active_workspace(cx);
this.update_entries(cx);
},
)
.detach();
let filter_editor = cx.new(|cx| {
let mut editor = Editor::single_line(window, cx);
@ -969,9 +957,7 @@ impl Sidebar {
return false;
}
if cx.has_flag::<AgentPanelTerminalFeatureFlag>()
&& let Some(terminal_id) = panel.active_terminal_id()
{
if let Some(terminal_id) = panel.active_terminal_id() {
self.active_entry = Some(ActiveEntry::Terminal {
terminal_id,
workspace: active_workspace,
@ -3329,9 +3315,6 @@ impl Sidebar {
terminal_id,
workspace,
} => {
if !cx.has_flag::<AgentPanelTerminalFeatureFlag>() {
return false;
}
let Some(workspace) = self
.find_workspace_in_current_window(cx, |candidate, _| candidate == workspace)
else {
@ -3351,9 +3334,6 @@ impl Sidebar {
window: &mut Window,
cx: &mut Context<Self>,
) {
if !cx.has_flag::<AgentPanelTerminalFeatureFlag>() {
return;
}
let Some(multi_workspace) = self.multi_workspace.upgrade() else {
return;
};
@ -4180,9 +4160,6 @@ impl Sidebar {
terminal_id,
workspace,
} => {
if !cx.has_flag::<AgentPanelTerminalFeatureFlag>() {
return;
}
if let Some(multi_workspace) = self.multi_workspace.upgrade() {
multi_workspace.update(cx, |multi_workspace, cx| {
multi_workspace.activate(workspace.clone(), None, window, cx);
@ -5728,9 +5705,6 @@ fn terminal_entries_for_workspace<S: std::hash::BuildHasher>(
branch_by_path: &HashMap<PathBuf, SharedString, S>,
cx: &App,
) -> impl Iterator<Item = TerminalEntry> {
if !cx.has_flag::<AgentPanelTerminalFeatureFlag>() {
return None.into_iter().flatten();
}
let Some(agent_panel) = workspace.read(cx).panel::<AgentPanel>(cx) else {
return None.into_iter().flatten();
};

View file

@ -33,12 +33,6 @@ fn init_test(cx: &mut TestAppContext) {
});
}
fn enable_agent_panel_terminal(cx: &mut TestAppContext) {
cx.update(|cx| {
cx.update_flags(true, vec!["agent-panel-terminal".to_string()]);
});
}
#[track_caller]
fn assert_active_thread(sidebar: &Sidebar, session_id: &acp::SessionId, msg: &str) {
let active = sidebar.active_entry.as_ref();
@ -1448,7 +1442,6 @@ fn setup_sidebar_with_agent_panel(
#[gpui::test]
async fn test_agent_panel_terminals_appear_in_sidebar_and_search(cx: &mut TestAppContext) {
let project = init_test_project_with_agent_panel("/my-project", cx).await;
enable_agent_panel_terminal(cx);
let (multi_workspace, cx) =
cx.add_window_view(|window, cx| MultiWorkspace::test_new(project.clone(), window, cx));
let (sidebar, panel) = setup_sidebar_with_agent_panel(&multi_workspace, cx);
@ -1529,7 +1522,6 @@ async fn test_agent_panel_terminal_shows_project_and_linked_worktree(cx: &mut Te
.update(cx, |project, cx| project.git_scans_complete(cx))
.await;
enable_agent_panel_terminal(cx);
let (multi_workspace, cx) =
cx.add_window_view(|window, cx| MultiWorkspace::test_new(main_project.clone(), window, cx));
let sidebar = setup_sidebar(&multi_workspace, cx);
@ -1560,7 +1552,6 @@ async fn test_agent_panel_terminal_shows_project_and_linked_worktree(cx: &mut Te
#[gpui::test]
async fn test_agent_panel_terminal_notifications_update_sidebar(cx: &mut TestAppContext) {
let project = init_test_project_with_agent_panel("/my-project", cx).await;
enable_agent_panel_terminal(cx);
let (multi_workspace, cx) =
cx.add_window_view(|window, cx| MultiWorkspace::test_new(project.clone(), window, cx));
let (sidebar, panel) = setup_sidebar_with_agent_panel(&multi_workspace, cx);
@ -1613,7 +1604,6 @@ async fn test_agent_panel_terminal_notifications_update_sidebar(cx: &mut TestApp
#[gpui::test]
async fn test_thread_switcher_can_activate_agent_panel_terminal(cx: &mut TestAppContext) {
let project = init_test_project_with_agent_panel("/my-project", cx).await;
enable_agent_panel_terminal(cx);
let (multi_workspace, cx) =
cx.add_window_view(|window, cx| MultiWorkspace::test_new(project.clone(), window, cx));
let (sidebar, panel) = setup_sidebar_with_agent_panel(&multi_workspace, cx);
@ -1690,7 +1680,6 @@ async fn test_archive_selected_thread_closes_selected_agent_panel_terminal(
cx: &mut TestAppContext,
) {
let project = init_test_project_with_agent_panel("/my-project", cx).await;
enable_agent_panel_terminal(cx);
let (multi_workspace, cx) =
cx.add_window_view(|window, cx| MultiWorkspace::test_new(project.clone(), window, cx));
let (sidebar, panel) = setup_sidebar_with_agent_panel(&multi_workspace, cx);
@ -1730,7 +1719,6 @@ async fn test_archive_selected_thread_closes_selected_agent_panel_terminal(
#[gpui::test]
async fn test_closing_active_agent_panel_terminal_activates_neighbor(cx: &mut TestAppContext) {
let project = init_test_project_with_agent_panel("/my-project", cx).await;
enable_agent_panel_terminal(cx);
let (multi_workspace, cx) =
cx.add_window_view(|window, cx| MultiWorkspace::test_new(project.clone(), window, cx));
let (sidebar, panel) = setup_sidebar_with_agent_panel(&multi_workspace, cx);