Skip to main content

sgr_agent_tools/
move_file.rs

1//! MoveTool — move or rename a file.
2
3use 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    /// Source file path
20    from: String,
21    /// Destination file path
22    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}