fix(webui): restore transcript-only session history

This commit is contained in:
Xubin Ren
2026-08-14 03:46:01 +09:00
parent af582246f1
commit fd7eb8e046
4 changed files with 656 additions and 29 deletions
@@ -31,6 +31,11 @@ from .ws_test_client import http_get as _http_get
_PORT = 29900
@pytest.fixture(autouse=True)
def _isolate_runtime_data(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
monkeypatch.setattr("nanobot.config.paths.get_data_dir", lambda: tmp_path)
class _MatrixChannel(BaseChannel):
name = "matrix"
display_name = "Matrix"
@@ -283,6 +288,53 @@ async def test_sessions_list_requires_bearer_token(
await server_task
@pytest.mark.asyncio
async def test_sessions_list_and_thread_restore_transcript_without_canonical_file(
bus: MagicMock, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setattr("nanobot.config.paths.get_data_dir", lambda: tmp_path)
sm = SessionManager(tmp_path / "workspace")
from nanobot.webui.transcript import append_transcript_object
key = "websocket:restored-history"
append_transcript_object(
key,
{"event": "user", "chat_id": "restored-history", "text": "original question"},
)
append_transcript_object(
key,
{"event": "message", "chat_id": "restored-history", "text": "original answer"},
)
assert not sm._get_session_path(key).exists()
port = _free_port()
channel = _ch(bus, session_manager=sm, port=port)
server_task = asyncio.create_task(channel.start())
try:
token = channel.gateway.tokens.issue_api_token(300)
auth = {"Authorization": f"Bearer {token}"}
listing = await _http_get(f"http://127.0.0.1:{port}/api/sessions", headers=auth)
thread = await _http_get(
f"http://127.0.0.1:{port}/api/sessions/"
"websocket%3Arestored-history/webui-thread",
headers=auth,
)
assert listing.status_code == 200
assert [row["key"] for row in listing.json()["sessions"]] == [key]
assert listing.json()["sessions"][0]["preview"] == "original question"
assert thread.status_code == 200
assert [message["content"] for message in thread.json()["messages"]] == [
"original question",
"original answer",
]
assert not sm._get_session_path(key).exists()
finally:
await channel.stop()
await server_task
@pytest.mark.asyncio
async def test_legacy_session_messages_route_is_not_exposed(
bus: MagicMock, tmp_path: Path
@@ -2267,6 +2319,40 @@ async def test_session_delete_removes_file(
await server_task
@pytest.mark.asyncio
async def test_session_delete_removes_transcript_without_canonical_file(
bus: MagicMock, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.setattr("nanobot.config.paths.get_data_dir", lambda: tmp_path)
sm = SessionManager(tmp_path / "workspace")
from nanobot.webui.transcript import append_transcript_object
key = "websocket:transcript-only"
append_transcript_object(
key,
{"event": "user", "chat_id": "transcript-only", "text": "recover me"},
)
assert not sm._get_session_path(key).exists()
webui_path = tmp_path / "webui" / f"{SessionManager.safe_key(key)}.jsonl"
assert webui_path.is_file()
channel = _ch(bus, session_manager=sm, port=_free_port())
server_task = asyncio.create_task(channel.start())
try:
response = await _webui_mutate(
channel,
"session.delete",
{"key": key},
)
assert response.status_code == 200
assert response.json()["deleted"] is True
assert not webui_path.exists()
finally:
await channel.stop()
await server_task
@pytest.mark.asyncio
async def test_webui_automations_route_lists_all_jobs_and_allows_user_actions(
bus: MagicMock, tmp_path: Path