sgr_agent_tools/
move_file.rs1use std::sync::Arc;
4
5use schemars::JsonSchema;
6use serde::Deserialize;
7use serde_json::Value;
8use sgr_agent_core::agent_tool::{Tool, ToolError, ToolOutput, parse_args};
9use sgr_agent_core::context::AgentContext;
10use sgr_agent_core::schema::json_schema_for;
11
12use crate::backend::FileBackend;
13use crate::helpers::backend_err;
14
15pub struct MoveTool<B: FileBackend>(pub Arc<B>);
16
17#[derive(Deserialize, JsonSchema)]
18struct MoveArgs {
19 from: String,
21 to: String,
23}
24
25#[async_trait::async_trait]
26impl<B: FileBackend> Tool for MoveTool<B> {
27 fn name(&self) -> &str {
28 "move_file"
29 }
30 fn description(&self) -> &str {
31 "Move or rename a file"
32 }
33 fn parameters_schema(&self) -> Value {
34 json_schema_for::<MoveArgs>()
35 }
36 async fn execute(&self, args: Value, _ctx: &mut AgentContext) -> Result<ToolOutput, ToolError> {
37 let a: MoveArgs = parse_args(&args)?;
38 self.0
39 .move_file(&a.from, &a.to)
40 .await
41 .map_err(backend_err)?;
42 Ok(ToolOutput::text(format!("Moved {} → {}", a.from, a.to)))
43 }
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49 use crate::mock_fs::MockFs;
50 use sgr_agent_core::agent_tool::Tool;
51
52 #[tokio::test]
53 async fn test_move_file() {
54 let fs = Arc::new(MockFs::new());
55 fs.add_file("old.txt", "data");
56 let tool = MoveTool(fs.clone());
57 let mut ctx = AgentContext::new();
58 let result = tool
59 .execute(
60 serde_json::json!({"from": "old.txt", "to": "new.txt"}),
61 &mut ctx,
62 )
63 .await
64 .unwrap();
65 assert!(result.content.contains("Moved old.txt"));
66 assert!(!fs.exists("old.txt"));
67 assert_eq!(fs.content("new.txt").unwrap(), "data");
68 }
69}