Give edit steps multibuffer a title (#15625)
Release Notes: - N/A Co-authored-by: Nathan <nathan@zed.dev>
This commit is contained in:
parent
ed7952f5ef
commit
0b175ac66e
3 changed files with 107 additions and 65 deletions
|
@ -341,7 +341,7 @@ pub struct SlashCommandId(clock::Lamport);
|
|||
#[derive(Debug)]
|
||||
pub struct EditStep {
|
||||
pub source_range: Range<language::Anchor>,
|
||||
pub operations: Option<EditStepOperations>,
|
||||
pub state: Option<EditStepState>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -358,22 +358,29 @@ pub struct EditSuggestion {
|
|||
pub initial_insertion: Option<InitialInsertion>,
|
||||
}
|
||||
|
||||
pub struct EditStepSuggestions {
|
||||
pub title: String,
|
||||
pub suggestions: HashMap<Model<Buffer>, Vec<EditSuggestionGroup>>,
|
||||
}
|
||||
|
||||
impl EditStep {
|
||||
pub fn edit_suggestions(
|
||||
&self,
|
||||
project: &Model<Project>,
|
||||
cx: &AppContext,
|
||||
) -> Task<HashMap<Model<Buffer>, Vec<EditSuggestionGroup>>> {
|
||||
let Some(EditStepOperations::Ready(operations)) = &self.operations else {
|
||||
return Task::ready(HashMap::default());
|
||||
) -> Option<Task<EditStepSuggestions>> {
|
||||
let Some(EditStepState::Resolved(resolution)) = &self.state else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let suggestion_tasks: Vec<_> = operations
|
||||
let title = resolution.step_title.clone();
|
||||
let suggestion_tasks: Vec<_> = resolution
|
||||
.operations
|
||||
.iter()
|
||||
.map(|operation| operation.edit_suggestion(project.clone(), cx))
|
||||
.collect();
|
||||
|
||||
cx.spawn(|mut cx| async move {
|
||||
Some(cx.spawn(|mut cx| async move {
|
||||
let suggestions = future::join_all(suggestion_tasks)
|
||||
.await
|
||||
.into_iter()
|
||||
|
@ -468,21 +475,24 @@ impl EditStep {
|
|||
suggestion_groups_by_buffer.insert(buffer, suggestion_groups);
|
||||
}
|
||||
|
||||
suggestion_groups_by_buffer
|
||||
})
|
||||
EditStepSuggestions {
|
||||
title,
|
||||
suggestions: suggestion_groups_by_buffer,
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
pub enum EditStepOperations {
|
||||
pub enum EditStepState {
|
||||
Pending(Task<Option<()>>),
|
||||
Ready(Vec<EditOperation>),
|
||||
Resolved(EditStepResolution),
|
||||
}
|
||||
|
||||
impl Debug for EditStepOperations {
|
||||
impl Debug for EditStepState {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
EditStepOperations::Pending(_) => write!(f, "EditStepOperations::Pending"),
|
||||
EditStepOperations::Ready(operations) => f
|
||||
EditStepState::Pending(_) => write!(f, "EditStepOperations::Pending"),
|
||||
EditStepState::Resolved(operations) => f
|
||||
.debug_struct("EditStepOperations::Parsed")
|
||||
.field("operations", operations)
|
||||
.finish(),
|
||||
|
@ -490,6 +500,25 @@ impl Debug for EditStepOperations {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, JsonSchema)]
|
||||
pub struct EditStepResolution {
|
||||
/// An extremely short title for the edit step represented by these operations.
|
||||
pub step_title: String,
|
||||
/// A sequence of operations to apply to the codebase.
|
||||
/// When multiple operations are required for a step, be sure to include multiple operations in this list.
|
||||
pub operations: Vec<EditOperation>,
|
||||
}
|
||||
|
||||
impl LanguageModelTool for EditStepResolution {
|
||||
fn name() -> String {
|
||||
"edit".into()
|
||||
}
|
||||
|
||||
fn description() -> String {
|
||||
"suggest edits to one or more locations in the codebase".into()
|
||||
}
|
||||
}
|
||||
|
||||
/// A description of an operation to apply to one location in the codebase.
|
||||
///
|
||||
/// This object represents a single edit operation that can be performed on a specific file
|
||||
|
@ -1324,7 +1353,7 @@ impl Context {
|
|||
ix,
|
||||
EditStep {
|
||||
source_range,
|
||||
operations: None,
|
||||
state: None,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
@ -1340,7 +1369,7 @@ impl Context {
|
|||
// Insert new steps and generate their corresponding tasks
|
||||
for (index, mut step) in new_edit_steps.into_iter().rev() {
|
||||
let task = self.generate_edit_step_operations(&step, cx);
|
||||
step.operations = Some(EditStepOperations::Pending(task));
|
||||
step.state = Some(EditStepState::Pending(task));
|
||||
self.edit_steps.insert(index, step);
|
||||
}
|
||||
|
||||
|
@ -1353,23 +1382,6 @@ impl Context {
|
|||
edit_step: &EditStep,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Task<Option<()>> {
|
||||
#[derive(Debug, Deserialize, JsonSchema)]
|
||||
struct EditTool {
|
||||
/// A sequence of operations to apply to the codebase.
|
||||
/// When multiple operations are required for a step, be sure to include multiple operations in this list.
|
||||
operations: Vec<EditOperation>,
|
||||
}
|
||||
|
||||
impl LanguageModelTool for EditTool {
|
||||
fn name() -> String {
|
||||
"edit".into()
|
||||
}
|
||||
|
||||
fn description() -> String {
|
||||
"suggest edits to one or more locations in the codebase".into()
|
||||
}
|
||||
}
|
||||
|
||||
let Some(model) = LanguageModelRegistry::read_global(cx).active_model() else {
|
||||
return Task::ready(Err(anyhow!("no active model")).log_err());
|
||||
};
|
||||
|
@ -1394,7 +1406,7 @@ impl Context {
|
|||
content: prompt,
|
||||
});
|
||||
|
||||
let tool_use = model.use_tool::<EditTool>(request, &cx).await?;
|
||||
let resolution = model.use_tool::<EditStepResolution>(request, &cx).await?;
|
||||
|
||||
this.update(&mut cx, |this, cx| {
|
||||
let step_index = this
|
||||
|
@ -1405,7 +1417,7 @@ impl Context {
|
|||
})
|
||||
.map_err(|_| anyhow!("edit step not found"))?;
|
||||
if let Some(edit_step) = this.edit_steps.get_mut(step_index) {
|
||||
edit_step.operations = Some(EditStepOperations::Ready(tool_use.operations));
|
||||
edit_step.state = Some(EditStepState::Resolved(resolution));
|
||||
cx.emit(ContextEvent::EditStepsChanged);
|
||||
}
|
||||
anyhow::Ok(())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue