mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-08 03:01:47 +00:00
fix(windows): terminal drain and cwd path conversion for native Windows
Two fixes for the local terminal backend on Windows (Git Bash): 1. `_drain()` in base.py: `select.select()` only works on sockets on Windows, not pipe file descriptors. On Windows, use blocking `os.read()` in the daemon thread instead. EOF arrives promptly when bash exits, so this is safe. 2. `_run_bash()` in local.py: When `self.cwd` is updated from `pwd` output, it contains Git Bash-style paths (`/c/Users/...`). `subprocess.Popen(cwd=...)` needs a native Windows path (`C:\Users\...`). Added a conversion before Popen. Without these fixes, all terminal() calls on Windows return empty output (exit code 126), and cwd tracking breaks. Tested on Windows 11 with Git for Windows + Python 3.13. Fixes #14638
This commit is contained in:
parent
7244a1f0d3
commit
c2d6b385f1
2 changed files with 28 additions and 1 deletions
|
|
@ -489,6 +489,26 @@ class BaseEnvironment(ABC):
|
||||||
|
|
||||||
def _drain():
|
def _drain():
|
||||||
fd = proc.stdout.fileno()
|
fd = proc.stdout.fileno()
|
||||||
|
# select.select does NOT work on pipe fds on Windows (only sockets).
|
||||||
|
# Use blocking os.read in a daemon thread instead — safe because
|
||||||
|
# EOF arrives promptly when bash exits.
|
||||||
|
if os.name == "nt":
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
chunk = os.read(fd, 4096)
|
||||||
|
if not chunk:
|
||||||
|
break
|
||||||
|
output_chunks.append(decoder.decode(chunk))
|
||||||
|
except (ValueError, OSError):
|
||||||
|
pass
|
||||||
|
finally:
|
||||||
|
try:
|
||||||
|
tail = decoder.decode(b"", final=True)
|
||||||
|
if tail:
|
||||||
|
output_chunks.append(tail)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return
|
||||||
idle_after_exit = 0
|
idle_after_exit = 0
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import signal
|
import signal
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
@ -403,6 +404,12 @@ class LocalEnvironment(BaseEnvironment):
|
||||||
)
|
)
|
||||||
self.cwd = safe_cwd
|
self.cwd = safe_cwd
|
||||||
|
|
||||||
|
# On Windows, self.cwd may be a Git Bash-style path (/c/Users/...)
|
||||||
|
# from pwd output. subprocess.Popen needs a native Windows path.
|
||||||
|
_popen_cwd = self.cwd
|
||||||
|
if _IS_WINDOWS and _popen_cwd and re.match(r'^/[a-zA-Z]/', _popen_cwd):
|
||||||
|
_popen_cwd = _popen_cwd[1].upper() + ':' + _popen_cwd[2:].replace('/', '\\')
|
||||||
|
|
||||||
proc = subprocess.Popen(
|
proc = subprocess.Popen(
|
||||||
args,
|
args,
|
||||||
text=True,
|
text=True,
|
||||||
|
|
@ -413,7 +420,7 @@ class LocalEnvironment(BaseEnvironment):
|
||||||
stderr=subprocess.STDOUT,
|
stderr=subprocess.STDOUT,
|
||||||
stdin=subprocess.PIPE if stdin_data is not None else subprocess.DEVNULL,
|
stdin=subprocess.PIPE if stdin_data is not None else subprocess.DEVNULL,
|
||||||
preexec_fn=None if _IS_WINDOWS else os.setsid,
|
preexec_fn=None if _IS_WINDOWS else os.setsid,
|
||||||
cwd=self.cwd,
|
cwd=_popen_cwd,
|
||||||
)
|
)
|
||||||
if not _IS_WINDOWS:
|
if not _IS_WINDOWS:
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue