fix(cli): surface last_active in search_sessions so -c works
This commit is contained in:
parent
debae25f1c
commit
cb7cfba6de
2 changed files with 57 additions and 3 deletions
|
|
@ -1483,16 +1483,30 @@ class SessionDB:
|
|||
limit: int = 20,
|
||||
offset: int = 0,
|
||||
) -> List[Dict[str, Any]]:
|
||||
"""List sessions, optionally filtered by source."""
|
||||
"""List sessions, optionally filtered by source.
|
||||
|
||||
Returns rows enriched with a computed ``last_active`` column (the
|
||||
latest message timestamp for the session, falling back to
|
||||
``started_at``) so callers can sort by "most recently used" instead
|
||||
of "most recently started".
|
||||
"""
|
||||
select_last_active = (
|
||||
"COALESCE("
|
||||
"(SELECT MAX(m.timestamp) FROM messages m WHERE m.session_id = s.id),"
|
||||
" s.started_at"
|
||||
") AS last_active"
|
||||
)
|
||||
with self._lock:
|
||||
if source:
|
||||
cursor = self._conn.execute(
|
||||
"SELECT * FROM sessions WHERE source = ? ORDER BY started_at DESC LIMIT ? OFFSET ?",
|
||||
f"SELECT s.*, {select_last_active} FROM sessions s "
|
||||
"WHERE s.source = ? ORDER BY s.started_at DESC LIMIT ? OFFSET ?",
|
||||
(source, limit, offset),
|
||||
)
|
||||
else:
|
||||
cursor = self._conn.execute(
|
||||
"SELECT * FROM sessions ORDER BY started_at DESC LIMIT ? OFFSET ?",
|
||||
f"SELECT s.*, {select_last_active} FROM sessions s "
|
||||
"ORDER BY s.started_at DESC LIMIT ? OFFSET ?",
|
||||
(limit, offset),
|
||||
)
|
||||
return [dict(row) for row in cursor.fetchall()]
|
||||
|
|
|
|||
|
|
@ -45,6 +45,46 @@ def test_resolve_last_session_prefers_last_active_over_started_at(monkeypatch):
|
|||
assert fake_db.closed
|
||||
|
||||
|
||||
def test_search_sessions_exposes_last_active_column(tmp_path, monkeypatch):
|
||||
# End-to-end: the actual SessionDB must surface a last_active column so
|
||||
# _resolve_last_session's sort works. A previous bug had last_active=None
|
||||
# on every row because search_sessions used `SELECT *` with no computed
|
||||
# column, silently breaking the -c resume behavior.
|
||||
monkeypatch.setenv("HERMES_HOME", str(tmp_path))
|
||||
monkeypatch.setattr("pathlib.Path.home", lambda: tmp_path)
|
||||
|
||||
import hermes_state
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
db = hermes_state.SessionDB(db_path=Path(tmp_path / "state.db"))
|
||||
try:
|
||||
db.create_session("s_started_later", source="cli")
|
||||
db.create_session("s_active_later", source="cli")
|
||||
# Force started_at ordering so the test is deterministic regardless
|
||||
# of how quickly the two inserts land.
|
||||
with db._lock:
|
||||
db._conn.execute("UPDATE sessions SET started_at=? WHERE id=?", (2000.0, "s_started_later"))
|
||||
db._conn.execute("UPDATE sessions SET started_at=? WHERE id=?", (1000.0, "s_active_later"))
|
||||
db._conn.commit()
|
||||
|
||||
db.append_message("s_active_later", role="user", content="hi")
|
||||
with db._lock:
|
||||
db._conn.execute(
|
||||
"UPDATE messages SET timestamp=? WHERE session_id=?",
|
||||
(3000.0, "s_active_later"),
|
||||
)
|
||||
db._conn.commit()
|
||||
|
||||
rows = db.search_sessions(source="cli", limit=5)
|
||||
ids = {r["id"]: r.get("last_active") for r in rows}
|
||||
|
||||
assert ids["s_started_later"] == 2000.0
|
||||
assert ids["s_active_later"] == 3000.0
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
def test_resolve_last_session_returns_none_when_empty(monkeypatch):
|
||||
monkeypatch.setattr("hermes_state.SessionDB", lambda: _FakeDB([]))
|
||||
assert _resolve_last_session("cli") is None
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue