feat: 完善后端 API OpenAPI 文档与统一错误响应 schema

This commit is contained in:
caoxiaozhu
2026-05-11 05:18:16 +00:00
parent b2beeaa136
commit 321dd6fdaf
20 changed files with 7359 additions and 225 deletions

View File

@@ -6,7 +6,8 @@ from fastapi import APIRouter, Depends, Header, HTTPException, status
from sqlalchemy.orm import Session
from app.api.deps import get_db
from app.core.config import get_settings
from app.core.config import get_settings as get_runtime_settings
from app.schemas.common import ErrorResponse
from app.schemas.settings import (
ModelConnectivityTestRead,
ModelConnectivityTestRequest,
@@ -22,9 +23,12 @@ DbSession = Annotated[Session, Depends(get_db)]
def require_hermes_agent_token(
authorization: Annotated[str | None, Header()] = None,
authorization: Annotated[
str | None,
Header(description="Hermes 读取运行时模型配置时使用的 Bearer Token。"),
] = None,
) -> None:
configured_token = str(get_settings().hermes_agent_shared_token or "").strip()
configured_token = str(get_runtime_settings().hermes_agent_shared_token or "").strip()
if not configured_token:
raise HTTPException(
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
@@ -40,12 +44,28 @@ def require_hermes_agent_token(
)
@router.get("", response_model=SettingsRead)
@router.get(
"",
response_model=SettingsRead,
summary="读取系统设置",
description="返回公司、管理员、模型、日志、邮件和 ONLYOFFICE 的设置快照。",
)
def get_settings(db: DbSession) -> SettingsRead:
return SettingsService(db).get_settings_snapshot()
@router.put("", response_model=SettingsRead)
@router.put(
"",
response_model=SettingsRead,
summary="保存系统设置",
description="保存系统设置,并同步运行时模型配置与 Hermes 使用的模型路由。",
responses={
status.HTTP_400_BAD_REQUEST: {
"model": ErrorResponse,
"description": "设置字段校验失败。",
}
},
)
def update_settings(payload: SettingsWrite, db: DbSession) -> SettingsRead:
try:
return SettingsService(db).save_settings_snapshot(payload)
@@ -53,8 +73,16 @@ def update_settings(payload: SettingsWrite, db: DbSession) -> SettingsRead:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(exc)) from exc
@router.post("/model-connectivity", response_model=ModelConnectivityTestRead)
def test_model_connectivity(payload: ModelConnectivityTestRequest, db: DbSession) -> ModelConnectivityTestRead:
@router.post(
"/model-connectivity",
response_model=ModelConnectivityTestRead,
summary="测试模型连通性",
description="验证指定模型服务端点是否可用;当未传 API Key 且提供 slot 时会尝试复用已保存密钥。",
)
def test_model_connectivity(
payload: ModelConnectivityTestRequest,
db: DbSession,
) -> ModelConnectivityTestRead:
resolved_payload = payload
if not payload.api_key and payload.slot:
@@ -69,6 +97,22 @@ def test_model_connectivity(payload: ModelConnectivityTestRequest, db: DbSession
"/runtime-models/{slot}",
response_model=RuntimeModelConfigRead,
dependencies=[Depends(require_hermes_agent_token)],
summary="读取 Hermes 运行时模型配置",
description="供 Hermes 进程读取主模型、备用模型、VLM 或 Embedding 模型的运行时配置。",
responses={
status.HTTP_401_UNAUTHORIZED: {
"model": ErrorResponse,
"description": "Hermes 令牌校验失败。",
},
status.HTTP_404_NOT_FOUND: {
"model": ErrorResponse,
"description": "指定模型槽位不存在。",
},
status.HTTP_503_SERVICE_UNAVAILABLE: {
"model": ErrorResponse,
"description": "Hermes 集成令牌尚未配置。",
},
},
)
def get_runtime_model_config(
slot: str,