Fix issues in EditFilesTool, ListDirectoryTool and BashTool (#26647)

Release Notes:

- N/A
This commit is contained in:
Antonio Scandurra 2025-03-13 10:41:27 +01:00 committed by GitHub
parent e842b4eade
commit 70c973f6c3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 110 additions and 41 deletions

View file

@ -1,4 +1,4 @@
use anyhow::{anyhow, Result};
use anyhow::{anyhow, Context as _, Result};
use assistant_tool::Tool;
use gpui::{App, Entity, Task};
use language_model::LanguageModelRequestMessage;
@ -6,11 +6,14 @@ use project::Project;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use util::command::new_smol_command;
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
pub struct BashToolInput {
/// The bash command to execute as a one-liner.
command: String,
/// Working directory for the command. This must be one of the root directories of the project.
working_directory: String,
}
pub struct BashTool;
@ -33,7 +36,7 @@ impl Tool for BashTool {
self: Arc<Self>,
input: serde_json::Value,
_messages: &[LanguageModelRequestMessage],
_project: Entity<Project>,
project: Entity<Project>,
cx: &mut App,
) -> Task<Result<String>> {
let input: BashToolInput = match serde_json::from_value(input) {
@ -41,23 +44,34 @@ impl Tool for BashTool {
Err(err) => return Task::ready(Err(anyhow!(err))),
};
let Some(worktree) = project
.read(cx)
.worktree_for_root_name(&input.working_directory, cx)
else {
return Task::ready(Err(anyhow!("Working directory not found in the project")));
};
let working_directory = worktree.read(cx).abs_path();
cx.spawn(|_| async move {
// Add 2>&1 to merge stderr into stdout for proper interleaving
// Add 2>&1 to merge stderr into stdout for proper interleaving.
let command = format!("{} 2>&1", input.command);
// Spawn a blocking task to execute the command
let output = futures::executor::block_on(async {
std::process::Command::new("bash")
.arg("-c")
.arg(&command)
.output()
.map_err(|err| anyhow!("Failed to execute bash command: {}", err))
})?;
let output = new_smol_command("bash")
.arg("-c")
.arg(&command)
.current_dir(working_directory)
.output()
.await
.context("Failed to execute bash command")?;
let output_string = String::from_utf8_lossy(&output.stdout).to_string();
if output.status.success() {
Ok(output_string)
if output_string.is_empty() {
Ok("Command executed successfully.".to_string())
} else {
Ok(output_string)
}
} else {
Ok(format!(
"Command failed with exit code {}\n{}",