"""Tests for context_compactor.py — constants and prompt templates. Uses mock imports to avoid loading the full app stack.""" import sys from unittest.mock import MagicMock # Mock heavy dependencies before importing for mod in [ 'sqlalchemy', 'sqlalchemy.orm', 'sqlalchemy.ext', 'sqlalchemy.ext.declarative', 'sqlalchemy.ext.hybrid', 'sqlalchemy.sql', 'sqlalchemy.sql.expression', 'src.database', 'core.models', 'core.database', ]: if mod not in sys.modules: sys.modules[mod] = MagicMock() from src.context_compactor import ( COMPACT_THRESHOLD, SELF_SUMMARY_SYSTEM_PROMPT, SUMMARY_MAX_TOKENS, trim_for_context, ) class TestCompactThreshold: def test_value(self): assert COMPACT_THRESHOLD == 0.85 def test_summary_max_tokens(self): assert SUMMARY_MAX_TOKENS == 1024 class TestSelfSummaryPrompt: def test_contains_goal_section(self): assert "### User Goal" in SELF_SUMMARY_SYSTEM_PROMPT def test_contains_what_was_done_section(self): assert "### What Was Done" in SELF_SUMMARY_SYSTEM_PROMPT def test_contains_current_state_section(self): assert "### Current State" in SELF_SUMMARY_SYSTEM_PROMPT def test_contains_pending_section(self): assert "### Pending / Next Steps" in SELF_SUMMARY_SYSTEM_PROMPT def test_contains_key_context_section(self): assert "### Key Context" in SELF_SUMMARY_SYSTEM_PROMPT def test_count_placeholder(self): assert "{count}" in SELF_SUMMARY_SYSTEM_PROMPT def test_n_placeholder(self): assert "{n}" in SELF_SUMMARY_SYSTEM_PROMPT def test_mentions_compactions(self): assert "Compactions so far" in SELF_SUMMARY_SYSTEM_PROMPT class TestTrimForContext: def test_keeps_current_large_user_message_by_truncating(self): huge = "A" * 20000 messages = [ {"role": "system", "content": "You are helpful."}, {"role": "user", "content": huge}, ] trimmed = trim_for_context(messages, context_length=2048, reserve_tokens=512) user_msgs = [m for m in trimmed if m.get("role") == "user"] assert len(user_msgs) == 1 content = user_msgs[0]["content"] assert "pasted message was too large" in content assert content.startswith("A") assert len(content) < len(huge) def test_drops_older_messages_before_latest_user_paste(self): huge = "B" * 12000 messages = [{"role": "system", "content": "You are helpful."}] messages.extend({"role": "user", "content": f"old-{i} " + ("x" * 1000)} for i in range(8)) messages.append({"role": "user", "content": huge}) trimmed = trim_for_context(messages, context_length=2048, reserve_tokens=512) assert trimmed[-1]["role"] == "user" assert "pasted message was too large" in trimmed[-1]["content"] assert "old-0" not in "\n".join(str(m.get("content", "")) for m in trimmed)