hugsbun's picture
first commit
ba52031
Raw
History Blame Contribute Delete
2.45 kB
"""
read_file tool β€” returns the current content of a file in the task workdir.
Allows the agent to inspect source files before deciding what to edit,
rather than guessing from test error messages alone.
"""
import logging
import os
from pydantic import ValidationError
from debug_env.server.schemas import ReadFileArgs, ToolResult
from debug_env.server.utils import validate_workdir_path
logger = logging.getLogger(__name__)
def read_file(workdir: str, path: str) -> ToolResult:
"""
Read *path* (relative to *workdir*) and return its content in ``logs``.
Pass rate is preserved from the last test run β€” reading a file does not
affect the score. The content is returned in ``logs`` so the agent can
inspect it in the same observation field it already reads.
Args:
workdir: Absolute path to the task working directory.
path: Filename to read, e.g. ``"broken_code.py"`` or ``"helper.py"``.
Returns:
:class:`ToolResult` with ``pass_rate=0.0`` and file content in ``logs``.
"""
try:
args = ReadFileArgs(path=path)
except ValidationError as e:
messages = [f"{' -> '.join(str(loc) for loc in err['loc'])}: {err['msg']}" for err in e.errors()]
msg = "Invalid read_file args β€” " + "; ".join(messages)
logger.warning(msg)
return ToolResult(pass_rate=0.0, logs=msg, success=False)
try:
full_path = validate_workdir_path(workdir, args.path)
except ValueError as e:
logger.warning(str(e))
return ToolResult(pass_rate=0.0, logs=str(e), success=False)
logger.info(f"Reading file: {full_path}")
if not os.path.exists(full_path):
available = [f for f in os.listdir(workdir) if f.endswith(".py") and not f.startswith("test_")]
msg = (
f"File '{args.path}' not found. "
f"Editable source files: {available}"
)
logger.warning(msg)
return ToolResult(pass_rate=0.0, logs=msg, success=False)
try:
with open(full_path) as f:
content = f.read()
logger.info(f"Read {len(content)} chars from '{args.path}'")
return ToolResult(
pass_rate=0.0,
logs=f"# {args.path}\n{content}",
success=True,
)
except OSError as e:
msg = f"Failed to read '{args.path}': {e}"
logger.error(msg)
return ToolResult(pass_rate=0.0, logs=msg, success=False)