mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 09:20:22 +08:00
feat: 手动代理节点支持、系统默认代理与跨格式流式 usage 提取
代理节点: - 支持手动添加代理节点(HTTP/HTTPS/SOCKS5),含地址、认证信息和区域标签 - 新增手动节点的 CRUD API 和前端管理界面 - 提供商代理配置从 URL 字符串迁移至代理节点选择器(proxy_node_id) - 新增系统默认代理节点设置,未单独配置代理的提供商自动回退使用 - 删除节点时自动清除系统默认代理引用并失效缓存 - 健康检查跳过手动节点(无心跳,始终在线) 流式处理: - CLI handler 跨格式转换时委托基类解析 Provider 原始事件的 usage - StreamProcessor 新增 _extract_usage_from_converted_event 从转换后事件补充提取 usage - 支持 Claude/OpenAI/OpenAI Responses/Gemini 多种 usage 格式
This commit is contained in:
@@ -408,8 +408,10 @@ class AnyrouterArchitecture(ProviderArchitecture):
|
||||
Returns:
|
||||
包含 acw_cookie 的配置
|
||||
"""
|
||||
# 从 config 获取代理配置
|
||||
proxy = config.get("proxy")
|
||||
# 从 config 获取代理配置(支持 proxy_node_id 和旧的 proxy URL)
|
||||
from src.clients.http_client import resolve_ops_proxy
|
||||
|
||||
proxy = resolve_ops_proxy(config)
|
||||
acw_cookie = await _get_acw_cookie(base_url, proxy=proxy)
|
||||
if acw_cookie:
|
||||
return {"acw_cookie": acw_cookie}
|
||||
|
||||
@@ -50,8 +50,10 @@ class ProviderConnector(ABC):
|
||||
self._expires_at: datetime | None = None
|
||||
self._last_error: str | None = None
|
||||
|
||||
# 代理配置
|
||||
self._proxy: str | None = self.config.get("proxy")
|
||||
# 代理配置(支持 proxy_node_id 和旧的 proxy URL)
|
||||
from src.clients.http_client import resolve_ops_proxy
|
||||
|
||||
self._proxy: str | None = resolve_ops_proxy(self.config)
|
||||
|
||||
# HTTP 客户端配置
|
||||
self._timeout = self.config.get("timeout", 30)
|
||||
|
||||
@@ -180,7 +180,9 @@ class NekoCodeArchitecture(ProviderArchitecture):
|
||||
"timeout": 10,
|
||||
"verify": get_ssl_context(),
|
||||
}
|
||||
proxy = config.get("proxy")
|
||||
from src.clients.http_client import resolve_ops_proxy
|
||||
|
||||
proxy = resolve_ops_proxy(config)
|
||||
if proxy:
|
||||
client_kwargs["proxy"] = proxy
|
||||
|
||||
|
||||
@@ -193,8 +193,10 @@ class YesCodeArchitecture(ProviderArchitecture):
|
||||
|
||||
cookie_header = _build_cookie_header(cookie_input)
|
||||
|
||||
# 获取代理配置
|
||||
proxy = config.get("proxy")
|
||||
# 获取代理配置(支持 proxy_node_id 和旧的 proxy URL)
|
||||
from src.clients.http_client import resolve_ops_proxy
|
||||
|
||||
proxy = resolve_ops_proxy(config)
|
||||
|
||||
try:
|
||||
# 构建 client 参数
|
||||
|
||||
@@ -916,8 +916,10 @@ class ProviderOpsService:
|
||||
f"endpoint={verify_endpoint}, headers={list(headers.keys())}"
|
||||
)
|
||||
|
||||
# 获取代理配置
|
||||
proxy = config.get("proxy")
|
||||
# 获取代理配置(支持 proxy_node_id 和旧的 proxy URL)
|
||||
from src.clients.http_client import resolve_ops_proxy
|
||||
|
||||
proxy = resolve_ops_proxy(config)
|
||||
|
||||
try:
|
||||
# 构建 httpx client 参数
|
||||
|
||||
@@ -55,7 +55,15 @@ class ProxyNodeHealthScheduler:
|
||||
db = create_session()
|
||||
try:
|
||||
now = datetime.now(timezone.utc)
|
||||
nodes = db.query(ProxyNode).filter(ProxyNode.status != ProxyNodeStatus.OFFLINE).all()
|
||||
# 仅检查非手动节点(手动节点无心跳,始终保持 ONLINE)
|
||||
nodes = (
|
||||
db.query(ProxyNode)
|
||||
.filter(
|
||||
ProxyNode.status != ProxyNodeStatus.OFFLINE,
|
||||
ProxyNode.is_manual == False, # noqa: E712
|
||||
)
|
||||
.all()
|
||||
)
|
||||
if not nodes:
|
||||
return
|
||||
|
||||
|
||||
@@ -168,6 +168,11 @@ class SystemConfigService:
|
||||
"value": 30,
|
||||
"description": "审计日志保留天数,超过此天数的审计日志将被自动清理",
|
||||
},
|
||||
# 系统代理
|
||||
"system_proxy_node_id": {
|
||||
"value": None,
|
||||
"description": "系统默认代理节点 ID,为空时直连。仅影响提供商出站请求(大模型API/余额查询/OAuth),不影响系统内部接口",
|
||||
},
|
||||
# SMTP 邮件配置
|
||||
"smtp_host": {
|
||||
"value": None,
|
||||
|
||||
Reference in New Issue
Block a user