mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 17:30:23 +08:00
feat(admin,pool,billing): 端点级模型测试、Provider 自动置顶、缓存 TTL 分级计费展示与账号状态增强
- 模型测试支持指定端点:新增 ModelTestDialog 组件,多端点时弹窗选择,单端点直接测试; 后端 test-model-failover 接口新增 endpoint_id 参数,支持 global/direct 模式下按端点过滤候选 - 创建 Provider 时优先级自动置顶(provider_priority 默认 None,后端取 min-1), 显式指定优先级时 shift 已有行;前端创建时不发送 priority,更新时保留 - 缓存计费 UI 增强:RequestDetailDrawer 支持 5min/1h 缓存创建 token 分级展示, 含按 TTL 匹配单价和分行成本计算;ModelDetailDrawer/ModelsTab 标签区分 5min/1h 缓存创建 - Pool 批量操作额度筛选拆分为「无5H限额」和「无周限额」,按 | 分隔 segment 匹配 - KeyFormDialog 优化非 vertex_ai 时布局,API 密钥输入内联到 grid 右列 - Codex refresher 结构化错误标记:401/402/403 使用 [OAUTH_EXPIRED]/[ACCOUNT_BLOCK] 前缀, 新增 deactivated_workspace 识别与分类 - 前后端 accountBlock 关键词同步:新增 token invalidated、deactivated_workspace 识别, OAuth 失效提示清理 block 前缀后展示 - PoolConfig 新增 batch_concurrency 配置(默认 8,上限 32) - 预设模型新增 gpt-5.4;TestResultDialog 响应式布局与 key 脱敏优化
This commit is contained in:
38
tests/unit/test_provider_query_failover_endpoint.py
Normal file
38
tests/unit/test_provider_query_failover_endpoint.py
Normal file
@@ -0,0 +1,38 @@
|
||||
from types import SimpleNamespace
|
||||
|
||||
from src.api.admin.provider_query import (
|
||||
_build_direct_test_candidates,
|
||||
_filter_test_candidates_by_endpoint,
|
||||
)
|
||||
|
||||
|
||||
def _build_provider() -> tuple[SimpleNamespace, SimpleNamespace, SimpleNamespace]:
|
||||
endpoint_a = SimpleNamespace(id="ep-a", api_format="openai:chat", is_active=True)
|
||||
endpoint_b = SimpleNamespace(id="ep-b", api_format="claude:cli", is_active=True)
|
||||
key_all = SimpleNamespace(
|
||||
id="key-all", is_active=True, api_formats=["openai:chat", "claude:cli"]
|
||||
)
|
||||
key_b = SimpleNamespace(id="key-b", is_active=True, api_formats=["claude:cli"])
|
||||
provider = SimpleNamespace(
|
||||
id="provider-1", endpoints=[endpoint_a, endpoint_b], api_keys=[key_all, key_b]
|
||||
)
|
||||
return provider, endpoint_a, endpoint_b
|
||||
|
||||
|
||||
def test_build_direct_test_candidates_respects_endpoint_id() -> None:
|
||||
provider, _endpoint_a, endpoint_b = _build_provider()
|
||||
|
||||
candidates = _build_direct_test_candidates(provider, endpoint_id=endpoint_b.id) # type: ignore[arg-type]
|
||||
|
||||
assert {candidate.endpoint.id for candidate in candidates} == {endpoint_b.id}
|
||||
assert {candidate.key.id for candidate in candidates} == {"key-all", "key-b"}
|
||||
|
||||
|
||||
def test_filter_test_candidates_by_endpoint_keeps_matching_candidates() -> None:
|
||||
provider, endpoint_a, endpoint_b = _build_provider()
|
||||
candidates = _build_direct_test_candidates(provider) # type: ignore[arg-type]
|
||||
|
||||
filtered = _filter_test_candidates_by_endpoint(candidates, endpoint_a.id)
|
||||
|
||||
assert {candidate.endpoint.id for candidate in filtered} == {endpoint_a.id}
|
||||
assert all(candidate.endpoint.id != endpoint_b.id for candidate in filtered)
|
||||
Reference in New Issue
Block a user