"""Tests for the OpenAI-compatible HTTP API.""" import pytest from fastapi.testclient import TestClient from cortex_ai.adapters import MockAdapter from cortex_ai.api import create_app from cortex_ai.config import CortexConfig, EngineConfig def make_client(api_key: str = "", thinking_mode: str = "chat") -> TestClient: cfg = CortexConfig(engine=EngineConfig(thinking_mode=thinking_mode)) cfg.server.api_key = api_key return TestClient(create_app(MockAdapter(), cfg)) def test_health_reports_model_and_tools(): body = make_client().get("/health").json() assert body["status"] == "ok" assert body["model"] == "Frankenstein-Labs/Cortex-ai" assert "calculate" in body["tools"] assert body["identity_interception"] == "deterministic" def test_identity_question_is_answered_before_model_inference(): class FailingAdapter(MockAdapter): def generate(self, *args, **kwargs): raise AssertionError("identity questions must not reach model inference") cfg = CortexConfig(engine=EngineConfig(thinking_mode="chat")) client = TestClient(create_app(FailingAdapter(), cfg)) response = client.post( "/v1/chat/completions", json={"messages": [{"role": "user", "content": "Qui a créé ce modèle ?"}]}, ) assert response.status_code == 200 assert response.json()["choices"][0]["message"]["content"].startswith( "Mon créateur est Abdoulaye Coumbassa" ) def test_english_identity_question_returns_english_canonical_response(): body = make_client().post( "/v1/chat/completions", json={"messages": [{"role": "user", "content": "Who is your creator?"}]}, ).json() assert body["choices"][0]["message"]["content"].startswith( "My creator is Abdoulaye Coumbassa" ) def test_models_endpoint_lists_cortex(): body = make_client().get("/v1/models").json() assert body["object"] == "list" entry = body["data"][0] assert entry["id"] == "Frankenstein-Labs/Cortex-ai" assert entry["owned_by"] == "Frankenstein-Labs" def test_chat_completion_shape(): r = make_client().post( "/v1/chat/completions", json={"messages": [{"role": "user", "content": "Bonjour"}]}, ) assert r.status_code == 200 body = r.json() assert body["object"] == "chat.completion" assert body["id"].startswith("chatcmpl-") assert body["choices"][0]["message"]["role"] == "assistant" assert body["choices"][0]["finish_reason"] == "stop" assert body["usage"]["total_tokens"] > 0 def test_chat_completion_executes_a_tool(): body = make_client().post( "/v1/chat/completions", json={"messages": [{"role": "user", "content": "Combien font 12 * 8 ?"}]}, ).json() assert body["tool_calls"][0]["name"] == "calculate" assert body["tool_calls"][0]["result"] == "96" assert body["tool_calls"][0]["ok"] is True def test_reasoning_is_exposed_in_thinking_mode(): body = make_client(thinking_mode="thinking").post( "/v1/chat/completions", json={"messages": [{"role": "user", "content": "Combien font 4 * 4 ?"}]}, ).json() assert body["reasoning_content"] def test_system_message_overrides_the_default_prompt(): body = make_client().post( "/v1/chat/completions", json={ "messages": [ {"role": "system", "content": "Tu es un assistant bref."}, {"role": "user", "content": "Bonjour"}, ] }, ).json() assert body["choices"][0]["message"]["content"] def test_auth_is_enforced_when_a_key_is_configured(): client = make_client(api_key="secret-de-test") assert client.post( "/v1/chat/completions", json={"messages": [{"role": "user", "content": "x"}]} ).status_code == 401 ok = client.post( "/v1/chat/completions", json={"messages": [{"role": "user", "content": "x"}]}, headers={"Authorization": "Bearer secret-de-test"}, ) assert ok.status_code == 200 def test_no_auth_required_when_no_key_is_configured(): assert make_client().post( "/v1/chat/completions", json={"messages": [{"role": "user", "content": "x"}]} ).status_code == 200 def test_empty_messages_are_rejected(): assert make_client().post("/v1/chat/completions", json={"messages": []}).status_code == 400 def test_streaming_is_refused_explicitly(): r = make_client().post( "/v1/chat/completions", json={"messages": [{"role": "user", "content": "x"}], "stream": True}, ) assert r.status_code == 400 assert "stream" in r.json()["detail"]