diff --git a/src/adclaw/__version__.py b/src/adclaw/__version__.py index b167678..3caf5a8 100644 --- a/src/adclaw/__version__.py +++ b/src/adclaw/__version__.py @@ -1,2 +1,2 @@ # -*- coding: utf-8 -*- -__version__ = "1.0.30" +__version__ = "1.0.31" diff --git a/src/adclaw/app/routers/providers.py b/src/adclaw/app/routers/providers.py index 30c73da..80eec86 100644 --- a/src/adclaw/app/routers/providers.py +++ b/src/adclaw/app/routers/providers.py @@ -36,6 +36,7 @@ ) router = APIRouter(prefix="/models", tags=["models"]) +HOST_AI_PROVIDER_ID = "adclaw-host-ai" class ProviderConfigRequest(BaseModel): @@ -116,6 +117,12 @@ def _build_provider_info( ) +def _provider_info_sort_key(provider: ProviderInfo) -> tuple[int, str]: + if provider.id == HOST_AI_PROVIDER_ID: + return (0, "") + return (1, provider.name.lower()) + + @router.get( "", response_model=List[ProviderInfo], @@ -123,7 +130,8 @@ def _build_provider_info( ) async def list_all_providers() -> List[ProviderInfo]: data = load_providers_json() - return [_build_provider_info(p, data) for p in list_providers()] + providers = [_build_provider_info(p, data) for p in list_providers()] + return sorted(providers, key=_provider_info_sort_key) @router.put( diff --git a/tests/test_adclaw_ai_usage.py b/tests/test_adclaw_ai_usage.py index 4aef7ab..b32f585 100644 --- a/tests/test_adclaw_ai_usage.py +++ b/tests/test_adclaw_ai_usage.py @@ -9,7 +9,12 @@ from fastapi import HTTPException from adclaw.app.routers import providers as provider_routes -from adclaw.providers.models import CustomProviderData, ModelInfo, ProvidersData +from adclaw.providers.models import ( + CustomProviderData, + ModelInfo, + ProviderDefinition, + ProvidersData, +) from adclaw.providers.store import ( ProviderUsageRequestError, fetch_provider_usage, @@ -214,3 +219,33 @@ def test_provider_usage_route_is_threadpool_safe_and_validation_guarded(): assert "def get_provider_usage(" in source assert "async def get_provider_usage(" not in source assert "except (ValueError, ValidationError)" in source + + +@pytest.mark.asyncio +async def test_list_all_providers_prioritizes_adclaw_ai(monkeypatch): + data = _host_ai_data() + xiaomi = ProviderDefinition( + id="xiaomi-codingplan", + name="Xiaomi Coding Plan", + models=[ModelInfo(id="mimo-v2.5", name="MiMo v2.5")], + ) + host_ai = ProviderDefinition( + id="adclaw-host-ai", + name="AdClaw AI", + models=data.custom_providers["adclaw-host-ai"].models, + is_custom=True, + ) + + monkeypatch.setattr(provider_routes, "load_providers_json", lambda: data) + monkeypatch.setattr( + provider_routes, + "list_providers", + lambda: [xiaomi, host_ai], + ) + + providers = await provider_routes.list_all_providers() + + assert [provider.id for provider in providers[:2]] == [ + "adclaw-host-ai", + "xiaomi-codingplan", + ]