Sweep coordinator (Step 16): - SweepCoordinator runs all 8 agents in parallel with 60s per-agent / 300s total timeout - Aggregates findings, actions, errors into SweepCoordinatorResult - Registered in FastAPI lifespan; triggered via POST /sweep Structured logging (Step 18): - logging_utils/structured.py: JSONFormatter emitting ts/level/logger/msg + custom fields - log_directive_event() for structured directive lifecycle logging - push_to_loki() async Loki push (graceful no-op if LOKI_URL unset) - configure_logging() replaces root handler at startup Tests (Steps 17+19): - conftest.py: mock_odoo, mock_pool, mock_llm fixtures - test_tool_validator.py: 9 tests covering validation, coercion, hallucination stripping - test_llm_router.py: 6 tests covering local/cloud/hybrid modes and HIPAA enforcement - test_peer_bus.py: 6 tests covering registration, timeout, depth, circular detection - test_finance_agent.py: 10 tests covering all 6 steps + sweep + peer request - test_memory_manager.py: 3 tests covering context build + hard cap enforcement - test_dispatch_router.py: 3 tests covering dispatch, rate limit, health endpoint - test_odoo_client.py: 4 tests covering search_read, write result, unlink warning - test_e2e_dispatch.py: 2 E2E tests - full dispatch cycle + peer bus communication README (Step 20): architecture diagram, privacy modes, quick start, env vars, structure Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
77 lines
2.5 KiB
Python
77 lines
2.5 KiB
Python
import pytest
|
|
from unittest.mock import AsyncMock, MagicMock
|
|
from agent_service.llm.llm_router import LLMRouter, HIPAA_LOCKED_AGENTS
|
|
from agent_service.llm.llm_types import LLMResponse
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_ollama():
|
|
ollama = MagicMock()
|
|
ollama.complete = AsyncMock(return_value=LLMResponse(
|
|
content='test', tool_calls=[], backend_used='ollama',
|
|
model_used='llama3', tokens_in=5, tokens_out=10, latency_ms=50,
|
|
))
|
|
ollama.ping = AsyncMock(return_value=True)
|
|
return ollama
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_claude():
|
|
claude = MagicMock()
|
|
claude.complete = AsyncMock(return_value=LLMResponse(
|
|
content='test claude', tool_calls=[], backend_used='claude',
|
|
model_used='claude-sonnet-4-6', tokens_in=5, tokens_out=10, latency_ms=100,
|
|
))
|
|
return claude
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_local_mode_always_ollama(mock_ollama, mock_claude):
|
|
router = LLMRouter(ollama=mock_ollama, claude=mock_claude, privacy_mode='local')
|
|
backend = await router.get_backend('crm_agent')
|
|
assert backend == 'ollama'
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_cloud_mode_uses_claude(mock_ollama, mock_claude):
|
|
router = LLMRouter(ollama=mock_ollama, claude=mock_claude, privacy_mode='cloud')
|
|
backend = await router.get_backend('crm_agent')
|
|
assert backend == 'claude'
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_hipaa_locked_always_ollama(mock_ollama, mock_claude):
|
|
router = LLMRouter(ollama=mock_ollama, claude=mock_claude, privacy_mode='cloud')
|
|
for agent in HIPAA_LOCKED_AGENTS:
|
|
backend = await router.get_backend(agent)
|
|
assert backend == 'ollama', f'{agent} should be ollama-only'
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_cloud_mode_no_claude_fallback(mock_ollama):
|
|
router = LLMRouter(ollama=mock_ollama, claude=None, privacy_mode='cloud')
|
|
backend = await router.get_backend('crm_agent')
|
|
assert backend == 'ollama'
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_env_override_respected(mock_ollama, mock_claude):
|
|
router = LLMRouter(
|
|
ollama=mock_ollama, claude=mock_claude,
|
|
privacy_mode='hybrid',
|
|
env_overrides={'crm_agent': 'claude'},
|
|
)
|
|
backend = await router.get_backend('crm_agent')
|
|
assert backend == 'claude'
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_env_override_cannot_override_hipaa(mock_ollama, mock_claude):
|
|
router = LLMRouter(
|
|
ollama=mock_ollama, claude=mock_claude,
|
|
privacy_mode='hybrid',
|
|
env_overrides={'finance_agent': 'claude'},
|
|
)
|
|
backend = await router.get_backend('finance_agent')
|
|
assert backend == 'ollama'
|