Remove Agent V2 feature flag (#52792)

It's happening.

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:

- N/A
This commit is contained in:
Mikayla Maki 2026-04-07 17:34:54 -07:00 committed by GitHub
parent 66d2cb20c9
commit 7bcdb12b4c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 65 additions and 312 deletions

3
Cargo.lock generated
View file

@ -12890,7 +12890,6 @@ checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
name = "platform_title_bar"
version = "0.1.0"
dependencies = [
"feature_flags",
"gpui",
"project",
"settings",
@ -15923,7 +15922,6 @@ dependencies = [
"edit_prediction",
"edit_prediction_ui",
"editor",
"feature_flags",
"fs",
"futures 0.3.32",
"fuzzy",
@ -16073,7 +16071,6 @@ dependencies = [
"anyhow",
"chrono",
"editor",
"feature_flags",
"fs",
"git",
"gpui",

View file

@ -717,7 +717,7 @@
// Default width of the project panel.
"default_width": 240,
// Where to dock the project panel. Can be 'left' or 'right'.
"dock": "left",
"dock": "right",
// Spacing between worktree entries in the project panel. Can be 'comfortable' or 'standard'.
"entry_spacing": "comfortable",
// Whether to show file icons in the project panel.
@ -819,7 +819,7 @@
// Default width of the outline panel.
"default_width": 300,
// Where to dock the outline panel. Can be 'left' or 'right'.
"dock": "left",
"dock": "right",
// Whether to show file icons in the outline panel.
"file_icons": true,
// Whether to show folder icons or chevrons for directories in the outline panel.
@ -871,7 +871,7 @@
// Whether to show the collaboration panel button in the status bar.
"button": true,
// Where to dock the collaboration panel. Can be 'left' or 'right'.
"dock": "left",
"dock": "right",
// Default width of the collaboration panel.
"default_width": 240,
},
@ -879,7 +879,7 @@
// Whether to show the git panel button in the status bar.
"button": true,
// Where to dock the git panel. Can be 'left' or 'right'.
"dock": "left",
"dock": "right",
// Default width of the git panel.
"default_width": 360,
// Style of the git status indicator in the panel.
@ -944,7 +944,7 @@
// Whether to show the agent panel button in the status bar.
"button": true,
// Where to dock the agent panel. Can be 'left', 'right' or 'bottom'.
"dock": "right",
"dock": "left",
// Whether the agent panel should use flexible (proportional) sizing.
//
// Default: true

View file

@ -728,14 +728,6 @@ mod tests {
use settings::ToolPermissionMode;
use settings::ToolPermissionsContent;
fn set_agent_v2_defaults(cx: &mut gpui::App) {
SettingsStore::update_global(cx, |store, cx| {
store.update_default_settings(cx, |defaults| {
PanelLayout::AGENT.write_to(defaults);
});
});
}
#[test]
fn test_compiled_regex_case_insensitive() {
let regex = CompiledRegex::new("rm\\s+-rf", false).unwrap();
@ -1216,9 +1208,6 @@ mod tests {
project::DisableAiSettings::register(cx);
AgentSettings::register(cx);
// Test defaults are editor layout; switch to agent V2.
set_agent_v2_defaults(cx);
// Should be Agent with an empty user layout (user hasn't customized).
let layout = AgentSettings::get_layout(cx);
let WindowLayout::Agent(Some(user_layout)) = layout else {
@ -1351,9 +1340,6 @@ mod tests {
project::DisableAiSettings::register(cx);
AgentSettings::register(cx);
// Apply the agent V2 defaults.
set_agent_v2_defaults(cx);
// User has agent=left (matches preset) and project_panel=left (does not)
SettingsStore::update_global(cx, |store, cx| {
store
@ -1442,7 +1428,7 @@ mod tests {
cx.run_until_parked();
// Read back the file and apply it, then switch to agent V2 defaults.
// Read back the file and apply it.
let written = fs.load(paths::settings_file().as_path()).await.unwrap();
cx.update(|cx| {
SettingsStore::update_global(cx, |store, cx| {
@ -1467,9 +1453,6 @@ mod tests {
);
assert_eq!(user_layout.git_panel_dock, Some(DockPosition::Left));
// Now switch defaults to agent V2.
set_agent_v2_defaults(cx);
// Even though defaults are now agent, the backfilled user settings
// keep everything in the editor layout. The user's experience
// hasn't changed.

View file

@ -19,7 +19,6 @@ use project::AgentId;
use serde::{Deserialize, Serialize};
use settings::{LanguageModelProviderSetting, LanguageModelSelection};
use feature_flags::{AgentV2FeatureFlag, FeatureFlagAppExt as _};
use zed_actions::agent::{
AddSelectionToThread, ConflictContent, ReauthenticateAgent, ResolveConflictedFilesWithAgent,
ResolveConflictsWithAgent, ReviewBranchDiff,
@ -923,16 +922,14 @@ impl AgentPanel {
panel.selected_agent = agent;
}
if let Some(ref start_thread_in) = serialized_panel.start_thread_in {
let is_worktree_flag_enabled =
cx.has_flag::<AgentV2FeatureFlag>();
let is_valid = match &start_thread_in {
StartThreadIn::LocalProject => true,
StartThreadIn::NewWorktree { .. } => {
let project = panel.project.read(cx);
is_worktree_flag_enabled && !project.is_via_collab()
!project.is_via_collab()
}
StartThreadIn::LinkedWorktree { path, .. } => {
is_worktree_flag_enabled && path.exists()
path.exists()
}
};
if is_valid {
@ -2083,9 +2080,6 @@ impl AgentPanel {
let new_target = match action {
StartThreadIn::LocalProject => StartThreadIn::LocalProject,
StartThreadIn::NewWorktree { .. } => {
if !cx.has_flag::<AgentV2FeatureFlag>() {
return;
}
if !self.project_has_git_repository(cx) {
log::error!(
"set_start_thread_in: cannot use worktree mode without a git repository"
@ -2101,9 +2095,6 @@ impl AgentPanel {
action.clone()
}
StartThreadIn::LinkedWorktree { .. } => {
if !cx.has_flag::<AgentV2FeatureFlag>() {
return;
}
if !self.project_has_git_repository(cx) {
log::error!(
"set_start_thread_in: cannot use LinkedWorktree without a git repository"
@ -3371,47 +3362,6 @@ impl AgentPanel {
})
}
fn render_recent_entries_menu(
&self,
icon: IconName,
corner: Corner,
cx: &mut Context<Self>,
) -> impl IntoElement {
let focus_handle = self.focus_handle(cx);
PopoverMenu::new("agent-nav-menu")
.trigger_with_tooltip(
IconButton::new("agent-nav-menu", icon).icon_size(IconSize::Small),
{
move |_window, cx| {
Tooltip::for_action_in(
"Toggle Recently Updated Threads",
&ToggleNavigationMenu,
&focus_handle,
cx,
)
}
},
)
.anchor(corner)
.with_handle(self.agent_navigation_menu_handle.clone())
.menu({
let menu = self.agent_navigation_menu.clone();
move |window, cx| {
telemetry::event!("View Thread History Clicked");
if let Some(menu) = menu.as_ref() {
menu.update(cx, |_, cx| {
cx.defer_in(window, |menu, window, cx| {
menu.rebuild(window, cx);
});
})
}
menu.clone()
}
})
}
fn render_toolbar_back_button(&self, cx: &mut Context<Self>) -> impl IntoElement {
let focus_handle = self.focus_handle(cx);
@ -3788,8 +3738,6 @@ impl AgentPanel {
selected_agent.into_any_element()
};
let show_history_menu = self.has_history_for_selected_agent(cx);
let has_v2_flag = cx.has_flag::<AgentV2FeatureFlag>();
let is_empty_state = !self.active_thread_has_messages(cx);
let is_in_history_or_config = matches!(
@ -3814,7 +3762,7 @@ impl AgentPanel {
}))
};
let use_v2_empty_toolbar = has_v2_flag && is_empty_state && !is_in_history_or_config;
let use_v2_empty_toolbar = is_empty_state && !is_in_history_or_config;
let max_content_width = AgentSettings::get_global(cx).max_content_width;
@ -3888,11 +3836,7 @@ impl AgentPanel {
|this| this.child(self.render_start_thread_in_selector(cx)),
)
.when(
has_v2_flag
&& matches!(
self.start_thread_in,
StartThreadIn::NewWorktree { .. }
),
matches!(self.start_thread_in, StartThreadIn::NewWorktree { .. }),
|this| this.child(self.render_new_worktree_branch_selector(cx)),
),
)
@ -3903,13 +3847,6 @@ impl AgentPanel {
.gap_1()
.pl_1()
.pr_1()
.when(show_history_menu && !has_v2_flag, |this| {
this.child(self.render_recent_entries_menu(
IconName::MenuAltTemp,
Corner::TopRight,
cx,
))
})
.child(full_screen_button)
.child(self.render_panel_options_menu(window, cx)),
)
@ -3956,13 +3893,6 @@ impl AgentPanel {
.pl_1()
.pr_1()
.child(new_thread_menu)
.when(show_history_menu && !has_v2_flag, |this| {
this.child(self.render_recent_entries_menu(
IconName::MenuAltTemp,
Corner::TopRight,
cx,
))
})
.child(full_screen_button)
.child(self.render_panel_options_menu(window, cx)),
)
@ -4491,7 +4421,6 @@ mod tests {
};
use acp_thread::{StubAgentConnection, ThreadStatus};
use agent_servers::CODEX_ID;
use feature_flags::FeatureFlagAppExt;
use fs::FakeFs;
use gpui::{TestAppContext, VisualTestContext};
use project::Project;
@ -4504,7 +4433,6 @@ mod tests {
async fn test_active_thread_serialize_and_load_round_trip(cx: &mut TestAppContext) {
init_test(cx);
cx.update(|cx| {
cx.update_flags(true, vec!["agent-v2".to_string()]);
agent::ThreadStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
});
@ -4625,7 +4553,6 @@ mod tests {
async fn test_non_native_thread_without_metadata_is_not_restored(cx: &mut TestAppContext) {
init_test(cx);
cx.update(|cx| {
cx.update_flags(true, vec!["agent-v2".to_string()]);
agent::ThreadStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
});
@ -5005,7 +4932,6 @@ mod tests {
async fn setup_panel(cx: &mut TestAppContext) -> (Entity<AgentPanel>, VisualTestContext) {
init_test(cx);
cx.update(|cx| {
cx.update_flags(true, vec!["agent-v2".to_string()]);
agent::ThreadStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
});
@ -5361,7 +5287,6 @@ mod tests {
async fn test_thread_target_local_project(cx: &mut TestAppContext) {
init_test(cx);
cx.update(|cx| {
cx.update_flags(true, vec!["agent-v2".to_string()]);
agent::ThreadStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
});
@ -5469,7 +5394,6 @@ mod tests {
async fn test_thread_target_serialization_round_trip(cx: &mut TestAppContext) {
init_test(cx);
cx.update(|cx| {
cx.update_flags(true, vec!["agent-v2".to_string()]);
agent::ThreadStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
});
@ -5571,7 +5495,6 @@ mod tests {
let fs = FakeFs::new(cx.executor());
cx.update(|cx| {
cx.update_flags(true, vec!["agent-v2".to_string()]);
agent::ThreadStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
<dyn fs::Fs>::set_global(fs.clone(), cx);
@ -5742,7 +5665,6 @@ mod tests {
init_test(cx);
let app_state = cx.update(|cx| {
cx.update_flags(true, vec!["agent-v2".to_string()]);
agent::ThreadStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
@ -5909,7 +5831,6 @@ mod tests {
init_test(cx);
cx.update(|cx| {
cx.update_flags(true, vec!["agent-v2".to_string()]);
agent::ThreadStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
});
@ -6101,7 +6022,6 @@ mod tests {
async fn test_new_workspace_inherits_global_last_used_agent(cx: &mut TestAppContext) {
init_test(cx);
cx.update(|cx| {
cx.update_flags(true, vec!["agent-v2".to_string()]);
agent::ThreadStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
// Use an isolated DB so parallel tests can't overwrite our global key.
@ -6155,7 +6075,6 @@ mod tests {
async fn test_workspaces_maintain_independent_agent_selection(cx: &mut TestAppContext) {
init_test(cx);
cx.update(|cx| {
cx.update_flags(true, vec!["agent-v2".to_string()]);
agent::ThreadStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
});
@ -6248,7 +6167,6 @@ mod tests {
async fn test_new_thread_uses_workspace_selected_agent(cx: &mut TestAppContext) {
init_test(cx);
cx.update(|cx| {
cx.update_flags(true, vec!["agent-v2".to_string()]);
agent::ThreadStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
});

View file

@ -45,9 +45,9 @@ use ::ui::IconName;
use agent_client_protocol as acp;
use agent_settings::{AgentProfileId, AgentSettings};
use command_palette_hooks::CommandPaletteFilter;
use feature_flags::{AgentV2FeatureFlag, FeatureFlagAppExt as _};
use feature_flags::FeatureFlagAppExt as _;
use fs::Fs;
use gpui::{Action, App, Context, Entity, SharedString, UpdateGlobal as _, Window, actions};
use gpui::{Action, App, Context, Entity, SharedString, Window, actions};
use language::{
LanguageRegistry,
language_settings::{AllLanguageSettings, EditPredictionProvider},
@ -59,7 +59,7 @@ use project::{AgentId, DisableAiSettings};
use prompt_store::PromptBuilder;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings::{DockPosition, DockSide, LanguageModelSelection, Settings as _, SettingsStore};
use settings::{LanguageModelSelection, Settings as _, SettingsStore};
use std::any::TypeId;
use workspace::Workspace;
@ -80,7 +80,6 @@ use zed_actions;
pub const DEFAULT_THREAD_TITLE: &str = "New Thread";
const PARALLEL_AGENT_LAYOUT_BACKFILL_KEY: &str = "parallel_agent_layout_backfilled";
actions!(
agent,
[
@ -511,43 +510,10 @@ pub fn init(
})
.detach();
// TODO: remove this field when we're ready remove the feature flag
maybe_backfill_editor_layout(fs, is_new_install, false, cx);
cx.observe_flag::<AgentV2FeatureFlag, _>(|is_enabled, cx| {
SettingsStore::update_global(cx, |store, cx| {
store.update_default_settings(cx, |defaults| {
if is_enabled {
defaults.agent.get_or_insert_default().dock = Some(DockPosition::Left);
defaults.project_panel.get_or_insert_default().dock = Some(DockSide::Right);
defaults.outline_panel.get_or_insert_default().dock = Some(DockSide::Right);
defaults.collaboration_panel.get_or_insert_default().dock =
Some(DockPosition::Right);
defaults.git_panel.get_or_insert_default().dock = Some(DockPosition::Right);
} else {
defaults.agent.get_or_insert_default().dock = Some(DockPosition::Right);
defaults.project_panel.get_or_insert_default().dock = Some(DockSide::Left);
defaults.outline_panel.get_or_insert_default().dock = Some(DockSide::Left);
defaults.collaboration_panel.get_or_insert_default().dock =
Some(DockPosition::Left);
defaults.git_panel.get_or_insert_default().dock = Some(DockPosition::Left);
}
});
});
})
.detach();
maybe_backfill_editor_layout(fs, is_new_install, cx);
}
fn maybe_backfill_editor_layout(
fs: Arc<dyn Fs>,
is_new_install: bool,
should_run: bool,
cx: &mut App,
) {
if !should_run {
return;
}
fn maybe_backfill_editor_layout(fs: Arc<dyn Fs>, is_new_install: bool, cx: &mut App) {
let kvp = db::kvp::KeyValueStore::global(cx);
let already_backfilled =
util::ResultExt::log_err(kvp.read_kvp(PARALLEL_AGENT_LAYOUT_BACKFILL_KEY))
@ -572,7 +538,7 @@ fn maybe_backfill_editor_layout(
fn update_command_palette_filter(cx: &mut App) {
let disable_ai = DisableAiSettings::get_global(cx).disable_ai;
let agent_enabled = AgentSettings::get_global(cx).enabled;
let agent_v2_enabled = cx.has_flag::<AgentV2FeatureFlag>();
let edit_prediction_provider = AllLanguageSettings::get_global(cx)
.edit_predictions
.provider;
@ -641,11 +607,7 @@ fn update_command_palette_filter(cx: &mut App) {
filter.show_action_types(&[TypeId::of::<zed_actions::OpenZedPredictOnboarding>()]);
}
if agent_v2_enabled {
filter.show_namespace("multi_workspace");
} else {
filter.hide_namespace("multi_workspace");
}
filter.show_namespace("multi_workspace");
});
}
@ -714,7 +676,6 @@ mod tests {
use command_palette_hooks::CommandPaletteFilter;
use db::kvp::KeyValueStore;
use editor::actions::AcceptEditPrediction;
use feature_flags::FeatureFlagAppExt;
use gpui::{BorrowAppContext, TestAppContext, px};
use project::DisableAiSettings;
use settings::{
@ -883,7 +844,7 @@ mod tests {
.is_none()
);
maybe_backfill_editor_layout(fs.clone(), false, true, cx);
maybe_backfill_editor_layout(fs.clone(), false, cx);
});
cx.run_until_parked();
@ -902,7 +863,7 @@ mod tests {
let fs = setup_backfill_test(cx).await;
cx.update(|cx| {
maybe_backfill_editor_layout(fs.clone(), true, true, cx);
maybe_backfill_editor_layout(fs.clone(), true, cx);
});
cx.run_until_parked();
@ -924,7 +885,7 @@ mod tests {
let fs = setup_backfill_test(cx).await;
cx.update(|cx| {
maybe_backfill_editor_layout(fs.clone(), false, true, cx);
maybe_backfill_editor_layout(fs.clone(), false, cx);
});
cx.run_until_parked();
@ -932,7 +893,7 @@ mod tests {
let after_first = fs.load(paths::settings_file().as_path()).await.unwrap();
cx.update(|cx| {
maybe_backfill_editor_layout(fs.clone(), false, true, cx);
maybe_backfill_editor_layout(fs.clone(), false, cx);
});
cx.run_until_parked();

View file

@ -22,7 +22,7 @@ use editor::scroll::Autoscroll;
use editor::{
Editor, EditorEvent, EditorMode, MultiBuffer, PathKey, SelectionEffects, SizingBehavior,
};
use feature_flags::{AgentSharingFeatureFlag, AgentV2FeatureFlag, FeatureFlagAppExt as _};
use feature_flags::{AgentSharingFeatureFlag, FeatureFlagAppExt as _};
use file_icons::FileIcons;
use fs::Fs;
use futures::FutureExt as _;
@ -2645,7 +2645,6 @@ impl ConversationView {
impl Render for ConversationView {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
self.sync_queued_message_editors(window, cx);
let v2_flag = cx.has_flag::<AgentV2FeatureFlag>();
v_flex()
.track_focus(&self.focus_handle)
@ -2654,17 +2653,18 @@ impl Render for ConversationView {
.child(match &self.server_state {
ServerState::Loading { .. } => v_flex()
.flex_1()
.when(v2_flag, |this| {
this.size_full().items_center().justify_center().child(
Label::new("Loading…").color(Color::Muted).with_animation(
"loading-agent-label",
Animation::new(Duration::from_secs(2))
.repeat()
.with_easing(pulsating_between(0.3, 0.7)),
|label, delta| label.alpha(delta),
),
)
})
.size_full()
.items_center()
.justify_center()
.child(
Label::new("Loading…").color(Color::Muted).with_animation(
"loading-agent-label",
Animation::new(Duration::from_secs(2))
.repeat()
.with_easing(pulsating_between(0.3, 0.7)),
|label, delta| label.alpha(delta),
),
)
.into_any(),
ServerState::LoadError { error: e, .. } => v_flex()
.flex_1()
@ -3437,7 +3437,6 @@ pub(crate) mod tests {
let fs = FakeFs::new(cx.executor());
cx.update(|cx| {
cx.update_flags(true, vec!["agent-v2".to_string()]);
agent::ThreadStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
<dyn Fs>::set_global(fs.clone(), cx);

View file

@ -3141,7 +3141,7 @@ impl ThreadView {
let editor_bg_color = cx.theme().colors().editor_background;
let editor_expanded = self.editor_expanded;
let has_messages = self.list_state.item_count() > 0;
let v2_empty_state = cx.has_flag::<AgentV2FeatureFlag>() && !has_messages;
let v2_empty_state = !has_messages;
let (expand_icon, expand_tooltip) = if editor_expanded {
(IconName::Minimize, "Minimize Message Editor")
} else {
@ -5158,7 +5158,7 @@ impl ThreadView {
pub(crate) fn sync_editor_mode_for_empty_state(&mut self, cx: &mut Context<Self>) {
let has_messages = self.list_state.item_count() > 0;
let v2_empty_state = cx.has_flag::<AgentV2FeatureFlag>() && !has_messages;
let v2_empty_state = !has_messages;
let mode = if v2_empty_state {
EditorMode::Full {
@ -6393,7 +6393,6 @@ impl ThreadView {
.when(is_collapsible || failed_or_canceled, |this| {
let diff_for_discard = if has_revealed_diff
&& is_cancelled_edit
&& cx.has_flag::<AgentV2FeatureFlag>()
{
tool_call.diffs().next().cloned()
} else {
@ -8621,7 +8620,7 @@ impl ThreadView {
impl Render for ThreadView {
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let has_messages = self.list_state.item_count() > 0;
let v2_empty_state = cx.has_flag::<AgentV2FeatureFlag>() && !has_messages;
let v2_empty_state = !has_messages;
let max_content_width = AgentSettings::get_global(cx).max_content_width;

View file

@ -16,7 +16,6 @@ use db::{
},
sqlez_macros::sql,
};
use feature_flags::{AgentV2FeatureFlag, FeatureFlagAppExt};
use futures::{FutureExt as _, future::Shared};
use gpui::{AppContext as _, Entity, Global, Subscription, Task};
use project::AgentId;
@ -28,16 +27,7 @@ use crate::DEFAULT_THREAD_TITLE;
pub fn init(cx: &mut App) {
ThreadMetadataStore::init_global(cx);
if cx.has_flag::<AgentV2FeatureFlag>() {
migrate_thread_metadata(cx);
}
cx.observe_flag::<AgentV2FeatureFlag, _>(|has_flag, cx| {
if has_flag {
migrate_thread_metadata(cx);
}
})
.detach();
migrate_thread_metadata(cx);
}
/// Migrate existing thread metadata from native agent thread store to the new metadata storage.
@ -343,10 +333,6 @@ impl ThreadMetadataStore {
}
pub fn save_all(&mut self, metadata: Vec<ThreadMetadata>, cx: &mut Context<Self>) {
if !cx.has_flag::<AgentV2FeatureFlag>() {
return;
}
for metadata in metadata {
self.save_internal(metadata);
}
@ -359,10 +345,6 @@ impl ThreadMetadataStore {
}
fn save(&mut self, metadata: ThreadMetadata, cx: &mut Context<Self>) {
if !cx.has_flag::<AgentV2FeatureFlag>() {
return;
}
self.save_internal(metadata);
cx.notify();
}
@ -412,10 +394,6 @@ impl ThreadMetadataStore {
work_dirs: PathList,
cx: &mut Context<Self>,
) {
if !cx.has_flag::<AgentV2FeatureFlag>() {
return;
}
if let Some(thread) = self.threads.get(session_id) {
self.save_internal(ThreadMetadata {
folder_paths: work_dirs,
@ -490,10 +468,6 @@ impl ThreadMetadataStore {
archived: bool,
cx: &mut Context<Self>,
) {
if !cx.has_flag::<AgentV2FeatureFlag>() {
return;
}
if let Some(thread) = self.threads.get(session_id) {
self.save_internal(ThreadMetadata {
archived,
@ -504,10 +478,6 @@ impl ThreadMetadataStore {
}
pub fn delete(&mut self, session_id: acp::SessionId, cx: &mut Context<Self>) {
if !cx.has_flag::<AgentV2FeatureFlag>() {
return;
}
if let Some(thread) = self.threads.get(&session_id) {
if let Some(session_ids) = self.threads_by_paths.get_mut(&thread.folder_paths) {
session_ids.remove(&session_id);
@ -997,7 +967,7 @@ mod tests {
use action_log::ActionLog;
use agent::DbThread;
use agent_client_protocol as acp;
use feature_flags::FeatureFlagAppExt;
use gpui::TestAppContext;
use project::FakeFs;
use project::Project;
@ -1047,7 +1017,6 @@ mod tests {
cx.update(|cx| {
let settings_store = settings::SettingsStore::test(cx);
cx.set_global(settings_store);
cx.update_flags(true, vec!["agent-v2".to_string()]);
ThreadMetadataStore::init_global(cx);
ThreadStore::init_global(cx);
});
@ -1088,7 +1057,6 @@ mod tests {
cx.update(|cx| {
let settings_store = settings::SettingsStore::test(cx);
cx.set_global(settings_store);
cx.update_flags(true, vec!["agent-v2".to_string()]);
ThreadMetadataStore::init_global(cx);
});

View file

@ -12,16 +12,6 @@ impl FeatureFlag for PanicFeatureFlag {
const NAME: &'static str = "panic";
}
pub struct AgentV2FeatureFlag;
impl FeatureFlag for AgentV2FeatureFlag {
const NAME: &'static str = "agent-v2";
fn enabled_for_staff() -> bool {
true
}
}
/// A feature flag for granting access to beta ACP features.
///
/// We reuse this feature flag for new betas, so don't delete it if it is not currently in use.

View file

@ -13,7 +13,6 @@ path = "src/platform_title_bar.rs"
doctest = false
[dependencies]
feature_flags.workspace = true
gpui.workspace = true
project.workspace = true
settings.workspace = true

View file

@ -1,7 +1,6 @@
pub mod platforms;
mod system_window_tabs;
use feature_flags::{AgentV2FeatureFlag, FeatureFlagAppExt};
use gpui::{
Action, AnyElement, App, Context, Decorations, Entity, Hsla, InteractiveElement, IntoElement,
MouseButton, ParentElement, StatefulInteractiveElement, Styled, WeakEntity, Window,
@ -111,7 +110,7 @@ impl PlatformTitleBar {
}
pub fn is_multi_workspace_enabled(cx: &App) -> bool {
cx.has_flag::<AgentV2FeatureFlag>() && !DisableAiSettings::get_global(cx).disable_ai
!DisableAiSettings::get_global(cx).disable_ai
}
}

View file

@ -28,7 +28,6 @@ cpal.workspace = true
edit_prediction.workspace = true
edit_prediction_ui.workspace = true
editor.workspace = true
feature_flags.workspace = true
fs.workspace = true
futures.workspace = true
fuzzy.workspace = true

View file

@ -1,4 +1,3 @@
use feature_flags::{AgentV2FeatureFlag, FeatureFlagAppExt as _};
use gpui::{Action as _, App};
use itertools::Itertools as _;
use settings::{
@ -7188,7 +7187,7 @@ fn ai_page(cx: &App) -> SettingsPage {
]
}
fn agent_configuration_section(cx: &App) -> Box<[SettingsPageItem]> {
fn agent_configuration_section(_cx: &App) -> Box<[SettingsPageItem]> {
let mut items = vec![
SettingsPageItem::SectionHeader("Agent Configuration"),
SettingsPageItem::SubPageLink(SubPageLink {
@ -7202,30 +7201,28 @@ fn ai_page(cx: &App) -> SettingsPage {
}),
];
if cx.has_flag::<AgentV2FeatureFlag>() {
items.push(SettingsPageItem::SettingItem(SettingItem {
title: "New Thread Location",
description: "Whether to start a new thread in the current local project or in a new Git worktree.",
field: Box::new(SettingField {
json_path: Some("agent.new_thread_location"),
pick: |settings_content| {
settings_content
.agent
.as_ref()?
.new_thread_location
.as_ref()
},
write: |settings_content, value| {
settings_content
.agent
.get_or_insert_default()
.new_thread_location = value;
},
}),
metadata: None,
files: USER,
}));
}
items.push(SettingsPageItem::SettingItem(SettingItem {
title: "New Thread Location",
description: "Whether to start a new thread in the current local project or in a new Git worktree.",
field: Box::new(SettingField {
json_path: Some("agent.new_thread_location"),
pick: |settings_content| {
settings_content
.agent
.as_ref()?
.new_thread_location
.as_ref()
},
write: |settings_content, value| {
settings_content
.agent
.get_or_insert_default()
.new_thread_location = value;
},
}),
metadata: None,
files: USER,
}));
items.extend([
SettingsPageItem::SettingItem(SettingItem {

View file

@ -24,7 +24,6 @@ agent_ui = { workspace = true, features = ["audio"] }
anyhow.workspace = true
chrono.workspace = true
editor.workspace = true
feature_flags.workspace = true
fs.workspace = true
git.workspace = true
gpui.workspace = true
@ -54,7 +53,6 @@ pretty_assertions.workspace = true
prompt_store.workspace = true
recent_projects = { workspace = true, features = ["test-support"] }
serde_json.workspace = true
feature_flags.workspace = true
fs = { workspace = true, features = ["test-support"] }
git.workspace = true
gpui = { workspace = true, features = ["test-support"] }

View file

@ -14,7 +14,6 @@ use agent_ui::{
};
use chrono::{DateTime, Utc};
use editor::Editor;
use feature_flags::{AgentV2FeatureFlag, FeatureFlagViewExt as _};
use gpui::{
Action as _, AnyElement, App, Context, Entity, FocusHandle, Focusable, KeyContext, ListState,
Pixels, Render, SharedString, WeakEntity, Window, WindowHandle, linear_color_stop,
@ -434,11 +433,6 @@ impl Sidebar {
})
.detach();
cx.observe_flag::<AgentV2FeatureFlag, _>(window, |_is_enabled, this, _window, cx| {
this.update_entries(cx);
})
.detach();
let workspaces: Vec<_> = multi_workspace.read(cx).workspaces().cloned().collect();
cx.defer_in(window, move |this, window, cx| {
for workspace in &workspaces {

View file

@ -6,7 +6,6 @@ use agent_ui::{
thread_metadata_store::ThreadMetadata,
};
use chrono::DateTime;
use feature_flags::FeatureFlagAppExt as _;
use fs::FakeFs;
use gpui::TestAppContext;
use pretty_assertions::assert_eq;
@ -24,7 +23,6 @@ fn init_test(cx: &mut TestAppContext) {
cx.set_global(settings_store);
theme_settings::init(theme::LoadThemes::JustBase, cx);
editor::init(cx);
cx.update_flags(false, vec!["agent-v2".into()]);
ThreadStore::init_global(cx);
ThreadMetadataStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
@ -1220,7 +1218,6 @@ async fn init_test_project_with_agent_panel(
) -> Entity<project::Project> {
agent_ui::test_support::init_test(cx);
cx.update(|cx| {
cx.update_flags(false, vec!["agent-v2".into()]);
ThreadStore::init_global(cx);
ThreadMetadataStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
@ -2078,7 +2075,7 @@ async fn test_focused_thread_tracks_user_intent(cx: &mut TestAppContext) {
workspace.panel::<AgentPanel>(cx).is_some(),
"Agent panel should exist"
);
let dock = workspace.right_dock().read(cx);
let dock = workspace.left_dock().read(cx);
assert!(
dock.is_open(),
"Clicking a thread should open the agent panel dock"
@ -2425,7 +2422,6 @@ async fn test_cmd_n_shows_new_thread_entry_in_absorbed_worktree(cx: &mut TestApp
// header and highlight it as active.
agent_ui::test_support::init_test(cx);
cx.update(|cx| {
cx.update_flags(false, vec!["agent-v2".into()]);
ThreadStore::init_global(cx);
ThreadMetadataStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
@ -2974,7 +2970,6 @@ async fn test_absorbed_worktree_running_thread_shows_live_status(cx: &mut TestAp
// live status (spinner + "(running)") in the sidebar.
agent_ui::test_support::init_test(cx);
cx.update(|cx| {
cx.update_flags(false, vec!["agent-v2".into()]);
ThreadStore::init_global(cx);
ThreadMetadataStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
@ -3077,7 +3072,6 @@ async fn test_absorbed_worktree_running_thread_shows_live_status(cx: &mut TestAp
async fn test_absorbed_worktree_completion_triggers_notification(cx: &mut TestAppContext) {
agent_ui::test_support::init_test(cx);
cx.update(|cx| {
cx.update_flags(false, vec!["agent-v2".into()]);
ThreadStore::init_global(cx);
ThreadMetadataStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
@ -3990,7 +3984,6 @@ async fn test_archive_thread_uses_next_threads_own_workspace(cx: &mut TestAppCon
// falling back to group_workspace only for Closed workspaces.
agent_ui::test_support::init_test(cx);
cx.update(|cx| {
cx.update_flags(false, vec!["agent-v2".into()]);
ThreadStore::init_global(cx);
ThreadMetadataStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
@ -4772,7 +4765,6 @@ async fn init_multi_project_test(
) -> (Arc<FakeFs>, Entity<project::Project>) {
agent_ui::test_support::init_test(cx);
cx.update(|cx| {
cx.update_flags(false, vec!["agent-v2".into()]);
ThreadStore::init_global(cx);
ThreadMetadataStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);
@ -5652,7 +5644,6 @@ mod property_test {
) {
agent_ui::test_support::init_test(cx);
cx.update(|cx| {
cx.update_flags(false, vec!["agent-v2".into()]);
ThreadStore::init_global(cx);
ThreadMetadataStore::init_global(cx);
language_model::LanguageModelRegistry::test(cx);

View file

@ -1,5 +1,4 @@
use anyhow::Result;
use feature_flags::{AgentV2FeatureFlag, FeatureFlagAppExt};
use gpui::PathPromptOptions;
use gpui::{
AnyView, App, Context, DragMoveEvent, Entity, EntityId, EventEmitter, FocusHandle, Focusable,
@ -438,7 +437,7 @@ impl MultiWorkspace {
}
pub fn multi_workspace_enabled(&self, cx: &App) -> bool {
cx.has_flag::<AgentV2FeatureFlag>() && !DisableAiSettings::get_global(cx).disable_ai
!DisableAiSettings::get_global(cx).disable_ai
}
pub fn toggle_sidebar(&mut self, window: &mut Window, cx: &mut Context<Self>) {

View file

@ -1,5 +1,4 @@
use super::*;
use feature_flags::FeatureFlagAppExt;
use fs::FakeFs;
use gpui::TestAppContext;
use project::{DisableAiSettings, ProjectGroupKey};
@ -12,7 +11,6 @@ fn init_test(cx: &mut TestAppContext) {
cx.set_global(settings_store);
theme_settings::init(theme::LoadThemes::JustBase, cx);
DisableAiSettings::register(cx);
cx.update_flags(false, vec!["agent-v2".into()]);
});
}

View file

@ -2525,7 +2525,6 @@ mod tests {
cx.update(|cx| {
cx.set_staff(true);
cx.update_flags(true, vec!["agent-v2".to_string()]);
});
let fs = fs::FakeFs::new(cx.executor());
@ -4082,7 +4081,6 @@ mod tests {
cx.update(|cx| {
cx.set_staff(true);
cx.update_flags(true, vec!["agent-v2".to_string()]);
});
let fs = fs::FakeFs::new(cx.executor());
@ -4127,7 +4125,6 @@ mod tests {
cx.update(|cx| {
cx.set_staff(true);
cx.update_flags(true, vec!["agent-v2".to_string()]);
});
let fs = fs::FakeFs::new(cx.executor());
@ -4184,7 +4181,6 @@ mod tests {
cx.update(|cx| {
cx.set_staff(true);
cx.update_flags(true, vec!["agent-v2".to_string()]);
});
let fs = fs::FakeFs::new(cx.executor());
@ -4275,7 +4271,6 @@ mod tests {
cx.update(|cx| {
cx.set_staff(true);
cx.update_flags(true, vec!["agent-v2".to_string()]);
});
let fs = fs::FakeFs::new(cx.executor());
@ -4381,7 +4376,6 @@ mod tests {
cx.update(|cx| {
cx.set_staff(true);
cx.update_flags(true, vec!["agent-v2".to_string()]);
});
let fs = fs::FakeFs::new(cx.executor());
@ -4485,7 +4479,6 @@ mod tests {
cx.update(|cx| {
cx.set_staff(true);
cx.update_flags(true, vec!["agent-v2".to_string()]);
});
let fs = fs::FakeFs::new(cx.executor());
@ -4542,7 +4535,6 @@ mod tests {
cx.update(|cx| {
cx.set_staff(true);
cx.update_flags(true, vec!["agent-v2".to_string()]);
});
let fs = fs::FakeFs::new(cx.executor());
@ -4702,7 +4694,6 @@ mod tests {
cx.update(|cx| {
cx.set_staff(true);
cx.update_flags(true, vec!["agent-v2".to_string()]);
});
let fs = fs::FakeFs::new(cx.executor());

View file

@ -2527,11 +2527,6 @@ fn run_multi_workspace_sidebar_visual_tests(
std::fs::create_dir_all(&workspace1_dir)?;
std::fs::create_dir_all(&workspace2_dir)?;
// Enable the agent-v2 feature flag so multi-workspace is active
cx.update(|cx| {
cx.update_flags(true, vec!["agent-v2".to_string()]);
});
// Create both projects upfront so we can build both workspaces during
// window creation, before the MultiWorkspace entity exists.
// This avoids a re-entrant read panic that occurs when Workspace::new
@ -3082,11 +3077,6 @@ fn run_start_thread_in_selector_visual_tests(
) -> Result<TestResult> {
use agent_ui::{AgentPanel, NewWorktreeBranchTarget, StartThreadIn, WorktreeCreationStatus};
// Enable feature flags so the thread target selector renders
cx.update(|cx| {
cx.update_flags(true, vec!["agent-v2".to_string()]);
});
// Create a temp directory with a real git repo so "New Worktree" is enabled
let temp_dir = tempfile::tempdir()?;
let temp_path = temp_dir.keep();

View file

@ -2497,10 +2497,6 @@ mod tests {
#[gpui::test]
async fn test_open_paths_action(cx: &mut TestAppContext) {
let app_state = init_test(cx);
cx.update(|cx| {
use feature_flags::FeatureFlagAppExt as _;
cx.update_flags(false, vec!["agent-v2".to_string()]);
});
app_state
.fs
.as_fake()
@ -5497,10 +5493,6 @@ mod tests {
#[gpui::test]
async fn test_open_paths_switches_to_best_workspace(cx: &mut TestAppContext) {
let app_state = init_test(cx);
cx.update(|cx| {
use feature_flags::FeatureFlagAppExt as _;
cx.update_flags(false, vec!["agent-v2".to_string()]);
});
app_state
.fs
@ -5702,10 +5694,6 @@ mod tests {
async fn test_quit_checks_all_workspaces_for_dirty_items(cx: &mut TestAppContext) {
let app_state = init_test(cx);
cx.update(init);
cx.update(|cx| {
use feature_flags::FeatureFlagAppExt as _;
cx.update_flags(false, vec!["agent-v2".to_string()]);
});
app_state
.fs
@ -5995,11 +5983,6 @@ mod tests {
let app_state = init_test(cx);
cx.update(|cx| {
use feature_flags::FeatureFlagAppExt as _;
cx.update_flags(false, vec!["agent-v2".to_string()]);
});
let dir1 = path!("/dir1");
let dir2 = path!("/dir2");
let dir3 = path!("/dir3");