Files
MoviePilot/app/api/endpoints/llm.py

84 lines
2.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from typing import Any, Dict, List, Optional, Union
from fastapi import Depends, Request, Response
from fastapi.responses import HTMLResponse
from app.agent.llm.gateway import resolve_llm_provider_runtime
from app.api.dependencies.auth import get_current_active_superuser_async
from app.api.response import ResponseAPIRouter
from app.schemas.common import ManageRequest as _SchemaManageRequest
from app.schemas.response import Response as _SchemaResponse
router = ResponseAPIRouter()
@router.post(
"/manage",
summary="LLM提供商统一管理",
# 各动作 data 形态不一:目录查询返回列表,其余动作返回映射,
# 须用具体联合类型声明,而非单一开放映射
response_model=_SchemaResponse[Union[List[Dict[str, Any]], Dict[str, Any]]],
)
async def manage_provider(
request: Request,
payload: _SchemaManageRequest,
_: object = Depends(get_current_active_superuser_async),
):
"""
LLM 提供商统一管理入口:前端上送 target/action/params 原样透传,
端点不定义任何提供商特定的名称、参数或响应字段;
OAuth 回跳地址由具名回调路由统一构造后注入动作参数
"""
params = dict(payload.params)
# 目录类查询动作的 target 可为空,此时无需回跳地址;
# 且 url_for 的路径参数不允许空值,必须先行防护
if payload.target:
params.setdefault(
"callback_url",
str(request.url_for("llm_provider_auth_callback", provider_id=payload.target)),
)
result = await resolve_llm_provider_runtime().provider_manage(
payload.target, payload.action, **params
)
return _SchemaResponse(
success=bool(result.get("success")),
message=result.get("message"),
data=result.get("data"),
)
@router.get(
"/provider-auth/callback/{provider_id}",
summary="LLM提供商OAuth回调",
response_class=Response,
name="llm_provider_auth_callback",
response_model=None,
responses={
200: {
"description": "OAuth 授权结果页面",
"content": {"text/html": {"schema": {"type": "string"}}},
}
},
)
async def llm_provider_auth_callback(
provider_id: str,
code: Optional[str] = None,
state: Optional[str] = None,
error: Optional[str] = None,
error_description: Optional[str] = None,
):
"""
处理需要浏览器回跳的 OAuth provider。
"""
success, message = await resolve_llm_provider_runtime().handle_chatgpt_callback(
provider_id,
code,
state,
error,
error_description,
)
# 该符号由 app.agent.llm.__getattr__ 惰性公开,Pylint 无法静态发现。
from app.agent.llm import render_auth_result_html # pylint: disable=no-name-in-module
return HTMLResponse(content=render_auth_result_html(success, message))