38 lines
1.0 KiB
Python
38 lines
1.0 KiB
Python
"""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]
|