Add copy-path tool (#27371)
<img width="631" alt="Screenshot 2025-03-24 at 11 01 10 AM" src="https://github.com/user-attachments/assets/7e144619-83d0-4455-8d80-cc7ec6a7b03e" /> Release Notes: - N/A
This commit is contained in:
parent
3205ae3884
commit
e9e6529df4
3 changed files with 123 additions and 0 deletions
|
@ -1,4 +1,5 @@
|
|||
mod bash_tool;
|
||||
mod copy_path_tool;
|
||||
mod delete_path_tool;
|
||||
mod diagnostics_tool;
|
||||
mod edit_files_tool;
|
||||
|
@ -14,6 +15,7 @@ mod thinking_tool;
|
|||
use std::sync::Arc;
|
||||
|
||||
use assistant_tool::ToolRegistry;
|
||||
use copy_path_tool::CopyPathTool;
|
||||
use gpui::App;
|
||||
use http_client::HttpClientWithUrl;
|
||||
use move_path_tool::MovePathTool;
|
||||
|
@ -36,6 +38,7 @@ pub fn init(http_client: Arc<HttpClientWithUrl>, cx: &mut App) {
|
|||
|
||||
let registry = ToolRegistry::global(cx);
|
||||
registry.register_tool(BashTool);
|
||||
registry.register_tool(CopyPathTool);
|
||||
registry.register_tool(DeletePathTool);
|
||||
registry.register_tool(MovePathTool);
|
||||
registry.register_tool(DiagnosticsTool);
|
||||
|
|
114
crates/assistant_tools/src/copy_path_tool.rs
Normal file
114
crates/assistant_tools/src/copy_path_tool.rs
Normal file
|
@ -0,0 +1,114 @@
|
|||
use anyhow::{anyhow, Result};
|
||||
use assistant_tool::{ActionLog, Tool};
|
||||
use gpui::{App, AppContext, 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 CopyPathToolInput {
|
||||
/// The source path of the file or directory to copy.
|
||||
/// If a directory is specified, its contents will be copied recursively (like `cp -r`).
|
||||
///
|
||||
/// <example>
|
||||
/// If the project has the following files:
|
||||
///
|
||||
/// - directory1/a/something.txt
|
||||
/// - directory2/a/things.txt
|
||||
/// - directory3/a/other.txt
|
||||
///
|
||||
/// You can copy the first file by providing a source_path of "directory1/a/something.txt"
|
||||
/// </example>
|
||||
pub source_path: String,
|
||||
|
||||
/// The destination path where the file or directory should be copied to.
|
||||
///
|
||||
/// <example>
|
||||
/// To copy "directory1/a/something.txt" to "directory2/b/copy.txt",
|
||||
/// provide a destination_path of "directory2/b/copy.txt"
|
||||
/// </example>
|
||||
pub destination_path: String,
|
||||
}
|
||||
|
||||
pub struct CopyPathTool;
|
||||
|
||||
impl Tool for CopyPathTool {
|
||||
fn name(&self) -> String {
|
||||
"copy-path".into()
|
||||
}
|
||||
|
||||
fn needs_confirmation(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn description(&self) -> String {
|
||||
include_str!("./copy_path_tool/description.md").into()
|
||||
}
|
||||
|
||||
fn input_schema(&self) -> serde_json::Value {
|
||||
let schema = schemars::schema_for!(CopyPathToolInput);
|
||||
serde_json::to_value(&schema).unwrap()
|
||||
}
|
||||
|
||||
fn ui_text(&self, input: &serde_json::Value) -> String {
|
||||
match serde_json::from_value::<CopyPathToolInput>(input.clone()) {
|
||||
Ok(input) => {
|
||||
let src = input.source_path.as_str();
|
||||
let dest = input.destination_path.as_str();
|
||||
format!("Copy `{src}` to `{dest}`")
|
||||
}
|
||||
Err(_) => "Copy path".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn run(
|
||||
self: Arc<Self>,
|
||||
input: serde_json::Value,
|
||||
_messages: &[LanguageModelRequestMessage],
|
||||
project: Entity<Project>,
|
||||
_action_log: Entity<ActionLog>,
|
||||
cx: &mut App,
|
||||
) -> Task<Result<String>> {
|
||||
let input = match serde_json::from_value::<CopyPathToolInput>(input) {
|
||||
Ok(input) => input,
|
||||
Err(err) => return Task::ready(Err(anyhow!(err))),
|
||||
};
|
||||
let copy_task = project.update(cx, |project, cx| {
|
||||
match project
|
||||
.find_project_path(&input.source_path, cx)
|
||||
.and_then(|project_path| project.entry_for_path(&project_path, cx))
|
||||
{
|
||||
Some(entity) => match project.find_project_path(&input.destination_path, cx) {
|
||||
Some(project_path) => {
|
||||
project.copy_entry(entity.id, None, project_path.path, cx)
|
||||
}
|
||||
None => Task::ready(Err(anyhow!(
|
||||
"Destination path {} was outside the project.",
|
||||
input.destination_path
|
||||
))),
|
||||
},
|
||||
None => Task::ready(Err(anyhow!(
|
||||
"Source path {} was not found in the project.",
|
||||
input.source_path
|
||||
))),
|
||||
}
|
||||
});
|
||||
|
||||
cx.background_spawn(async move {
|
||||
match copy_task.await {
|
||||
Ok(_) => Ok(format!(
|
||||
"Copied {} to {}",
|
||||
input.source_path, input.destination_path
|
||||
)),
|
||||
Err(err) => Err(anyhow!(
|
||||
"Failed to copy {} to {}: {}",
|
||||
input.source_path,
|
||||
input.destination_path,
|
||||
err
|
||||
)),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
6
crates/assistant_tools/src/copy_path_tool/description.md
Normal file
6
crates/assistant_tools/src/copy_path_tool/description.md
Normal file
|
@ -0,0 +1,6 @@
|
|||
Copies a file or directory in the project, and returns confirmation that the copy succeeded.
|
||||
Directory contents will be copied recursively (like `cp -r`).
|
||||
|
||||
This tool should be used when it's desirable to create a copy of a file or directory without modifying the original.
|
||||
It's much more efficient than doing this by separately reading and then writing the file or directory's contents,
|
||||
so this tool should be preferred over that approach whenever copying is the goal.
|
Loading…
Add table
Add a link
Reference in a new issue