Compare commits

...

3 Commits

Author SHA1 Message Date
Piotr Osiewicz
0ecd3f5342 Make workflow text representation slightly prettier 2024-08-09 14:52:44 +02:00
Piotr Osiewicz
e48bf6b2cf Track step resolution process in the editor 2024-08-09 14:35:27 +02:00
Piotr Osiewicz
6f708b0cda WIP: add LLM output inspection mode 2024-08-09 13:34:17 +02:00
3 changed files with 113 additions and 8 deletions

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-microscope"><path d="M6 18h8"/><path d="M3 22h18"/><path d="M14 22a7 7 0 1 0 0-14h-1"/><path d="M9 14h2"/><path d="M9 12a2 2 0 0 1-2-2V6h6v4a2 2 0 0 1-2 2Z"/><path d="M12 6V3a1 1 0 0 0-1-1H9a1 1 0 0 0-1 1v3"/></svg>

After

Width:  |  Height:  |  Size: 418 B

View File

@@ -64,13 +64,13 @@ use std::{
};
use terminal_view::{terminal_panel::TerminalPanel, TerminalView};
use text::OffsetRangeExt;
use ui::TintColor;
use ui::{
prelude::*,
utils::{format_distance_from_now, DateTimeType},
Avatar, AvatarShape, ButtonLike, ContextMenu, Disclosure, ElevationIndex, KeyBinding, ListItem,
ListItemSpacing, PopoverMenu, PopoverMenuHandle, Tooltip,
};
use ui::{TintColor, ToggleButton};
use util::ResultExt;
use workspace::{
dock::{DockPosition, Panel, PanelEvent},
@@ -1587,7 +1587,7 @@ impl WorkflowStepStatus {
}
}
#[derive(Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Eq, PartialEq)]
struct ActiveWorkflowStep {
range: Range<language::Anchor>,
resolved: bool,
@@ -1617,6 +1617,7 @@ pub struct ContextEditor {
active_workflow_step: Option<ActiveWorkflowStep>,
assistant_panel: WeakView<AssistantPanel>,
error_message: Option<SharedString>,
debug_editor: Option<View<Editor>>,
}
const DEFAULT_TAB_TITLE: &str = "New Context";
@@ -1676,6 +1677,7 @@ impl ContextEditor {
active_workflow_step: None,
assistant_panel,
error_message: None,
debug_editor: None,
};
this.update_message_headers(cx);
this.insert_slash_command_output_sections(sections, cx);
@@ -1872,7 +1874,10 @@ impl ContextEditor {
cx.propagate();
}
fn debug_workflow_steps(&mut self, _: &DebugWorkflowSteps, cx: &mut ViewContext<Self>) {
fn update_debug_editor(&self, cx: &mut ViewContext<Self>) {
let Some(editor) = &self.debug_editor else {
return;
};
let mut output = String::new();
for (i, step) in self.context.read(cx).workflow_steps().iter().enumerate() {
output.push_str(&format!("Step {}:\n", i + 1));
@@ -1892,7 +1897,20 @@ impl ContextEditor {
}) => {
output.push_str("Resolution:\n");
output.push_str(&format!(" {:?}\n", title));
output.push_str(&format!(" {:?}\n", suggestions));
for (buffer, suggestions) in suggestions {
let path = buffer
.read(cx)
.file()
.and_then(|file| file.path().to_str())
.unwrap_or("untitled");
writeln!(output, " Path: {path}").ok();
if !suggestions.is_empty() {
writeln!(output, " Suggestions:").ok();
for suggestion in suggestions {
writeln!(output, " {suggestion:?}").ok();
}
}
}
}
crate::WorkflowStepStatus::Pending(_) => {
output.push_str("Resolution: Pending\n");
@@ -1903,15 +1921,31 @@ impl ContextEditor {
}
output.push('\n');
}
editor.update(cx, |this, cx| {
this.set_text(output, cx);
});
}
fn debug_workflow_steps(&mut self, _: &DebugWorkflowSteps, cx: &mut ViewContext<Self>) {
let editor = self
.workspace
.update(cx, |workspace, cx| Editor::new_in_workspace(workspace, cx));
if let Ok(editor) = editor {
cx.spawn(|_, mut cx| async move {
cx.spawn(|this, mut cx| async move {
let editor = editor.await?;
editor.update(&mut cx, |editor, cx| editor.set_text(output, cx))
editor
.update(&mut cx, |editor, cx| {
editor.set_read_only(true);
editor.buffer().update(cx, |this, cx| {
this.set_title("Assistant Output".into(), cx);
});
})
.ok();
this.update(&mut cx, |this, cx| {
this.debug_editor = Some(editor);
this.update_debug_editor(cx);
})
})
.detach_and_notify_err(cx);
}
@@ -2046,10 +2080,12 @@ impl ContextEditor {
}
ContextEvent::WorkflowStepsRemoved(removed) => {
self.remove_workflow_steps(removed, cx);
self.update_debug_editor(cx);
cx.notify();
}
ContextEvent::WorkflowStepUpdated(updated) => {
self.update_workflow_step(updated.clone(), cx);
self.update_debug_editor(cx);
cx.notify();
}
ContextEvent::SummaryChanged => {
@@ -2492,8 +2528,19 @@ impl ContextEditor {
self.hide_workflow_step(old_step.range, cx);
}
if let Some(new_step) = new_step {
if let Some(editor) = &self.debug_editor {
let is_active = self
.workspace
.update(cx, |this, cx| this.activate_item(editor, true, false, cx))
.unwrap_or_default();
if !is_active {
self.debug_editor.take();
}
} else if let Some(new_step) = new_step.clone() {
self.show_workflow_step(new_step.range.clone(), cx);
}
if let Some(new_step) = new_step {
self.active_workflow_step = Some(new_step);
}
}
@@ -3660,6 +3707,61 @@ impl Render for ContextEditorToolbarItem {
let right_side = h_flex()
.gap_2()
.child(
IconButton::new("toggle-debug-mode", IconName::Microscope)
.tooltip(|cx| Tooltip::text("Inspect LLM responses", cx))
.visible_on_hover("toolbar")
.selected(self.active_context_editor.as_ref().map_or(false, |this| {
this.update(cx, |this, cx| {
if let Some(debug_editor) = &this.debug_editor {
this.workspace
.update(cx, |this, cx| {
this.active_item(cx).map_or(false, |item| {
item.item_id() == debug_editor.entity_id()
})
})
.unwrap_or_default()
} else {
false
}
})
.unwrap_or_default()
}))
.on_click(cx.listener(|this, _, cx| {
this.active_context_editor.as_ref().map(|editor| {
editor
.update(cx, |this, cx| {
if let Some(debug_editor) = &this.debug_editor {
let activated = this
.workspace
.update(cx, |this, cx| {
if this.active_item(cx).map_or(false, |item| {
item.item_id() != debug_editor.entity_id()
}) {
this.activate_item(
debug_editor,
true,
false,
cx,
)
} else {
true
}
})
.ok()
.unwrap_or_default();
if !activated {
this.debug_editor.take();
}
}
if this.debug_editor.is_none() {
this.debug_workflow_steps(&Default::default(), cx);
}
})
.ok();
});
})),
)
.child(ModelSelector::new(
self.fs.clone(),
ButtonLike::new("active-model")

View File

@@ -203,6 +203,7 @@ pub enum IconName {
MessageBubbles,
Mic,
MicMute,
Microscope,
Minimize,
Option,
PageDown,
@@ -366,6 +367,7 @@ impl IconName {
IconName::MessageBubbles => "icons/conversations.svg",
IconName::Mic => "icons/mic.svg",
IconName::MicMute => "icons/mic_mute.svg",
IconName::Microscope => "icons/microscope.svg",
IconName::Minimize => "icons/minimize.svg",
IconName::Option => "icons/option.svg",
IconName::PageDown => "icons/page_down.svg",