Add diagnostic information to context of inline assistant (#18096)

Roy Williams created

Release Notes:

- Added Diagnostic information to inline assistant. This enables users
to just say "Fix this" and have the model know what the errors are.

Change summary

assets/prompts/content_prompt.hbs | 11 +++++++++++
crates/assistant/src/prompts.rs   | 23 +++++++++++++++++++++--
2 files changed, 32 insertions(+), 2 deletions(-)

Detailed changes

assets/prompts/content_prompt.hbs 🔗

@@ -47,6 +47,17 @@ And here's the section to rewrite based on that prompt again for reference:
 <rewrite_this>
 {{{rewrite_section}}}
 </rewrite_this>
+
+{{#if diagnostic_errors}}
+{{#each diagnostic_errors}}
+<diagnostic_error>
+    <line_number>{{line_number}}</line_number>
+    <error_message>{{error_message}}</error_message>
+    <code_content>{{code_content}}</code_content>
+</diagnostic_error>
+{{/each}}
+{{/if}}
+
 {{/if}}
 
 Only make changes that are necessary to fulfill the prompt, leave everything else as-is. All surrounding {{content_type}} will be preserved.

crates/assistant/src/prompts.rs 🔗

@@ -4,13 +4,20 @@ use fs::Fs;
 use futures::StreamExt;
 use gpui::AssetSource;
 use handlebars::{Handlebars, RenderError};
-use language::{BufferSnapshot, LanguageName};
+use language::{BufferSnapshot, LanguageName, Point};
 use parking_lot::Mutex;
 use serde::Serialize;
 use std::{ops::Range, path::PathBuf, sync::Arc, time::Duration};
 use text::LineEnding;
 use util::ResultExt;
 
+#[derive(Serialize)]
+pub struct ContentPromptDiagnosticContext {
+    pub line_number: usize,
+    pub error_message: String,
+    pub code_content: String,
+}
+
 #[derive(Serialize)]
 pub struct ContentPromptContext {
     pub content_type: String,
@@ -20,6 +27,7 @@ pub struct ContentPromptContext {
     pub document_content: String,
     pub user_prompt: String,
     pub rewrite_section: Option<String>,
+    pub diagnostic_errors: Vec<ContentPromptDiagnosticContext>,
 }
 
 #[derive(Serialize)]
@@ -261,6 +269,17 @@ impl PromptBuilder {
         } else {
             None
         };
+        let diagnostics = buffer.diagnostics_in_range::<_, Point>(range, false);
+        let diagnostic_errors: Vec<ContentPromptDiagnosticContext> = diagnostics
+            .map(|entry| {
+                let start = entry.range.start;
+                ContentPromptDiagnosticContext {
+                    line_number: (start.row + 1) as usize,
+                    error_message: entry.diagnostic.message.clone(),
+                    code_content: buffer.text_for_range(entry.range.clone()).collect(),
+                }
+            })
+            .collect();
 
         let context = ContentPromptContext {
             content_type: content_type.to_string(),
@@ -270,8 +289,8 @@ impl PromptBuilder {
             document_content,
             user_prompt,
             rewrite_section,
+            diagnostic_errors,
         };
-
         self.handlebars.lock().render("content_prompt", &context)
     }