[enhance] add edit and impl range for read.
This commit is contained in:
parent
bf4e66ca36
commit
a9b3a47f05
93
src/agent.rs
93
src/agent.rs
@ -16,6 +16,8 @@ pub enum ToolError {
|
|||||||
Io(#[from] std::io::Error),
|
Io(#[from] std::io::Error),
|
||||||
#[error("Command execution failed: {0}")]
|
#[error("Command execution failed: {0}")]
|
||||||
CommandFailed(String),
|
CommandFailed(String),
|
||||||
|
#[error("Invalid line range: {0}")]
|
||||||
|
InvalidLineRange(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create file tool
|
// Create file tool
|
||||||
@ -105,6 +107,10 @@ impl Tool for DeleteFileTool {
|
|||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct ReadFileArgs {
|
pub struct ReadFileArgs {
|
||||||
path: String,
|
path: String,
|
||||||
|
#[serde(default)]
|
||||||
|
start_line: Option<usize>,
|
||||||
|
#[serde(default)]
|
||||||
|
end_line: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
@ -119,13 +125,21 @@ impl Tool for ReadFileTool {
|
|||||||
async fn definition(&self, _prompt: String) -> ToolDefinition {
|
async fn definition(&self, _prompt: String) -> ToolDefinition {
|
||||||
ToolDefinition {
|
ToolDefinition {
|
||||||
name: Self::NAME.to_string(),
|
name: Self::NAME.to_string(),
|
||||||
description: "Read the content of a file".to_string(),
|
description: "Read the content of a file, optionally with line range".to_string(),
|
||||||
parameters: json!({
|
parameters: json!({
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Path of the file to read"
|
"description": "Path of the file to read"
|
||||||
|
},
|
||||||
|
"start_line": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Optional: Starting line number (1-based, inclusive)"
|
||||||
|
},
|
||||||
|
"end_line": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Optional: Ending line number (1-based, inclusive)"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": ["path"]
|
"required": ["path"]
|
||||||
@ -135,8 +149,81 @@ impl Tool for ReadFileTool {
|
|||||||
|
|
||||||
async fn call(&self, args: Self::Args) -> Result<Self::Output, Self::Error> {
|
async fn call(&self, args: Self::Args) -> Result<Self::Output, Self::Error> {
|
||||||
let content = fs::read_to_string(&args.path)?;
|
let content = fs::read_to_string(&args.path)?;
|
||||||
println!("file content:\n{}", content);
|
|
||||||
Ok(format!("file content:\n{}", content))
|
let result = match (args.start_line, args.end_line) {
|
||||||
|
(Some(start), Some(end)) if start > end || start == 0 => {
|
||||||
|
return Err(ToolError::InvalidLineRange(
|
||||||
|
format!("Invalid range: start={}, end={}", start, end)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
(Some(start), Some(end)) => {
|
||||||
|
content.lines()
|
||||||
|
.skip(start.saturating_sub(1))
|
||||||
|
.take(end - start + 1)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n")
|
||||||
|
}
|
||||||
|
(Some(start), None) => {
|
||||||
|
content.lines()
|
||||||
|
.skip(start.saturating_sub(1))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n")
|
||||||
|
}
|
||||||
|
(None, Some(end)) => {
|
||||||
|
content.lines()
|
||||||
|
.take(end)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n")
|
||||||
|
}
|
||||||
|
(None, None) => content,
|
||||||
|
};
|
||||||
|
|
||||||
|
println!("file content:\n{}", result);
|
||||||
|
Ok(format!("file content:\n{}", result))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Edit file tool
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct EditFileArgs {
|
||||||
|
path: String,
|
||||||
|
content: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct EditFileTool;
|
||||||
|
|
||||||
|
impl Tool for EditFileTool {
|
||||||
|
const NAME: &'static str = "edit_file";
|
||||||
|
type Error = ToolError;
|
||||||
|
type Args = EditFileArgs;
|
||||||
|
type Output = String;
|
||||||
|
|
||||||
|
async fn definition(&self, _prompt: String) -> ToolDefinition {
|
||||||
|
ToolDefinition {
|
||||||
|
name: Self::NAME.to_string(),
|
||||||
|
description: "Edit or overwrite an existing file with new content".to_string(),
|
||||||
|
parameters: json!({
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"path": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Path of the file to edit"
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "New content to write to the file"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["path", "content"]
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn call(&self, args: Self::Args) -> Result<Self::Output, Self::Error> {
|
||||||
|
fs::write(&args.path, &args.content)?;
|
||||||
|
println!("file edited: {}", args.path);
|
||||||
|
Ok(format!("file edited: {}", args.path))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -26,6 +26,7 @@ async fn main() {
|
|||||||
.tool(agent::CreateFileTool)
|
.tool(agent::CreateFileTool)
|
||||||
.tool(agent::DeleteFileTool)
|
.tool(agent::DeleteFileTool)
|
||||||
.tool(agent::ReadFileTool)
|
.tool(agent::ReadFileTool)
|
||||||
|
.tool(agent::EditFileTool)
|
||||||
.tool(agent::ExecuteCommandTool)
|
.tool(agent::ExecuteCommandTool)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user