diff --git a/crates/agent/src/tests/mod.rs b/crates/agent/src/tests/mod.rs index df466b8805..22d05feb88 100644 --- a/crates/agent/src/tests/mod.rs +++ b/crates/agent/src/tests/mod.rs @@ -3842,6 +3842,11 @@ async fn test_title_generation_failure_allows_retry(cx: &mut TestAppContext) { thread.read_with(cx, |thread, _| { assert_eq!(thread.title(), None); assert!(thread.has_failed_title_generation()); + assert!( + thread + .title_generation_error() + .is_some_and(|error| error.contains("Internal server error")) + ); assert!(!thread.is_generating_title()); }); @@ -3852,6 +3857,7 @@ async fn test_title_generation_failure_allows_retry(cx: &mut TestAppContext) { thread.read_with(cx, |thread, _| { assert!(!thread.has_failed_title_generation()); + assert_eq!(thread.title_generation_error(), None); assert!(thread.is_generating_title()); }); @@ -3862,6 +3868,7 @@ async fn test_title_generation_failure_allows_retry(cx: &mut TestAppContext) { thread.read_with(cx, |thread, _| { assert_eq!(thread.title(), Some("Retried title".into())); assert!(!thread.has_failed_title_generation()); + assert_eq!(thread.title_generation_error(), None); assert!(!thread.is_generating_title()); }); } diff --git a/crates/agent/src/thread.rs b/crates/agent/src/thread.rs index 8dd22ec3fe..585e9eb82a 100644 --- a/crates/agent/src/thread.rs +++ b/crates/agent/src/thread.rs @@ -1219,7 +1219,7 @@ pub struct Thread { updated_at: DateTime, title: Option, pending_title_generation: Option>, - title_generation_failed: bool, + title_generation_error: Option, pending_summary_generation: Option>>>, summary: Option, messages: Vec>, @@ -1369,7 +1369,7 @@ impl Thread { updated_at: Utc::now(), title: None, pending_title_generation: None, - title_generation_failed: false, + title_generation_error: None, pending_summary_generation: None, summary: None, messages: Vec::new(), @@ -1748,7 +1748,7 @@ impl Thread { Some(db_thread.title.clone()) }, pending_title_generation: None, - title_generation_failed: false, + title_generation_error: None, pending_summary_generation: None, summary: db_thread.detailed_summary, messages: db_thread.messages, @@ -3751,7 +3751,11 @@ impl Thread { } pub fn has_failed_title_generation(&self) -> bool { - self.title_generation_failed + self.title_generation_error.is_some() + } + + pub fn title_generation_error(&self) -> Option { + self.title_generation_error.clone() } pub fn can_generate_title(&self) -> bool { @@ -3854,7 +3858,7 @@ impl Thread { on_generated_title: Option)>>, cx: &mut Context, ) { - self.title_generation_failed = false; + self.title_generation_error = None; log::debug!("Generating title with model: {:?}", model.name()); let temperature = AgentSettings::temperature_for_model(&model, cx); @@ -3865,22 +3869,26 @@ impl Thread { .await .context("failed to generate thread title") .map(SharedString::from) - .log_err() }); self.pending_title_generation = Some(cx.spawn(async move |this, cx| { let title = title_generation.await; _ = this.update(cx, |this, cx| { this.pending_title_generation = None; - if let Some(title) = title { - this.set_title(title.clone(), cx); - if let Some(on_generated_title) = on_generated_title { - on_generated_title(title, cx); + match title { + Ok(title) => { + this.set_title(title.clone(), cx); + if let Some(on_generated_title) = on_generated_title { + on_generated_title(title, cx); + } + } + Err(error) => { + let error = format!("{error:#}"); + log::error!("{error}"); + this.title_generation_error = Some(error.into()); + cx.emit(TitleUpdated); + cx.notify(); } - } else { - this.title_generation_failed = true; - cx.emit(TitleUpdated); - cx.notify(); } }); })); @@ -3889,7 +3897,7 @@ impl Thread { pub fn set_title(&mut self, title: SharedString, cx: &mut Context) { self.pending_title_generation = None; - self.title_generation_failed = false; + self.title_generation_error = None; if Some(&title) != self.title.as_ref() { self.title = Some(title); cx.emit(TitleUpdated); diff --git a/crates/agent_ui/src/agent_panel.rs b/crates/agent_ui/src/agent_panel.rs index bf6f61295b..c610bf0a06 100644 --- a/crates/agent_ui/src/agent_panel.rs +++ b/crates/agent_ui/src/agent_panel.rs @@ -5333,9 +5333,9 @@ impl AgentPanel { let is_generating_title = native_thread .as_ref() .is_some_and(|thread| thread.read(cx).is_generating_title()); - let title_generation_failed = native_thread + let title_generation_error = native_thread .as_ref() - .is_some_and(|thread| thread.read(cx).has_failed_title_generation()); + .and_then(|thread| thread.read(cx).title_generation_error()); if let Some(title_editor) = server_view_ref .root_thread_view() @@ -5374,7 +5374,7 @@ impl AgentPanel { }) .child(title_editor); - if title_generation_failed { + if let Some(title_generation_error) = title_generation_error { h_flex() .w_full() .gap_1() @@ -5383,7 +5383,14 @@ impl AgentPanel { IconButton::new("retry-thread-title", IconName::XCircle) .icon_color(Color::Error) .icon_size(IconSize::Small) - .tooltip(Tooltip::text("Title generation failed. Retry")) + .tooltip(move |_window, cx| { + Tooltip::with_meta( + "Title generation failed. Click to retry.", + None, + title_generation_error.clone(), + cx, + ) + }) .on_click({ let conversation_view = conversation_view.clone(); let workspace = self.workspace.clone();