diff --git a/crates/agent_ui/src/acp/thread_view.rs b/crates/agent_ui/src/acp/thread_view.rs index 1c9e3f83e383658051f7799a7e3096f532addbe1..3dc99b781a336392e247975862d218ae6b8dea9a 100644 --- a/crates/agent_ui/src/acp/thread_view.rs +++ b/crates/agent_ui/src/acp/thread_view.rs @@ -498,7 +498,17 @@ impl AcpThreadView { Some(new_version_available_tx), ); - let connect_task = agent.connect(root_dir.as_deref(), delegate, cx); + let agent_name = agent.name(); + let timeout = cx.background_executor().timer(Duration::from_secs(30)); + let connect_task = smol::future::or( + agent.connect(root_dir.as_deref(), delegate, cx), + async move { + timeout.await; + Err(anyhow::Error::new(LoadError::Other( + format!("{agent_name} is unable to initialize after 30 seconds.").into(), + ))) + }, + ); let load_task = cx.spawn_in(window, async move |this, cx| { let connection = match connect_task.await { Ok((connection, login)) => { @@ -7358,4 +7368,54 @@ pub(crate) mod tests { assert_eq!(text, expected_txt); }) } + + #[gpui::test] + async fn test_initialize_timeout(cx: &mut TestAppContext) { + init_test(cx); + + struct InfiniteInitialize; + + impl AgentServer for InfiniteInitialize { + fn telemetry_id(&self) -> &'static str { + "test" + } + + fn logo(&self) -> ui::IconName { + ui::IconName::Ai + } + + fn name(&self) -> SharedString { + "Test".into() + } + + fn connect( + &self, + _root_dir: Option<&Path>, + _delegate: AgentServerDelegate, + cx: &mut App, + ) -> Task, Option)>> + { + cx.spawn(async |_| futures::future::pending().await) + } + + fn into_any(self: Rc) -> Rc { + self + } + } + + let (thread_view, cx) = setup_thread_view(InfiniteInitialize, cx).await; + + cx.executor().advance_clock(Duration::from_secs(31)); + cx.run_until_parked(); + + let error = thread_view.read_with(cx, |thread_view, _| match &thread_view.thread_state { + ThreadState::LoadError(err) => err.clone(), + _ => panic!("Incorrect thread state"), + }); + + match error { + LoadError::Other(str) => assert!(str.contains("initialize")), + _ => panic!("Unexpected load error"), + } + } }