Ryanhub - file viewer
filename: chat/tools.py
branch: main
back to repo
import os
import subprocess
import json
from typing import Any
from sandbox import safe_path

_agent_cfg_path = os.path.join(os.path.dirname(__file__), "agent", "config.json")
WORKSPACE = None
if os.path.exists(_agent_cfg_path):
    try:
        with open(_agent_cfg_path, "r", encoding="utf-8") as _f:
            _agent_cfg = json.load(_f)
            WORKSPACE = _agent_cfg.get("WORKSPACE")
    except Exception:
        WORKSPACE = None

_agent_tools_path = os.path.join(os.path.dirname(__file__), "agent", "tools.json")
TOOLS_META = None
if os.path.exists(_agent_tools_path):
    try:
        with open(_agent_tools_path, "r", encoding="utf-8") as _f:
            TOOLS_META = json.load(_f)
    except Exception:
        TOOLS_META = None

def get_tools_meta():
    return TOOLS_META


def list_files(path: str = "", **kwargs) -> str:
    """List files under `path` inside the workspace. If `path` is empty, list whole workspace."""
    try:
        if path:
            base = safe_path(path)
        else:
            base = os.path.abspath(WORKSPACE)

        files = []
        for root, _, filenames in os.walk(base):
            for f in filenames:
                rel = os.path.relpath(os.path.join(root, f), os.path.abspath(WORKSPACE))
                files.append(rel)
        return "\n".join(files) or "(empty)"
    except Exception as e:
        return f"[error listing files] {e}"


def read_file(path: str, **kwargs) -> str:
    try:
        p = safe_path(path)
        with open(p, "r", encoding="utf-8") as f:
            data = f.read()
            if not data:
                return "file is empty"
            return data
    except Exception as e:
        return f"[error reading file] {e}"


def write_file(path: str, content: str, **kwargs) -> str:
    try:
        p = safe_path(path)
        os.makedirs(os.path.dirname(p), exist_ok=True)
        with open(p, "w", encoding="utf-8") as f:
            f.write(content)
        return f"Wrote {p}"
    except Exception as e:
        return f"[error writing file] {e}"


def run_command(command: str, timeout: int = 30, **kwargs) -> str:
    try:
        completed = subprocess.run(
            command,
            shell=True,
            cwd=os.path.abspath(WORKSPACE),
            capture_output=True,
            text=True,
            timeout=int(timeout),
            stdin=subprocess.DEVNULL,
        )
        out = completed.stdout or ""
        err = completed.stderr or ""
        if completed.returncode != 0:
            return f"[exit {completed.returncode}]\n{out}{err}"
        return out + err
    except Exception as e:
        return f"[error running command] {e}"


def research(query: str, **kwargs) -> str:
    return f"research not implemented: {query}"


TOOLS = {
    "list_files": list_files,
    "read_file": read_file,
    "write_file": write_file,
    "run_command": run_command,
    "research": research,
}