mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-21 16:18:55 +00:00
fix(cli): restore session cwd on mid-chat /resume and /sessions
This commit is contained in:
parent
f099b469de
commit
228d8de19c
1 changed files with 73 additions and 0 deletions
|
|
@ -1,3 +1,4 @@
|
|||
import os
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
|
|
@ -153,6 +154,78 @@ class TestCliResumeCommand:
|
|||
assert "<half" in printed
|
||||
|
||||
|
||||
class TestCliResumeRestoresCwd:
|
||||
"""Mid-chat /resume must retarget the working directory to where the
|
||||
session was started — the same contract as a startup ``hermes -c`` /
|
||||
``--resume``.
|
||||
|
||||
Regression coverage for #38562: ``_restore_session_cwd()`` was wired into
|
||||
the startup resume paths but not into ``_handle_resume_command()``, so an
|
||||
interactive ``/resume`` (and ``/sessions <id>``, which delegates here) left
|
||||
the process + ``TERMINAL_CWD`` pointing at whatever directory the user had
|
||||
cd'd into — so the terminal/code-exec tools and relative paths ran in the
|
||||
wrong repo.
|
||||
"""
|
||||
|
||||
def _resumable_cli(self, session_meta):
|
||||
cli_obj = _make_cli()
|
||||
cli_obj._session_db.get_session.return_value = session_meta
|
||||
cli_obj._session_db.get_messages_as_conversation.return_value = [
|
||||
{"role": "user", "content": "hello"},
|
||||
]
|
||||
cli_obj._session_db.resolve_resume_session_id.return_value = session_meta["id"]
|
||||
return cli_obj
|
||||
|
||||
def test_handle_resume_restores_recorded_cwd(self, tmp_path):
|
||||
recorded = str(tmp_path)
|
||||
cli_obj = self._resumable_cli({"id": "sess_dir", "title": "Dir", "cwd": recorded})
|
||||
|
||||
with (
|
||||
patch("hermes_cli.main._resolve_session_by_name_or_id", return_value="sess_dir"),
|
||||
patch("cli._cprint"),
|
||||
patch.object(cli_obj, "_console_print"),
|
||||
patch("os.chdir") as mock_chdir,
|
||||
patch.dict(os.environ, {}, clear=False),
|
||||
):
|
||||
cli_obj._handle_resume_command("/resume Dir")
|
||||
# Assert inside the patch.dict scope — it restores os.environ on exit.
|
||||
assert os.environ.get("TERMINAL_CWD") == recorded
|
||||
|
||||
mock_chdir.assert_called_once_with(recorded)
|
||||
|
||||
def test_handle_resume_without_recorded_cwd_does_not_chdir(self):
|
||||
# Gateway/remote/older sessions record no cwd — restore must no-op.
|
||||
cli_obj = self._resumable_cli({"id": "sess_dir", "title": "Dir"})
|
||||
|
||||
with (
|
||||
patch("hermes_cli.main._resolve_session_by_name_or_id", return_value="sess_dir"),
|
||||
patch("cli._cprint"),
|
||||
patch.object(cli_obj, "_console_print"),
|
||||
patch("os.chdir") as mock_chdir,
|
||||
):
|
||||
cli_obj._handle_resume_command("/resume Dir")
|
||||
|
||||
mock_chdir.assert_not_called()
|
||||
|
||||
def test_sessions_command_restores_recorded_cwd(self, tmp_path):
|
||||
# /sessions <id> delegates to the resume flow, so it restores cwd too.
|
||||
recorded = str(tmp_path)
|
||||
cli_obj = self._resumable_cli({"id": "sess_dir", "title": "Dir", "cwd": recorded})
|
||||
|
||||
with (
|
||||
patch("hermes_cli.main._resolve_session_by_name_or_id", return_value="sess_dir"),
|
||||
patch("cli._cprint"),
|
||||
patch.object(cli_obj, "_console_print"),
|
||||
patch("os.chdir") as mock_chdir,
|
||||
patch.dict(os.environ, {}, clear=False),
|
||||
):
|
||||
cli_obj._handle_sessions_command("/sessions Dir")
|
||||
# Assert inside the patch.dict scope — it restores os.environ on exit.
|
||||
assert os.environ.get("TERMINAL_CWD") == recorded
|
||||
|
||||
mock_chdir.assert_called_once_with(recorded)
|
||||
|
||||
|
||||
class TestPendingResumeNumberedSelection:
|
||||
"""Bare `/resume` arms a one-shot prompt so the next bare number resumes.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue