refactor: 全局适配 ApiFamily/EndpointKind 结构化标识体系

将新的 (ApiFamily, EndpointKind) / `family:kind` 签名体系应用到整个代码库:
- API Handlers: 所有 adapter/handler 使用新的签名格式
- Services: provider, model, usage, cache, auth 等服务层适配
- Database: ProviderEndpoint 新增 api_family/endpoint_kind 字段
- Frontend: Provider 管理、Usage 表格等组件适配
- Tests: 更新所有相关测试用例
This commit is contained in:
fawney19
2026-02-01 17:28:00 +08:00
parent c246ccfc91
commit 7b66505634
219 changed files with 4732 additions and 2545 deletions

View File

@@ -163,8 +163,15 @@ class NewApiBalanceAction(BalanceAction):
# 检查是否是认证失败(未登录、无权限等)- Cookie 已失效
auth_fail_indicators = [
"未登录", "请登录", "login", "unauthorized", "无权限", "权限不足",
"turnstile", "captcha", "验证码", # 需要人机验证
"未登录",
"请登录",
"login",
"unauthorized",
"无权限",
"权限不足",
"turnstile",
"captcha",
"验证码", # 需要人机验证
]
is_auth_fail = any(ind in message.lower() for ind in auth_fail_indicators)
if is_auth_fail:

View File

@@ -2,12 +2,12 @@
Provider 架构模块
"""
from src.services.provider_ops.architectures.anyrouter import AnyrouterArchitecture
from src.services.provider_ops.architectures.base import (
ProviderArchitecture,
ProviderConnector,
VerifyResult,
)
from src.services.provider_ops.architectures.anyrouter import AnyrouterArchitecture
from src.services.provider_ops.architectures.cubence import CubenceArchitecture
from src.services.provider_ops.architectures.generic_api import GenericApiArchitecture
from src.services.provider_ops.architectures.nekocode import NekoCodeArchitecture

View File

@@ -11,7 +11,6 @@ from typing import Any
import httpx
from src.core.logger import logger
from src.utils.ssl_utils import get_ssl_context
from src.services.provider_ops.actions import (
AnyrouterBalanceAction,
ProviderAction,
@@ -22,6 +21,7 @@ from src.services.provider_ops.architectures.base import (
VerifyResult,
)
from src.services.provider_ops.types import ConnectorAuthType, ProviderActionType
from src.utils.ssl_utils import get_ssl_context
# acw_sc__v2 算法常量
_XOR_KEY = "3000176000856006061501533003690027800375"

View File

@@ -3,23 +3,22 @@ Provider 架构抽象基类
"""
from abc import ABC, abstractmethod
from collections.abc import AsyncIterator
from contextlib import asynccontextmanager
from dataclasses import dataclass
from datetime import datetime, timezone
from typing import Any
from collections.abc import AsyncIterator
import httpx
from src.services.provider_ops.actions.base import ProviderAction
from src.utils.ssl_utils import get_ssl_context
from src.services.provider_ops.types import (
ConnectorAuthType,
ConnectorState,
ConnectorStatus,
ProviderActionType,
)
from src.utils.ssl_utils import get_ssl_context
# ==================== 连接器基类 ====================
@@ -488,8 +487,6 @@ class ProviderArchitecture(ABC):
for a in self.supported_actions
],
"default_connector": (
self.supported_connectors[0].auth_type.value
if self.supported_connectors
else None
self.supported_connectors[0].auth_type.value if self.supported_connectors else None
),
}

View File

@@ -80,7 +80,16 @@ class ProviderOpsService:
"""
# 凭据中需要加密的字段
SENSITIVE_FIELDS = {"api_key", "password", "session_token", "session_cookie", "token_cookie", "auth_cookie", "cookie_string", "cookie"}
SENSITIVE_FIELDS = {
"api_key",
"password",
"session_token",
"session_cookie",
"token_cookie",
"auth_cookie",
"cookie_string",
"cookie",
}
def __init__(self, db: Session):
self.db = db
@@ -385,9 +394,7 @@ class ProviderOpsService:
Returns:
操作结果
"""
result = await self.execute_action(
provider_id, ProviderActionType.QUERY_BALANCE, config
)
result = await self.execute_action(provider_id, ProviderActionType.QUERY_BALANCE, config)
# 成功或 auth_expired 时缓存auth_expired 带有 cookie_expired 信息供前端显示警告)
if result.status in (ActionStatus.SUCCESS, ActionStatus.AUTH_EXPIRED) and result.data:
@@ -485,7 +492,9 @@ class ProviderOpsService:
"response_time_ms": result.response_time_ms,
}
await CacheService.set(cache_key, cache_data, AUTH_FAILED_CACHE_TTL)
logger.info(f"余额缓存已写入(认证失败): provider_id={provider_id}, message={result.message}")
logger.info(
f"余额缓存已写入(认证失败): provider_id={provider_id}, message={result.message}"
)
async def _cache_balance(self, provider_id: str, result: ActionResult) -> None:
"""缓存余额结果"""
@@ -504,7 +513,9 @@ class ProviderOpsService:
}
await CacheService.set(cache_key, cache_data, BALANCE_CACHE_TTL)
logger.debug(f"余额缓存已写入: provider_id={provider_id}, extra={data.get('extra') if data else None}")
logger.debug(
f"余额缓存已写入: provider_id={provider_id}, extra={data.get('extra') if data else None}"
)
async def _cache_balance_from_verify(
self,
@@ -633,7 +644,9 @@ class ProviderOpsService:
if key in self.SENSITIVE_FIELDS and isinstance(value, str):
if value: # 只加密非空值
encrypted[key] = self.crypto.encrypt(value)
logger.debug(f"加密字段 {key}: 原始长度={len(value)}, 加密后长度={len(encrypted[key])}")
logger.debug(
f"加密字段 {key}: 原始长度={len(value)}, 加密后长度={len(encrypted[key])}"
)
else:
logger.warning(f"跳过空值字段 {key}")
encrypted[key] = value
@@ -705,8 +718,14 @@ class ProviderOpsService:
if saved_config:
saved_credentials = self._decrypt_credentials(saved_config.connector_credentials)
sensitive_fields = [
"api_key", "password", "session_token", "cookie_string", "cookie",
"token_cookie", "auth_cookie", "session_cookie", # Cookie 认证字段
"api_key",
"password",
"session_token",
"cookie_string",
"cookie",
"token_cookie",
"auth_cookie",
"session_cookie", # Cookie 认证字段
]
for field in sensitive_fields:
@@ -738,11 +757,7 @@ class ProviderOpsService:
if provider_ids is None:
# 查询所有已配置的 Provider
providers = self.db.query(Provider).filter(Provider.is_active.is_(True)).all()
provider_ids = [
p.id
for p in providers
if p.config and p.config.get("provider_ops")
]
provider_ids = [p.id for p in providers if p.config and p.config.get("provider_ops")]
if not provider_ids:
return {}