zeta: Allow viewing prompt details in rate completion modal (#23142)

Co-Authored-by: Danilo <danilo@zed.dev>

Release Notes:

- N/A

---------

Co-authored-by: Danilo <danilo@zed.dev>
Co-authored-by: Danilo Leal <daniloleal09@gmail.com>
Co-authored-by: Thorsten Ball <mrnugget@gmail.com>
This commit is contained in:
Bennet Bo Fenner 2025-01-15 12:10:46 +01:00 committed by GitHub
parent ae746937af
commit bd3f64c5a1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -37,6 +37,7 @@ pub struct RateCompletionModal {
selected_index: usize, selected_index: usize,
focus_handle: FocusHandle, focus_handle: FocusHandle,
_subscription: gpui::Subscription, _subscription: gpui::Subscription,
current_view: RateCompletionView,
} }
struct ActiveCompletion { struct ActiveCompletion {
@ -44,6 +45,21 @@ struct ActiveCompletion {
feedback_editor: View<Editor>, feedback_editor: View<Editor>,
} }
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
enum RateCompletionView {
SuggestedEdits,
RawInput,
}
impl RateCompletionView {
pub fn name(&self) -> &'static str {
match self {
Self::SuggestedEdits => "Suggested Edits",
Self::RawInput => "Recorded Events & Input",
}
}
}
impl RateCompletionModal { impl RateCompletionModal {
pub fn toggle(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) { pub fn toggle(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
if let Some(zeta) = Zeta::global(cx) { if let Some(zeta) = Zeta::global(cx) {
@ -60,6 +76,7 @@ impl RateCompletionModal {
focus_handle: cx.focus_handle(), focus_handle: cx.focus_handle(),
active_completion: None, active_completion: None,
_subscription: subscription, _subscription: subscription,
current_view: RateCompletionView::SuggestedEdits,
} }
} }
@ -266,6 +283,87 @@ impl RateCompletionModal {
cx.notify(); cx.notify();
} }
fn render_view_nav(&self, cx: &ViewContext<Self>) -> impl IntoElement {
h_flex()
.h_8()
.px_1()
.border_b_1()
.border_color(cx.theme().colors().border)
.bg(cx.theme().colors().elevated_surface_background)
.gap_1()
.child(
Button::new(
ElementId::Name("suggested-edits".into()),
RateCompletionView::SuggestedEdits.name(),
)
.label_size(LabelSize::Small)
.on_click(cx.listener(move |this, _, cx| {
this.current_view = RateCompletionView::SuggestedEdits;
cx.notify();
}))
.toggle_state(self.current_view == RateCompletionView::SuggestedEdits),
)
.child(
Button::new(
ElementId::Name("raw-input".into()),
RateCompletionView::RawInput.name(),
)
.label_size(LabelSize::Small)
.on_click(cx.listener(move |this, _, cx| {
this.current_view = RateCompletionView::RawInput;
cx.notify();
}))
.toggle_state(self.current_view == RateCompletionView::RawInput),
)
}
fn render_suggested_edits(&self, cx: &mut ViewContext<Self>) -> Option<gpui::Stateful<Div>> {
let active_completion = self.active_completion.as_ref()?;
let bg_color = cx.theme().colors().editor_background;
Some(
div()
.id("diff")
.p_4()
.size_full()
.bg(bg_color)
.overflow_scroll()
.whitespace_nowrap()
.child(CompletionDiffElement::new(
&active_completion.completion,
cx,
)),
)
}
fn render_raw_input(&self, cx: &mut ViewContext<Self>) -> Option<gpui::Stateful<Div>> {
Some(
v_flex()
.size_full()
.overflow_hidden()
.relative()
.child(
div()
.id("raw-input")
.py_4()
.px_6()
.size_full()
.bg(cx.theme().colors().editor_background)
.overflow_scroll()
.child(if let Some(active_completion) = &self.active_completion {
format!(
"{}\n{}",
active_completion.completion.input_events,
active_completion.completion.input_excerpt
)
} else {
"No active completion".to_string()
}),
)
.id("raw-input-view"),
)
}
fn render_active_completion(&mut self, cx: &mut ViewContext<Self>) -> Option<impl IntoElement> { fn render_active_completion(&mut self, cx: &mut ViewContext<Self>) -> Option<impl IntoElement> {
let active_completion = self.active_completion.as_ref()?; let active_completion = self.active_completion.as_ref()?;
let completion_id = active_completion.completion.id; let completion_id = active_completion.completion.id;
@ -281,31 +379,31 @@ impl RateCompletionModal {
.text(cx) .text(cx)
.is_empty(); .is_empty();
let label_container = || h_flex().pl_1().gap_1p5(); let label_container = h_flex().pl_1().gap_1p5();
Some( Some(
v_flex() v_flex()
.size_full() .size_full()
.overflow_hidden() .overflow_hidden()
.relative()
.child( .child(
div() v_flex()
.id("diff")
.py_4()
.px_6()
.size_full() .size_full()
.bg(bg_color) .overflow_hidden()
.overflow_scroll() .relative()
.whitespace_nowrap() .child(self.render_view_nav(cx))
.child(CompletionDiffElement::new(&active_completion.completion, cx)), .when_some(match self.current_view {
RateCompletionView::SuggestedEdits => self.render_suggested_edits(cx),
RateCompletionView::RawInput => self.render_raw_input(cx),
}, |this, element| this.child(element))
) )
.when_some((!rated).then(|| ()), |this, _| { .when(!rated, |this| {
this.child( this.child(
h_flex() h_flex()
.p_2() .p_2()
.gap_2() .gap_2()
.border_y_1() .border_y_1()
.border_color(border_color) .border_color(border_color)
.child( .child(
Icon::new(IconName::Info) Icon::new(IconName::Info)
.size(IconSize::XSmall) .size(IconSize::XSmall)
@ -317,14 +415,14 @@ impl RateCompletionModal {
.pr_2() .pr_2()
.flex_wrap() .flex_wrap()
.child( .child(
Label::new("Ensure you explain why this completion is negative or positive. In case it's negative, report what you expected instead.") Label::new("Explain why this completion is good or bad. If it's negative, describe what you expected instead.")
.size(LabelSize::Small) .size(LabelSize::Small)
.color(Color::Muted) .color(Color::Muted)
) )
) )
) )
}) })
.when_some((!rated).then(|| ()), |this, _| { .when(!rated, |this| {
this.child( this.child(
div() div()
.h_40() .h_40()
@ -344,7 +442,7 @@ impl RateCompletionModal {
.justify_between() .justify_between()
.children(if rated { .children(if rated {
Some( Some(
label_container() label_container
.child( .child(
Icon::new(IconName::Check) Icon::new(IconName::Check)
.size(IconSize::Small) .size(IconSize::Small)
@ -354,7 +452,7 @@ impl RateCompletionModal {
) )
} else if active_completion.completion.edits.is_empty() { } else if active_completion.completion.edits.is_empty() {
Some( Some(
label_container() label_container
.child( .child(
Icon::new(IconName::Warning) Icon::new(IconName::Warning)
.size(IconSize::Small) .size(IconSize::Small)
@ -363,7 +461,7 @@ impl RateCompletionModal {
.child(Label::new("No edits produced.").color(Color::Muted)), .child(Label::new("No edits produced.").color(Color::Muted)),
) )
} else { } else {
Some(label_container()) Some(label_container)
}) })
.child( .child(
h_flex() h_flex()
@ -440,16 +538,16 @@ impl Render for RateCompletionModal {
.shadow_lg() .shadow_lg()
.child( .child(
v_flex() v_flex()
.border_r_1()
.border_color(border_color)
.w_72() .w_72()
.h_full() .h_full()
.border_r_1()
.border_color(border_color)
.flex_shrink_0() .flex_shrink_0()
.overflow_hidden() .overflow_hidden()
.child( .child(
h_flex() h_flex()
.h_8()
.px_2() .px_2()
.py_1()
.justify_between() .justify_between()
.border_b_1() .border_b_1()
.border_color(border_color) .border_color(border_color)
@ -475,7 +573,7 @@ impl Render for RateCompletionModal {
div() div()
.p_2() .p_2()
.child( .child(
Label::new("No completions yet. Use the editor to generate some and rate them!") Label::new("No completions yet. Use the editor to generate some, and make sure to rate them!")
.color(Color::Muted), .color(Color::Muted),
) )
.into_any_element(), .into_any_element(),
@ -506,7 +604,7 @@ impl Render for RateCompletionModal {
.child( .child(
h_flex() h_flex()
.id("completion-content") .id("completion-content")
.gap_2p5() .gap_3()
.child( .child(
Icon::new(icon_name) Icon::new(icon_name)
.color(icon_color) .color(icon_color)
@ -515,7 +613,7 @@ impl Render for RateCompletionModal {
.child( .child(
v_flex() v_flex()
.child( .child(
h_flex().gap_2() h_flex().gap_1()
.child(Label::new(file_name).size(LabelSize::Small)) .child(Label::new(file_name).size(LabelSize::Small))
.when_some(file_path, |this, p| this.child(Label::new(p).size(LabelSize::Small).color(Color::Muted))) .when_some(file_path, |this, p| this.child(Label::new(p).size(LabelSize::Small).color(Color::Muted)))
) )