From ec921e3319a5596e964dfb55a2574d1006c8cc67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=B1=E6=BD=AE?= Date: Sat, 28 Feb 2026 22:39:55 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=A8=A1=E5=9E=8B=E9=80=89?= =?UTF-8?q?=E6=8B=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- routes/bot_manager.py | 158 ++++++++++++++++++++---------------------- 1 file changed, 77 insertions(+), 81 deletions(-) diff --git a/routes/bot_manager.py b/routes/bot_manager.py index dc88e96..7ca14b9 100644 --- a/routes/bot_manager.py +++ b/routes/bot_manager.py @@ -649,12 +649,21 @@ class ModelInfo(BaseModel): api_key: Optional[str] # 掩码显示 +class NewAPIModelResponse(BaseModel): + """New API 模型响应""" + id: str + object: str = "model" + created: Optional[int] = None + owned_by: str = "system" + + class BotSettingsResponse(BaseModel): """Bot 设置响应""" bot_id: str name: str # bot 名称 model_id: Optional[str] model: Optional[ModelInfo] # 关联的模型信息 + models: List[NewAPIModelResponse] = [] # 用户可用的模型列表 language: str avatar_url: Optional[str] description: Optional[str] @@ -1675,6 +1684,47 @@ async def get_bot_settings(bot_uuid: str, authorization: Optional[str] = Header( pool = get_db_pool_manager().pool + # 获取用户可用的模型列表 + models_list = [] + try: + async with pool.connection() as conn: + async with conn.cursor() as cursor: + # 获取用户的 new_api_session 和 new_api_user_id(子账号使用主账号的) + effective_user_id = await get_parent_user_id(user_id) + await cursor.execute(""" + SELECT new_api_session, new_api_user_id + FROM agent_user + WHERE id = %s + """, (effective_user_id,)) + row = await cursor.fetchone() + + if row and row[0] and row[1]: + new_api_session = row[0] + new_api_user_id = row[1] + + # 调用 New API 获取模型列表 + proxy = get_new_api_proxy() + cookies = {"session": new_api_session} + + result = await proxy.get_user_models(cookies, new_api_user_id) + + if result.get("success"): + data = result.get("data", []) + if isinstance(data, list): + for model in data: + models_list.append(NewAPIModelResponse( + id=model if isinstance(model, str) else model.get("id", ""), + object="model", + created=None, + owned_by="system" + )) + except Exception as e: + # 获取模型列表失败不影响主流程,返回空列表 + print(f"Failed to fetch models: {e}") + + # 获取模型 ID 列表用于检查 + available_model_ids = [m.id for m in models_list] + async with pool.connection() as conn: async with conn.cursor() as cursor: await cursor.execute(""" @@ -1694,13 +1744,34 @@ async def get_bot_settings(bot_uuid: str, authorization: Optional[str] = Header( effective_user_id = await get_parent_user_id(user_id) is_owner = (str(owner_id) == str(effective_user_id)) - # 获取关联的模型信息 - # 注意:model_id 现在来自 New API,格式为 "Provider/ModelName" - # 不再从本地 agent_models 表查询 - model_info = None + # 检查 model_id 是否在可用模型列表中 model_id = settings.get('model_id') + model_needs_update = False + + if model_id and available_model_ids and model_id not in available_model_ids: + # 模型已下线,需要更新为第一个可用模型 + print(f"Bot {bot_uuid} has outdated model {model_id}, updating to first available model") + if models_list: + model_id = models_list[0].id + model_needs_update = True + + # 如果没有 model_id 或需要更新,使用第一个可用模型 + if not model_id and models_list: + model_id = models_list[0].id + model_needs_update = True + + # 如果需要更新模型,保存到数据库 + if model_needs_update and is_owner: + settings['model_id'] = model_id + await cursor.execute(""" + UPDATE agent_bots + SET settings = %s, updated_at = NOW() + WHERE id = %s + """, (json.dumps(settings), bot_uuid)) + + # 获取关联的模型信息 + model_info = None if model_id: - # 直接使用 model_id 作为模型信息 model_info = ModelInfo( id=model_id, name=model_id, @@ -1734,6 +1805,7 @@ async def get_bot_settings(bot_uuid: str, authorization: Optional[str] = Header( name=bot_name, model_id=model_id, model=model_info, + models=models_list, language=settings.get('language', 'zh'), avatar_url=settings.get('avatar_url'), description=settings.get('description'), @@ -3967,82 +4039,6 @@ async def sync_bot_from_source( ) -# ============== New API 模型和令牌管理 API ============== - -class NewAPIModelResponse(BaseModel): - """New API 模型响应""" - id: str - object: str = "model" - created: Optional[int] = None - owned_by: str = "system" - - -@router.get("/api/v1/newapi/models", response_model=List[NewAPIModelResponse]) -async def get_newapi_models(authorization: Optional[str] = Header(None)): - """ - 获取用户可用的模型列表(从 New API) - - Args: - authorization: Bearer token - - Returns: - List[NewAPIModelResponse]: 模型列表 - """ - user_valid, user_id, _ = await verify_user_auth(authorization) - if not user_valid: - raise HTTPException( - status_code=401, - detail="Unauthorized" - ) - - pool = get_db_pool_manager().pool - - async with pool.connection() as conn: - async with conn.cursor() as cursor: - # 获取用户的 new_api_session 和 new_api_user_id - await cursor.execute(""" - SELECT new_api_session, new_api_user_id - FROM agent_user - WHERE id = %s - """, (user_id,)) - row = await cursor.fetchone() - - if not row or not row[0] or not row[1]: - raise HTTPException( - status_code=400, - detail="New API session not found. Please log in again." - ) - - new_api_session = row[0] - new_api_user_id = row[1] - - # 调用 New API 获取模型列表 - proxy = get_new_api_proxy() - cookies = {"session": new_api_session} - - result = await proxy.get_user_models(cookies, new_api_user_id) - - if not result.get("success"): - raise HTTPException( - status_code=500, - detail=result.get("message", "Failed to fetch models from New API") - ) - - # 解析模型列表 - models = [] - data = result.get("data", []) - if isinstance(data, list): - for model in data: - models.append(NewAPIModelResponse( - id=model if isinstance(model, str) else model.get("id", ""), - object="model", - created=None, - owned_by="system" - )) - - return models - - # ============== 子账号管理 API ============== @router.post("/api/v1/subaccounts", response_model=UserLoginResponse)