50 lines
1.8 KiB
Python
50 lines
1.8 KiB
Python
"""Regression: stale stream cleanup must not discard pending user turns.
|
|
|
|
A server restart drops the in-memory STREAMS table. Browser reload then calls
|
|
get_session(), which clears stale active_stream_id state. For long conversations
|
|
that already have messages, the pending_user_message can be the only durable copy
|
|
of the user turn that was submitted just before the restart.
|
|
"""
|
|
|
|
import api.config as config
|
|
import api.models as models
|
|
from api.models import Session, get_session
|
|
|
|
|
|
def test_stale_stream_cleanup_recovers_pending_turn_on_non_empty_session(tmp_path, monkeypatch):
|
|
session_dir = tmp_path / "sessions"
|
|
session_dir.mkdir()
|
|
monkeypatch.setattr(models, "SESSION_DIR", session_dir)
|
|
monkeypatch.setattr(models, "SESSION_INDEX_FILE", session_dir / "_index.json")
|
|
models.SESSIONS.clear()
|
|
config.STREAMS.clear()
|
|
|
|
s = Session(
|
|
session_id="stale_stream_nonempty",
|
|
title="Existing long chat",
|
|
messages=[
|
|
{"role": "user", "content": "previous prompt", "timestamp": 100},
|
|
{"role": "assistant", "content": "previous answer", "timestamp": 101},
|
|
],
|
|
)
|
|
s.active_stream_id = "dead_stream"
|
|
s.pending_user_message = "new prompt that must survive restart"
|
|
s.pending_attachments = [{"name": "note.txt", "path": "/tmp/note.txt"}]
|
|
s.pending_started_at = 123
|
|
s.save()
|
|
|
|
recovered = get_session("stale_stream_nonempty")
|
|
|
|
assert recovered.active_stream_id is None
|
|
assert recovered.pending_user_message is None
|
|
assert any(
|
|
msg.get("role") == "user"
|
|
and msg.get("content") == "new prompt that must survive restart"
|
|
and msg.get("_recovered") is True
|
|
for msg in recovered.messages
|
|
)
|
|
assert any(
|
|
msg.get("role") == "assistant" and msg.get("_error") is True
|
|
for msg in recovered.messages
|
|
)
|