mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
Merge pull request #13724 from NousResearch/bb/tui-resume-all-sources
fix(tui): /resume picker shows telegram/discord/etc sessions
This commit is contained in:
commit
90fca3c7e0
2 changed files with 104 additions and 6 deletions
76
tests/gateway/test_session_list_allowed_sources.py
Normal file
76
tests/gateway/test_session_list_allowed_sources.py
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
"""Regression tests for the TUI gateway's ``session.list`` handler.
|
||||
|
||||
Reported during TUI v2 blitz retest: the ``/resume`` modal inside a TUI
|
||||
session only surfaced ``tui``/``cli`` rows, hiding telegram sessions users
|
||||
could still resume directly via ``hermes --tui --resume <id>``.
|
||||
|
||||
The fix widens the picker to a curated allowlist of user-facing sources
|
||||
(tui/cli + chat adapters) while still filtering internal/system sources.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from tui_gateway import server
|
||||
|
||||
|
||||
class _StubDB:
|
||||
def __init__(self, rows):
|
||||
self.rows = rows
|
||||
self.calls: list[dict] = []
|
||||
|
||||
def list_sessions_rich(self, **kwargs):
|
||||
self.calls.append(kwargs)
|
||||
return list(self.rows)
|
||||
|
||||
|
||||
def _call(limit: int = 20):
|
||||
return server.handle_request({
|
||||
"id": "1",
|
||||
"method": "session.list",
|
||||
"params": {"limit": limit},
|
||||
})
|
||||
|
||||
|
||||
def test_session_list_includes_telegram_but_filters_internal_sources(monkeypatch):
|
||||
rows = [
|
||||
{"id": "tui-1", "source": "tui", "started_at": 9},
|
||||
{"id": "tool-1", "source": "tool", "started_at": 8},
|
||||
{"id": "tg-1", "source": "telegram", "started_at": 7},
|
||||
{"id": "acp-1", "source": "acp", "started_at": 6},
|
||||
{"id": "cli-1", "source": "cli", "started_at": 5},
|
||||
]
|
||||
db = _StubDB(rows)
|
||||
monkeypatch.setattr(server, "_get_db", lambda: db)
|
||||
|
||||
resp = _call(limit=10)
|
||||
sessions = resp["result"]["sessions"]
|
||||
ids = [s["id"] for s in sessions]
|
||||
|
||||
assert "tg-1" in ids and "tui-1" in ids and "cli-1" in ids, ids
|
||||
assert "tool-1" not in ids and "acp-1" not in ids, ids
|
||||
|
||||
|
||||
def test_session_list_fetches_wider_window_before_filtering(monkeypatch):
|
||||
db = _StubDB([{"id": "x", "source": "cli", "started_at": 1}])
|
||||
monkeypatch.setattr(server, "_get_db", lambda: db)
|
||||
|
||||
_call(limit=10)
|
||||
|
||||
assert len(db.calls) == 1
|
||||
assert db.calls[0].get("source") is None, db.calls[0]
|
||||
assert db.calls[0].get("limit") == 100, db.calls[0]
|
||||
|
||||
|
||||
def test_session_list_preserves_ordering_after_filter(monkeypatch):
|
||||
rows = [
|
||||
{"id": "newest", "source": "telegram", "started_at": 5},
|
||||
{"id": "internal", "source": "tool", "started_at": 4},
|
||||
{"id": "middle", "source": "tui", "started_at": 3},
|
||||
{"id": "oldest", "source": "discord", "started_at": 1},
|
||||
]
|
||||
monkeypatch.setattr(server, "_get_db", lambda: _StubDB(rows))
|
||||
|
||||
resp = _call()
|
||||
ids = [s["id"] for s in resp["result"]["sessions"]]
|
||||
|
||||
assert ids == ["newest", "middle", "oldest"]
|
||||
|
|
@ -1231,12 +1231,34 @@ def _(rid, params: dict) -> dict:
|
|||
@method("session.list")
|
||||
def _(rid, params: dict) -> dict:
|
||||
try:
|
||||
db = _get_db()
|
||||
# Show both TUI and CLI sessions — TUI is the successor to the CLI,
|
||||
# so users expect to resume their old CLI sessions here too.
|
||||
tui = db.list_sessions_rich(source="tui", limit=params.get("limit", 20))
|
||||
cli = db.list_sessions_rich(source="cli", limit=params.get("limit", 20))
|
||||
rows = sorted(tui + cli, key=lambda s: s.get("started_at") or 0, reverse=True)[:params.get("limit", 20)]
|
||||
# Resume picker should include human conversation surfaces beyond
|
||||
# tui/cli (notably telegram from blitz row #7), but avoid internal
|
||||
# sources that clutter the modal (tool/acp/etc).
|
||||
allow = frozenset(
|
||||
{
|
||||
"cli",
|
||||
"tui",
|
||||
"telegram",
|
||||
"discord",
|
||||
"slack",
|
||||
"whatsapp",
|
||||
"wecom",
|
||||
"weixin",
|
||||
"feishu",
|
||||
"signal",
|
||||
"mattermost",
|
||||
"matrix",
|
||||
"qq",
|
||||
}
|
||||
)
|
||||
|
||||
limit = int(params.get("limit", 20) or 20)
|
||||
fetch_limit = max(limit * 5, 100)
|
||||
rows = [
|
||||
s
|
||||
for s in _get_db().list_sessions_rich(source=None, limit=fetch_limit)
|
||||
if (s.get("source") or "").strip().lower() in allow
|
||||
][:limit]
|
||||
return _ok(rid, {"sessions": [
|
||||
{"id": s["id"], "title": s.get("title") or "", "preview": s.get("preview") or "",
|
||||
"started_at": s.get("started_at") or 0, "message_count": s.get("message_count") or 0,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue