from __future__ import annotations import asyncio from functools import partial from pathlib import Path from typing import Any from app.agents.tools.types import RegisteredTool, ToolResult PROJECT_ROOT = Path(__file__).resolve().parents[5] def _validate_path(raw_path: str) -> Path: """경로를 검증하고 절대 경로로 변환합니다.""" resolved = (PROJECT_ROOT / raw_path).resolve() if not resolved.is_relative_to(PROJECT_ROOT): raise ValueError(f"프로젝트 외부 경로 접근 불가: {raw_path}") return resolved def _write_sync(path: Path, content: str) -> None: path.parent.mkdir(parents=True, exist_ok=True) path.write_text(content, encoding="utf-8") def create_write_file_tool() -> RegisteredTool: """파일 쓰기 도구를 생성합니다.""" async def execute(params: dict[str, Any]) -> ToolResult: raw_path: str = params["path"] content: str = params["content"] try: path = _validate_path(raw_path) except ValueError as e: return ToolResult(data=f"오류: {e}") loop = asyncio.get_running_loop() try: await loop.run_in_executor(None, partial(_write_sync, path, content)) except Exception as e: return ToolResult(data=f"파일 쓰기 실패: {e}") return ToolResult(data=f"파일 작성 완료: {raw_path}") return RegisteredTool( name="write_file", description="파일에 내용을 씁니다. 프로젝트 내 파일만 수정 가능합니다.", compact_description="파일 쓰기", concurrency_safe=False, execute=execute, )