diff --git a/assets/prompts/edit_workflow.hbs b/assets/prompts/suggest_edits.hbs similarity index 100% rename from assets/prompts/edit_workflow.hbs rename to assets/prompts/suggest_edits.hbs diff --git a/crates/assistant/src/assistant_panel.rs b/crates/assistant/src/assistant_panel.rs index 19d92bbc02..3d498d94eb 100644 --- a/crates/assistant/src/assistant_panel.rs +++ b/crates/assistant/src/assistant_panel.rs @@ -1462,6 +1462,7 @@ type MessageHeader = MessageMetadata; #[derive(Clone)] enum AssistError { + FileRequired, PaymentRequired, MaxMonthlySpendReached, Message(SharedString), @@ -1628,7 +1629,10 @@ impl ContextEditor { self.last_error = None; - if let Some(user_message) = self + if request_type == RequestType::SuggestEdits && !self.context.read(cx).contains_files(cx) { + self.last_error = Some(AssistError::FileRequired); + cx.notify(); + } else if let Some(user_message) = self .context .update(cx, |context, cx| context.assist(request_type, cx)) { @@ -3740,6 +3744,7 @@ impl ContextEditor { .elevation_2(cx) .occlude() .child(match last_error { + AssistError::FileRequired => self.render_file_required_error(cx), AssistError::PaymentRequired => self.render_payment_required_error(cx), AssistError::MaxMonthlySpendReached => { self.render_max_monthly_spend_reached_error(cx) @@ -3752,6 +3757,41 @@ impl ContextEditor { ) } + fn render_file_required_error(&self, cx: &mut ViewContext) -> AnyElement { + v_flex() + .gap_0p5() + .child( + h_flex() + .gap_1p5() + .items_center() + .child(Icon::new(IconName::Warning).color(Color::Warning)) + .child( + Label::new("Suggest Edits needs a file to edit").weight(FontWeight::MEDIUM), + ), + ) + .child( + div() + .id("error-message") + .max_h_24() + .overflow_y_scroll() + .child(Label::new( + "To include files, type /file or /tab in your prompt.", + )), + ) + .child( + h_flex() + .justify_end() + .mt_1() + .child(Button::new("dismiss", "Dismiss").on_click(cx.listener( + |this, _, cx| { + this.last_error = None; + cx.notify(); + }, + ))), + ) + .into_any() + } + fn render_payment_required_error(&self, cx: &mut ViewContext) -> AnyElement { const ERROR_MESSAGE: &str = "Free tier exceeded. Subscribe and add payment to continue using Zed LLMs. You'll be billed at cost for tokens used."; diff --git a/crates/assistant/src/context.rs b/crates/assistant/src/context.rs index f5e8174748..a1de9d3b40 100644 --- a/crates/assistant/src/context.rs +++ b/crates/assistant/src/context.rs @@ -2,8 +2,9 @@ mod context_tests; use crate::{ - prompts::PromptBuilder, slash_command::SlashCommandLine, AssistantEdit, AssistantPatch, - AssistantPatchStatus, MessageId, MessageStatus, + prompts::PromptBuilder, + slash_command::{file_command::FileCommandMetadata, SlashCommandLine}, + AssistantEdit, AssistantPatch, AssistantPatchStatus, MessageId, MessageStatus, }; use anyhow::{anyhow, Context as _, Result}; use assistant_slash_command::{ @@ -66,7 +67,7 @@ impl ContextId { } } -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum RequestType { /// Request a normal chat response from the model. Chat, @@ -989,6 +990,20 @@ impl Context { &self.slash_command_output_sections } + pub fn contains_files(&self, cx: &AppContext) -> bool { + let buffer = self.buffer.read(cx); + self.slash_command_output_sections.iter().any(|section| { + section.is_valid(buffer) + && section + .metadata + .as_ref() + .and_then(|metadata| { + serde_json::from_value::(metadata.clone()).ok() + }) + .is_some() + }) + } + pub fn pending_tool_uses(&self) -> Vec<&PendingToolUse> { self.pending_tool_uses_by_id.values().collect() } diff --git a/crates/assistant/src/prompts.rs b/crates/assistant/src/prompts.rs index 2d0829086c..50fee242ea 100644 --- a/crates/assistant/src/prompts.rs +++ b/crates/assistant/src/prompts.rs @@ -311,7 +311,7 @@ impl PromptBuilder { } pub fn generate_workflow_prompt(&self) -> Result { - self.handlebars.lock().render("edit_workflow", &()) + self.handlebars.lock().render("suggest_edits", &()) } pub fn generate_project_slash_command_prompt( diff --git a/docs/src/assistant/prompting.md b/docs/src/assistant/prompting.md index 0dca671b47..18bda28bbf 100644 --- a/docs/src/assistant/prompting.md +++ b/docs/src/assistant/prompting.md @@ -137,7 +137,7 @@ Zed has the following internal prompt templates: - `content_prompt.hbs`: Used for generating content in the editor. - `terminal_assistant_prompt.hbs`: Used for the terminal assistant feature. -- `edit_workflow.hbs`: Used for generating the edit workflow prompt. +- `suggest_edits.hbs`: Used for generating the model instructions for the XML Suggest Edits should return. - `step_resolution.hbs`: Used for generating the step resolution prompt. At this point it is unknown if we will expand templates further to be user-creatable. @@ -215,7 +215,7 @@ The following templates can be overridden: given system information and latest terminal output if relevant. ``` -3. `edit_workflow.hbs`: Used for generating the edit workflow prompt. +3. `suggest_edits.hbs`: Used for generating the model instructions for the XML Suggest Edits should return. 4. `step_resolution.hbs`: Used for generating the step resolution prompt.