diff --git a/gateway/run.py b/gateway/run.py index 14bd3ff0d..3d9648bf7 100644 --- a/gateway/run.py +++ b/gateway/run.py @@ -7228,13 +7228,19 @@ class GatewayRunner: logger.debug("Failed to list titled sessions: %s", e) return f"Could not list sessions: {e}" - # Resolve the name to a session ID + # Resolve the name to a session ID. target_id = self._session_db.resolve_session_by_title(name) if not target_id: return ( f"No session found matching '**{name}**'.\n" "Use `/resume` with no arguments to see available sessions." ) + # Compression creates child continuations that hold the live transcript. + # Follow that chain so gateway /resume matches CLI behavior (#15000). + try: + target_id = self._session_db.resolve_resume_session_id(target_id) + except Exception as e: + logger.debug("Failed to resolve resume continuation for %s: %s", target_id, e) # Check if already on that session current_entry = self.session_store.get_or_create_session(source) diff --git a/tests/gateway/test_resume_command.py b/tests/gateway/test_resume_command.py index 4c82f4894..c451b3fe3 100644 --- a/tests/gateway/test_resume_command.py +++ b/tests/gateway/test_resume_command.py @@ -179,6 +179,40 @@ class TestHandleResumeCommand: assert call_args[0][1] == "sess_v2" db.close() + @pytest.mark.asyncio + async def test_resume_follows_compression_continuation(self, tmp_path): + """Gateway /resume should reopen the live descendant after compression.""" + from hermes_state import SessionDB + + db = SessionDB(db_path=tmp_path / "state.db") + db.create_session("compressed_root", "telegram") + db.set_session_title("compressed_root", "Compressed Work") + db.end_session("compressed_root", "compression") + db.create_session("compressed_child", "telegram", parent_session_id="compressed_root") + db.append_message("compressed_child", "user", "hello from continuation") + db.create_session("current_session_001", "telegram") + + event = _make_event(text="/resume Compressed Work") + runner = _make_runner( + session_db=db, + current_session_id="current_session_001", + event=event, + ) + runner.session_store.load_transcript.side_effect = ( + lambda session_id: [{"role": "user", "content": "hello from continuation"}] + if session_id == "compressed_child" + else [] + ) + + result = await runner._handle_resume_command(event) + + assert "Resumed session" in result + assert "(1 message)" in result + call_args = runner.session_store.switch_session.call_args + assert call_args[0][1] == "compressed_child" + runner.session_store.load_transcript.assert_called_with("compressed_child") + db.close() + @pytest.mark.asyncio async def test_resume_clears_running_agent(self, tmp_path): """Switching sessions clears any cached running agent."""