Source code for folderbot.tools.write_file

"""Write file tool."""

from enum import Enum

from pydantic import BaseModel, Field

from ..bot import BotContext
from .base import ToolResult
from .registry import folder_bot, get_services


[docs] class WriteMode(str, Enum): """Write mode for file operations.""" overwrite = "overwrite" append = "append"
[docs] class WriteFileRequest(BaseModel, frozen=True): """Request for writing a file.""" path: str = Field( description="File path relative to the root folder (e.g., 'notes/todo.md')" ) content: str = Field(description="Content to write to the file") mode: WriteMode = Field( default=WriteMode.overwrite, description="Write mode: 'overwrite' replaces file content, 'append' adds to end.", )
[docs] @folder_bot.tool( name="write_file", request_type=WriteFileRequest, response_type=ToolResult, ) async def write_file( request: WriteFileRequest, _context: BotContext | None = None ) -> ToolResult: """Create or update a file in the folder. The file path must satisfy the configured include rules. Use this to help the user manage their notes, todos, and documentation. """ services = get_services(_context) if services is None: return ToolResult(content="Services not available", is_error=True) file_path = services.validate_path(request.path) if file_path is None: return ToolResult(content="Invalid path: access denied", is_error=True) rel_path = str(file_path.relative_to(services.root)) if not services.is_file_allowed(rel_path): return ToolResult( content=f"Cannot write to '{request.path}': does not match allowed file patterns", is_error=True, ) if request.mode == WriteMode.append and not services.is_append_allowed(rel_path): return ToolResult( content=f"Cannot append to '{request.path}': not in append_allowed patterns", is_error=True, ) try: file_path.parent.mkdir(parents=True, exist_ok=True) file_existed = file_path.exists() content = request.content if request.mode == WriteMode.append and file_existed: existing = file_path.read_text(encoding="utf-8", errors="replace") content = existing + content file_path.write_text(content, encoding="utf-8") if request.mode == WriteMode.append: action = "Appended to" if file_existed else "Created" else: action = "Updated" if file_existed else "Created" return ToolResult(content=f"{action} {rel_path}") except Exception as e: return ToolResult(content=f"Error writing file: {e}", is_error=True)