"""Scoped file-read tool for the project folder feature.""" from __future__ import annotations from langchain_core.tools import tool from app.core.ws_context import execute_on_client def _is_unsafe_path(rel: str) -> bool: if not rel: return True norm = rel.replace("\\", "/") if norm.startswith("/"): return True # Windows drive letter if len(rel) >= 2 and rel[1] == ":": return True parts = norm.split("/") return ".." in parts @tool async def read_project_folder_file(project_id: str, relative_path: str) -> str: """Read full content of a file inside the project's linked folder.""" if _is_unsafe_path(relative_path): return "Access denied" result = await execute_on_client( action="read_project_folder_file", data={"projectId": project_id, "relativePath": relative_path}, ) content = result.get("content", "") if not content: return f"File not found: {relative_path}" return content FOLDER_TOOLS = [read_project_folder_file]