7a0da7932b
OSV-Scanner (Scheduled) / scan-scheduled (push) Failing after 0s
Create Release / test-gate (push) Has been cancelled
Create Release / release-gate (push) Has been cancelled
Create Release / ci-gate (push) Has been cancelled
Create Release / version-check (push) Has been cancelled
Create Release / e2e-test-gate (push) Has been cancelled
Create Release / responsive-test-gate (push) Has been cancelled
Create Release / compat-test-gate (push) Has been cancelled
Create Release / compose-integration-gate (push) Has been cancelled
Create Release / vulture-gate (push) Has been cancelled
Create Release / build (push) Has been cancelled
Create Release / provenance (push) Has been cancelled
Create Release / prerelease-docker (push) Has been cancelled
Create Release / publish-docker (push) Has been cancelled
Create Release / create-release (push) Has been cancelled
Create Release / cleanup-changelog (push) Has been cancelled
Create Release / trigger-pypi (push) Has been cancelled
Create Release / monitor-pypi (push) Has been cancelled
Create Release / Clean up orphan prerelease tags and signatures (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-form] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-metrics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [research-workflow] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-core] (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [history-news] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [library] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [link-analytics] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-core] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [chat-lifecycle] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [error-benchmark] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [settings-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) (push) Has been cancelled
Docker Tests (Consolidated) / Accessibility Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Unit Tests (push) Has been cancelled
Docker Tests (Consolidated) / LLM Example Tests (push) Has been cancelled
Docker Tests (Consolidated) / Production Image Smoke Test (push) Has been cancelled
Docker Tests (Consolidated) / Infrastructure Tests (push) Has been cancelled
OSSF Scorecard / OSSF Security Scorecard Analysis (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [mobile] (push) Has been cancelled
Backwards Compatibility / Verify Encryption Constants (push) Has been cancelled
Backwards Compatibility / PyPI Version Compatibility (push) Has been cancelled
Backwards Compatibility / Database Migration Tests (push) Has been cancelled
CodeQL Advanced / Analyze (python) (push) Has been cancelled
Docker Tests (Consolidated) / detect-changes (push) Has been cancelled
Docker Tests (Consolidated) / Build Test Image (push) Has been cancelled
Docker Tests (Consolidated) / All Pytest Tests + Coverage (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [accessibility] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [api-crud] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-login] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-pages] (push) Has been cancelled
Docker Tests (Consolidated) / UI Tests (Puppeteer) [auth-register] (push) Has been cancelled
245 lines
8.6 KiB
Python
245 lines
8.6 KiB
Python
"""
|
|
Advanced tests for ChatContextManager.
|
|
|
|
Tests context window limits, summarization, and context building.
|
|
"""
|
|
|
|
from src.local_deep_research.chat.context import ChatContextManager
|
|
|
|
|
|
class TestContextBuilding:
|
|
"""Tests for building research context."""
|
|
|
|
def test_build_research_context_structure(self):
|
|
"""Test that research context has expected structure."""
|
|
messages = [
|
|
{"role": "user", "content": "Test query", "message_type": "query"}
|
|
]
|
|
|
|
manager = ChatContextManager("test-session", messages, {})
|
|
context = manager.build_research_context()
|
|
|
|
expected_keys = [
|
|
"session_id",
|
|
"original_query",
|
|
"accumulated_findings",
|
|
"past_findings",
|
|
"key_entities",
|
|
"topics",
|
|
"is_multi_turn",
|
|
"turn_count",
|
|
]
|
|
for key in expected_keys:
|
|
assert key in context, f"Missing key: {key}"
|
|
|
|
def test_is_multi_turn_false_for_empty(self):
|
|
"""Test is_multi_turn is False for empty messages."""
|
|
manager = ChatContextManager("test-session", [], {})
|
|
context = manager.build_research_context()
|
|
assert context["is_multi_turn"] is False
|
|
|
|
def test_is_multi_turn_false_with_only_user_messages(self):
|
|
"""Test is_multi_turn is False when only user messages (no assistant response yet)."""
|
|
messages = [
|
|
{"role": "user", "content": "Query", "message_type": "query"}
|
|
]
|
|
manager = ChatContextManager("test-session", messages, {})
|
|
context = manager.build_research_context()
|
|
assert context["is_multi_turn"] is False
|
|
|
|
def test_is_multi_turn_true_with_assistant_response(self):
|
|
"""Test is_multi_turn is True when an assistant response exists."""
|
|
messages = [
|
|
{"role": "user", "content": "Query", "message_type": "query"},
|
|
{
|
|
"role": "assistant",
|
|
"content": "Response",
|
|
"message_type": "response",
|
|
},
|
|
]
|
|
manager = ChatContextManager("test-session", messages, {})
|
|
context = manager.build_research_context()
|
|
assert context["is_multi_turn"] is True
|
|
|
|
def test_turn_count_accuracy(self):
|
|
"""Test that turn_count matches message count."""
|
|
messages = [
|
|
{"role": "user", "content": f"Msg {i}", "message_type": "query"}
|
|
for i in range(5)
|
|
]
|
|
manager = ChatContextManager("test-session", messages, {})
|
|
context = manager.build_research_context()
|
|
assert context["turn_count"] == 5
|
|
|
|
|
|
class TestFindingsExtraction:
|
|
"""Tests for extracting findings from history."""
|
|
|
|
def test_extract_findings_from_assistant_messages(self):
|
|
"""Test extracting findings from assistant messages."""
|
|
messages = [
|
|
{"role": "user", "content": "Query", "message_type": "query"},
|
|
{
|
|
"role": "assistant",
|
|
"content": "Finding 1",
|
|
"message_type": "response",
|
|
"research_id": "r1",
|
|
},
|
|
{
|
|
"role": "user",
|
|
"content": "Follow up",
|
|
"message_type": "followup",
|
|
},
|
|
{
|
|
"role": "assistant",
|
|
"content": "Finding 2",
|
|
"message_type": "response",
|
|
"research_id": "r2",
|
|
},
|
|
]
|
|
|
|
manager = ChatContextManager("test-session", messages, {})
|
|
findings = manager._extract_findings_from_history()
|
|
|
|
assert "Finding 1" in findings
|
|
assert "Finding 2" in findings
|
|
|
|
def test_extract_findings_skips_user_messages(self):
|
|
"""Test that user messages are not included in findings."""
|
|
messages = [
|
|
{"role": "user", "content": "User query", "message_type": "query"},
|
|
{
|
|
"role": "assistant",
|
|
"content": "Assistant finding",
|
|
"message_type": "response",
|
|
"research_id": "r1",
|
|
},
|
|
]
|
|
|
|
manager = ChatContextManager("test-session", messages, {})
|
|
findings = manager._extract_findings_from_history()
|
|
|
|
assert "User query" not in findings
|
|
assert "Assistant finding" in findings
|
|
|
|
def test_extract_findings_limits_to_max(self):
|
|
"""Test that findings are limited to MAX_FINDINGS_TO_INCLUDE."""
|
|
messages = []
|
|
for i in range(10):
|
|
messages.append(
|
|
{
|
|
"role": "assistant",
|
|
"content": f"Finding {i}",
|
|
"message_type": "response",
|
|
"research_id": f"r{i}",
|
|
}
|
|
)
|
|
|
|
manager = ChatContextManager("test-session", messages, {})
|
|
findings = manager._extract_findings_from_history()
|
|
|
|
# Should only have last MAX_FINDINGS_TO_INCLUDE
|
|
assert "Finding 9" in findings
|
|
assert "Finding 0" not in findings
|
|
|
|
|
|
class TestContextUpdates:
|
|
"""Tests for extracting context updates."""
|
|
|
|
def test_extract_context_updates_creates_summary(self):
|
|
"""Test that context updates include summary creation."""
|
|
manager = ChatContextManager("test-session", [], {})
|
|
updates = manager.extract_context_updates(
|
|
"New research content here with details"
|
|
)
|
|
|
|
assert "summary_addition" in updates
|
|
assert len(updates["summary_addition"]) > 0
|
|
|
|
def test_create_summary_truncates_long_content(self):
|
|
"""Test that summary creation truncates long content."""
|
|
manager = ChatContextManager("test-session", [], {})
|
|
long_content = "A" * 1000
|
|
|
|
summary = manager._create_summary(long_content)
|
|
|
|
assert len(summary) <= 310 # 300 + "..."
|
|
assert summary.endswith("...")
|
|
|
|
def test_create_summary_handles_empty_content(self):
|
|
"""Test that empty content returns empty summary."""
|
|
manager = ChatContextManager("test-session", [], {})
|
|
summary = manager._create_summary("")
|
|
assert summary == ""
|
|
|
|
|
|
class TestStepMessageFiltering:
|
|
"""Tests that step messages are excluded from context building."""
|
|
|
|
def test_step_messages_excluded_from_turn_count(self):
|
|
"""Step messages should not count as conversation turns."""
|
|
messages = [
|
|
{"role": "user", "content": "Query", "message_type": "query"},
|
|
{
|
|
"role": "assistant",
|
|
"content": "Searching...",
|
|
"message_type": "step",
|
|
},
|
|
{
|
|
"role": "assistant",
|
|
"content": "Found results",
|
|
"message_type": "response",
|
|
"research_id": "r1",
|
|
},
|
|
]
|
|
manager = ChatContextManager("test-session", messages, {})
|
|
context = manager.build_research_context()
|
|
# step is filtered → only 2 messages visible
|
|
assert context["turn_count"] == 2
|
|
|
|
def test_step_messages_excluded_from_is_multi_turn(self):
|
|
"""is_multi_turn should not be True from step messages alone."""
|
|
messages = [
|
|
{"role": "user", "content": "Query", "message_type": "query"},
|
|
{
|
|
"role": "assistant",
|
|
"content": "Searching...",
|
|
"message_type": "step",
|
|
},
|
|
]
|
|
manager = ChatContextManager("test-session", messages, {})
|
|
context = manager.build_research_context()
|
|
# Only user message remains after filtering → not multi-turn
|
|
assert context["is_multi_turn"] is False
|
|
|
|
def test_step_messages_excluded_from_findings(self):
|
|
"""Step messages with research_id should not appear in findings."""
|
|
messages = [
|
|
{
|
|
"role": "assistant",
|
|
"content": "Searching now...",
|
|
"message_type": "step",
|
|
"research_id": "r1",
|
|
},
|
|
{
|
|
"role": "assistant",
|
|
"content": "Real finding",
|
|
"message_type": "response",
|
|
"research_id": "r1",
|
|
},
|
|
]
|
|
manager = ChatContextManager("test-session", messages, {})
|
|
findings = manager._extract_findings_from_history()
|
|
assert "Searching now..." not in findings
|
|
assert "Real finding" in findings
|
|
|
|
def test_messages_without_message_type_pass_through(self):
|
|
"""Legacy messages with no message_type field are not filtered out."""
|
|
messages = [
|
|
{"role": "user", "content": "Old query"},
|
|
{"role": "assistant", "content": "Old response"},
|
|
]
|
|
manager = ChatContextManager("test-session", messages, {})
|
|
context = manager.build_research_context()
|
|
assert context["turn_count"] == 2
|