feat: 优化任务调度和插件管理,支持路径规范化及插件 ID 自动生成

This commit is contained in:
墨梓柒
2025-11-24 21:29:04 +08:00
parent a1dd26d578
commit 513182067d
8 changed files with 248 additions and 79 deletions

View File

@@ -8,7 +8,7 @@ from fastapi import APIRouter, HTTPException, Body
from typing import Any
from src.common.logger import get_logger
from src.config.config import Config, APIAdapterConfig, CONFIG_DIR
from src.config.config import Config, APIAdapterConfig, CONFIG_DIR, PROJECT_ROOT
from src.config.official_configs import (
BotConfig,
PersonalityConfig,
@@ -421,6 +421,38 @@ async def update_model_config_section(section_name: str, section_data: Any = Bod
# ===== 适配器配置管理接口 =====
def _normalize_adapter_path(path: str) -> str:
"""将路径转换为绝对路径(如果是相对路径,则相对于项目根目录)"""
if not path:
return path
# 如果已经是绝对路径,直接返回
if os.path.isabs(path):
return path
# 相对路径,转换为相对于项目根目录的绝对路径
return os.path.normpath(os.path.join(PROJECT_ROOT, path))
def _to_relative_path(path: str) -> str:
"""尝试将绝对路径转换为相对于项目根目录的相对路径,如果无法转换则返回原路径"""
if not path or not os.path.isabs(path):
return path
try:
# 尝试获取相对路径
rel_path = os.path.relpath(path, PROJECT_ROOT)
# 如果相对路径不是以 .. 开头(说明文件在项目目录内),则返回相对路径
if not rel_path.startswith('..'):
return rel_path
except (ValueError, TypeError):
# 在 Windows 上如果路径在不同驱动器relpath 会抛出 ValueError
pass
# 无法转换为相对路径,返回绝对路径
return path
@router.get("/adapter-config/path")
async def get_adapter_config_path():
"""获取保存的适配器配置文件路径"""
@@ -438,13 +470,19 @@ async def get_adapter_config_path():
if not adapter_config_path:
return {"success": True, "path": None}
# 将路径规范化为绝对路径
abs_path = _normalize_adapter_path(adapter_config_path)
# 检查文件是否存在并返回最后修改时间
if os.path.exists(adapter_config_path):
if os.path.exists(abs_path):
import datetime
mtime = os.path.getmtime(adapter_config_path)
mtime = os.path.getmtime(abs_path)
last_modified = datetime.datetime.fromtimestamp(mtime).isoformat()
return {"success": True, "path": adapter_config_path, "lastModified": last_modified}
# 返回相对路径(如果可能)
display_path = _to_relative_path(abs_path)
return {"success": True, "path": display_path, "lastModified": last_modified}
else:
# 文件不存在,返回原路径
return {"success": True, "path": adapter_config_path, "lastModified": None}
except Exception as e:
@@ -471,15 +509,21 @@ async def save_adapter_config_path(data: dict[str, str] = Body(...)):
else:
webui_data = {}
# 将路径规范化为绝对路径
abs_path = _normalize_adapter_path(path)
# 尝试转换为相对路径保存(如果文件在项目目录内)
save_path = _to_relative_path(abs_path)
# 更新路径
webui_data["adapter_config_path"] = path
webui_data["adapter_config_path"] = save_path
# 保存
os.makedirs("data", exist_ok=True)
with open(webui_data_path, "w", encoding="utf-8") as f:
json.dump(webui_data, f, ensure_ascii=False, indent=2)
logger.info(f"适配器配置路径已保存: {path}")
logger.info(f"适配器配置路径已保存: {save_path}(绝对路径: {abs_path}")
return {"success": True, "message": "路径已保存"}
except HTTPException:
@@ -496,19 +540,22 @@ async def get_adapter_config(path: str):
if not path:
raise HTTPException(status_code=400, detail="路径参数不能为空")
# 将路径规范化为绝对路径
abs_path = _normalize_adapter_path(path)
# 检查文件是否存在
if not os.path.exists(path):
if not os.path.exists(abs_path):
raise HTTPException(status_code=404, detail=f"配置文件不存在: {path}")
# 检查文件扩展名
if not path.endswith(".toml"):
if not abs_path.endswith(".toml"):
raise HTTPException(status_code=400, detail="只支持 .toml 格式的配置文件")
# 读取文件内容
with open(path, "r", encoding="utf-8") as f:
with open(abs_path, "r", encoding="utf-8") as f:
content = f.read()
logger.info(f"已读取适配器配置: {path}")
logger.info(f"已读取适配器配置: {path} (绝对路径: {abs_path})")
return {"success": True, "content": content}
except HTTPException:
@@ -530,8 +577,11 @@ async def save_adapter_config(data: dict[str, str] = Body(...)):
if content is None:
raise HTTPException(status_code=400, detail="配置内容不能为空")
# 将路径规范化为绝对路径
abs_path = _normalize_adapter_path(path)
# 检查文件扩展名
if not path.endswith(".toml"):
if not abs_path.endswith(".toml"):
raise HTTPException(status_code=400, detail="只支持 .toml 格式的配置文件")
# 验证 TOML 格式
@@ -542,13 +592,15 @@ async def save_adapter_config(data: dict[str, str] = Body(...)):
raise HTTPException(status_code=400, detail=f"TOML 格式错误: {str(e)}")
# 确保目录存在
os.makedirs(os.path.dirname(path) if os.path.dirname(path) else ".", exist_ok=True)
dir_path = os.path.dirname(abs_path)
if dir_path:
os.makedirs(dir_path, exist_ok=True)
# 保存文件
with open(path, "w", encoding="utf-8") as f:
with open(abs_path, "w", encoding="utf-8") as f:
f.write(content)
logger.info(f"适配器配置已保存: {path}")
logger.info(f"适配器配置已保存: {path} (绝对路径: {abs_path})")
return {"success": True, "message": "配置已保存"}
except HTTPException: