mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-11-02 21:34:32 +08:00
新增 Runcrate OpenAI-compatible 预设(https://api.runcrate.ai/v1),沿用共享 openai_compatible 通道,模型目录通过 /v1/models 发现;附带模型发现的边界回归测试。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
61 lines
2.2 KiB
Python
61 lines
2.2 KiB
Python
"""Runcrate 预设通过共享 OpenAI 兼容通道发现模型的边界回归。"""
|
||
|
||
from unittest.mock import AsyncMock
|
||
|
||
import httpx
|
||
import pytest
|
||
|
||
from app.agent.llm.provider import LLMProviderManager
|
||
from app.foundation.singleton import Singleton
|
||
|
||
|
||
@pytest.fixture
|
||
def manager(monkeypatch):
|
||
"""隔离管理器单例及目录缓存,防止测试影响其他 provider。"""
|
||
key = (LLMProviderManager, (), frozenset())
|
||
monkeypatch.setattr(Singleton, "_instances", {k: v for k, v in Singleton._instances.items() if k != key})
|
||
instance = LLMProviderManager()
|
||
monkeypatch.setattr(instance, "get_models_dev_data", AsyncMock(return_value={}))
|
||
return instance
|
||
|
||
|
||
@pytest.mark.asyncio
|
||
@pytest.mark.parametrize(
|
||
"base_url, expected_url",
|
||
[
|
||
(None, "https://api.runcrate.ai/v1/models"),
|
||
("https://relay.example/v1", "https://relay.example/v1/models"),
|
||
],
|
||
)
|
||
async def test_runcrate_discovers_authenticated_models(manager, monkeypatch, base_url, expected_url):
|
||
"""预设及覆盖地址都传递密钥,保留带厂商前缀的完整模型 ID,不推断缺失的上下文元数据。"""
|
||
requests = []
|
||
|
||
def respond(request):
|
||
requests.append(request)
|
||
return httpx.Response(
|
||
200,
|
||
json={
|
||
"object": "list",
|
||
"data": [
|
||
{"id": "deepseek-ai/DeepSeek-V4.1-Flash", "object": "model", "created": 0},
|
||
{"id": "zai-org/GLM-5.3-Flash", "object": "model", "created": 0},
|
||
],
|
||
},
|
||
)
|
||
|
||
monkeypatch.setattr(
|
||
manager,
|
||
"_build_sdk_http_client",
|
||
lambda use_proxy: httpx.AsyncClient(transport=httpx.MockTransport(respond)),
|
||
)
|
||
|
||
models = await manager.list_models("runcrate", api_key="test-runcrate-key", base_url=base_url)
|
||
|
||
assert len(requests) == 1
|
||
assert requests[0].method == "GET"
|
||
assert str(requests[0].url) == expected_url
|
||
assert requests[0].headers["Authorization"] == "Bearer test-runcrate-key"
|
||
assert [model["id"] for model in models] == ["deepseek-ai/DeepSeek-V4.1-Flash", "zai-org/GLM-5.3-Flash"]
|
||
assert all(model["source"] == "provider" and model["context_tokens"] is None for model in models)
|