fix:修复插件组件无法正确获取插件配置的问题

This commit is contained in:
Windpicker-owo
2025-09-06 20:39:59 +08:00
parent 657b12015b
commit 742b47c099
7 changed files with 116 additions and 22 deletions

1
bot.py
View File

@@ -82,7 +82,6 @@ def easter_egg():
async def graceful_shutdown(): async def graceful_shutdown():
try: try:
logger.info("正在优雅关闭麦麦...") logger.info("正在优雅关闭麦麦...")
# 停止所有异步任务 # 停止所有异步任务
await async_task_manager.stop_and_wait_all_tasks() await async_task_manager.stop_and_wait_all_tasks()

View File

@@ -113,6 +113,9 @@ class MainSystem:
"""清理资源""" """清理资源"""
try: try:
# 停止消息重组器 # 停止消息重组器
from src.plugin_system.core.event_manager import event_manager
from src.plugin_system import EventType
asyncio.run(event_manager.trigger_event(EventType.ON_STOP,plugin_name="SYSTEM"))
from src.utils.message_chunker import reassembler from src.utils.message_chunker import reassembler
import asyncio import asyncio

View File

@@ -34,8 +34,14 @@ class BaseEventHandler(ABC):
if EventType.UNKNOWN in self.init_subscribe: if EventType.UNKNOWN in self.init_subscribe:
raise NotImplementedError("事件处理器必须指定 event_type") raise NotImplementedError("事件处理器必须指定 event_type")
from src.plugin_system.core.component_registry import component_registry # 优先使用实例级别的 plugin_config如果没有则使用类级别的配置
self.plugin_config = component_registry.get_plugin_config(self.plugin_name) # 事件管理器会在注册时通过 set_plugin_config 设置实例级别的配置
instance_config = getattr(self, "plugin_config", None)
if instance_config is not None:
self.plugin_config = instance_config
else:
# 如果实例级别没有配置,则使用类级别的配置(向后兼容)
self.plugin_config = getattr(self.__class__, "plugin_config", {})
@abstractmethod @abstractmethod
async def execute(self, kwargs: dict | None) -> Tuple[bool, bool, Optional[str]]: async def execute(self, kwargs: dict | None) -> Tuple[bool, bool, Optional[str]]:
@@ -101,6 +107,9 @@ class BaseEventHandler(ABC):
""" """
self.plugin_name = plugin_name self.plugin_name = plugin_name
def set_plugin_config(self,plugin_config) -> None:
self.plugin_config = plugin_config
def get_config(self, key: str, default=None): def get_config(self, key: str, default=None):
"""获取插件配置值,支持嵌套键访问 """获取插件配置值,支持嵌套键访问

View File

@@ -1,3 +1,4 @@
from pathlib import Path
import re import re
from typing import Dict, List, Optional, Any, Pattern, Tuple, Union, Type from typing import Dict, List, Optional, Any, Pattern, Tuple, Union, Type
@@ -170,6 +171,8 @@ class ComponentRegistry:
return False return False
action_class.plugin_name = action_info.plugin_name action_class.plugin_name = action_info.plugin_name
# 设置插件配置
action_class.plugin_config = self.get_plugin_config(action_info.plugin_name) or {}
self._action_registry[action_name] = action_class self._action_registry[action_name] = action_class
# 如果启用,添加到默认动作集 # 如果启用,添加到默认动作集
@@ -188,6 +191,8 @@ class ComponentRegistry:
return False return False
command_class.plugin_name = command_info.plugin_name command_class.plugin_name = command_info.plugin_name
# 设置插件配置
command_class.plugin_config = self.get_plugin_config(command_info.plugin_name) or {}
self._command_registry[command_name] = command_class self._command_registry[command_name] = command_class
# 如果启用了且有匹配模式 # 如果启用了且有匹配模式
@@ -220,6 +225,8 @@ class ComponentRegistry:
self._plus_command_registry: Dict[str, Type[PlusCommand]] = {} self._plus_command_registry: Dict[str, Type[PlusCommand]] = {}
plus_command_class.plugin_name = plus_command_info.plugin_name plus_command_class.plugin_name = plus_command_info.plugin_name
# 设置插件配置
plus_command_class.plugin_config = self.get_plugin_config(plus_command_info.plugin_name) or {}
self._plus_command_registry[plus_command_name] = plus_command_class self._plus_command_registry[plus_command_name] = plus_command_class
logger.debug(f"已注册PlusCommand组件: {plus_command_name}") logger.debug(f"已注册PlusCommand组件: {plus_command_name}")
@@ -230,6 +237,8 @@ class ComponentRegistry:
tool_name = tool_info.name tool_name = tool_info.name
tool_class.plugin_name = tool_info.plugin_name tool_class.plugin_name = tool_info.plugin_name
# 设置插件配置
tool_class.plugin_config = self.get_plugin_config(tool_info.plugin_name) or {}
self._tool_registry[tool_name] = tool_class self._tool_registry[tool_name] = tool_class
# 如果是llm可用的且启用的工具,添加到 llm可用工具列表 # 如果是llm可用的且启用的工具,添加到 llm可用工具列表
@@ -249,6 +258,8 @@ class ComponentRegistry:
return False return False
handler_class.plugin_name = handler_info.plugin_name handler_class.plugin_name = handler_info.plugin_name
# 设置插件配置
handler_class.plugin_config = self.get_plugin_config(handler_info.plugin_name) or {}
self._event_handler_registry[handler_name] = handler_class self._event_handler_registry[handler_name] = handler_class
if not handler_info.enabled: if not handler_info.enabled:
@@ -259,7 +270,7 @@ class ComponentRegistry:
# 使用EventManager进行事件处理器注册 # 使用EventManager进行事件处理器注册
from src.plugin_system.core.event_manager import event_manager from src.plugin_system.core.event_manager import event_manager
return event_manager.register_event_handler(handler_class) return event_manager.register_event_handler(handler_class,self.get_plugin_config(handler_info.plugin_name) or {})
# === 组件移除相关 === # === 组件移除相关 ===
@@ -656,20 +667,35 @@ class ComponentRegistry:
plugin_info = self.get_plugin_info(plugin_name) plugin_info = self.get_plugin_info(plugin_name)
return plugin_info.components if plugin_info else [] return plugin_info.components if plugin_info else []
def get_plugin_config(self, plugin_name: str) -> Optional[dict]: def get_plugin_config(self, plugin_name: str) -> dict:
"""获取插件配置 """获取插件配置
Args: Args:
plugin_name: 插件名称 plugin_name: 插件名称
Returns: Returns:
Optional[dict]: 插件配置字典或None dict: 插件配置字典,如果插件实例不存在或配置为空,返回空字典
""" """
# 从插件管理器获取插件实例的配置 # 从插件管理器获取插件实例的配置
from src.plugin_system.core.plugin_manager import plugin_manager from src.plugin_system.core.plugin_manager import plugin_manager
plugin_instance = plugin_manager.get_plugin_instance(plugin_name) plugin_instance = plugin_manager.get_plugin_instance(plugin_name)
return plugin_instance.config if plugin_instance else None if plugin_instance and plugin_instance.config:
return plugin_instance.config
# 如果插件实例不存在,尝试从配置文件读取
try:
import toml
config_path = Path("config") / "plugins" / plugin_name / "config.toml"
if config_path.exists():
with open(config_path, 'r', encoding='utf-8') as f:
config_data = toml.load(f)
logger.debug(f"从配置文件读取插件 {plugin_name} 的配置")
return config_data
except Exception as e:
logger.debug(f"读取插件 {plugin_name} 配置文件失败: {e}")
return {}
def get_registry_stats(self) -> Dict[str, Any]: def get_registry_stats(self) -> Dict[str, Any]:
"""获取注册中心统计信息""" """获取注册中心统计信息"""

View File

@@ -166,6 +166,7 @@ class EventManager:
# 创建事件处理器实例,传递插件配置 # 创建事件处理器实例,传递插件配置
handler_instance = handler_class() handler_instance = handler_class()
handler_instance.plugin_config = plugin_config
if plugin_config is not None and hasattr(handler_instance, 'set_plugin_config'): if plugin_config is not None and hasattr(handler_instance, 'set_plugin_config'):
handler_instance.set_plugin_config(plugin_config) handler_instance.set_plugin_config(plugin_config)

View File

@@ -233,21 +233,6 @@ class LauchNapcatAdapterHandler(BaseEventHandler):
logger.info("功能配置已迁移到插件系统") logger.info("功能配置已迁移到插件系统")
logger.info("开始启动Napcat Adapter") logger.info("开始启动Napcat Adapter")
message_send_instance.maibot_router = router message_send_instance.maibot_router = router
# 设置插件配置
message_send_instance.set_plugin_config(self.plugin_config)
# 设置chunker的插件配置
chunker.set_plugin_config(self.plugin_config)
# 设置response_pool的插件配置
from .src.response_pool import set_plugin_config as set_response_pool_config
set_response_pool_config(self.plugin_config)
# 设置send_handler的插件配置
send_handler.set_plugin_config(self.plugin_config)
# 设置message_handler的插件配置
message_handler.set_plugin_config(self.plugin_config)
# 设置notice_handler的插件配置
notice_handler.set_plugin_config(self.plugin_config)
# 设置meta_event_handler的插件配置
meta_event_handler.set_plugin_config(self.plugin_config)
# 创建单独的异步任务,防止阻塞主线程 # 创建单独的异步任务,防止阻塞主线程
asyncio.create_task(napcat_server(self.plugin_config)) asyncio.create_task(napcat_server(self.plugin_config))
asyncio.create_task(mmc_start_com(self.plugin_config)) asyncio.create_task(mmc_start_com(self.plugin_config))
@@ -355,3 +340,21 @@ class NapcatAdapterPlugin(BasePlugin):
if issubclass(handler, BaseEventHandler): if issubclass(handler, BaseEventHandler):
components.append((handler.get_handler_info(), handler)) components.append((handler.get_handler_info(), handler))
return components return components
async def on_plugin_loaded(self):
# 设置插件配置
message_send_instance.set_plugin_config(self.config)
# 设置chunker的插件配置
chunker.set_plugin_config(self.config)
# 设置response_pool的插件配置
from .src.response_pool import set_plugin_config as set_response_pool_config
set_response_pool_config(self.config)
# 设置send_handler的插件配置
send_handler.set_plugin_config(self.config)
# 设置message_handler的插件配置
message_handler.set_plugin_config(self.config)
# 设置notice_handler的插件配置
notice_handler.set_plugin_config(self.config)
# 设置meta_event_handler的插件配置
meta_event_handler.set_plugin_config(self.config)
# 设置其他handler的插件配置现在由component_registry在注册时自动设置

53
test_plugin_config_fix.py Normal file
View File

@@ -0,0 +1,53 @@
#!/usr/bin/env python3
"""
测试脚本用于验证LauchNapcatAdapterHandler的plugin_config修复
"""
import sys
import os
from pathlib import Path
# 添加项目根目录到Python路径
project_root = Path(__file__).parent
sys.path.insert(0, str(project_root))
from src.plugins.built_in.napcat_adapter_plugin.plugin import LauchNapcatAdapterHandler
def test_plugin_config_fix():
"""测试plugin_config修复"""
print("测试LauchNapcatAdapterHandler的plugin_config修复...")
# 创建测试配置
test_config = {
"napcat_server": {
"mode": "reverse",
"host": "localhost",
"port": 8095
},
"maibot_server": {
"host": "localhost",
"port": 8000
}
}
# 创建处理器实例
handler = LauchNapcatAdapterHandler()
# 设置插件配置(模拟事件管理器注册时的行为)
handler.plugin_config = test_config
print(f"设置的plugin_config: {handler.plugin_config}")
# 测试配置访问
if handler.plugin_config is not None and handler.plugin_config == test_config:
print("✅ plugin_config修复成功")
print(f"✅ 可以正常访问配置: napcat_server.mode = {handler.plugin_config.get('napcat_server', {}).get('mode')}")
return True
else:
print("❌ plugin_config修复失败")
print(f"❌ 当前plugin_config: {handler.plugin_config}")
return False
if __name__ == "__main__":
success = test_plugin_config_fix()
sys.exit(0 if success else 1)