Add Bash tool (#26597)
<img width="636" alt="Screenshot 2025-03-12 at 4 24 18 PM" src="https://github.com/user-attachments/assets/6f317031-f495-4a5a-8260-79a56b10d628" /> <img width="634" alt="Screenshot 2025-03-12 at 4 24 36 PM" src="https://github.com/user-attachments/assets/27283432-4f94-49f3-9d61-a0a9c737de40" /> Release Notes: - N/A
This commit is contained in:
parent
009b90291e
commit
9be7934f12
3 changed files with 74 additions and 0 deletions
|
@ -1,3 +1,4 @@
|
|||
mod bash_tool;
|
||||
mod delete_path_tool;
|
||||
mod edit_files_tool;
|
||||
mod list_directory_tool;
|
||||
|
@ -8,6 +9,7 @@ mod regex_search;
|
|||
use assistant_tool::ToolRegistry;
|
||||
use gpui::App;
|
||||
|
||||
use crate::bash_tool::BashTool;
|
||||
use crate::delete_path_tool::DeletePathTool;
|
||||
use crate::edit_files_tool::EditFilesTool;
|
||||
use crate::list_directory_tool::ListDirectoryTool;
|
||||
|
@ -25,4 +27,5 @@ pub fn init(cx: &mut App) {
|
|||
registry.register_tool(EditFilesTool);
|
||||
registry.register_tool(RegexSearchTool);
|
||||
registry.register_tool(DeletePathTool);
|
||||
registry.register_tool(BashTool);
|
||||
}
|
||||
|
|
70
crates/assistant_tools/src/bash_tool.rs
Normal file
70
crates/assistant_tools/src/bash_tool.rs
Normal file
|
@ -0,0 +1,70 @@
|
|||
use anyhow::{anyhow, Result};
|
||||
use assistant_tool::Tool;
|
||||
use gpui::{App, Entity, Task};
|
||||
use language_model::LanguageModelRequestMessage;
|
||||
use project::Project;
|
||||
use schemars::JsonSchema;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct BashToolInput {
|
||||
/// The bash command to execute as a one-liner.
|
||||
command: String,
|
||||
}
|
||||
|
||||
pub struct BashTool;
|
||||
|
||||
impl Tool for BashTool {
|
||||
fn name(&self) -> String {
|
||||
"bash".to_string()
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
include_str!("./bash_tool/description.md").to_string()
|
||||
}
|
||||
|
||||
fn input_schema(&self) -> serde_json::Value {
|
||||
let schema = schemars::schema_for!(BashToolInput);
|
||||
serde_json::to_value(&schema).unwrap()
|
||||
}
|
||||
|
||||
fn run(
|
||||
self: Arc<Self>,
|
||||
input: serde_json::Value,
|
||||
_messages: &[LanguageModelRequestMessage],
|
||||
_project: Entity<Project>,
|
||||
cx: &mut App,
|
||||
) -> Task<Result<String>> {
|
||||
let input: BashToolInput = match serde_json::from_value(input) {
|
||||
Ok(input) => input,
|
||||
Err(err) => return Task::ready(Err(anyhow!(err))),
|
||||
};
|
||||
|
||||
cx.spawn(|_| async move {
|
||||
// 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_string = String::from_utf8_lossy(&output.stdout).to_string();
|
||||
|
||||
if output.status.success() {
|
||||
Ok(output_string)
|
||||
} else {
|
||||
Ok(format!(
|
||||
"Command failed with exit code {}\n{}",
|
||||
output.status.code().unwrap_or(-1),
|
||||
&output_string
|
||||
))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
1
crates/assistant_tools/src/bash_tool/description.md
Normal file
1
crates/assistant_tools/src/bash_tool/description.md
Normal file
|
@ -0,0 +1 @@
|
|||
Executes a bash one-liner and returns the combined output. This tool spawns a bash process, combines stdout and stderr into one interleaved stream as they are produced (preserving the order of writes), and captures that stream into a string which is returned. Use this tool when you need to run shell commands to get information about the system or process files.
|
Loading…
Add table
Add a link
Reference in a new issue