mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-09 08:21:50 +00:00
fix(cli): use Rich [dim] tag instead of ANSI escape in _restore_session_cwd
Replace [{_DIM}] with [dim] in all _restore_session_cwd and
_preload_resumed_session messages that go through _console_print (Rich
Console.print). _DIM is an ANSI escape (\x1b[2;3m) that Rich cannot
parse as a markup tag, causing MarkupError on session resume when the
stored cwd is missing or inaccessible.
Also uses [/dim] closing tag for explicit tag matching.
Fixes #39469
This commit is contained in:
parent
ff5652d0f6
commit
391b594752
2 changed files with 71 additions and 5 deletions
10
cli.py
10
cli.py
|
|
@ -5097,9 +5097,9 @@ class HermesCLI:
|
|||
resolved_id = self.session_id
|
||||
if resolved_id and resolved_id != self.session_id:
|
||||
ChatConsole().print(
|
||||
f"[{_DIM}]Session {_escape(self.session_id)} was compressed into "
|
||||
f"[dim]Session {_escape(self.session_id)} was compressed into "
|
||||
f"{_escape(resolved_id)}; resuming the descendant with your "
|
||||
f"transcript.[/]"
|
||||
f"transcript.[/dim]"
|
||||
)
|
||||
self.session_id = resolved_id
|
||||
resolved_meta = self._session_db.get_session(self.session_id)
|
||||
|
|
@ -5378,7 +5378,7 @@ class HermesCLI:
|
|||
if quiet:
|
||||
print(msg, file=sys.stderr)
|
||||
else:
|
||||
self._console_print(f"[{_DIM}]{_escape(msg)}[/]")
|
||||
self._console_print(f"[dim]{_escape(msg)}[/dim]")
|
||||
return
|
||||
|
||||
try:
|
||||
|
|
@ -5388,7 +5388,7 @@ class HermesCLI:
|
|||
if quiet:
|
||||
print(msg, file=sys.stderr)
|
||||
else:
|
||||
self._console_print(f"[{_DIM}]{_escape(msg)}[/]")
|
||||
self._console_print(f"[dim]{_escape(msg)}[/dim]")
|
||||
return
|
||||
|
||||
# Retarget the terminal/code-exec tools to match the process cwd.
|
||||
|
|
@ -5398,7 +5398,7 @@ class HermesCLI:
|
|||
if quiet:
|
||||
print(msg, file=sys.stderr)
|
||||
else:
|
||||
self._console_print(f"[{_DIM}]{_escape(msg)}[/]")
|
||||
self._console_print(f"[dim]{_escape(msg)}[/dim]")
|
||||
|
||||
def _preload_resumed_session(self) -> bool:
|
||||
"""Load a resumed session's history from the DB early (before first chat).
|
||||
|
|
|
|||
|
|
@ -221,3 +221,69 @@ class TestPendingResumeNumberedSelection:
|
|||
|
||||
# A non-resume command disarms the one-shot prompt (#34584).
|
||||
assert cli_obj._pending_resume_sessions is None
|
||||
|
||||
|
||||
class TestRestoreSessionCwdMarkup:
|
||||
"""Regression: _restore_session_cwd must not crash with Rich MarkupError.
|
||||
|
||||
Lines that used ``[{_DIM}]`` inside Rich markup triggered
|
||||
``rich.errors.MarkupError: closing tag [/] at position N has nothing to
|
||||
close`` because ``_DIM`` is an ANSI escape (``\\x1b[2;3m``), not a valid
|
||||
Rich tag. The fix replaces ``[{_DIM}]`` with Rich's native ``[dim]`` tag.
|
||||
See: https://github.com/NousResearch/hermes-agent/issues/39469
|
||||
"""
|
||||
|
||||
def test_missing_dir_does_not_raise_markup_error(self):
|
||||
"""Session cwd gone → dim warning, no MarkupError."""
|
||||
cli_obj = _make_cli()
|
||||
console = MagicMock()
|
||||
cli_obj._output_console = MagicMock(return_value=console)
|
||||
|
||||
# Use a path that definitely does not exist.
|
||||
cli_obj._restore_session_cwd({"cwd": "/nonexistent/path/to/nowhere"})
|
||||
|
||||
# Should have printed a warning via console.print, not crashed.
|
||||
assert console.print.called
|
||||
printed = str(console.print.call_args)
|
||||
assert "Working directory is gone" in printed or "gone" in printed.lower()
|
||||
|
||||
def test_chdir_failure_does_not_raise_markup_error(self, tmp_path):
|
||||
"""os.chdir fails → dim warning, no MarkupError."""
|
||||
import os
|
||||
cli_obj = _make_cli()
|
||||
console = MagicMock()
|
||||
cli_obj._output_console = MagicMock(return_value=console)
|
||||
|
||||
# Create a directory, then make it unreadable (simulate chdir failure).
|
||||
target = tmp_path / "locked"
|
||||
target.mkdir()
|
||||
|
||||
# Patch os.chdir to raise OSError for our target path.
|
||||
original_chdir = os.chdir
|
||||
def fake_chdir(path):
|
||||
if str(path) == str(target):
|
||||
raise OSError("Permission denied")
|
||||
return original_chdir(path)
|
||||
|
||||
with patch("os.chdir", side_effect=fake_chdir):
|
||||
cli_obj._restore_session_cwd({"cwd": str(target)})
|
||||
|
||||
assert console.print.called
|
||||
printed = str(console.print.call_args)
|
||||
assert "Could not enter" in printed or "permission" in printed.lower()
|
||||
|
||||
def test_success_path_does_not_raise_markup_error(self, tmp_path):
|
||||
"""Successful cwd switch → dim info, no MarkupError."""
|
||||
import os
|
||||
cli_obj = _make_cli()
|
||||
console = MagicMock()
|
||||
cli_obj._output_console = MagicMock(return_value=console)
|
||||
|
||||
original_cwd = os.getcwd()
|
||||
try:
|
||||
cli_obj._restore_session_cwd({"cwd": str(tmp_path)})
|
||||
assert console.print.called
|
||||
printed = str(console.print.call_args)
|
||||
assert "Working directory" in printed or "working" in printed.lower()
|
||||
finally:
|
||||
os.chdir(original_cwd)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue