完成请求推送,但组装mes还有问题

This commit is contained in:
2026-05-04 00:33:29 +08:00
parent 7fc9e10c99
commit 2050a30a52
93 changed files with 9499 additions and 2719 deletions

View File

@@ -2,24 +2,28 @@ from fastapi import APIRouter, HTTPException, UploadFile, File
from pydantic import BaseModel, Field
from typing import Dict, Optional, List, Any
import json
import os
import sys
from pathlib import Path
from core.config import settings
from cryptography.fernet import Fernet
import base64
from services.comfyui_workflow_manager import workflow_manager
from services.llm_model_service import LLMModelService
router = APIRouter(prefix="/api-config", tags=["API Configuration"])
# 加密密钥(实际项目中应该从环境变量读取)
ENCRYPTION_KEY = os.getenv('API_ENCRYPTION_KEY', Fernet.generate_key().decode())
fernet = Fernet(ENCRYPTION_KEY.encode() if isinstance(ENCRYPTION_KEY, str) else ENCRYPTION_KEY)
# 配置文件路径
CONFIG_DIR = Path(settings.DATA_PATH) / "apiconfig"
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
# 调试信息:打印配置目录路径
print(f"[API Config] DATA_PATH: {settings.DATA_PATH}", file=sys.stderr)
print(f"[API Config] CONFIG_DIR: {CONFIG_DIR}", file=sys.stderr)
print(f"[API Config] CONFIG_DIR exists: {CONFIG_DIR.exists()}", file=sys.stderr)
if CONFIG_DIR.exists():
config_files = list(CONFIG_DIR.glob("*.json"))
print(f"[API Config] Found {len(config_files)} config files", file=sys.stderr)
for f in config_files:
print(f" - {f.name}", file=sys.stderr)
class ApiConfigItem(BaseModel):
"""单个 API 配置项"""
@@ -50,32 +54,8 @@ class ProfileResponse(BaseModel):
apis: Dict[str, dict] # apiKey 字段会被移除或脱敏
def encrypt_api_key(api_key: str) -> str:
"""加密 API Key"""
if not api_key:
return ""
encrypted = fernet.encrypt(api_key.encode())
return base64.urlsafe_b64encode(encrypted).decode()
def decrypt_api_key(encrypted_key: str) -> str:
"""解密 API Key仅在后端内部使用"""
if not encrypted_key:
return ""
try:
decoded = base64.urlsafe_b64decode(encrypted_key.encode())
decrypted = fernet.decrypt(decoded)
return decrypted.decode()
except Exception:
return ""
def mask_api_key(api_key: str) -> str:
"""脱敏 API Key返回给前端"""
if not api_key or len(api_key) < 8:
return "****"
return api_key[:4] + "****" + api_key[-4:]
def load_profile(profile_id: str) -> Optional[dict]:
"""加载配置文件"""
@@ -119,29 +99,28 @@ def get_all_profiles():
@router.get("/profiles/{profile_id}", response_model=ProfileResponse)
def get_profile(profile_id: str):
"""获取单个配置文件API Key 已脱敏"""
"""获取单个配置文件(明文存储,不返回 API Key"""
profile = load_profile(profile_id)
if not profile:
raise HTTPException(status_code=404, detail="配置文件不存在")
# 脱敏所有 API Key
masked_apis = {}
# 移除 API Key 字段,不返回给前端
safe_apis = {}
for category, api_config in profile.get("apis", {}).items():
masked_config = api_config.copy()
if "apiKey" in masked_config and masked_config["apiKey"]:
masked_config["apiKey"] = mask_api_key(masked_config["apiKey"])
masked_apis[category] = masked_config
safe_config = api_config.copy()
safe_config.pop("apiKey", None)
safe_apis[category] = safe_config
return {
"id": profile.get("id", profile_id),
"name": profile.get("name", profile_id),
"apis": masked_apis
"apis": safe_apis
}
@router.post("/profiles", response_model=ProfileResponse)
def create_or_update_profile(request: ProfileSaveRequest):
"""创建或更新配置文件(增量更新)"""
"""创建或更新配置文件(增量更新,明文存储 API Key"""
# 加载现有配置
existing_profile = load_profile(request.profileId)
@@ -150,16 +129,11 @@ def create_or_update_profile(request: ProfileSaveRequest):
for category, api_config in request.apis.items():
api_config_dict = api_config.dict(exclude_none=True)
# 处理 API Key 加密
if api_config.apiKey and api_config.apiKey != "****":
# 如果是新的明文 key加密它
api_config_dict["apiKey"] = encrypt_api_key(api_config.apiKey)
elif api_config.apiKey == "****":
# 如果是脱敏的 key保留原有的加密 key
if category in existing_profile.get("apis", {}):
api_config_dict["apiKey"] = existing_profile["apis"][category].get("apiKey", "")
else:
api_config_dict.pop("apiKey", None)
# 如果前端传入了空的 apiKey保留原有的 key
if api_config.apiKey == "" and category in existing_profile.get("apis", {}):
existing_key = existing_profile["apis"][category].get("apiKey", "")
if existing_key:
api_config_dict["apiKey"] = existing_key
# 更新配置
if "apis" not in existing_profile:
@@ -177,28 +151,25 @@ def create_or_update_profile(request: ProfileSaveRequest):
"apis": {}
}
# 添加所有 API 配置
# 添加所有 API 配置(明文存储)
for category, api_config in request.apis.items():
api_config_dict = api_config.dict(exclude_none=True)
if api_config_dict.get("apiKey"):
api_config_dict["apiKey"] = encrypt_api_key(api_config_dict["apiKey"])
profile_data["apis"][category] = api_config_dict
# 保存配置文件
save_profile(request.profileId, profile_data)
# 返回脱敏后的数据
masked_apis = {}
# 返回不包含 API Key 的数据
safe_apis = {}
for category, api_config in profile_data.get("apis", {}).items():
masked_config = api_config.copy()
if "apiKey" in masked_config and masked_config["apiKey"]:
masked_config["apiKey"] = mask_api_key(masked_config["apiKey"])
masked_apis[category] = masked_config
safe_config = api_config.copy()
safe_config.pop("apiKey", None)
safe_apis[category] = safe_config
return {
"id": profile_data.get("id", request.profileId),
"name": profile_data.get("name", request.profileId),
"apis": masked_apis
"apis": safe_apis
}
@@ -217,13 +188,31 @@ def delete_profile(profile_id: str):
def test_connection(api_config: ApiConfigItem):
"""测试 API 连接并获取模型列表"""
try:
api_key_to_use = api_config.apiKey or ""
# 如果 API Key 为空,尝试从已保存的配置中获取
if not api_key_to_use and api_config.category:
# 遍历所有配置文件,找到包含该 category 的配置
for config_file in CONFIG_DIR.glob("*.json"):
try:
with open(config_file, 'r', encoding='utf-8') as f:
profile = json.load(f)
# 检查是否包含该 category
if api_config.category in profile.get("apis", {}):
api_key_to_use = profile["apis"][api_config.category].get("apiKey", "")
if api_key_to_use:
break
except Exception:
continue
# 检测提供商类型
provider = LLMModelService.detect_provider(api_config.apiUrl)
# 获取模型列表
models = LLMModelService.get_models_by_provider(
provider=provider,
api_key=api_config.apiKey or "",
api_key=api_key_to_use,
api_url=api_config.apiUrl
)