Files
wehub-resource-sync 5296d0e97c
CI / Ban suppressions and legacy annotations (push) Has been cancelled
CI / pytest (push) Has been cancelled
CI / ruff-check (push) Has been cancelled
CI / ruff-format (push) Has been cancelled
CI / ty (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:35:44 +08:00

147 lines
4.6 KiB
Python

"""Tests for the llama.cpp OpenAI-compatible provider."""
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from free_claude_code.config.constants import ANTHROPIC_DEFAULT_MAX_OUTPUT_TOKENS
from free_claude_code.core.anthropic.stream_contracts import parse_sse_text
from free_claude_code.providers.base import ProviderConfig
from free_claude_code.providers.openai_chat import OpenAIChatProvider
from tests.providers.request_factory import make_messages_request
from tests.providers.support import passthrough_rate_limiter, profiled_provider
LLAMACPP_MODEL = "llamacpp-community/qwen2.5-7b-instruct"
@pytest.fixture
def provider() -> OpenAIChatProvider:
return profiled_provider(
"llamacpp",
ProviderConfig(api_key="llamacpp", base_url="http://localhost:8080/v1"),
rate_limiter=passthrough_rate_limiter(),
)
@pytest.mark.parametrize(
("configured", "expected"),
[
("http://localhost:8080", "http://localhost:8080/v1"),
("http://localhost:8080/", "http://localhost:8080/v1"),
("http://localhost:8080/v1", "http://localhost:8080/v1"),
("http://localhost:8080/v1/", "http://localhost:8080/v1"),
],
)
def test_init_normalizes_openai_base_url(configured: str, expected: str) -> None:
with patch(
"free_claude_code.providers.openai_chat.provider.AsyncOpenAI"
) as openai_client:
provider = profiled_provider(
"llamacpp",
ProviderConfig(api_key="llamacpp", base_url=configured),
rate_limiter=passthrough_rate_limiter(),
)
assert provider._base_url == expected
assert openai_client.call_args.kwargs["base_url"] == expected
def test_init_uses_openai_chat_client() -> None:
config = ProviderConfig(
api_key="llamacpp",
base_url="http://localhost:8080/v1/",
http_read_timeout=600.0,
http_write_timeout=15.0,
http_connect_timeout=5.0,
)
with patch(
"free_claude_code.providers.openai_chat.provider.AsyncOpenAI"
) as openai_client:
provider = profiled_provider(
"llamacpp", config, rate_limiter=passthrough_rate_limiter()
)
assert provider._provider_name == "LLAMACPP"
assert provider._base_url == "http://localhost:8080/v1"
assert provider._api_key == "llamacpp"
timeout = openai_client.call_args.kwargs["timeout"]
assert (timeout.read, timeout.write, timeout.connect) == (600.0, 15.0, 5.0)
def test_build_request_body_uses_openai_chat_shape(
provider: OpenAIChatProvider,
) -> None:
request = make_messages_request(LLAMACPP_MODEL, max_tokens=None)
body = provider._build_request_body(request)
assert body["model"] == LLAMACPP_MODEL
assert body["max_tokens"] == ANTHROPIC_DEFAULT_MAX_OUTPUT_TOKENS
assert body["messages"][0]["role"] == "system"
assert "thinking" not in body
def test_disabled_thinking_does_not_replay_assistant_reasoning(
provider: OpenAIChatProvider,
) -> None:
request = make_messages_request(
LLAMACPP_MODEL,
system=None,
messages=[
{"role": "user", "content": "Hi"},
{
"role": "assistant",
"content": [
{"type": "thinking", "thinking": "private", "signature": "s"},
{"type": "text", "text": "visible"},
],
},
],
)
body = provider._build_request_body(request, thinking_enabled=False)
assert "private" not in str(body)
assert "visible" in str(body)
@pytest.mark.asyncio
async def test_stream_response_uses_shared_openai_chat_provider(
provider: OpenAIChatProvider,
) -> None:
chunk = MagicMock()
chunk.choices = [
MagicMock(
delta=MagicMock(
content="Hello from llama.cpp",
reasoning_content=None,
tool_calls=None,
),
finish_reason="stop",
)
]
chunk.usage = MagicMock(prompt_tokens=8, completion_tokens=4)
async def stream():
yield chunk
with patch.object(
provider._client.chat.completions,
"create",
new_callable=AsyncMock,
return_value=stream(),
) as create:
output = "".join(
[
event
async for event in provider.stream_response(
make_messages_request(LLAMACPP_MODEL)
)
]
)
assert create.call_args.kwargs["stream"] is True
assert create.call_args.kwargs["model"] == LLAMACPP_MODEL
assert "Hello from llama.cpp" in output
assert parse_sse_text(output)[-1].event == "message_stop"