diff --git a/src/backend/services/worker_client.py b/src/backend/services/worker_client.py new file mode 100644 index 0000000..7da8650 --- /dev/null +++ b/src/backend/services/worker_client.py @@ -0,0 +1,47 @@ +import httpx + +from src.backend.config import settings + + +class WorkerClient: + def __init__(self): + self.base_url = settings.worker_url + + async def process( + self, + prompt: str, + system_prompt: str, + model: str, + session_id: str | None = None, + ) -> dict: + async with httpx.AsyncClient(timeout=300.0) as client: + resp = await client.post( + f"{self.base_url}/process", + json={ + "prompt": prompt, + "system_prompt": system_prompt, + "model": model, + "session_id": session_id, + }, + ) + return resp.json() + + async def summarize( + self, + exchanges: list[dict], + mode: str = "incremental", + ) -> dict: + async with httpx.AsyncClient(timeout=300.0) as client: + resp = await client.post( + f"{self.base_url}/summarize", + json={"exchanges": exchanges, "mode": mode}, + ) + return resp.json() + + async def health(self) -> bool: + try: + async with httpx.AsyncClient(timeout=5.0) as client: + resp = await client.get(f"{self.base_url}/health") + return resp.status_code == 200 + except Exception: + return False diff --git a/tests/test_services.py b/tests/test_services.py index e50ea21..0d29561 100644 --- a/tests/test_services.py +++ b/tests/test_services.py @@ -1,6 +1,7 @@ from src.backend.config import settings import pytest +from unittest.mock import AsyncMock, MagicMock, patch def test_settings_loads_api_key(): @@ -109,3 +110,80 @@ def test_envelope_fail(): result = fail("NOT_FOUND", "Resource not found") assert result["success"] is False assert result["error"]["code"] == "NOT_FOUND" + + +@pytest.mark.asyncio +async def test_worker_client_process(): + from src.backend.services.worker_client import WorkerClient + + mock_response = MagicMock() + mock_response.status_code = 200 + mock_response.json.return_value = { + "success": True, + "result": "The answer is 42.", + "session_id": "sess-123", + } + + with patch("src.backend.services.worker_client.httpx.AsyncClient") as MockClient: + mock_client_instance = AsyncMock() + mock_client_instance.post.return_value = mock_response + mock_client_instance.__aenter__ = AsyncMock(return_value=mock_client_instance) + mock_client_instance.__aexit__ = AsyncMock(return_value=False) + MockClient.return_value = mock_client_instance + + client = WorkerClient() + result = await client.process( + prompt="What is the answer?", + system_prompt="You know everything.", + model="claude-sonnet-4-6", + ) + + assert result["success"] is True + assert result["result"] == "The answer is 42." + + +@pytest.mark.asyncio +async def test_worker_client_summarize(): + from src.backend.services.worker_client import WorkerClient + + mock_response = MagicMock() + mock_response.status_code = 200 + mock_response.json.return_value = { + "success": True, + "summary": "[2026-05-25] Discussed the meaning of life.", + } + + with patch("src.backend.services.worker_client.httpx.AsyncClient") as MockClient: + mock_client_instance = AsyncMock() + mock_client_instance.post.return_value = mock_response + mock_client_instance.__aenter__ = AsyncMock(return_value=mock_client_instance) + mock_client_instance.__aexit__ = AsyncMock(return_value=False) + MockClient.return_value = mock_client_instance + + client = WorkerClient() + result = await client.summarize( + exchanges=[{"prompt": "What?", "result": "42."}], + mode="incremental", + ) + + assert result["success"] is True + assert "Discussed" in result["summary"] + + +@pytest.mark.asyncio +async def test_worker_client_health(): + from src.backend.services.worker_client import WorkerClient + + mock_response = AsyncMock() + mock_response.status_code = 200 + + with patch("src.backend.services.worker_client.httpx.AsyncClient") as MockClient: + mock_client_instance = AsyncMock() + mock_client_instance.get.return_value = mock_response + mock_client_instance.__aenter__ = AsyncMock(return_value=mock_client_instance) + mock_client_instance.__aexit__ = AsyncMock(return_value=False) + MockClient.return_value = mock_client_instance + + client = WorkerClient() + is_healthy = await client.health() + assert is_healthy is True