diff --git a/crates/agent_ui/src/acp/thread_view.rs b/crates/agent_ui/src/acp/thread_view.rs index 41e0548efe4cf2191337e4d1c962b0a764bb2316..af06d33240cfbe49746bf3a228cd8cf10dc305b4 100644 --- a/crates/agent_ui/src/acp/thread_view.rs +++ b/crates/agent_ui/src/acp/thread_view.rs @@ -478,6 +478,8 @@ impl AcpServerView { this.handle_load_error(err, window, cx); } else if let Some(active) = this.active_thread() { active.update(cx, |active, cx| active.handle_any_thread_error(err, cx)); + } else { + this.handle_load_error(err, window, cx); } cx.notify(); }) @@ -2950,6 +2952,38 @@ pub(crate) mod tests { }); } + #[gpui::test] + async fn test_connect_failure_transitions_to_load_error(cx: &mut TestAppContext) { + init_test(cx); + + let (thread_view, cx) = setup_thread_view(FailingAgentServer, cx).await; + + thread_view.read_with(cx, |view, cx| { + let title = view.title(cx); + assert_eq!( + title.as_ref(), + "Error Loading Codex CLI", + "Tab title should show the agent name with an error prefix" + ); + match &view.server_state { + ServerState::LoadError(LoadError::Other(msg)) => { + assert!( + msg.contains("Invalid gzip header"), + "Error callout should contain the underlying extraction error, got: {msg}" + ); + } + other => panic!( + "Expected LoadError::Other, got: {}", + match other { + ServerState::Loading(_) => "Loading (stuck!)", + ServerState::LoadError(_) => "LoadError (wrong variant)", + ServerState::Connected(_) => "Connected", + } + ), + } + }); + } + #[gpui::test] async fn test_auth_required_on_initial_connect(cx: &mut TestAppContext) { init_test(cx); @@ -3460,6 +3494,36 @@ pub(crate) mod tests { } } + struct FailingAgentServer; + + impl AgentServer for FailingAgentServer { + fn logo(&self) -> ui::IconName { + ui::IconName::AiOpenAi + } + + fn name(&self) -> SharedString { + "Codex CLI".into() + } + + fn connect( + &self, + _root_dir: Option<&Path>, + _delegate: AgentServerDelegate, + _cx: &mut App, + ) -> Task, Option)>> { + Task::ready(Err(anyhow!( + "extracting downloaded asset for \ + https://github.com/zed-industries/codex-acp/releases/download/v0.9.4/\ + codex-acp-0.9.4-aarch64-pc-windows-msvc.zip: \ + failed to iterate over archive: Invalid gzip header" + ))) + } + + fn into_any(self: Rc) -> Rc { + self + } + } + #[derive(Clone)] struct StubSessionList { sessions: Vec,