acp: Enable history for external agents for all users (#49449)

Ben Brandt and Bennet Bo Fenner created

Removes the feature flag around listing and loading existing sessions
for external agents.

Release Notes

- acp: Expose session history for all external agents that support it.

Co-authored-by: Bennet Bo Fenner <bennetbo@gmx.de>

Change summary

Cargo.lock                             |  1 
crates/acp_thread/src/connection.rs    | 10 +++---
crates/agent/src/agent.rs              |  4 +-
crates/agent_servers/Cargo.toml        |  1 
crates/agent_servers/src/acp.rs        | 38 +++++++++++----------------
crates/agent_ui/src/acp/thread_view.rs | 12 ++++----
6 files changed, 28 insertions(+), 38 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -277,7 +277,6 @@ dependencies = [
  "collections",
  "credentials_provider",
  "env_logger 0.11.8",
- "feature_flags",
  "fs",
  "futures 0.3.31",
  "google_ai",

crates/acp_thread/src/connection.rs 🔗

@@ -38,7 +38,7 @@ pub trait AgentConnection {
     ) -> Task<Result<Entity<AcpThread>>>;
 
     /// Whether this agent supports loading existing sessions.
-    fn supports_load_session(&self, _cx: &App) -> bool {
+    fn supports_load_session(&self) -> bool {
         false
     }
 
@@ -54,7 +54,7 @@ pub trait AgentConnection {
     }
 
     /// Whether this agent supports closing existing sessions.
-    fn supports_close_session(&self, _cx: &App) -> bool {
+    fn supports_close_session(&self) -> bool {
         false
     }
 
@@ -64,7 +64,7 @@ pub trait AgentConnection {
     }
 
     /// Whether this agent supports resuming existing sessions without loading history.
-    fn supports_resume_session(&self, _cx: &App) -> bool {
+    fn supports_resume_session(&self) -> bool {
         false
     }
 
@@ -82,8 +82,8 @@ pub trait AgentConnection {
     }
 
     /// Whether this agent supports showing session history.
-    fn supports_session_history(&self, cx: &App) -> bool {
-        self.supports_load_session(cx) || self.supports_resume_session(cx)
+    fn supports_session_history(&self) -> bool {
+        self.supports_load_session() || self.supports_resume_session()
     }
 
     fn auth_methods(&self) -> &[acp::AuthMethod];

crates/agent/src/agent.rs 🔗

@@ -1247,7 +1247,7 @@ impl acp_thread::AgentConnection for NativeAgentConnection {
             .update(cx, |agent, cx| agent.new_session(project, cx))))
     }
 
-    fn supports_load_session(&self, _cx: &App) -> bool {
+    fn supports_load_session(&self) -> bool {
         true
     }
 
@@ -1262,7 +1262,7 @@ impl acp_thread::AgentConnection for NativeAgentConnection {
             .update(cx, |agent, cx| agent.open_thread(session.session_id, cx))
     }
 
-    fn supports_close_session(&self, _cx: &App) -> bool {
+    fn supports_close_session(&self) -> bool {
         true
     }
 

crates/agent_servers/Cargo.toml 🔗

@@ -21,7 +21,6 @@ acp_tools.workspace = true
 acp_thread.workspace = true
 action_log.workspace = true
 agent-client-protocol.workspace = true
-feature_flags.workspace = true
 anyhow.workspace = true
 async-trait.workspace = true
 chrono.workspace = true

crates/agent_servers/src/acp.rs 🔗

@@ -7,7 +7,6 @@ use action_log::ActionLog;
 use agent_client_protocol::{self as acp, Agent as _, ErrorCode};
 use anyhow::anyhow;
 use collections::HashMap;
-use feature_flags::{AcpBetaFeatureFlag, FeatureFlagAppExt as _};
 use futures::AsyncBufReadExt as _;
 use futures::io::BufReader;
 use project::Project;
@@ -585,17 +584,15 @@ impl AgentConnection for AcpConnection {
         })
     }
 
-    fn supports_load_session(&self, cx: &App) -> bool {
-        cx.has_flag::<AcpBetaFeatureFlag>() && self.agent_capabilities.load_session
+    fn supports_load_session(&self) -> bool {
+        self.agent_capabilities.load_session
     }
 
-    fn supports_resume_session(&self, cx: &App) -> bool {
-        cx.has_flag::<AcpBetaFeatureFlag>()
-            && self
-                .agent_capabilities
-                .session_capabilities
-                .resume
-                .is_some()
+    fn supports_resume_session(&self) -> bool {
+        self.agent_capabilities
+            .session_capabilities
+            .resume
+            .is_some()
     }
 
     fn load_session(
@@ -605,7 +602,7 @@ impl AgentConnection for AcpConnection {
         cwd: &Path,
         cx: &mut App,
     ) -> Task<Result<Entity<AcpThread>>> {
-        if !cx.has_flag::<AcpBetaFeatureFlag>() || !self.agent_capabilities.load_session {
+        if !self.agent_capabilities.load_session {
             return Task::ready(Err(anyhow!(LoadError::Other(
                 "Loading sessions is not supported by this agent.".into()
             ))));
@@ -673,12 +670,11 @@ impl AgentConnection for AcpConnection {
         cwd: &Path,
         cx: &mut App,
     ) -> Task<Result<Entity<AcpThread>>> {
-        if !cx.has_flag::<AcpBetaFeatureFlag>()
-            || self
-                .agent_capabilities
-                .session_capabilities
-                .resume
-                .is_none()
+        if self
+            .agent_capabilities
+            .session_capabilities
+            .resume
+            .is_none()
         {
             return Task::ready(Err(anyhow!(LoadError::Other(
                 "Resuming sessions is not supported by this agent.".into()
@@ -887,12 +883,8 @@ impl AgentConnection for AcpConnection {
         }) as _)
     }
 
-    fn session_list(&self, cx: &mut App) -> Option<Rc<dyn AgentSessionList>> {
-        if cx.has_flag::<AcpBetaFeatureFlag>() {
-            self.session_list.clone().map(|s| s as _)
-        } else {
-            None
-        }
+    fn session_list(&self, _cx: &mut App) -> Option<Rc<dyn AgentSessionList>> {
+        self.session_list.clone().map(|s| s as _)
     }
 
     fn into_any(self: Rc<Self>) -> Rc<dyn Any> {

crates/agent_ui/src/acp/thread_view.rs 🔗

@@ -491,11 +491,11 @@ impl AcpServerView {
             let mut resumed_without_history = false;
             let result = if let Some(resume) = resume_thread.clone() {
                 cx.update(|_, cx| {
-                    if connection.supports_load_session(cx) {
+                    if connection.supports_load_session() {
                         connection
                             .clone()
                             .load_session(resume, project.clone(), &session_cwd, cx)
-                    } else if connection.supports_resume_session(cx) {
+                    } else if connection.supports_resume_session() {
                         resumed_without_history = true;
                         connection
                             .clone()
@@ -666,7 +666,7 @@ impl AcpServerView {
 
         let connection = thread.read(cx).connection().clone();
         let session_id = thread.read(cx).session_id().clone();
-        let session_list = if connection.supports_session_history(cx) {
+        let session_list = if connection.supports_session_history() {
             connection.session_list(cx)
         } else {
             None
@@ -1485,7 +1485,7 @@ impl AcpServerView {
             return;
         };
         if connected.threads.contains_key(&subagent_id)
-            || !connected.connection.supports_load_session(cx)
+            || !connected.connection.supports_load_session()
         {
             return;
         }
@@ -3519,7 +3519,7 @@ pub(crate) mod tests {
             Task::ready(Ok(thread))
         }
 
-        fn supports_resume_session(&self, _cx: &App) -> bool {
+        fn supports_resume_session(&self) -> bool {
             true
         }
 
@@ -3847,7 +3847,7 @@ pub(crate) mod tests {
             Task::ready(Ok(thread))
         }
 
-        fn supports_load_session(&self, _cx: &App) -> bool {
+        fn supports_load_session(&self) -> bool {
             true
         }