Merge branch 'dev' of https://github.com/MaiM-with-u/MaiBot into dev
This commit is contained in:
@@ -59,14 +59,14 @@ class SmartGreetingAction(BaseAction):
|
|||||||
# ===== 功能定义必须项 =====
|
# ===== 功能定义必须项 =====
|
||||||
action_parameters = {
|
action_parameters = {
|
||||||
"username": "要问候的用户名(可选)",
|
"username": "要问候的用户名(可选)",
|
||||||
"greeting_style": "问候风格:casual(随意)、formal(正式)、friendly(友好),默认casual"
|
"greeting_style": "问候风格:casual(随意)、formal(正式)、friendly(友好),默认casual",
|
||||||
}
|
}
|
||||||
|
|
||||||
action_require = [
|
action_require = [
|
||||||
"用户发送包含问候词汇的消息时使用",
|
"用户发送包含问候词汇的消息时使用",
|
||||||
"检测到新用户加入时使用",
|
"检测到新用户加入时使用",
|
||||||
"响应友好交流需求时使用",
|
"响应友好交流需求时使用",
|
||||||
"避免在短时间内重复问候同一用户"
|
"避免在短时间内重复问候同一用户",
|
||||||
]
|
]
|
||||||
|
|
||||||
associated_types = ["text", "emoji"]
|
associated_types = ["text", "emoji"]
|
||||||
@@ -115,12 +115,12 @@ class SmartGreetingAction(BaseAction):
|
|||||||
style_templates = {
|
style_templates = {
|
||||||
"casual": "嗨{username}!很开心见到你~",
|
"casual": "嗨{username}!很开心见到你~",
|
||||||
"formal": "您好{username},很荣幸为您服务!",
|
"formal": "您好{username},很荣幸为您服务!",
|
||||||
"friendly": "你好{username}!欢迎来到这里,希望我们能成为好朋友!😊"
|
"friendly": "你好{username}!欢迎来到这里,希望我们能成为好朋友!😊",
|
||||||
}
|
}
|
||||||
|
|
||||||
selected_template = style_templates.get(style, template)
|
selected_template = style_templates.get(style, template)
|
||||||
username_display = f" {username}" if username else ""
|
username_display = f" {username}" if username else ""
|
||||||
|
|
||||||
return selected_template.format(username=username_display)
|
return selected_template.format(username=username_display)
|
||||||
|
|
||||||
async def _generate_llm_greeting(self, username: str, style: str) -> str:
|
async def _generate_llm_greeting(self, username: str, style: str) -> str:
|
||||||
@@ -150,7 +150,7 @@ class SmartGreetingAction(BaseAction):
|
|||||||
model_config=model_config,
|
model_config=model_config,
|
||||||
request_type="plugin.greeting",
|
request_type="plugin.greeting",
|
||||||
temperature=0.7,
|
temperature=0.7,
|
||||||
max_tokens=100
|
max_tokens=100,
|
||||||
)
|
)
|
||||||
|
|
||||||
if success and response:
|
if success and response:
|
||||||
@@ -201,14 +201,14 @@ class HelpfulAction(BaseAction):
|
|||||||
action_parameters = {
|
action_parameters = {
|
||||||
"help_type": "帮助类型:explanation(解释)、suggestion(建议)、guidance(指导)、tips(提示)",
|
"help_type": "帮助类型:explanation(解释)、suggestion(建议)、guidance(指导)、tips(提示)",
|
||||||
"topic": "帮助主题或用户关心的问题",
|
"topic": "帮助主题或用户关心的问题",
|
||||||
"complexity": "复杂度:simple(简单)、medium(中等)、advanced(高级)"
|
"complexity": "复杂度:simple(简单)、medium(中等)、advanced(高级)",
|
||||||
}
|
}
|
||||||
|
|
||||||
action_require = [
|
action_require = [
|
||||||
"用户表达困惑或寻求帮助时使用",
|
"用户表达困惑或寻求帮助时使用",
|
||||||
"检测到用户遇到技术问题时使用",
|
"检测到用户遇到技术问题时使用",
|
||||||
"对话中出现知识盲点时主动提供帮助",
|
"对话中出现知识盲点时主动提供帮助",
|
||||||
"避免过度频繁地提供帮助,要恰到好处"
|
"避免过度频繁地提供帮助,要恰到好处",
|
||||||
]
|
]
|
||||||
|
|
||||||
associated_types = ["text", "emoji"]
|
associated_types = ["text", "emoji"]
|
||||||
@@ -246,7 +246,7 @@ class HelpfulAction(BaseAction):
|
|||||||
"""生成帮助消息"""
|
"""生成帮助消息"""
|
||||||
# 获取配置
|
# 获取配置
|
||||||
enable_llm = self.api.get_config("help.enable_llm", False)
|
enable_llm = self.api.get_config("help.enable_llm", False)
|
||||||
|
|
||||||
if enable_llm:
|
if enable_llm:
|
||||||
return await self._generate_llm_help(help_type, topic, complexity)
|
return await self._generate_llm_help(help_type, topic, complexity)
|
||||||
else:
|
else:
|
||||||
@@ -258,11 +258,11 @@ class HelpfulAction(BaseAction):
|
|||||||
"explanation": f"关于{topic},我来为你解释一下:这是一个{complexity}级别的概念...",
|
"explanation": f"关于{topic},我来为你解释一下:这是一个{complexity}级别的概念...",
|
||||||
"suggestion": f"针对{topic},我建议你可以尝试以下方法...",
|
"suggestion": f"针对{topic},我建议你可以尝试以下方法...",
|
||||||
"guidance": f"在{topic}方面,我可以为你提供一些指导...",
|
"guidance": f"在{topic}方面,我可以为你提供一些指导...",
|
||||||
"tips": f"关于{topic},这里有一些实用的小贴士..."
|
"tips": f"关于{topic},这里有一些实用的小贴士...",
|
||||||
}
|
}
|
||||||
|
|
||||||
base_message = help_templates.get(help_type, f"关于{topic},我很乐意为你提供帮助!")
|
base_message = help_templates.get(help_type, f"关于{topic},我很乐意为你提供帮助!")
|
||||||
|
|
||||||
# 根据复杂度调整消息
|
# 根据复杂度调整消息
|
||||||
if complexity == "advanced":
|
if complexity == "advanced":
|
||||||
base_message += "\n\n这个话题比较深入,需要一些基础知识。"
|
base_message += "\n\n这个话题比较深入,需要一些基础知识。"
|
||||||
@@ -291,11 +291,7 @@ class HelpfulAction(BaseAction):
|
|||||||
|
|
||||||
model_config = next(iter(models.values()))
|
model_config = next(iter(models.values()))
|
||||||
success, response, reasoning, model_name = await self.api.generate_with_model(
|
success, response, reasoning, model_name = await self.api.generate_with_model(
|
||||||
prompt=prompt,
|
prompt=prompt, model_config=model_config, request_type="plugin.help", temperature=0.7, max_tokens=300
|
||||||
model_config=model_config,
|
|
||||||
request_type="plugin.help",
|
|
||||||
temperature=0.7,
|
|
||||||
max_tokens=300
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if success and response:
|
if success and response:
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ class BaseAction(ABC):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def get_action_info(cls) -> "ActionInfo":
|
def get_action_info(cls) -> "ActionInfo":
|
||||||
"""从类属性生成ActionInfo
|
"""从类属性生成ActionInfo
|
||||||
|
|
||||||
所有信息都从类属性中读取,确保一致性和完整性。
|
所有信息都从类属性中读取,确保一致性和完整性。
|
||||||
Action类必须定义所有必要的类属性。
|
Action类必须定义所有必要的类属性。
|
||||||
|
|
||||||
@@ -376,7 +376,7 @@ class BaseAction(ABC):
|
|||||||
|
|
||||||
# 从类属性读取名称,如果没有定义则使用类名自动生成
|
# 从类属性读取名称,如果没有定义则使用类名自动生成
|
||||||
name = getattr(cls, "action_name", cls.__name__.lower().replace("action", ""))
|
name = getattr(cls, "action_name", cls.__name__.lower().replace("action", ""))
|
||||||
|
|
||||||
# 从类属性读取描述,如果没有定义则使用文档字符串的第一行
|
# 从类属性读取描述,如果没有定义则使用文档字符串的第一行
|
||||||
description = getattr(cls, "action_description", None)
|
description = getattr(cls, "action_description", None)
|
||||||
if description is None:
|
if description is None:
|
||||||
|
|||||||
@@ -36,17 +36,17 @@ class ChatMode(Enum):
|
|||||||
@dataclass
|
@dataclass
|
||||||
class PythonDependency:
|
class PythonDependency:
|
||||||
"""Python包依赖信息"""
|
"""Python包依赖信息"""
|
||||||
|
|
||||||
package_name: str # 包名称
|
package_name: str # 包名称
|
||||||
version: str = "" # 版本要求,例如: ">=1.0.0", "==2.1.3", ""表示任意版本
|
version: str = "" # 版本要求,例如: ">=1.0.0", "==2.1.3", ""表示任意版本
|
||||||
optional: bool = False # 是否为可选依赖
|
optional: bool = False # 是否为可选依赖
|
||||||
description: str = "" # 依赖描述
|
description: str = "" # 依赖描述
|
||||||
install_name: str = "" # 安装时的包名(如果与import名不同)
|
install_name: str = "" # 安装时的包名(如果与import名不同)
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
if not self.install_name:
|
if not self.install_name:
|
||||||
self.install_name = self.package_name
|
self.install_name = self.package_name
|
||||||
|
|
||||||
def get_pip_requirement(self) -> str:
|
def get_pip_requirement(self) -> str:
|
||||||
"""获取pip安装格式的依赖字符串"""
|
"""获取pip安装格式的依赖字符串"""
|
||||||
if self.version:
|
if self.version:
|
||||||
@@ -141,7 +141,7 @@ class PluginInfo:
|
|||||||
self.python_dependencies = []
|
self.python_dependencies = []
|
||||||
if self.metadata is None:
|
if self.metadata is None:
|
||||||
self.metadata = {}
|
self.metadata = {}
|
||||||
|
|
||||||
def get_missing_packages(self) -> List[PythonDependency]:
|
def get_missing_packages(self) -> List[PythonDependency]:
|
||||||
"""检查缺失的Python包"""
|
"""检查缺失的Python包"""
|
||||||
missing = []
|
missing = []
|
||||||
@@ -152,7 +152,7 @@ class PluginInfo:
|
|||||||
if not dep.optional:
|
if not dep.optional:
|
||||||
missing.append(dep)
|
missing.append(dep)
|
||||||
return missing
|
return missing
|
||||||
|
|
||||||
def get_pip_requirements(self) -> List[str]:
|
def get_pip_requirements(self) -> List[str]:
|
||||||
"""获取所有pip安装格式的依赖"""
|
"""获取所有pip安装格式的依赖"""
|
||||||
return [dep.get_pip_requirement() for dep in self.python_dependencies]
|
return [dep.get_pip_requirement() for dep in self.python_dependencies]
|
||||||
|
|||||||
@@ -7,8 +7,7 @@
|
|||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import importlib
|
import importlib
|
||||||
from typing import List, Dict, Tuple, Optional
|
from typing import List, Dict, Tuple
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from src.common.logger import get_logger
|
from src.common.logger import get_logger
|
||||||
from src.plugin_system.base.component_types import PythonDependency
|
from src.plugin_system.base.component_types import PythonDependency
|
||||||
@@ -22,19 +21,21 @@ class DependencyManager:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.install_log: List[str] = []
|
self.install_log: List[str] = []
|
||||||
self.failed_installs: Dict[str, str] = {}
|
self.failed_installs: Dict[str, str] = {}
|
||||||
|
|
||||||
def check_dependencies(self, dependencies: List[PythonDependency]) -> Tuple[List[PythonDependency], List[PythonDependency]]:
|
def check_dependencies(
|
||||||
|
self, dependencies: List[PythonDependency]
|
||||||
|
) -> Tuple[List[PythonDependency], List[PythonDependency]]:
|
||||||
"""检查依赖包状态
|
"""检查依赖包状态
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
dependencies: 依赖包列表
|
dependencies: 依赖包列表
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple[List[PythonDependency], List[PythonDependency]]: (缺失的依赖, 可选缺失的依赖)
|
Tuple[List[PythonDependency], List[PythonDependency]]: (缺失的依赖, 可选缺失的依赖)
|
||||||
"""
|
"""
|
||||||
missing_required = []
|
missing_required = []
|
||||||
missing_optional = []
|
missing_optional = []
|
||||||
|
|
||||||
for dep in dependencies:
|
for dep in dependencies:
|
||||||
if not self._is_package_available(dep.package_name):
|
if not self._is_package_available(dep.package_name):
|
||||||
if dep.optional:
|
if dep.optional:
|
||||||
@@ -45,9 +46,9 @@ class DependencyManager:
|
|||||||
logger.error(f"必需依赖包缺失: {dep.package_name} - {dep.description}")
|
logger.error(f"必需依赖包缺失: {dep.package_name} - {dep.description}")
|
||||||
else:
|
else:
|
||||||
logger.debug(f"依赖包已存在: {dep.package_name}")
|
logger.debug(f"依赖包已存在: {dep.package_name}")
|
||||||
|
|
||||||
return missing_required, missing_optional
|
return missing_required, missing_optional
|
||||||
|
|
||||||
def _is_package_available(self, package_name: str) -> bool:
|
def _is_package_available(self, package_name: str) -> bool:
|
||||||
"""检查包是否可用"""
|
"""检查包是否可用"""
|
||||||
try:
|
try:
|
||||||
@@ -55,34 +56,34 @@ class DependencyManager:
|
|||||||
return True
|
return True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def install_dependencies(self, dependencies: List[PythonDependency], auto_install: bool = False) -> bool:
|
def install_dependencies(self, dependencies: List[PythonDependency], auto_install: bool = False) -> bool:
|
||||||
"""安装依赖包
|
"""安装依赖包
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
dependencies: 需要安装的依赖包列表
|
dependencies: 需要安装的依赖包列表
|
||||||
auto_install: 是否自动安装(True时不询问用户)
|
auto_install: 是否自动安装(True时不询问用户)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: 安装是否成功
|
bool: 安装是否成功
|
||||||
"""
|
"""
|
||||||
if not dependencies:
|
if not dependencies:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
logger.info(f"需要安装 {len(dependencies)} 个依赖包")
|
logger.info(f"需要安装 {len(dependencies)} 个依赖包")
|
||||||
|
|
||||||
# 显示将要安装的包
|
# 显示将要安装的包
|
||||||
for dep in dependencies:
|
for dep in dependencies:
|
||||||
install_cmd = dep.get_pip_requirement()
|
install_cmd = dep.get_pip_requirement()
|
||||||
logger.info(f" - {install_cmd} {'(可选)' if dep.optional else '(必需)'}")
|
logger.info(f" - {install_cmd} {'(可选)' if dep.optional else '(必需)'}")
|
||||||
if dep.description:
|
if dep.description:
|
||||||
logger.info(f" 说明: {dep.description}")
|
logger.info(f" 说明: {dep.description}")
|
||||||
|
|
||||||
if not auto_install:
|
if not auto_install:
|
||||||
# 这里可以添加用户确认逻辑
|
# 这里可以添加用户确认逻辑
|
||||||
logger.warning("手动安装模式:请手动运行 pip install 命令安装依赖包")
|
logger.warning("手动安装模式:请手动运行 pip install 命令安装依赖包")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# 执行安装
|
# 执行安装
|
||||||
success_count = 0
|
success_count = 0
|
||||||
for dep in dependencies:
|
for dep in dependencies:
|
||||||
@@ -90,26 +91,26 @@ class DependencyManager:
|
|||||||
success_count += 1
|
success_count += 1
|
||||||
else:
|
else:
|
||||||
self.failed_installs[dep.package_name] = f"安装失败: {dep.get_pip_requirement()}"
|
self.failed_installs[dep.package_name] = f"安装失败: {dep.get_pip_requirement()}"
|
||||||
|
|
||||||
logger.info(f"依赖安装完成: {success_count}/{len(dependencies)} 个成功")
|
logger.info(f"依赖安装完成: {success_count}/{len(dependencies)} 个成功")
|
||||||
return success_count == len(dependencies)
|
return success_count == len(dependencies)
|
||||||
|
|
||||||
def _install_single_package(self, dependency: PythonDependency) -> bool:
|
def _install_single_package(self, dependency: PythonDependency) -> bool:
|
||||||
"""安装单个包"""
|
"""安装单个包"""
|
||||||
pip_requirement = dependency.get_pip_requirement()
|
pip_requirement = dependency.get_pip_requirement()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
logger.info(f"正在安装: {pip_requirement}")
|
logger.info(f"正在安装: {pip_requirement}")
|
||||||
|
|
||||||
# 使用subprocess安装包
|
# 使用subprocess安装包
|
||||||
cmd = [sys.executable, "-m", "pip", "install", pip_requirement]
|
cmd = [sys.executable, "-m", "pip", "install", pip_requirement]
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
cmd,
|
cmd,
|
||||||
capture_output=True,
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
timeout=300 # 5分钟超时
|
timeout=300, # 5分钟超时
|
||||||
)
|
)
|
||||||
|
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
logger.info(f"✅ 成功安装: {pip_requirement}")
|
logger.info(f"✅ 成功安装: {pip_requirement}")
|
||||||
self.install_log.append(f"成功安装: {pip_requirement}")
|
self.install_log.append(f"成功安装: {pip_requirement}")
|
||||||
@@ -119,28 +120,29 @@ class DependencyManager:
|
|||||||
logger.error(f"错误输出: {result.stderr}")
|
logger.error(f"错误输出: {result.stderr}")
|
||||||
self.install_log.append(f"安装失败: {pip_requirement} - {result.stderr}")
|
self.install_log.append(f"安装失败: {pip_requirement} - {result.stderr}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
logger.error(f"❌ 安装超时: {pip_requirement}")
|
logger.error(f"❌ 安装超时: {pip_requirement}")
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"❌ 安装异常: {pip_requirement} - {str(e)}")
|
logger.error(f"❌ 安装异常: {pip_requirement} - {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def generate_requirements_file(self, plugins_dependencies: List[List[PythonDependency]],
|
def generate_requirements_file(
|
||||||
output_path: str = "plugin_requirements.txt") -> bool:
|
self, plugins_dependencies: List[List[PythonDependency]], output_path: str = "plugin_requirements.txt"
|
||||||
|
) -> bool:
|
||||||
"""生成插件依赖的requirements文件
|
"""生成插件依赖的requirements文件
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
plugins_dependencies: 所有插件的依赖列表
|
plugins_dependencies: 所有插件的依赖列表
|
||||||
output_path: 输出文件路径
|
output_path: 输出文件路径
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: 生成是否成功
|
bool: 生成是否成功
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
all_deps = {}
|
all_deps = {}
|
||||||
|
|
||||||
# 合并所有插件的依赖
|
# 合并所有插件的依赖
|
||||||
for plugin_deps in plugins_dependencies:
|
for plugin_deps in plugins_dependencies:
|
||||||
for dep in plugin_deps:
|
for dep in plugin_deps:
|
||||||
@@ -152,39 +154,39 @@ class DependencyManager:
|
|||||||
logger.warning(f"依赖版本冲突: {key} ({existing.version} vs {dep.version})")
|
logger.warning(f"依赖版本冲突: {key} ({existing.version} vs {dep.version})")
|
||||||
else:
|
else:
|
||||||
all_deps[key] = dep
|
all_deps[key] = dep
|
||||||
|
|
||||||
# 写入requirements文件
|
# 写入requirements文件
|
||||||
with open(output_path, "w", encoding="utf-8") as f:
|
with open(output_path, "w", encoding="utf-8") as f:
|
||||||
f.write("# 插件依赖包自动生成\n")
|
f.write("# 插件依赖包自动生成\n")
|
||||||
f.write("# Auto-generated plugin dependencies\n\n")
|
f.write("# Auto-generated plugin dependencies\n\n")
|
||||||
|
|
||||||
# 按包名排序
|
# 按包名排序
|
||||||
sorted_deps = sorted(all_deps.values(), key=lambda x: x.install_name)
|
sorted_deps = sorted(all_deps.values(), key=lambda x: x.install_name)
|
||||||
|
|
||||||
for dep in sorted_deps:
|
for dep in sorted_deps:
|
||||||
requirement = dep.get_pip_requirement()
|
requirement = dep.get_pip_requirement()
|
||||||
if dep.description:
|
if dep.description:
|
||||||
f.write(f"# {dep.description}\n")
|
f.write(f"# {dep.description}\n")
|
||||||
if dep.optional:
|
if dep.optional:
|
||||||
f.write(f"# Optional dependency\n")
|
f.write("# Optional dependency\n")
|
||||||
f.write(f"{requirement}\n\n")
|
f.write(f"{requirement}\n\n")
|
||||||
|
|
||||||
logger.info(f"已生成插件依赖文件: {output_path} ({len(all_deps)} 个包)")
|
logger.info(f"已生成插件依赖文件: {output_path} ({len(all_deps)} 个包)")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"生成requirements文件失败: {str(e)}")
|
logger.error(f"生成requirements文件失败: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_install_summary(self) -> Dict[str, any]:
|
def get_install_summary(self) -> Dict[str, any]:
|
||||||
"""获取安装摘要"""
|
"""获取安装摘要"""
|
||||||
return {
|
return {
|
||||||
"install_log": self.install_log.copy(),
|
"install_log": self.install_log.copy(),
|
||||||
"failed_installs": self.failed_installs.copy(),
|
"failed_installs": self.failed_installs.copy(),
|
||||||
"total_attempts": len(self.install_log),
|
"total_attempts": len(self.install_log),
|
||||||
"failed_count": len(self.failed_installs)
|
"failed_count": len(self.failed_installs),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# 全局依赖管理器实例
|
# 全局依赖管理器实例
|
||||||
dependency_manager = DependencyManager()
|
dependency_manager = DependencyManager()
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ if TYPE_CHECKING:
|
|||||||
from src.common.logger import get_logger
|
from src.common.logger import get_logger
|
||||||
from src.plugin_system.core.component_registry import component_registry
|
from src.plugin_system.core.component_registry import component_registry
|
||||||
from src.plugin_system.core.dependency_manager import dependency_manager
|
from src.plugin_system.core.dependency_manager import dependency_manager
|
||||||
from src.plugin_system.base.component_types import ComponentType, PluginInfo, PythonDependency
|
from src.plugin_system.base.component_types import ComponentType, PluginInfo
|
||||||
|
|
||||||
logger = get_logger("plugin_manager")
|
logger = get_logger("plugin_manager")
|
||||||
|
|
||||||
@@ -347,57 +347,55 @@ class PluginManager:
|
|||||||
|
|
||||||
def check_all_dependencies(self, auto_install: bool = False) -> Dict[str, any]:
|
def check_all_dependencies(self, auto_install: bool = False) -> Dict[str, any]:
|
||||||
"""检查所有插件的Python依赖包
|
"""检查所有插件的Python依赖包
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
auto_install: 是否自动安装缺失的依赖包
|
auto_install: 是否自动安装缺失的依赖包
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Dict[str, any]: 检查结果摘要
|
Dict[str, any]: 检查结果摘要
|
||||||
"""
|
"""
|
||||||
logger.info("开始检查所有插件的Python依赖包...")
|
logger.info("开始检查所有插件的Python依赖包...")
|
||||||
|
|
||||||
all_required_missing = []
|
all_required_missing = []
|
||||||
all_optional_missing = []
|
all_optional_missing = []
|
||||||
plugin_status = {}
|
plugin_status = {}
|
||||||
|
|
||||||
for plugin_name, plugin_instance in self.loaded_plugins.items():
|
for plugin_name, _plugin_instance in self.loaded_plugins.items():
|
||||||
plugin_info = component_registry.get_plugin_info(plugin_name)
|
plugin_info = component_registry.get_plugin_info(plugin_name)
|
||||||
if not plugin_info or not plugin_info.python_dependencies:
|
if not plugin_info or not plugin_info.python_dependencies:
|
||||||
plugin_status[plugin_name] = {"status": "no_dependencies", "missing": []}
|
plugin_status[plugin_name] = {"status": "no_dependencies", "missing": []}
|
||||||
continue
|
continue
|
||||||
|
|
||||||
logger.info(f"检查插件 {plugin_name} 的依赖...")
|
logger.info(f"检查插件 {plugin_name} 的依赖...")
|
||||||
|
|
||||||
missing_required, missing_optional = dependency_manager.check_dependencies(
|
missing_required, missing_optional = dependency_manager.check_dependencies(plugin_info.python_dependencies)
|
||||||
plugin_info.python_dependencies
|
|
||||||
)
|
|
||||||
|
|
||||||
if missing_required:
|
if missing_required:
|
||||||
all_required_missing.extend(missing_required)
|
all_required_missing.extend(missing_required)
|
||||||
plugin_status[plugin_name] = {
|
plugin_status[plugin_name] = {
|
||||||
"status": "missing_required",
|
"status": "missing_required",
|
||||||
"missing": [dep.package_name for dep in missing_required],
|
"missing": [dep.package_name for dep in missing_required],
|
||||||
"optional_missing": [dep.package_name for dep in missing_optional]
|
"optional_missing": [dep.package_name for dep in missing_optional],
|
||||||
}
|
}
|
||||||
logger.error(f"插件 {plugin_name} 缺少必需依赖: {[dep.package_name for dep in missing_required]}")
|
logger.error(f"插件 {plugin_name} 缺少必需依赖: {[dep.package_name for dep in missing_required]}")
|
||||||
elif missing_optional:
|
elif missing_optional:
|
||||||
all_optional_missing.extend(missing_optional)
|
all_optional_missing.extend(missing_optional)
|
||||||
plugin_status[plugin_name] = {
|
plugin_status[plugin_name] = {
|
||||||
"status": "missing_optional",
|
"status": "missing_optional",
|
||||||
"missing": [],
|
"missing": [],
|
||||||
"optional_missing": [dep.package_name for dep in missing_optional]
|
"optional_missing": [dep.package_name for dep in missing_optional],
|
||||||
}
|
}
|
||||||
logger.warning(f"插件 {plugin_name} 缺少可选依赖: {[dep.package_name for dep in missing_optional]}")
|
logger.warning(f"插件 {plugin_name} 缺少可选依赖: {[dep.package_name for dep in missing_optional]}")
|
||||||
else:
|
else:
|
||||||
plugin_status[plugin_name] = {"status": "ok", "missing": []}
|
plugin_status[plugin_name] = {"status": "ok", "missing": []}
|
||||||
logger.info(f"插件 {plugin_name} 依赖检查通过")
|
logger.info(f"插件 {plugin_name} 依赖检查通过")
|
||||||
|
|
||||||
# 汇总结果
|
# 汇总结果
|
||||||
total_missing = len(set(dep.package_name for dep in all_required_missing))
|
total_missing = len(set(dep.package_name for dep in all_required_missing))
|
||||||
total_optional_missing = len(set(dep.package_name for dep in all_optional_missing))
|
total_optional_missing = len(set(dep.package_name for dep in all_optional_missing))
|
||||||
|
|
||||||
logger.info(f"依赖检查完成 - 缺少必需包: {total_missing}个, 缺少可选包: {total_optional_missing}个")
|
logger.info(f"依赖检查完成 - 缺少必需包: {total_missing}个, 缺少可选包: {total_optional_missing}个")
|
||||||
|
|
||||||
# 如果需要自动安装
|
# 如果需要自动安装
|
||||||
install_success = True
|
install_success = True
|
||||||
if auto_install and all_required_missing:
|
if auto_install and all_required_missing:
|
||||||
@@ -405,47 +403,48 @@ class PluginManager:
|
|||||||
unique_required = {}
|
unique_required = {}
|
||||||
for dep in all_required_missing:
|
for dep in all_required_missing:
|
||||||
unique_required[dep.package_name] = dep
|
unique_required[dep.package_name] = dep
|
||||||
|
|
||||||
logger.info(f"开始自动安装 {len(unique_required)} 个必需依赖包...")
|
logger.info(f"开始自动安装 {len(unique_required)} 个必需依赖包...")
|
||||||
install_success = dependency_manager.install_dependencies(
|
install_success = dependency_manager.install_dependencies(list(unique_required.values()), auto_install=True)
|
||||||
list(unique_required.values()),
|
|
||||||
auto_install=True
|
|
||||||
)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"total_plugins_checked": len(plugin_status),
|
"total_plugins_checked": len(plugin_status),
|
||||||
"plugins_with_missing_required": len([p for p in plugin_status.values() if p["status"] == "missing_required"]),
|
"plugins_with_missing_required": len(
|
||||||
"plugins_with_missing_optional": len([p for p in plugin_status.values() if p["status"] == "missing_optional"]),
|
[p for p in plugin_status.values() if p["status"] == "missing_required"]
|
||||||
|
),
|
||||||
|
"plugins_with_missing_optional": len(
|
||||||
|
[p for p in plugin_status.values() if p["status"] == "missing_optional"]
|
||||||
|
),
|
||||||
"total_missing_required": total_missing,
|
"total_missing_required": total_missing,
|
||||||
"total_missing_optional": total_optional_missing,
|
"total_missing_optional": total_optional_missing,
|
||||||
"plugin_status": plugin_status,
|
"plugin_status": plugin_status,
|
||||||
"auto_install_attempted": auto_install and bool(all_required_missing),
|
"auto_install_attempted": auto_install and bool(all_required_missing),
|
||||||
"auto_install_success": install_success,
|
"auto_install_success": install_success,
|
||||||
"install_summary": dependency_manager.get_install_summary()
|
"install_summary": dependency_manager.get_install_summary(),
|
||||||
}
|
}
|
||||||
|
|
||||||
def generate_plugin_requirements(self, output_path: str = "plugin_requirements.txt") -> bool:
|
def generate_plugin_requirements(self, output_path: str = "plugin_requirements.txt") -> bool:
|
||||||
"""生成所有插件依赖的requirements文件
|
"""生成所有插件依赖的requirements文件
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
output_path: 输出文件路径
|
output_path: 输出文件路径
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: 生成是否成功
|
bool: 生成是否成功
|
||||||
"""
|
"""
|
||||||
logger.info("开始生成插件依赖requirements文件...")
|
logger.info("开始生成插件依赖requirements文件...")
|
||||||
|
|
||||||
all_dependencies = []
|
all_dependencies = []
|
||||||
|
|
||||||
for plugin_name, plugin_instance in self.loaded_plugins.items():
|
for plugin_name, _plugin_instance in self.loaded_plugins.items():
|
||||||
plugin_info = component_registry.get_plugin_info(plugin_name)
|
plugin_info = component_registry.get_plugin_info(plugin_name)
|
||||||
if plugin_info and plugin_info.python_dependencies:
|
if plugin_info and plugin_info.python_dependencies:
|
||||||
all_dependencies.append(plugin_info.python_dependencies)
|
all_dependencies.append(plugin_info.python_dependencies)
|
||||||
|
|
||||||
if not all_dependencies:
|
if not all_dependencies:
|
||||||
logger.info("没有找到任何插件依赖")
|
logger.info("没有找到任何插件依赖")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return dependency_manager.generate_requirements_file(all_dependencies, output_path)
|
return dependency_manager.generate_requirements_file(all_dependencies, output_path)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class MuteAction(BaseAction):
|
|||||||
]
|
]
|
||||||
|
|
||||||
# 关联类型
|
# 关联类型
|
||||||
associated_types = ["text","command"]
|
associated_types = ["text", "command"]
|
||||||
|
|
||||||
async def execute(self) -> Tuple[bool, Optional[str]]:
|
async def execute(self) -> Tuple[bool, Optional[str]]:
|
||||||
"""执行智能禁言判定"""
|
"""执行智能禁言判定"""
|
||||||
|
|||||||
Reference in New Issue
Block a user