assistant2: Handle non-text files in context pickers (#22795)

Agus Zubiaga and Danilo created

We'll now show an error message if the user tries to add a directory
that contains no text files or when they try to add a single non-text
file.

Release Notes:

- N/A

---------

Co-authored-by: Danilo <danilo@zed.dev>

Change summary

crates/assistant2/src/context_picker/directory_context_picker.rs | 37 +
crates/assistant2/src/context_picker/file_context_picker.rs      | 39 +
2 files changed, 49 insertions(+), 27 deletions(-)

Detailed changes

crates/assistant2/src/context_picker/directory_context_picker.rs 🔗

@@ -231,27 +231,36 @@ impl PickerDelegate for DirectoryContextPickerDelegate {
                     .collect::<Vec<_>>()
             })?;
 
-            let open_all_buffers_tasks = cx.background_executor().spawn(async move {
-                let mut buffers = Vec::with_capacity(open_buffer_tasks.len());
-
-                for open_buffer_task in open_buffer_tasks {
-                    let buffer = open_buffer_task.await?;
-
-                    buffers.push(buffer);
-                }
-
-                anyhow::Ok(buffers)
-            });
-
-            let buffers = open_all_buffers_tasks.await?;
+            let buffers = futures::future::join_all(open_buffer_tasks).await;
 
             this.update(&mut cx, |this, cx| {
                 let mut text = String::new();
 
-                for buffer in buffers {
+                let mut ok_count = 0;
+
+                for buffer in buffers.into_iter().flatten() {
                     let buffer = buffer.read(cx);
                     let path = buffer.file().map_or(&path, |file| file.path());
                     push_fenced_codeblock(&path, buffer.text(), &mut text);
+                    ok_count += 1;
+                }
+
+                if ok_count == 0 {
+                    let Some(workspace) = workspace.upgrade() else {
+                        return anyhow::Ok(());
+                    };
+
+                    workspace.update(cx, |workspace, cx| {
+                        workspace.show_error(
+                            &anyhow::anyhow!(
+                                "Could not read any text files from {}",
+                                path.display()
+                            ),
+                            cx,
+                        );
+                    });
+
+                    return anyhow::Ok(());
                 }
 
                 this.delegate

crates/assistant2/src/context_picker/file_context_picker.rs 🔗

@@ -239,21 +239,34 @@ impl PickerDelegate for FileContextPickerDelegate {
                 return anyhow::Ok(());
             };
 
-            let buffer = open_buffer_task.await?;
-
-            this.update(&mut cx, |this, cx| {
-                this.delegate
-                    .context_store
-                    .update(cx, |context_store, cx| {
-                        context_store.insert_file(buffer.read(cx));
-                    })?;
-
-                match confirm_behavior {
-                    ConfirmBehavior::KeepOpen => {}
-                    ConfirmBehavior::Close => this.delegate.dismissed(cx),
+            let result = open_buffer_task.await;
+
+            this.update(&mut cx, |this, cx| match result {
+                Ok(buffer) => {
+                    this.delegate
+                        .context_store
+                        .update(cx, |context_store, cx| {
+                            context_store.insert_file(buffer.read(cx));
+                        })?;
+
+                    match confirm_behavior {
+                        ConfirmBehavior::KeepOpen => {}
+                        ConfirmBehavior::Close => this.delegate.dismissed(cx),
+                    }
+
+                    anyhow::Ok(())
                 }
+                Err(err) => {
+                    let Some(workspace) = workspace.upgrade() else {
+                        return anyhow::Ok(());
+                    };
 
-                anyhow::Ok(())
+                    workspace.update(cx, |workspace, cx| {
+                        workspace.show_error(&err, cx);
+                    });
+
+                    anyhow::Ok(())
+                }
             })??;
 
             anyhow::Ok(())