mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-08 13:12:08 +00:00
refactor(ssh): extract shared _is_ssh_remote_tilde_cwd predicate
Follow-up to the salvaged SSH-tilde-cwd fix. The predicate "backend == ssh and (cwd == ~ or cwd.startswith(~/))" was inlined at each expanduser guard site, which is how the test simulator drifted from production (it grew an SSH guard on a top-level-alias branch that has no production counterpart). - Add tools/terminal_tool._is_ssh_remote_tilde_cwd(backend, cwd) as the single source of truth (case/whitespace-tolerant). - Use it in _get_env_config and the gateway config bridge. - Test simulator imports the real helper instead of re-implementing the predicate; revert the phantom SSH guard on the top-level-alias branch (production maps top-level cwd: to a plain env var, not TERMINAL_CWD via an SSH-guarded path — that branch tested nothing real).
This commit is contained in:
parent
83fb8ec277
commit
4651ac64a1
3 changed files with 26 additions and 21 deletions
|
|
@ -1481,13 +1481,11 @@ if _config_path.exists():
|
|||
# never receives a literal "~/" which the kernel rejects.
|
||||
# SSH cwd is interpreted by the remote shell, so preserve
|
||||
# "~" / "~/..." for the SSH backend instead of expanding it
|
||||
# to the Hermes host/container HOME (often /opt/data).
|
||||
# to the Hermes host/container HOME (often /opt/data). Shared
|
||||
# predicate with terminal_tool so the two sites can't drift.
|
||||
if _cfg_key == "cwd" and isinstance(_val, str):
|
||||
_raw_cwd = _val.strip()
|
||||
if not (
|
||||
_terminal_backend == "ssh"
|
||||
and (_raw_cwd == "~" or _raw_cwd.startswith("~/"))
|
||||
):
|
||||
from tools.terminal_tool import _is_ssh_remote_tilde_cwd
|
||||
if not _is_ssh_remote_tilde_cwd(_terminal_backend, _val.strip()):
|
||||
_val = os.path.expanduser(_val)
|
||||
if isinstance(_val, (list, dict)):
|
||||
os.environ[_env_var] = json.dumps(_val)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@ asserting the expected env var outcomes.
|
|||
import os
|
||||
import json
|
||||
|
||||
from tools.terminal_tool import _is_ssh_remote_tilde_cwd
|
||||
|
||||
|
||||
def _simulate_config_bridge(cfg: dict, initial_env: dict | None = None):
|
||||
"""Simulate the gateway config bridge logic from gateway/run.py.
|
||||
|
|
@ -51,12 +53,9 @@ def _simulate_config_bridge(cfg: dict, initial_env: dict | None = None):
|
|||
# Expand shell tilde for local/container backends so subprocess.Popen
|
||||
# never receives a literal "~/" which the kernel rejects. SSH cwd is
|
||||
# interpreted by the remote shell, so preserve "~" / "~/..." there.
|
||||
# Uses the same production predicate as gateway/run.py.
|
||||
if cfg_key == "cwd" and isinstance(val, str):
|
||||
raw_cwd = val.strip()
|
||||
if not (
|
||||
terminal_backend == "ssh"
|
||||
and (raw_cwd == "~" or raw_cwd.startswith("~/"))
|
||||
):
|
||||
if not _is_ssh_remote_tilde_cwd(terminal_backend, val.strip()):
|
||||
val = os.path.expanduser(val)
|
||||
if isinstance(val, list):
|
||||
env[env_var] = json.dumps(val)
|
||||
|
|
@ -73,15 +72,7 @@ def _simulate_config_bridge(cfg: dict, initial_env: dict | None = None):
|
|||
alias_val = cfg.get(alias_key)
|
||||
if isinstance(alias_val, str) and alias_val.strip():
|
||||
if alias_key == "cwd":
|
||||
alias_backend = str(
|
||||
cfg.get("backend") or env.get("TERMINAL_ENV") or ""
|
||||
).strip().lower()
|
||||
raw_cwd = alias_val.strip()
|
||||
if not (
|
||||
alias_backend == "ssh"
|
||||
and (raw_cwd == "~" or raw_cwd.startswith("~/"))
|
||||
):
|
||||
alias_val = os.path.expanduser(alias_val)
|
||||
alias_val = os.path.expanduser(alias_val)
|
||||
env[alias_env] = alias_val.strip()
|
||||
|
||||
# --- Replicate lines 144-147: MESSAGING_CWD fallback ---
|
||||
|
|
|
|||
|
|
@ -1216,6 +1216,22 @@ _HOST_CWD_PREFIXES = ("/Users/", "/home/", "C:\\", "C:/")
|
|||
_CONTAINER_BACKENDS = frozenset({"docker", "singularity", "modal", "daytona"})
|
||||
|
||||
|
||||
def _is_ssh_remote_tilde_cwd(backend: str, cwd: str) -> bool:
|
||||
"""Return True when *cwd* is a tilde path that the remote SSH shell must
|
||||
expand itself, so the Hermes host/container must NOT ``expanduser`` it.
|
||||
|
||||
SSH ``cwd`` is interpreted by the *remote* shell (``cd ~`` / ``cd ~/x``
|
||||
over ``ssh ... bash -c``). Expanding ``~`` locally would rewrite it to the
|
||||
Hermes host HOME (often ``/opt/data`` under Docker) and inject a
|
||||
nonexistent path into the remote session. Only ``~`` / ``~/...`` on the
|
||||
``ssh`` backend qualify; absolute remote paths still pass through
|
||||
unchanged, and every other backend keeps expanding locally.
|
||||
"""
|
||||
if (backend or "").strip().lower() != "ssh":
|
||||
return False
|
||||
return cwd == "~" or cwd.startswith("~/")
|
||||
|
||||
|
||||
def _is_unusable_container_cwd(cwd: str) -> bool:
|
||||
"""Return True if *cwd* is a host/relative path that won't work as the
|
||||
working directory inside a container sandbox.
|
||||
|
|
@ -1286,7 +1302,7 @@ def _get_env_config() -> Dict[str, Any]:
|
|||
# /workspace and track the original host path separately. Otherwise keep the
|
||||
# normal sandbox behavior and discard host paths.
|
||||
cwd = os.getenv("TERMINAL_CWD", default_cwd)
|
||||
if cwd and not (env_type == "ssh" and (cwd == "~" or cwd.startswith("~/"))):
|
||||
if cwd and not _is_ssh_remote_tilde_cwd(env_type, cwd):
|
||||
cwd = os.path.expanduser(cwd)
|
||||
host_cwd = None
|
||||
if env_type == "docker" and mount_docker_cwd:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue