diff --git a/assets/prompts/step_resolution.hbs b/assets/prompts/step_resolution.hbs
index 74bc43e078..523584dafc 100644
--- a/assets/prompts/step_resolution.hbs
+++ b/assets/prompts/step_resolution.hbs
@@ -1,22 +1,27 @@
-Your task is to map a step from the conversation above to suggestions on symbols inside the provided source files.
+
+Your task is to map a step from a workflow to locations in source code where code needs to be changed to fulfill that step.
+Given a workflow containing background context plus a series of tags, you will resolve *one* of these step tags to resolve to one or more locations in the code.
+With each location, you will produce a brief, one-line description of the changes to be made.
-Guidelines:
+
- There's no need to describe *what* to do, just *where* to do it.
+- Only reference locations that actually exist (unless you're creating a file).
- If creating a file, assume any subsequent updates are included at the time of creation.
-- Don't create and then update a file.
-- We'll create it in one shot.
+- Don't create and then update a file. Always create new files in shot.
- Prefer updating symbols lower in the syntax tree if possible.
- Never include suggestions on a parent symbol and one of its children in the same suggestions block.
- Never nest an operation with another operation or include CDATA or other content. All suggestions are leaf nodes.
-- Include a description attribute for each operation with a brief, one-line description of the change to perform.
- Descriptions are required for all suggestions except delete.
- When generating multiple suggestions, ensure the descriptions are specific to each individual operation.
- Avoid referring to the location in the description. Focus on the change to be made, not the location where it's made. That's implicit with the symbol you provide.
- Don't generate multiple suggestions at the same location. Instead, combine them together in a single operation with a succinct combined description.
+
+
-Example 1:
-
-User:
+
+
+
+
```rs src/rectangle.rs
struct Rectangle {
width: f64,
@@ -30,12 +35,21 @@ impl Rectangle {
}
```
+We need to add methods to calculate the area and perimeter of the rectangle. Can you help with that?
+
+
+Sure, I can help with that!
+
Add new methods 'calculate_area' and 'calculate_perimeter' to the Rectangle struct
Implement the 'Display' trait for the Rectangle struct
+
+
-What are the suggestions for the step: Add a new method 'calculate_area' to the Rectangle struct
+
+Add new methods 'calculate_area' and 'calculate_perimeter' to the Rectangle struct
+
-A (wrong):
+
{
"title": "Add Rectangle methods",
"suggestions": [
@@ -53,10 +67,9 @@ A (wrong):
}
]
}
+
-This demonstrates what NOT to do. NEVER append multiple children at the same location.
-
-A (corrected):
+
{
"title": "Add Rectangle methods",
"suggestions": [
@@ -68,11 +81,13 @@ A (corrected):
}
]
}
+
-User:
-What are the suggestions for the step: Implement the 'Display' trait for the Rectangle struct
+
+Implement the 'Display' trait for the Rectangle struct
+
-A:
+
-Example 2:
-
-User:
+
+
+
```rs src/user.rs
struct User {
pub name: String,
@@ -105,13 +121,19 @@ impl User {
}
}
```
-
+
+
+Certainly!
Update the 'print_info' method to use formatted output
Remove the 'email' field from the User struct
+
+
-What are the suggestions for the step: Update the 'print_info' method to use formatted output
+
+Update the 'print_info' method to use formatted output
+
-A:
+
-User:
-What are the suggestions for the step: Remove the 'email' field from the User struct
+
+Remove the 'email' field from the User struct
+
-A:
+
+
-Example 3:
-
-User:
+
+
+
```rs src/vehicle.rs
struct Vehicle {
make: String,
@@ -159,13 +185,18 @@ impl Vehicle {
}
}
```
-
+
+
Add a 'use std::fmt;' statement at the beginning of the file
Add a new method 'start_engine' in the Vehicle impl block
+
+
-What are the suggestions for the step: Add a 'use std::fmt;' statement at the beginning of the file
+
+Add a 'use std::fmt;' statement at the beginning of the file
+
-A:
+
-User:
-What are the suggestions for the step: Add a new method 'start_engine' in the Vehicle impl block
+
+Add a new method 'start_engine' in the Vehicle impl block
+
-A:
+
+
-Example 4:
-
-User:
+
+
+
```rs src/employee.rs
struct Employee {
name: String,
@@ -219,12 +254,18 @@ impl Employee {
}
}
```
-
+
+
Make salary an f32
+Remove the 'department' field and update the 'print_details' method
+
+
-What are the suggestions for the step: Make salary an f32
+
+Make salary an f32
+
-A (wrong):
+
{
"title": "Change salary to f32",
"suggestions": [
@@ -242,10 +283,9 @@ A (wrong):
}
]
}
+
-This example demonstrates what not to do. `struct Employee salary` is a child of `struct Employee`.
-
-A (corrected):
+
{
"title": "Change salary to f32",
"suggestions": [
@@ -257,11 +297,13 @@ A (corrected):
}
]
}
+
-User:
-What are the correct suggestions for the step: Remove the 'department' field and update the 'print_details' method
+
+Remove the 'department' field and update the 'print_details' method
+
-A:
+
+
-Example 5:
-
-User:
+
+
+
```rs src/game.rs
struct Player {
name: String,
@@ -305,10 +349,17 @@ impl Game {
}
}
```
-
+
+
Add a 'level' field to Player and update the 'new' method
+
+
-A:
+
+Add a 'level' field to Player and update the 'new' method
+
+
+
+
-Example 6:
-
-User:
+
+
+
```rs src/config.rs
use std::collections::HashMap;
@@ -343,10 +396,17 @@ impl Config {
}
}
```
-
+
+
Add a 'load_from_file' method to Config and import necessary modules
+
+
-A:
+
+Add a 'load_from_file' method to Config and import necessary modules
+
+
+
+
-Example 7:
-
-User:
+
+
+
```rs src/database.rs
pub(crate) struct Database {
connection: Connection,
@@ -383,10 +445,17 @@ impl Database {
}
}
```
-
+
+
Add error handling to the 'query' method and create a custom error type
+
+
-A:
+
+Add error handling to the 'query' method and create a custom error type
+
+
+
+
+
Now generate the suggestions for the following step:
+
+
+{{{workflow_context}}}
+
+
+
+{{{step_to_resolve}}}
+
diff --git a/crates/assistant/src/assistant_panel.rs b/crates/assistant/src/assistant_panel.rs
index fc1d77b81b..ef840aa1c8 100644
--- a/crates/assistant/src/assistant_panel.rs
+++ b/crates/assistant/src/assistant_panel.rs
@@ -2911,7 +2911,7 @@ impl ContextEditor {
let mut assist_ids = Vec::new();
for (excerpt_id, suggestion_group) in suggestion_groups {
for suggestion in &suggestion_group.suggestions {
- assist_ids.extend(suggestion.show(
+ assist_ids.extend(suggestion.kind.show(
&editor,
excerpt_id,
workspace,
diff --git a/crates/assistant/src/context.rs b/crates/assistant/src/context.rs
index 4d41f54a2c..f144f6c96a 100644
--- a/crates/assistant/src/context.rs
+++ b/crates/assistant/src/context.rs
@@ -2974,12 +2974,12 @@ mod tests {
model
.as_fake()
- .respond_to_last_tool_use(tool::WorkflowStepResolution {
+ .respond_to_last_tool_use(tool::WorkflowStepResolutionTool {
step_title: "Title".into(),
- suggestions: vec![tool::WorkflowSuggestion {
+ suggestions: vec![tool::WorkflowSuggestionTool {
path: "/root/hello.rs".into(),
// Simulate a symbol name that's slightly different than our outline query
- kind: tool::WorkflowSuggestionKind::Update {
+ kind: tool::WorkflowSuggestionToolKind::Update {
symbol: "fn main()".into(),
description: "Extract a greeting function".into(),
},
diff --git a/crates/assistant/src/context_inspector.rs b/crates/assistant/src/context_inspector.rs
index 340411bbbe..eb79557955 100644
--- a/crates/assistant/src/context_inspector.rs
+++ b/crates/assistant/src/context_inspector.rs
@@ -11,7 +11,7 @@ use ui::{
div, h_flex, px, Color, Element as _, ParentElement as _, Styled, ViewContext, WindowContext,
};
-use crate::{Context, ResolvedWorkflowStep, WorkflowSuggestion};
+use crate::{Context, ResolvedWorkflowStep, WorkflowSuggestion, WorkflowSuggestionKind};
type StepRange = Range;
@@ -68,7 +68,7 @@ impl ContextInspector {
.and_then(|file| file.path().to_str())
.unwrap_or("untitled");
let snapshot = buffer.text_snapshot();
- writeln!(output, " {buffer_path}:").ok()?;
+ writeln!(output, "Path: {buffer_path}:").ok()?;
for group in suggestion_groups {
for suggestion in &group.suggestions {
pretty_print_workflow_suggestion(&mut output, suggestion, &snapshot);
@@ -163,7 +163,7 @@ impl ContextInspector {
}
fn pretty_print_anchor(
out: &mut String,
- anchor: &language::Anchor,
+ anchor: language::Anchor,
snapshot: &text::BufferSnapshot,
) {
use std::fmt::Write;
@@ -177,9 +177,9 @@ fn pretty_print_range(
) {
use std::fmt::Write;
write!(out, " Range: ").ok();
- pretty_print_anchor(out, &range.start, snapshot);
+ pretty_print_anchor(out, range.start, snapshot);
write!(out, "..").ok();
- pretty_print_anchor(out, &range.end, snapshot);
+ pretty_print_anchor(out, range.end, snapshot);
}
fn pretty_print_workflow_suggestion(
@@ -188,37 +188,46 @@ fn pretty_print_workflow_suggestion(
snapshot: &text::BufferSnapshot,
) {
use std::fmt::Write;
- let (range, description, position) = match suggestion {
- WorkflowSuggestion::Update { range, description } => (Some(range), Some(description), None),
- WorkflowSuggestion::CreateFile { description } => (None, Some(description), None),
- WorkflowSuggestion::AppendChild {
- position,
- description,
+ let (position, description, range) = match &suggestion.kind {
+ WorkflowSuggestionKind::Update { range, description } => {
+ (None, Some(description), Some(range))
}
- | WorkflowSuggestion::InsertSiblingBefore {
+ WorkflowSuggestionKind::CreateFile { description } => (None, Some(description), None),
+ WorkflowSuggestionKind::AppendChild {
position,
description,
- }
- | WorkflowSuggestion::InsertSiblingAfter {
+ } => (Some(position), Some(description), None),
+ WorkflowSuggestionKind::InsertSiblingBefore {
position,
description,
- }
- | WorkflowSuggestion::PrependChild {
+ } => (Some(position), Some(description), None),
+ WorkflowSuggestionKind::InsertSiblingAfter {
position,
description,
- } => (None, Some(description), Some(position)),
-
- WorkflowSuggestion::Delete { range } => (Some(range), None, None),
+ } => (Some(position), Some(description), None),
+ WorkflowSuggestionKind::PrependChild {
+ position,
+ description,
+ } => (Some(position), Some(description), None),
+ WorkflowSuggestionKind::Delete { range } => (None, None, Some(range)),
};
+ writeln!(out, " Tool input: {}", suggestion.tool_input).ok();
+ writeln!(
+ out,
+ " Tool output: {}",
+ serde_json::to_string_pretty(&suggestion.tool_output)
+ .expect("Should not fail on valid struct serialization")
+ )
+ .ok();
if let Some(description) = description {
writeln!(out, " Description: {description}").ok();
}
if let Some(range) = range {
- pretty_print_range(out, range, snapshot);
+ pretty_print_range(out, &range, snapshot);
}
if let Some(position) = position {
write!(out, " Position: ").ok();
- pretty_print_anchor(out, position, snapshot);
+ pretty_print_anchor(out, *position, snapshot);
write!(out, "\n").ok();
}
write!(out, "\n").ok();
diff --git a/crates/assistant/src/prompts.rs b/crates/assistant/src/prompts.rs
index 4bbab19a9a..ddd4681a4b 100644
--- a/crates/assistant/src/prompts.rs
+++ b/crates/assistant/src/prompts.rs
@@ -31,6 +31,15 @@ pub struct TerminalAssistantPromptContext {
pub user_prompt: String,
}
+/// Context required to generate a workflow step resolution prompt.
+#[derive(Debug, Serialize)]
+pub struct StepResolutionContext {
+ /// The full context, including ... tags
+ pub workflow_context: String,
+ /// The text of the specific step from the context to resolve
+ pub step_to_resolve: String,
+}
+
pub struct PromptBuilder {
handlebars: Arc>>,
}
@@ -278,7 +287,10 @@ impl PromptBuilder {
self.handlebars.lock().render("edit_workflow", &())
}
- pub fn generate_step_resolution_prompt(&self) -> Result {
- self.handlebars.lock().render("step_resolution", &())
+ pub fn generate_step_resolution_prompt(
+ &self,
+ context: &StepResolutionContext,
+ ) -> Result {
+ self.handlebars.lock().render("step_resolution", context)
}
}
diff --git a/crates/assistant/src/workflow.rs b/crates/assistant/src/workflow.rs
index 5a208434c2..ecb0545c4d 100644
--- a/crates/assistant/src/workflow.rs
+++ b/crates/assistant/src/workflow.rs
@@ -1,4 +1,6 @@
-use crate::{AssistantPanel, Context, InlineAssistId, InlineAssistant};
+use crate::{
+ prompts::StepResolutionContext, AssistantPanel, Context, InlineAssistId, InlineAssistant,
+};
use anyhow::{anyhow, Error, Result};
use collections::HashMap;
use editor::Editor;
@@ -10,7 +12,7 @@ use project::Project;
use rope::Point;
use serde::{Deserialize, Serialize};
use smol::stream::StreamExt;
-use std::{cmp, ops::Range, sync::Arc};
+use std::{cmp, fmt::Write, ops::Range, sync::Arc};
use text::{AnchorRangeExt as _, OffsetRangeExt as _};
use util::ResultExt as _;
use workspace::Workspace;
@@ -34,7 +36,36 @@ pub struct WorkflowSuggestionGroup {
}
#[derive(Clone, Debug, Eq, PartialEq)]
-pub enum WorkflowSuggestion {
+pub struct WorkflowSuggestion {
+ pub kind: WorkflowSuggestionKind,
+ pub tool_input: String,
+ pub tool_output: tool::WorkflowSuggestionTool,
+}
+
+impl WorkflowSuggestion {
+ pub fn range(&self) -> Range {
+ self.kind.range()
+ }
+
+ pub fn show(
+ &self,
+ editor: &View,
+ excerpt_id: editor::ExcerptId,
+ workspace: &WeakView,
+ assistant_panel: &View,
+ cx: &mut ui::ViewContext,
+ ) -> Option {
+ self.kind
+ .show(editor, excerpt_id, workspace, assistant_panel, cx)
+ }
+
+ fn try_merge(&mut self, other: &mut WorkflowSuggestion, snapshot: &BufferSnapshot) -> bool {
+ self.kind.try_merge(&other.kind, snapshot)
+ }
+}
+
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum WorkflowSuggestionKind {
Update {
range: Range,
description: String,
@@ -87,6 +118,15 @@ impl WorkflowStepResolution {
.text_for_range(self.tagged_range.clone())
.collect::();
+ let mut workflow_context = String::new();
+ for message in context.messages(cx) {
+ write!(&mut workflow_context, "", message.role).unwrap();
+ for chunk in context_buffer.read(cx).text_for_range(message.offset_range) {
+ write!(&mut workflow_context, "{chunk}").unwrap();
+ }
+ write!(&mut workflow_context, "").unwrap();
+ }
+
Some(cx.spawn(|this, mut cx| async move {
let result = async {
let Some(model) = model else {
@@ -99,7 +139,12 @@ impl WorkflowStepResolution {
cx.notify();
})?;
- let mut prompt = prompt_builder.generate_step_resolution_prompt()?;
+ let resolution_context = StepResolutionContext {
+ workflow_context,
+ step_to_resolve: step_text.clone(),
+ };
+ let mut prompt =
+ prompt_builder.generate_step_resolution_prompt(&resolution_context)?;
prompt.push_str(&step_text);
request.messages.push(LanguageModelRequestMessage {
role: Role::User,
@@ -108,7 +153,7 @@ impl WorkflowStepResolution {
// Invoke the model to get its edit suggestions for this workflow step.
let mut stream = model
- .use_tool_stream::(request, &cx)
+ .use_tool_stream::(request, &cx)
.await?;
while let Some(chunk) = stream.next().await {
let chunk = chunk?;
@@ -119,14 +164,16 @@ impl WorkflowStepResolution {
}
let resolution = this.update(&mut cx, |this, _| {
- serde_json::from_str::(&this.output)
+ serde_json::from_str::(&this.output)
})??;
// Translate the parsed suggestions to our internal types, which anchor the suggestions to locations in the code.
let suggestion_tasks: Vec<_> = resolution
.suggestions
.iter()
- .map(|suggestion| suggestion.resolve(project.clone(), cx.clone()))
+ .map(|suggestion| {
+ suggestion.resolve(step_text.clone(), project.clone(), cx.clone())
+ })
.collect();
// Expand the context ranges of each suggestion and group suggestions with overlapping context ranges.
@@ -152,7 +199,7 @@ impl WorkflowStepResolution {
suggestions.sort_by(|a, b| a.range().cmp(&b.range(), &snapshot));
// Merge overlapping suggestions
- suggestions.dedup_by(|a, b| b.try_merge(&a, &snapshot));
+ suggestions.dedup_by(|a, b| b.try_merge(a, &snapshot));
// Create context ranges for each suggestion
for suggestion in suggestions {
@@ -214,40 +261,40 @@ impl WorkflowStepResolution {
}
}
-impl WorkflowSuggestion {
+impl WorkflowSuggestionKind {
pub fn range(&self) -> Range {
match self {
- WorkflowSuggestion::Update { range, .. } => range.clone(),
- WorkflowSuggestion::CreateFile { .. } => language::Anchor::MIN..language::Anchor::MAX,
- WorkflowSuggestion::InsertSiblingBefore { position, .. }
- | WorkflowSuggestion::InsertSiblingAfter { position, .. }
- | WorkflowSuggestion::PrependChild { position, .. }
- | WorkflowSuggestion::AppendChild { position, .. } => *position..*position,
- WorkflowSuggestion::Delete { range } => range.clone(),
+ Self::Update { range, .. } => range.clone(),
+ Self::CreateFile { .. } => language::Anchor::MIN..language::Anchor::MAX,
+ Self::InsertSiblingBefore { position, .. }
+ | Self::InsertSiblingAfter { position, .. }
+ | Self::PrependChild { position, .. }
+ | Self::AppendChild { position, .. } => *position..*position,
+ Self::Delete { range } => range.clone(),
}
}
pub fn description(&self) -> Option<&str> {
match self {
- WorkflowSuggestion::Update { description, .. }
- | WorkflowSuggestion::CreateFile { description }
- | WorkflowSuggestion::InsertSiblingBefore { description, .. }
- | WorkflowSuggestion::InsertSiblingAfter { description, .. }
- | WorkflowSuggestion::PrependChild { description, .. }
- | WorkflowSuggestion::AppendChild { description, .. } => Some(description),
- WorkflowSuggestion::Delete { .. } => None,
+ Self::Update { description, .. }
+ | Self::CreateFile { description }
+ | Self::InsertSiblingBefore { description, .. }
+ | Self::InsertSiblingAfter { description, .. }
+ | Self::PrependChild { description, .. }
+ | Self::AppendChild { description, .. } => Some(description),
+ Self::Delete { .. } => None,
}
}
fn description_mut(&mut self) -> Option<&mut String> {
match self {
- WorkflowSuggestion::Update { description, .. }
- | WorkflowSuggestion::CreateFile { description }
- | WorkflowSuggestion::InsertSiblingBefore { description, .. }
- | WorkflowSuggestion::InsertSiblingAfter { description, .. }
- | WorkflowSuggestion::PrependChild { description, .. }
- | WorkflowSuggestion::AppendChild { description, .. } => Some(description),
- WorkflowSuggestion::Delete { .. } => None,
+ Self::Update { description, .. }
+ | Self::CreateFile { description }
+ | Self::InsertSiblingBefore { description, .. }
+ | Self::InsertSiblingAfter { description, .. }
+ | Self::PrependChild { description, .. }
+ | Self::AppendChild { description, .. } => Some(description),
+ Self::Delete { .. } => None,
}
}
@@ -286,16 +333,16 @@ impl WorkflowSuggestion {
let snapshot = buffer.read(cx).snapshot(cx);
match self {
- WorkflowSuggestion::Update { range, description } => {
+ Self::Update { range, description } => {
initial_prompt = description.clone();
suggestion_range = snapshot.anchor_in_excerpt(excerpt_id, range.start)?
..snapshot.anchor_in_excerpt(excerpt_id, range.end)?;
}
- WorkflowSuggestion::CreateFile { description } => {
+ Self::CreateFile { description } => {
initial_prompt = description.clone();
suggestion_range = editor::Anchor::min()..editor::Anchor::min();
}
- WorkflowSuggestion::InsertSiblingBefore {
+ Self::InsertSiblingBefore {
position,
description,
} => {
@@ -311,7 +358,7 @@ impl WorkflowSuggestion {
line_start..line_start
});
}
- WorkflowSuggestion::InsertSiblingAfter {
+ Self::InsertSiblingAfter {
position,
description,
} => {
@@ -327,7 +374,7 @@ impl WorkflowSuggestion {
line_start..line_start
});
}
- WorkflowSuggestion::PrependChild {
+ Self::PrependChild {
position,
description,
} => {
@@ -343,7 +390,7 @@ impl WorkflowSuggestion {
line_start..line_start
});
}
- WorkflowSuggestion::AppendChild {
+ Self::AppendChild {
position,
description,
} => {
@@ -359,7 +406,7 @@ impl WorkflowSuggestion {
line_start..line_start
});
}
- WorkflowSuggestion::Delete { range } => {
+ Self::Delete { range } => {
initial_prompt = "Delete".to_string();
suggestion_range = snapshot.anchor_in_excerpt(excerpt_id, range.start)?
..snapshot.anchor_in_excerpt(excerpt_id, range.end)?;
@@ -392,15 +439,15 @@ pub mod tool {
use schemars::JsonSchema;
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
- pub struct WorkflowStepResolution {
+ pub struct WorkflowStepResolutionTool {
/// 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 suggestions: Vec,
+ pub suggestions: Vec,
}
- impl LanguageModelTool for WorkflowStepResolution {
+ impl LanguageModelTool for WorkflowStepResolutionTool {
fn name() -> String {
"edit".into()
}
@@ -429,16 +476,17 @@ pub mod tool {
/// programmatic changes to source code. It provides a structured way to describe
/// edits for features like refactoring tools or AI-assisted coding suggestions.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
- pub struct WorkflowSuggestion {
+ pub struct WorkflowSuggestionTool {
/// The path to the file containing the relevant operation
pub path: String,
#[serde(flatten)]
- pub kind: WorkflowSuggestionKind,
+ pub kind: WorkflowSuggestionToolKind,
}
- impl WorkflowSuggestion {
+ impl WorkflowSuggestionTool {
pub(super) async fn resolve(
&self,
+ tool_input: String,
project: Model,
mut cx: AsyncAppContext,
) -> Result<(Model, super::WorkflowSuggestion)> {
@@ -475,9 +523,8 @@ pub mod tool {
let snapshot = buffer.update(&mut cx, |buffer, _| buffer.snapshot())?;
let outline = snapshot.outline(None).context("no outline for buffer")?;
- let suggestion;
- match kind {
- WorkflowSuggestionKind::Update {
+ let kind = match kind {
+ WorkflowSuggestionToolKind::Update {
symbol,
description,
} => {
@@ -494,12 +541,12 @@ pub mod tool {
snapshot.line_len(symbol.range.end.row),
);
let range = snapshot.anchor_before(start)..snapshot.anchor_after(end);
- suggestion = super::WorkflowSuggestion::Update { range, description };
+ WorkflowSuggestionKind::Update { range, description }
}
- WorkflowSuggestionKind::Create { description } => {
- suggestion = super::WorkflowSuggestion::CreateFile { description };
+ WorkflowSuggestionToolKind::Create { description } => {
+ WorkflowSuggestionKind::CreateFile { description }
}
- WorkflowSuggestionKind::InsertSiblingBefore {
+ WorkflowSuggestionToolKind::InsertSiblingBefore {
symbol,
description,
} => {
@@ -514,12 +561,12 @@ pub mod tool {
annotation_range.start
}),
);
- suggestion = super::WorkflowSuggestion::InsertSiblingBefore {
+ WorkflowSuggestionKind::InsertSiblingBefore {
position,
description,
- };
+ }
}
- WorkflowSuggestionKind::InsertSiblingAfter {
+ WorkflowSuggestionToolKind::InsertSiblingAfter {
symbol,
description,
} => {
@@ -528,12 +575,12 @@ pub mod tool {
.with_context(|| format!("symbol not found: {:?}", symbol))?
.to_point(&snapshot);
let position = snapshot.anchor_after(symbol.range.end);
- suggestion = super::WorkflowSuggestion::InsertSiblingAfter {
+ WorkflowSuggestionKind::InsertSiblingAfter {
position,
description,
- };
+ }
}
- WorkflowSuggestionKind::PrependChild {
+ WorkflowSuggestionToolKind::PrependChild {
symbol,
description,
} => {
@@ -548,18 +595,18 @@ pub mod tool {
.body_range
.map_or(symbol.range.start, |body_range| body_range.start),
);
- suggestion = super::WorkflowSuggestion::PrependChild {
+ WorkflowSuggestionKind::PrependChild {
position,
description,
- };
+ }
} else {
- suggestion = super::WorkflowSuggestion::PrependChild {
+ WorkflowSuggestionKind::PrependChild {
position: language::Anchor::MIN,
description,
- };
+ }
}
}
- WorkflowSuggestionKind::AppendChild {
+ WorkflowSuggestionToolKind::AppendChild {
symbol,
description,
} => {
@@ -574,18 +621,18 @@ pub mod tool {
.body_range
.map_or(symbol.range.end, |body_range| body_range.end),
);
- suggestion = super::WorkflowSuggestion::AppendChild {
+ WorkflowSuggestionKind::AppendChild {
position,
description,
- };
+ }
} else {
- suggestion = super::WorkflowSuggestion::PrependChild {
+ WorkflowSuggestionKind::PrependChild {
position: language::Anchor::MAX,
description,
- };
+ }
}
}
- WorkflowSuggestionKind::Delete { symbol } => {
+ WorkflowSuggestionToolKind::Delete { symbol } => {
let symbol = outline
.find_most_similar(&symbol)
.with_context(|| format!("symbol not found: {:?}", symbol))?
@@ -599,9 +646,15 @@ pub mod tool {
snapshot.line_len(symbol.range.end.row),
);
let range = snapshot.anchor_before(start)..snapshot.anchor_after(end);
- suggestion = super::WorkflowSuggestion::Delete { range };
+ WorkflowSuggestionKind::Delete { range }
}
- }
+ };
+
+ let suggestion = WorkflowSuggestion {
+ kind,
+ tool_output: self.clone(),
+ tool_input,
+ };
Ok((buffer, suggestion))
}
@@ -609,7 +662,7 @@ pub mod tool {
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(tag = "kind")]
- pub enum WorkflowSuggestionKind {
+ pub enum WorkflowSuggestionToolKind {
/// Rewrites the specified symbol entirely based on the given description.
/// This operation completely replaces the existing symbol with new content.
Update {