agent: Remove `MAX_PARALLEL_SUBAGENTS` (#49593)

Bennet Bo Fenner created

Before you mark this PR as ready for review, make sure that you have:
- [x] Added a solid test coverage and/or screenshots from doing manual
testing
- [x] Done a self-review taking into account security and performance
aspects
- [x] Aligned any UI changes with the [UI
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)

Requests will be rate-limited by our internal logic, but it will "just"
work.

Release Notes:

- N/A

Change summary

crates/agent/src/agent.rs     |  8 ---
crates/agent/src/tests/mod.rs | 79 -------------------------------------
crates/agent/src/thread.rs    |  8 ---
3 files changed, 95 deletions(-)

Detailed changes

crates/agent/src/agent.rs 🔗

@@ -1603,14 +1603,6 @@ impl NativeThreadEnvironment {
             ));
         }
 
-        let running_count = parent_thread.running_subagent_count();
-        if running_count >= MAX_PARALLEL_SUBAGENTS {
-            return Err(anyhow!(
-                "Maximum parallel subagents ({}) reached. Wait for existing subagents to complete.",
-                MAX_PARALLEL_SUBAGENTS
-            ));
-        }
-
         let allowed_tools = match allowed_tools {
             Some(tools) => {
                 let parent_tool_names: std::collections::HashSet<&str> =

crates/agent/src/tests/mod.rs 🔗

@@ -4818,85 +4818,6 @@ async fn test_parent_cancel_stops_subagent(cx: &mut TestAppContext) {
     });
 }
 
-#[gpui::test]
-async fn test_thread_environment_max_parallel_subagents_enforced(cx: &mut TestAppContext) {
-    init_test(cx);
-    always_allow_tools(cx);
-
-    cx.update(|cx| {
-        cx.update_flags(true, vec!["subagents".to_string()]);
-    });
-
-    let fs = FakeFs::new(cx.executor());
-    fs.insert_tree(path!("/test"), json!({})).await;
-    let project = Project::test(fs.clone(), [path!("/test").as_ref()], cx).await;
-    let project_context = cx.new(|_cx| ProjectContext::default());
-    let context_server_store = project.read_with(cx, |project, _| project.context_server_store());
-    let context_server_registry =
-        cx.new(|cx| ContextServerRegistry::new(context_server_store.clone(), cx));
-    cx.update(LanguageModelRegistry::test);
-    let model = Arc::new(FakeLanguageModel::default());
-    let thread_store = cx.new(|cx| ThreadStore::new(cx));
-    let native_agent = NativeAgent::new(
-        project.clone(),
-        thread_store,
-        Templates::new(),
-        None,
-        fs,
-        &mut cx.to_async(),
-    )
-    .await
-    .unwrap();
-    let parent_thread = cx.new(|cx| {
-        Thread::new(
-            project.clone(),
-            project_context,
-            context_server_registry,
-            Templates::new(),
-            Some(model.clone()),
-            cx,
-        )
-    });
-
-    let mut handles = Vec::new();
-    for _ in 0..MAX_PARALLEL_SUBAGENTS {
-        let handle = cx
-            .update(|cx| {
-                NativeThreadEnvironment::create_subagent_thread(
-                    native_agent.downgrade(),
-                    parent_thread.clone(),
-                    "some title".to_string(),
-                    "some task".to_string(),
-                    None,
-                    None,
-                    cx,
-                )
-            })
-            .expect("Expected to be able to create subagent thread");
-        handles.push(handle);
-    }
-
-    let result = cx.update(|cx| {
-        NativeThreadEnvironment::create_subagent_thread(
-            native_agent.downgrade(),
-            parent_thread.clone(),
-            "some title".to_string(),
-            "some task".to_string(),
-            None,
-            None,
-            cx,
-        )
-    });
-    assert!(result.is_err());
-    assert_eq!(
-        result.err().unwrap().to_string(),
-        format!(
-            "Maximum parallel subagents ({}) reached. Wait for existing subagents to complete.",
-            MAX_PARALLEL_SUBAGENTS
-        )
-    );
-}
-
 #[gpui::test]
 async fn test_subagent_tool_returns_summary(cx: &mut TestAppContext) {
     init_test(cx);

crates/agent/src/thread.rs 🔗

@@ -61,7 +61,6 @@ use uuid::Uuid;
 const TOOL_CANCELED_MESSAGE: &str = "Tool canceled by user";
 pub const MAX_TOOL_NAME_LENGTH: usize = 64;
 pub const MAX_SUBAGENT_DEPTH: u8 = 4;
-pub const MAX_PARALLEL_SUBAGENTS: usize = 8;
 
 /// Context passed to a subagent thread for lifecycle management
 #[derive(Clone, Debug, Serialize, Deserialize)]
@@ -2616,13 +2615,6 @@ impl Thread {
             .collect()
     }
 
-    pub fn running_subagent_count(&self) -> usize {
-        self.running_subagents
-            .iter()
-            .filter(|s| s.upgrade().is_some())
-            .count()
-    }
-
     pub fn is_subagent(&self) -> bool {
         self.subagent_context.is_some()
     }