193 lines
6.6 KiB
Python
193 lines
6.6 KiB
Python
"""Test coverage for source field threading on process-wakeup synthetic turns."""
|
|
|
|
import time
|
|
from pathlib import Path
|
|
|
|
from api.models import Session, _append_recovered_pending_turn, _apply_core_sync_or_error_marker
|
|
from api.routes import _checkpoint_user_message_for_eager_session_save
|
|
from api.streaming import _materialize_pending_user_turn_before_error, _merge_display_messages_after_agent_result
|
|
|
|
|
|
def test_append_recovered_pending_turn_stamps_process_wakeup_source():
|
|
"""Verify _append_recovered_pending_turn stamps _source when pending_user_source is process_wakeup."""
|
|
s = Session(
|
|
session_id="test-session-1",
|
|
pending_user_message="[IMPORTANT: Process completed]",
|
|
pending_user_source="process_wakeup",
|
|
)
|
|
recovered = _append_recovered_pending_turn(s)
|
|
assert recovered is not None
|
|
assert recovered["role"] == "user"
|
|
assert recovered["content"] == "[IMPORTANT: Process completed]"
|
|
assert recovered["_source"] == "process_wakeup"
|
|
assert recovered["_recovered"] is True
|
|
|
|
|
|
def test_append_recovered_pending_turn_skips_webui_source():
|
|
"""Verify _append_recovered_pending_turn does NOT stamp _source when source is webui (default)."""
|
|
s = Session(
|
|
session_id="test-session-2",
|
|
pending_user_message="Normal user message",
|
|
pending_user_source="webui",
|
|
)
|
|
recovered = _append_recovered_pending_turn(s)
|
|
assert recovered is not None
|
|
assert recovered["role"] == "user"
|
|
assert recovered["content"] == "Normal user message"
|
|
assert "_source" not in recovered
|
|
assert recovered["_recovered"] is True
|
|
|
|
|
|
def test_append_recovered_pending_turn_defaults_to_no_source():
|
|
"""Verify _append_recovered_pending_turn does NOT stamp _source when pending_user_source is None."""
|
|
s = Session(
|
|
session_id="test-session-3",
|
|
pending_user_message="Another user message",
|
|
pending_user_source=None,
|
|
)
|
|
recovered = _append_recovered_pending_turn(s)
|
|
assert recovered is not None
|
|
assert recovered["role"] == "user"
|
|
assert "_source" not in recovered
|
|
|
|
|
|
def test_checkpoint_user_message_stamps_process_wakeup_source():
|
|
"""Verify eager-path checkpoint stamps _source on message dict when source is process_wakeup."""
|
|
s = Session(session_id="test-session-4")
|
|
s.messages = []
|
|
_checkpoint_user_message_for_eager_session_save(
|
|
s,
|
|
msg="[IMPORTANT: Wakeup prompt]",
|
|
attachments=[],
|
|
started_at=time.time(),
|
|
source="process_wakeup",
|
|
)
|
|
assert len(s.messages) == 1
|
|
user_msg = s.messages[0]
|
|
assert user_msg["role"] == "user"
|
|
assert user_msg["content"] == "[IMPORTANT: Wakeup prompt]"
|
|
assert user_msg["_source"] == "process_wakeup"
|
|
|
|
|
|
def test_checkpoint_user_message_skips_webui_source():
|
|
"""Verify eager-path checkpoint does NOT stamp _source when source is webui (default)."""
|
|
s = Session(session_id="test-session-5")
|
|
s.messages = []
|
|
_checkpoint_user_message_for_eager_session_save(
|
|
s,
|
|
msg="Normal user message",
|
|
attachments=[],
|
|
started_at=time.time(),
|
|
source="webui",
|
|
)
|
|
assert len(s.messages) == 1
|
|
user_msg = s.messages[0]
|
|
assert user_msg["role"] == "user"
|
|
assert user_msg["content"] == "Normal user message"
|
|
assert "_source" not in user_msg
|
|
|
|
|
|
def test_checkpoint_user_message_defaults_to_no_source():
|
|
"""Verify eager-path checkpoint does NOT stamp _source when source is omitted (defaults to webui)."""
|
|
s = Session(session_id="test-session-6")
|
|
s.messages = []
|
|
_checkpoint_user_message_for_eager_session_save(
|
|
s,
|
|
msg="Another user message",
|
|
attachments=[],
|
|
started_at=time.time(),
|
|
)
|
|
assert len(s.messages) == 1
|
|
user_msg = s.messages[0]
|
|
assert user_msg["role"] == "user"
|
|
assert user_msg["content"] == "Another user message"
|
|
assert "_source" not in user_msg
|
|
|
|
|
|
def test_session_pending_user_source_persisted():
|
|
"""Verify pending_user_source survives serialization and deserialization."""
|
|
s = Session(
|
|
session_id="test-session-7",
|
|
pending_user_message="Test message",
|
|
pending_user_source="process_wakeup",
|
|
)
|
|
s_dict = {k: getattr(s, k, None) for k in [
|
|
'session_id', 'pending_user_message', 'pending_user_source'
|
|
]}
|
|
assert s_dict["pending_user_source"] == "process_wakeup"
|
|
|
|
# Reconstruct from dict
|
|
s2 = Session(**s_dict)
|
|
assert s2.pending_user_source == "process_wakeup"
|
|
|
|
|
|
def test_merge_display_materializes_missing_process_wakeup_user_turn():
|
|
merged = _merge_display_messages_after_agent_result(
|
|
[],
|
|
[],
|
|
[{"role": "assistant", "content": "done"}],
|
|
"[IMPORTANT: Wakeup prompt]",
|
|
source="process_wakeup",
|
|
)
|
|
|
|
assert merged[0]["role"] == "user"
|
|
assert merged[0]["content"] == "[IMPORTANT: Wakeup prompt]"
|
|
assert merged[0]["_source"] == "process_wakeup"
|
|
assert merged[1]["role"] == "assistant"
|
|
|
|
|
|
def test_merge_display_stamps_process_wakeup_source_on_echoed_user_turn():
|
|
merged = _merge_display_messages_after_agent_result(
|
|
[],
|
|
[],
|
|
[
|
|
{"role": "user", "content": "[IMPORTANT: Wakeup prompt]"},
|
|
{"role": "assistant", "content": "done"},
|
|
],
|
|
"[IMPORTANT: Wakeup prompt]",
|
|
source="process_wakeup",
|
|
)
|
|
|
|
assert merged[0]["role"] == "user"
|
|
assert merged[0]["_source"] == "process_wakeup"
|
|
assert merged[1]["role"] == "assistant"
|
|
|
|
|
|
def test_merge_display_leaves_webui_user_turn_unmarked():
|
|
merged = _merge_display_messages_after_agent_result(
|
|
[],
|
|
[],
|
|
[{"role": "assistant", "content": "done"}],
|
|
"Normal user message",
|
|
source="webui",
|
|
)
|
|
|
|
assert merged[0]["role"] == "user"
|
|
assert "_source" not in merged[0]
|
|
|
|
|
|
def test_materialize_pending_user_turn_before_error_stamps_process_wakeup_source():
|
|
s = Session(
|
|
session_id="test-session-8",
|
|
pending_user_message="[IMPORTANT: Wakeup prompt]",
|
|
pending_user_source="process_wakeup",
|
|
)
|
|
s.messages = []
|
|
|
|
assert _materialize_pending_user_turn_before_error(s) is True
|
|
assert s.messages[0]["_source"] == "process_wakeup"
|
|
|
|
|
|
def test_apply_core_sync_or_error_marker_clears_pending_user_source(tmp_path):
|
|
s = Session(
|
|
session_id="test-session-9",
|
|
pending_user_message="[IMPORTANT: Wakeup prompt]",
|
|
pending_user_source="process_wakeup",
|
|
)
|
|
s.messages = [{"role": "assistant", "content": "done"}]
|
|
s.pending_started_at = time.time()
|
|
s.save = lambda *args, **kwargs: None
|
|
|
|
assert _apply_core_sync_or_error_marker(s, Path(tmp_path / "missing-core.json")) is True
|
|
assert s.pending_user_source is None
|