Skip to main content

ararajuba_tools_coding/fs/
write.rs

1//! `write_file` tool — write content to a file, creating parent dirs.
2
3use ararajuba_core::tools::tool::{tool, ToolDef};
4use serde_json::json;
5use std::path::Path;
6
7/// Create the `write_file` tool.
8///
9/// Overwrites the target file. Creates parent directories if needed.
10/// For partial edits prefer `patch_file`.
11pub fn write_file_tool() -> ToolDef {
12    tool("write_file")
13        .description("Write content to a file. Creates parent directories if needed.")
14        .input_schema(json!({
15            "type": "object",
16            "properties": {
17                "path":    { "type": "string", "description": "File path to write" },
18                "content": { "type": "string", "description": "Content to write" }
19            },
20            "required": ["path", "content"]
21        }))
22        .execute(|input| async move {
23            let path = input["path"]
24                .as_str()
25                .ok_or_else(|| "missing required field: path".to_string())?;
26            let content = input["content"]
27                .as_str()
28                .ok_or_else(|| "missing required field: content".to_string())?;
29
30            // Create parent directories
31            if let Some(parent) = Path::new(path).parent() {
32                tokio::fs::create_dir_all(parent)
33                    .await
34                    .map_err(|e| format!("failed to create directories: {e}"))?;
35            }
36
37            let bytes = content.as_bytes().len();
38            tokio::fs::write(path, content)
39                .await
40                .map_err(|e| format!("failed to write file: {e}"))?;
41
42            Ok(json!({
43                "ok": true,
44                "bytes_written": bytes
45            }))
46        })
47        .build()
48}
49
50#[cfg(test)]
51mod tests {
52    use super::*;
53
54    #[test]
55    fn tool_metadata() {
56        let t = write_file_tool();
57        assert_eq!(t.name, "write_file");
58        assert!(t.description.is_some());
59        assert!(t.execute.is_some());
60    }
61}