import asyncio import os from uuid import uuid4 import pytest from fastapi import FastAPI from httpx import ASGITransport, AsyncClient import memory_gateway.api_v2 as api_v2 from memory_gateway.evermemos_client import EverMemOSClient from memory_gateway.openviking_client import OpenVikingClient from memory_gateway.repositories import InMemoryRepository from memory_gateway.schemas_v2 import BackendRefStatus, BackendType, IngestRequest, IngestResponse, OperationStatus from memory_gateway.server_auth import verify_api_key_compat from memory_gateway.services_v2 import MemoryGatewayV2Service pytestmark = pytest.mark.skipif( os.environ.get("RUN_REAL_BACKEND_TESTS") != "1", reason="real backend ingest test is opt-in; set RUN_REAL_BACKEND_TESTS=1", ) def _env(name: str) -> str: value = os.environ.get(name) if not value: pytest.skip(f"{name} is required for real backend ingest test") return value def test_real_openviking_and_evermemos_ingest_writes_memory_refs(): openviking_base_url = _env("OPENVIKING_BASE_URL") evermemos_base_url = _env("EVERMEMOS_BASE_URL") openviking_api_key = os.environ.get("OPENVIKING_API_KEY", "") evermemos_api_key = os.environ.get("EVERMEMOS_API_KEY", "") openviking_ingest_path = os.environ.get("OPENVIKING_INGEST_PATH") evermemos_ingest_path = os.environ.get("EVERMEMOS_INGEST_PATH") async def openviking_factory(): return OpenVikingClient( mode="real", base_url=openviking_base_url, api_key=openviking_api_key, ingest_path=openviking_ingest_path, ) repo = InMemoryRepository() service = MemoryGatewayV2Service( repo=repo, openviking_client_factory=openviking_factory, evermemos_client=EverMemOSClient( mode="real", base_url=evermemos_base_url, api_key=evermemos_api_key, ingest_path=evermemos_ingest_path, ), ) run_id = uuid4().hex[:12] response = asyncio.run(post_ingest(service, run_id)) refs = repo.list_memory_refs(session_id=f"real_ingest_sess_{run_id}", limit=10) assert {ref.backend_type for ref in refs} == {BackendType.OPENVIKING, BackendType.EVERMEMOS} assert all(ref.content_hash for ref in refs) openviking_ref = next(ref for ref in refs if ref.backend_type == BackendType.OPENVIKING) evermemos_ref = next(ref for ref in refs if ref.backend_type == BackendType.EVERMEMOS) assert openviking_ref.status == BackendRefStatus.SUCCESS if evermemos_ref.status == BackendRefStatus.SUCCESS: assert response.status == OperationStatus.SUCCESS assert evermemos_ref.native_id assert evermemos_ref.native_uri else: assert evermemos_ref.status == BackendRefStatus.FAILED assert response.status == OperationStatus.PARTIAL_SUCCESS assert evermemos_ref.error_message async def post_ingest(service: MemoryGatewayV2Service, run_id: str): api_v2.v2_service = service app = FastAPI() app.dependency_overrides[verify_api_key_compat] = lambda: None app.include_router(api_v2.router) request = IngestRequest( workspace_id=os.environ.get("REAL_BACKEND_WORKSPACE_ID", "ws_real_ingest"), user_id=os.environ.get("REAL_BACKEND_USER_ID", "user_real_ingest"), agent_id=os.environ.get("REAL_BACKEND_AGENT_ID", "agent_real_ingest"), session_id=f"real_ingest_sess_{run_id}", turn_id=f"real_ingest_turn_{run_id}", request_id=f"real_ingest_req_{run_id}", idempotency_key=f"real_ingest_idem_{run_id}", namespace=os.environ.get("REAL_BACKEND_NAMESPACE", "workspace/ws_real_ingest/user/user_real_ingest"), source_type="integration_test", source_event_id=f"real_ingest_evt_{run_id}", role="user", content=f"Memory Gateway real ingest smoke test {run_id}", metadata={"source_channel": "integration_test"}, ) async with AsyncClient(transport=ASGITransport(app=app), base_url="http://test") as client: response = await client.post("/v2/conversations/ingest", json=request.model_dump(mode="json")) response.raise_for_status() return IngestResponse.model_validate(response.json())