Skip to content

Commit

Permalink
assistant: Show error messages in popover notification (#15808)
Browse files Browse the repository at this point in the history
<img width="644" alt="image"
src="https://github.com/user-attachments/assets/ee6f2e60-e50a-481e-98b4-6c4b72a9b882">


Release Notes:

- N/A

---------

Co-authored-by: Thorsten <[email protected]>
  • Loading branch information
bennetbo and Thorsten authored Aug 5, 2024
1 parent 294892c commit be0ccf4
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 40 deletions.
133 changes: 93 additions & 40 deletions crates/assistant/src/assistant_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ use fs::Fs;
use gpui::{
div, percentage, point, Action, Animation, AnimationExt, AnyElement, AnyView, AppContext,
AsyncWindowContext, ClipboardItem, Context as _, DismissEvent, Empty, Entity, EventEmitter,
FocusHandle, FocusableView, InteractiveElement, IntoElement, Model, ParentElement, Pixels,
Render, SharedString, StatefulInteractiveElement, Styled, Subscription, Task, Transformation,
UpdateGlobal, View, ViewContext, VisualContext, WeakView, WindowContext,
FocusHandle, FocusableView, FontWeight, InteractiveElement, IntoElement, Model, ParentElement,
Pixels, Render, SharedString, StatefulInteractiveElement, Styled, Subscription, Task,
Transformation, UpdateGlobal, View, ViewContext, VisualContext, WeakView, WindowContext,
};
use indexed_docs::IndexedDocsStore;
use language::{
Expand Down Expand Up @@ -1316,6 +1316,7 @@ pub struct ContextEditor {
_subscriptions: Vec<Subscription>,
active_edit_step: Option<ActiveEditStep>,
assistant_panel: WeakView<AssistantPanel>,
error_message: Option<SharedString>,
}

const DEFAULT_TAB_TITLE: &str = "New Context";
Expand Down Expand Up @@ -1373,6 +1374,7 @@ impl ContextEditor {
_subscriptions,
active_edit_step: None,
assistant_panel,
error_message: None,
};
this.update_message_headers(cx);
this.insert_slash_command_output_sections(sections, cx);
Expand Down Expand Up @@ -1406,7 +1408,9 @@ impl ContextEditor {

fn assist(&mut self, _: &Assist, cx: &mut ViewContext<Self>) {
if !self.apply_edit_step(cx) {
self.error_message = None;
self.send_to_model(cx);
cx.notify();
}
}

Expand Down Expand Up @@ -1804,6 +1808,9 @@ impl ContextEditor {
}
}
ContextEvent::Operation(_) => {}
ContextEvent::AssistError(error_message) => {
self.error_message = Some(SharedString::from(error_message.clone()));
}
}
}

Expand Down Expand Up @@ -2142,7 +2149,10 @@ impl ContextEditor {
div()
.id("error")
.tooltip(move |cx| Tooltip::text(error.clone(), cx))
.child(Icon::new(IconName::XCircle)),
.child(
Icon::new(IconName::ExclamationTriangle)
.color(Color::Error),
),
)
} else {
None
Expand Down Expand Up @@ -2327,25 +2337,33 @@ impl ContextEditor {
.unwrap_or_else(|| Cow::Borrowed(DEFAULT_TAB_TITLE))
}

fn render_notice(&self, cx: &mut ViewContext<Self>) -> Option<impl IntoElement> {
fn dismiss_error_message(&mut self, cx: &mut ViewContext<Self>) {
self.error_message = None;
cx.notify();
}

fn render_notice(&self, cx: &mut ViewContext<Self>) -> Option<AnyElement> {
let nudge = self
.assistant_panel
.upgrade()
.map(|assistant_panel| assistant_panel.read(cx).show_zed_ai_notice);

if nudge.unwrap_or(false) {
if let Some(error) = self.error_message.clone() {
Some(Self::render_error_popover(error, cx).into_any_element())
} else if nudge.unwrap_or(false) {
Some(
v_flex()
.elevation_3(cx)
.p_4()
.p_2()
.gap_2()
.child(Label::new("Use Zed AI"))
.child(
div()
.id("sign-in")
.child(Label::new("Sign in to use Zed AI"))
.cursor_pointer()
.on_click(cx.listener(|this, _event, cx| {
Label::new("Use Zed AI")
.size(LabelSize::Small)
.color(Color::Muted),
)
.child(h_flex().justify_end().child(
Button::new("sign-in", "Sign in to use Zed AI").on_click(cx.listener(
|this, _event, cx| {
let client = this
.workspace
.update(cx, |workspace, _| workspace.client().clone())
Expand All @@ -2358,8 +2376,10 @@ impl ContextEditor {
})
.detach_and_log_err(cx)
}
})),
),
},
)),
))
.into_any_element(),
)
} else if let Some(configuration_error) = configuration_error(cx) {
let label = match configuration_error {
Expand All @@ -2369,27 +2389,51 @@ impl ContextEditor {
Some(
v_flex()
.elevation_3(cx)
.p_4()
.p_2()
.gap_2()
.child(Label::new(label))
.child(Label::new(label).size(LabelSize::Small).color(Color::Muted))
.child(
div()
.id("open-configuration")
.child(Label::new("Open configuration"))
.cursor_pointer()
.on_click({
let focus_handle = self.focus_handle(cx).clone();
move |_event, cx| {
focus_handle.dispatch_action(&ShowConfiguration, cx);
}
}),
),
h_flex().justify_end().child(
Button::new("open-configuration", "Open configuration")
.icon(IconName::Settings)
.icon_size(IconSize::Small)
.on_click({
let focus_handle = self.focus_handle(cx).clone();
move |_event, cx| {
focus_handle.dispatch_action(&ShowConfiguration, cx);
}
}),
),
)
.into_any_element(),
)
} else {
None
}
}

fn render_error_popover(error: SharedString, cx: &mut ViewContext<Self>) -> Div {
v_flex()
.p_2()
.elevation_2(cx)
.bg(cx.theme().colors().surface_background)
.min_w_24()
.occlude()
.child(
Label::new("Error interacting with language model")
.size(LabelSize::Small)
.weight(FontWeight::BOLD)
.color(Color::Muted),
)
.child(Label::new(error).size(LabelSize::Small))
.child(
h_flex().justify_end().child(
Button::new("dismiss", "Dismiss")
.on_click(cx.listener(|this, _, cx| this.dismiss_error_message(cx))),
),
)
}

fn render_send_button(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let focus_handle = self.focus_handle(cx).clone();
let button_text = match self.workflow_step_for_cursor(cx) {
Expand Down Expand Up @@ -2487,23 +2531,32 @@ impl Render for ContextEditor {
div()
.flex_grow()
.bg(cx.theme().colors().editor_background)
.child(self.editor.clone())
.child(self.editor.clone()),
)
.child(
h_flex()
.flex_none()
.relative()
.when_some(self.render_notice(cx), |this, notice| {
this.child(
div()
.absolute()
.w_3_4()
.min_w_24()
.max_w_128()
.right_4()
.bottom_9()
.child(notice),
)
})
.child(
h_flex()
.w_full()
.absolute()
.bottom_0()
.p_4()
.right_4()
.bottom_2()
.justify_end()
.child(
v_flex()
.gap_2()
.items_end()
.when_some(self.render_notice(cx), |this, notice| {
this.child(notice)
})
.child(self.render_send_button(cx)),
),
.child(self.render_send_button(cx)),
),
)
}
Expand Down
5 changes: 5 additions & 0 deletions crates/assistant/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ impl ContextOperation {

#[derive(Debug, Clone)]
pub enum ContextEvent {
AssistError(String),
MessagesEdited,
SummaryChanged,
EditStepsChanged,
Expand Down Expand Up @@ -1580,6 +1581,10 @@ impl Context {
.err()
.map(|error| error.to_string().trim().to_string());

if let Some(error_message) = error_message.as_ref() {
cx.emit(ContextEvent::AssistError(error_message.to_string()));
}

this.update_metadata(assistant_message_id, cx, |metadata| {
if let Some(error_message) = error_message.as_ref() {
metadata.status =
Expand Down

0 comments on commit be0ccf4

Please sign in to comment.