Files
awoooi/apps/api/tests/test_chat_manager_ollama_routing.py
Your Name 6b93c8f454
Some checks failed
CD Pipeline / tests (push) Successful in 5m26s
Code Review / ai-code-review (push) Successful in 25s
CD Pipeline / build-and-deploy (push) Successful in 8m11s
CD Pipeline / post-deploy-checks (push) Has been cancelled
fix(chat): route OpenClaw chat through Ollama lane
2026-05-05 15:57:26 +08:00

106 lines
3.0 KiB
Python

from __future__ import annotations
from pathlib import Path
from types import SimpleNamespace
from typing import Any
import pytest
from src.services import chat_manager as chat_module
from src.services.chat_manager import ChatManager
class _FakeResponse:
def __init__(self, content: str = "老闆,系統目前穩定。") -> None:
self._content = content
def raise_for_status(self) -> None:
return None
def json(self) -> dict[str, Any]:
return {
"message": {"content": self._content},
"prompt_eval_count": 11,
"eval_count": 13,
}
class _FakeAsyncClient:
posted: list[tuple[str, dict[str, Any]]] = []
def __init__(self, *args: Any, **kwargs: Any) -> None:
self.args = args
self.kwargs = kwargs
async def __aenter__(self) -> _FakeAsyncClient:
return self
async def __aexit__(self, *args: Any) -> None:
return None
async def post(self, url: str, *, json: dict[str, Any]) -> _FakeResponse:
self.posted.append((url, json))
return _FakeResponse()
def _settings() -> SimpleNamespace:
return SimpleNamespace(OPENCLAW_DEFAULT_MODEL="qwen3:14b")
@pytest.fixture(autouse=True)
def _reset_fake_client() -> None:
_FakeAsyncClient.posted = []
@pytest.mark.asyncio
async def test_openclaw_chat_uses_ollama_interactive_lane(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(chat_module.httpx, "AsyncClient", _FakeAsyncClient)
monkeypatch.setattr(chat_module, "get_settings", _settings)
monkeypatch.setattr(
chat_module,
"resolve_ollama_endpoint",
lambda workload_type: "http://gcp-a:11435",
)
result = await ChatManager()._call_openclaw("system context", "幫我看狀態")
assert result is not None
assert "qwen3:14b" in result
assert "免費" in result
assert len(_FakeAsyncClient.posted) == 1
url, payload = _FakeAsyncClient.posted[0]
assert url == "http://gcp-a:11435/api/chat"
assert payload["model"] == "qwen3:14b"
assert payload["messages"][0]["role"] == "system"
assert payload["messages"][1] == {"role": "user", "content": "幫我看狀態"}
@pytest.mark.asyncio
async def test_nemoclaw_chat_uses_resolved_interactive_lane(
monkeypatch: pytest.MonkeyPatch,
) -> None:
monkeypatch.setattr(chat_module.httpx, "AsyncClient", _FakeAsyncClient)
monkeypatch.setattr(
chat_module,
"resolve_ollama_endpoint",
lambda workload_type: "http://gcp-a:11435",
)
result = await ChatManager()._call_nemotron("system context", "補充觀點")
assert result is not None
url, payload = _FakeAsyncClient.posted[0]
assert url == "http://gcp-a:11435/api/chat"
assert payload["model"] == "deepseek-r1:14b"
def test_chat_manager_has_no_direct_gemini_generation_path() -> None:
source_path = Path(chat_module.__file__).resolve()
source = source_path.read_text(encoding="utf-8")
assert "generativelanguage.googleapis.com" not in source
assert "GEMINI_API_KEY" not in source