zeta2 inspector: Sort by scores and add score components tooltip (#39821)

Release Notes:

- N/A

Co-authored-by: Agus <agus@zed.dev>
This commit is contained in:
Michael Sloan
2025-10-08 23:14:40 +00:00
committed by GitHub
co-authored by Agus
parent c1e3958c26
commit 3d0312f4c7
3 changed files with 90 additions and 9 deletions
Generated
+2
View File
@@ -20730,6 +20730,8 @@ dependencies = [
"indoc",
"language",
"log",
"multi_buffer",
"ordered-float 2.10.1",
"pretty_assertions",
"project",
"serde",
+2
View File
@@ -22,6 +22,8 @@ futures.workspace = true
gpui.workspace = true
language.workspace = true
log.workspace = true
multi_buffer.workspace = true
ordered-float.workspace = true
project.workspace = true
serde.workspace = true
text.workspace = true
+86 -9
View File
@@ -1,16 +1,20 @@
use std::{collections::hash_map::Entry, path::PathBuf, str::FromStr, sync::Arc, time::Duration};
use std::{
cmp::Reverse, collections::hash_map::Entry, path::PathBuf, str::FromStr, sync::Arc,
time::Duration,
};
use chrono::TimeDelta;
use client::{Client, UserStore};
use cloud_llm_client::predict_edits_v3::PromptFormat;
use cloud_llm_client::predict_edits_v3::{DeclarationScoreComponents, PromptFormat};
use collections::HashMap;
use editor::{Editor, EditorEvent, EditorMode, ExcerptRange, MultiBuffer};
use futures::{StreamExt as _, channel::oneshot};
use gpui::{
Entity, EventEmitter, FocusHandle, Focusable, Subscription, Task, WeakEntity, actions,
prelude::*,
CursorStyle, Entity, EventEmitter, FocusHandle, Focusable, Subscription, Task, WeakEntity,
actions, prelude::*,
};
use language::{Buffer, DiskState};
use ordered_float::OrderedFloat;
use project::{Project, WorktreeId};
use ui::{ContextMenu, ContextMenuEntry, DropdownMenu, prelude::*};
use ui_input::SingleLineInput;
@@ -298,6 +302,8 @@ impl Zeta2Inspector {
this.update_in(cx, |this, window, cx| {
let context_editor = cx.new(|cx| {
let mut excerpt_score_components = HashMap::default();
let multibuffer = cx.new(|cx| {
let mut multibuffer = MultiBuffer::new(language::Capability::ReadOnly);
let excerpt_file = Arc::new(ExcerptMetadataFile {
@@ -328,7 +334,14 @@ impl Zeta2Inspector {
cx,
);
for snippet in &prediction.context.declarations {
let mut declarations = prediction.context.declarations.clone();
declarations.sort_unstable_by_key(|declaration| {
Reverse(OrderedFloat(
declaration.score(DeclarationStyle::Declaration),
))
});
for snippet in &declarations {
let path = this
.project
.read(cx)
@@ -336,10 +349,10 @@ impl Zeta2Inspector {
let snippet_file = Arc::new(ExcerptMetadataFile {
title: RelPath::unix(&format!(
"{} (Score density: {})",
"{} (Score: {})",
path.map(|p| p.path.display(path_style).to_string())
.unwrap_or_else(|| "".to_string()),
snippet.score_density(DeclarationStyle::Declaration)
snippet.score(DeclarationStyle::Declaration)
))
.unwrap()
.into(),
@@ -359,17 +372,26 @@ impl Zeta2Inspector {
buffer
});
multibuffer.push_excerpts(
let excerpt_ids = multibuffer.push_excerpts(
excerpt_buffer,
[ExcerptRange::new(text::Anchor::MIN..text::Anchor::MAX)],
cx,
);
let excerpt_id = excerpt_ids.first().unwrap();
excerpt_score_components
.insert(*excerpt_id, snippet.components.clone());
}
multibuffer
});
Editor::new(EditorMode::full(), multibuffer, None, window, cx)
let mut editor =
Editor::new(EditorMode::full(), multibuffer, None, window, cx);
editor.register_addon(ZetaContextAddon {
excerpt_score_components,
});
editor
});
let PredictionDebugInfo {
@@ -807,3 +829,58 @@ impl language::File for ExcerptMetadataFile {
false
}
}
struct ZetaContextAddon {
excerpt_score_components: HashMap<editor::ExcerptId, DeclarationScoreComponents>,
}
impl editor::Addon for ZetaContextAddon {
fn to_any(&self) -> &dyn std::any::Any {
self
}
fn render_buffer_header_controls(
&self,
excerpt_info: &multi_buffer::ExcerptInfo,
_window: &Window,
_cx: &App,
) -> Option<AnyElement> {
let score_components = self.excerpt_score_components.get(&excerpt_info.id)?.clone();
Some(
div()
.id(excerpt_info.id.to_proto() as usize)
.child(ui::Icon::new(IconName::Info))
.cursor(CursorStyle::PointingHand)
.tooltip(move |_, cx| {
cx.new(|_| ScoreComponentsTooltip::new(&score_components))
.into()
})
.into_any(),
)
}
}
struct ScoreComponentsTooltip {
text: SharedString,
}
impl ScoreComponentsTooltip {
fn new(components: &DeclarationScoreComponents) -> Self {
Self {
text: format!("{:#?}", components).into(),
}
}
}
impl Render for ScoreComponentsTooltip {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div().pl_2().pt_2p5().child(
div()
.elevation_2(cx)
.py_1()
.px_2()
.child(ui::Label::new(self.text.clone()).buffer_font(cx)),
)
}
}