mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
fix(file_tools): resolve relative paths against TERMINAL_CWD for worktree isolation
Adds a _resolve_path() helper that reads TERMINAL_CWD and uses it as the base for relative path resolution. Applied to _check_sensitive_path, read_file_tool, _update_read_timestamp, and _check_file_staleness. Absolute paths and non-worktree sessions (no TERMINAL_CWD) are unaffected — falls back to os.getcwd(). Fixes #12689.
This commit is contained in:
parent
b65f6ca7fe
commit
4c40ec96e6
1 changed files with 15 additions and 4 deletions
|
|
@ -71,6 +71,17 @@ _BLOCKED_DEVICE_PATHS = frozenset({
|
|||
})
|
||||
|
||||
|
||||
def _resolve_path(filepath: str) -> Path:
|
||||
"""Resolve a path relative to TERMINAL_CWD (the worktree base directory)
|
||||
instead of the main repository root.
|
||||
"""
|
||||
p = Path(filepath).expanduser()
|
||||
if not p.is_absolute():
|
||||
base = os.environ.get("TERMINAL_CWD", os.getcwd())
|
||||
p = Path(base) / p
|
||||
return p.resolve()
|
||||
|
||||
|
||||
def _is_blocked_device(filepath: str) -> bool:
|
||||
"""Return True if the path would hang the process (infinite output or blocking input).
|
||||
|
||||
|
|
@ -102,7 +113,7 @@ _SENSITIVE_EXACT_PATHS = {"/var/run/docker.sock", "/run/docker.sock"}
|
|||
def _check_sensitive_path(filepath: str) -> str | None:
|
||||
"""Return an error message if the path targets a sensitive system location."""
|
||||
try:
|
||||
resolved = os.path.realpath(os.path.expanduser(filepath))
|
||||
resolved = str(_resolve_path(filepath))
|
||||
except (OSError, ValueError):
|
||||
resolved = filepath
|
||||
normalized = os.path.normpath(os.path.expanduser(filepath))
|
||||
|
|
@ -347,7 +358,7 @@ def read_file_tool(path: str, offset: int = 1, limit: int = 500, task_id: str =
|
|||
),
|
||||
})
|
||||
|
||||
_resolved = Path(path).expanduser().resolve()
|
||||
_resolved = _resolve_path(path)
|
||||
|
||||
# ── Binary file guard ─────────────────────────────────────────
|
||||
# Block binary files by extension (no I/O).
|
||||
|
|
@ -555,7 +566,7 @@ def _update_read_timestamp(filepath: str, task_id: str) -> None:
|
|||
refreshes the stored timestamp to match the file's new state.
|
||||
"""
|
||||
try:
|
||||
resolved = str(Path(filepath).expanduser().resolve())
|
||||
resolved = str(_resolve_path(filepath))
|
||||
current_mtime = os.path.getmtime(resolved)
|
||||
except (OSError, ValueError):
|
||||
return
|
||||
|
|
@ -574,7 +585,7 @@ def _check_file_staleness(filepath: str, task_id: str) -> str | None:
|
|||
or was never read. Does not block — the write still proceeds.
|
||||
"""
|
||||
try:
|
||||
resolved = str(Path(filepath).expanduser().resolve())
|
||||
resolved = str(_resolve_path(filepath))
|
||||
except (OSError, ValueError):
|
||||
return None
|
||||
with _read_tracker_lock:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue