ReMe/reme_ai/retrieve/working/write_file_op.py

89 lines
3 KiB
Python

"""Write file operation module.
This module provides a tool operation for writing content to files.
It supports creating new files or overwriting existing files, and automatically
creates parent directories if they don't exist.
"""
from pathlib import Path
from flowllm.core.context import C
from flowllm.core.op import BaseAsyncToolOp
from flowllm.core.schema import ToolCall
@C.register_op()
class WriteFileOp(BaseAsyncToolOp):
"""Write file operation.
This operation writes content to a specified file. If the file doesn't exist,
it will be created. If parent directories don't exist, they will be created automatically.
"""
file_path = __file__
def __init__(self, **kwargs):
kwargs.setdefault("raise_exception", False)
super().__init__(**kwargs)
def build_tool_call(self) -> ToolCall:
"""Build and return the tool call schema for this operator."""
tool_params = {
"name": "WriteFile",
"description": self.get_prompt("tool_desc"),
"input_schema": {
"file_path": {
"type": "string",
"description": self.get_prompt("file_path"),
"required": True,
},
"content": {
"type": "string",
"description": self.get_prompt("content"),
"required": True,
},
},
}
return ToolCall(**tool_params)
async def async_execute(self):
"""Execute the write file operation."""
file_path: str = self.input_dict.get("file_path", "").strip()
content: str = self.input_dict.get("content", "")
# Validate file_path
if not file_path:
raise ValueError("The 'file_path' parameter cannot be empty.")
# Resolve file path
file_path_obj = Path(file_path).expanduser().resolve()
# Check if path is a directory
if file_path_obj.exists() and file_path_obj.is_dir():
raise ValueError(f"Path is a directory, not a file: {file_path_obj}")
# Create parent directories if they don't exist
file_path_obj.parent.mkdir(parents=True, exist_ok=True)
# Check if file exists
file_exists = file_path_obj.exists() and file_path_obj.is_file()
# Write content to file
file_path_obj.write_text(content, encoding="utf-8")
# Format success message
if file_exists:
result = f"Successfully overwrote file: {file_path_obj}"
else:
result = f"Successfully created and wrote to new file: {file_path_obj}"
self.set_output(result)
async def async_default_execute(self, e: Exception = None, **_kwargs):
"""Fill outputs with a default failure message when execution fails."""
file_path: str = self.input_dict.get("file_path", "").strip()
error_msg = f'Failed to write file "{file_path}"'
if e:
error_msg += f": {str(e)}"
self.set_output(error_msg)