test(cli,gateway): cover bracket-stripping and gateway session-ID lookup

- CLI: bracketed/quoted target resolves; mismatched single bracket passes through unchanged.
- Gateway: bracketed session ID resolves; bare untitled session ID resolves via get_session() fallback.
This commit is contained in:
Teknium 2026-05-25 00:44:24 -07:00
parent 1c7a783c42
commit 4fbdf0e893
2 changed files with 98 additions and 0 deletions

View file

@ -75,3 +75,44 @@ class TestCliResumeCommand:
assert "out of range" in printed.lower()
assert "/resume" in printed
assert cli_obj.session_id == "current_session"
def test_handle_resume_strips_outer_brackets(self):
"""Users copy `<session_id>` from the usage hint literally.
Strip outer ``<>``, ``[]``, ``""``, and ``''`` before lookup so
``/resume <abc123>`` works the same as ``/resume abc123``.
"""
cli_obj = _make_cli()
cli_obj._session_db.get_session.return_value = {"id": "sess_alpha", "title": "Alpha"}
cli_obj._session_db.get_messages_as_conversation.return_value = []
cli_obj._session_db.resolve_resume_session_id.return_value = "sess_alpha"
for raw in ("<sess_alpha>", "[sess_alpha]", '"sess_alpha"', "'sess_alpha'"):
cli_obj.session_id = "current_session"
with (
patch("hermes_cli.main._resolve_session_by_name_or_id", return_value="sess_alpha"),
patch("cli._cprint"),
):
cli_obj._handle_resume_command(f"/resume {raw}")
assert cli_obj.session_id == "sess_alpha", (
f"bracket-stripping failed for {raw!r}: session_id stayed {cli_obj.session_id}"
)
def test_handle_resume_does_not_strip_partial_brackets(self):
"""Mismatched or single brackets must pass through unmodified.
``"<half`` (just an open angle) is not a wrapping pair, so the
lookup should treat it verbatim preserving the existing
not-found error path instead of mangling the input.
"""
cli_obj = _make_cli()
cli_obj._session_db.get_session.return_value = None
with (
patch("hermes_cli.main._resolve_session_by_name_or_id", return_value=None),
patch("cli._cprint") as mock_cprint,
):
cli_obj._handle_resume_command("/resume <half")
printed = " ".join(str(call) for call in mock_cprint.call_args_list)
assert "<half" in printed

View file

@ -301,3 +301,60 @@ class TestHandleResumeCommand:
assert real_key not in runner._agent_cache
db.close()
@pytest.mark.asyncio
async def test_resume_strips_outer_brackets(self, tmp_path):
"""Users may copy `<session_id>` from the usage hint literally.
The gateway should strip outer ``<>``, ``[]``, ``""``, and ``''``
before lookup so ``/resume <abc123>`` works the same as
``/resume abc123``.
"""
from hermes_state import SessionDB
db = SessionDB(db_path=tmp_path / "state.db")
db.create_session("abc123", "telegram")
db.set_session_title("abc123", "Bracketed")
db.create_session("current_session_001", "telegram")
for raw in ("<abc123>", "[abc123]", '"abc123"', "'abc123'"):
event = _make_event(text=f"/resume {raw}")
runner = _make_runner(
session_db=db,
current_session_id="current_session_001",
event=event,
)
result = await runner._handle_resume_command(event)
# Either the session was resumed (and we get a "Resumed" / "Already on" reply)
# or it was found-then-redirected. Failure mode = "No session found matching '<abc123>'".
assert "abc123" not in str(result) or "not found" not in str(result).lower(), (
f"bracket stripping failed for {raw!r}: gateway returned {result!r}"
)
db.close()
@pytest.mark.asyncio
async def test_resume_resolves_by_session_id(self, tmp_path):
"""The gateway should accept a bare session ID, not just a title.
Before this fix, /resume in the gateway only called
``resolve_session_by_title``, so ``/resume <session_id>`` always
returned "Session not found" even for valid IDs.
"""
from hermes_state import SessionDB
db = SessionDB(db_path=tmp_path / "state.db")
db.create_session("unnamed_session_xyz", "telegram")
# Deliberately no title set — this session can ONLY be resolved by ID.
db.create_session("current_session_001", "telegram")
event = _make_event(text="/resume unnamed_session_xyz")
runner = _make_runner(
session_db=db,
current_session_id="current_session_001",
event=event,
)
result = await runner._handle_resume_command(event)
# Should NOT be the not-found error.
assert "not found" not in str(result).lower(), (
f"session-id lookup failed: {result!r}"
)
db.close()