Merge afc branch into dev, prioritizing afc changes and migrating database async modifications from dev

This commit is contained in:
Windpicker-owo
2025-09-27 23:37:40 +08:00
138 changed files with 12183 additions and 5968 deletions

View File

@@ -121,6 +121,13 @@ async def generate_reply(
if not extra_info and action_data:
extra_info = action_data.get("extra_info", "")
# 如果action_data中有thinking添加到extra_info中
if action_data and (thinking := action_data.get("thinking")):
if extra_info:
extra_info += f"\n\n思考过程:{thinking}"
else:
extra_info = f"思考过程:{thinking}"
# 调用回复器生成回复
success, llm_response_dict, prompt = await replyer.generate_reply_with_context(
reply_to=reply_to,

View File

@@ -80,7 +80,7 @@ def message_dict_to_message_recv(message_dict: Dict[str, Any]) -> Optional[Messa
message_info = {
"platform": message_dict.get("chat_info_platform", ""),
"message_id": message_dict.get("message_id"),
"message_id": message_dict.get("message_id") or message_dict.get("chat_info_message_id") or message_dict.get("id"),
"time": message_dict.get("time"),
"group_info": group_info,
"user_info": user_info,
@@ -89,15 +89,16 @@ def message_dict_to_message_recv(message_dict: Dict[str, Any]) -> Optional[Messa
"template_info": template_info,
}
message_dict = {
new_message_dict = {
"message_info": message_info,
"raw_message": message_dict.get("processed_plain_text"),
"processed_plain_text": message_dict.get("processed_plain_text"),
}
message_recv = MessageRecv(message_dict)
message_recv = MessageRecv(new_message_dict)
logger.info(f"[SendAPI] 找到匹配的回复消息,发送者: {message_dict.get('user_nickname', '')}")
logger.info(message_recv)
return message_recv
@@ -246,7 +247,7 @@ async def text_to_stream(
typing: bool = False,
reply_to: str = "",
reply_to_message: Optional[Dict[str, Any]] = None,
set_reply: bool = False,
set_reply: bool = True,
storage_message: bool = True,
) -> bool:
"""向指定流发送文本消息
@@ -275,7 +276,7 @@ async def text_to_stream(
async def emoji_to_stream(
emoji_base64: str, stream_id: str, storage_message: bool = True, set_reply: bool = False
emoji_base64: str, stream_id: str, storage_message: bool = True, set_reply: bool = True
) -> bool:
"""向指定流发送表情包
@@ -293,7 +294,7 @@ async def emoji_to_stream(
async def image_to_stream(
image_base64: str, stream_id: str, storage_message: bool = True, set_reply: bool = False
image_base64: str, stream_id: str, storage_message: bool = True, set_reply: bool = True
) -> bool:
"""向指定流发送图片
@@ -315,7 +316,7 @@ async def command_to_stream(
stream_id: str,
storage_message: bool = True,
display_message: str = "",
set_reply: bool = False,
set_reply: bool = True,
) -> bool:
"""向指定流发送命令
@@ -340,7 +341,7 @@ async def custom_to_stream(
typing: bool = False,
reply_to: str = "",
reply_to_message: Optional[Dict[str, Any]] = None,
set_reply: bool = False,
set_reply: bool = True,
storage_message: bool = True,
show_log: bool = True,
) -> bool:

View File

@@ -93,7 +93,6 @@ class BaseAction(ABC):
self.associated_types: list[str] = getattr(self.__class__, "associated_types", []).copy()
self.chat_type_allow: ChatType = getattr(self.__class__, "chat_type_allow", ChatType.ALL)
# =============================================================================
# 便捷属性 - 直接在初始化时获取常用聊天信息(带类型注解)
# =============================================================================
@@ -398,6 +397,7 @@ class BaseAction(ABC):
try:
# 1. 从注册中心获取Action类
from src.plugin_system.core.component_registry import component_registry
action_class = component_registry.get_component_class(action_name, ComponentType.ACTION)
if not action_class:
logger.error(f"{log_prefix} 未找到Action: {action_name}")
@@ -406,7 +406,7 @@ class BaseAction(ABC):
# 2. 准备实例化参数
# 复用当前Action的大部分上下文信息
called_action_data = action_data if action_data is not None else self.action_data
component_info = component_registry.get_component_info(action_name, ComponentType.ACTION)
if not component_info:
logger.warning(f"{log_prefix} 未找到Action组件信息: {action_name}")

View File

@@ -0,0 +1,55 @@
from abc import ABC, abstractmethod
from typing import List, Optional, TYPE_CHECKING
from src.common.data_models.message_manager_data_model import StreamContext
from .component_types import ChatType
from src.plugin_system.base.component_types import ChatterInfo, ComponentType
if TYPE_CHECKING:
from src.chat.planner_actions.action_manager import ChatterActionManager
from src.plugins.built_in.affinity_flow_chatter.planner import ChatterActionPlanner as ActionPlanner
class BaseChatter(ABC):
chatter_name: str = ""
"""Chatter组件的名称"""
chatter_description: str = ""
"""Chatter组件的描述"""
chat_types: List[ChatType] = [ChatType.PRIVATE, ChatType.GROUP]
def __init__(self, stream_id: str, action_manager: 'ChatterActionManager'):
"""
初始化聊天处理器
Args:
stream_id: 聊天流ID
action_manager: 动作管理器
"""
self.stream_id = stream_id
self.action_manager = action_manager
@abstractmethod
async def execute(self, context: StreamContext) -> dict:
"""
执行聊天处理流程
Args:
context: StreamContext对象包含聊天流的所有消息信息
Returns:
处理结果字典
"""
pass
@classmethod
def get_chatter_info(cls) -> "ChatterInfo":
"""从类属性生成ChatterInfo
Returns:
ChatterInfo对象
"""
return ChatterInfo(
name=cls.chatter_name,
description=cls.chatter_description or "No description provided.",
chat_type_allow=cls.chat_types[0],
component_type=ComponentType.CHATTER,
)

View File

@@ -73,7 +73,7 @@ class BaseCommand(ABC):
return True
# 检查是否为群聊消息
is_group = hasattr(self.message, "is_group_message") and self.message.is_group_message
is_group = self.message.message_info.group_info
if self.chat_type_allow == ChatType.GROUP and is_group:
return True

View File

@@ -98,7 +98,7 @@ class BaseEventHandler(ABC):
weight=cls.weight,
intercept_message=cls.intercept_message,
)
def set_plugin_name(self, plugin_name: str) -> None:
"""设置插件名称
@@ -107,9 +107,9 @@ class BaseEventHandler(ABC):
"""
self.plugin_name = plugin_name
def set_plugin_config(self,plugin_config) -> None:
def set_plugin_config(self, plugin_config) -> None:
self.plugin_config = plugin_config
def get_config(self, key: str, default=None):
"""获取插件配置值,支持嵌套键访问

View File

@@ -17,6 +17,7 @@ class ComponentType(Enum):
TOOL = "tool" # 工具组件
SCHEDULER = "scheduler" # 定时任务组件(预留)
EVENT_HANDLER = "event_handler" # 事件处理组件
CHATTER = "chatter" # 聊天处理器组件
def __str__(self) -> str:
return self.value
@@ -39,8 +40,8 @@ class ActionActivationType(Enum):
# 聊天模式枚举
class ChatMode(Enum):
"""聊天模式枚举"""
FOCUS = "focus" # Focus聊天模式
FOCUS = "focus" # 专注模式
NORMAL = "normal" # Normal聊天模式
PROACTIVE = "proactive" # 主动思考模式
PRIORITY = "priority" # 优先级聊天模式
@@ -54,8 +55,8 @@ class ChatMode(Enum):
class ChatType(Enum):
"""聊天类型枚举,用于限制插件在不同聊天环境中的使用"""
GROUP = "group" # 仅群聊可用
PRIVATE = "private" # 仅私聊可用
GROUP = "group" # 仅群聊可用
ALL = "all" # 群聊和私聊都可用
def __str__(self):
@@ -69,7 +70,7 @@ class EventType(Enum):
"""
ON_START = "on_start" # 启动事件,用于调用按时任务
ON_STOP ="on_stop"
ON_STOP = "on_stop"
ON_MESSAGE = "on_message"
ON_PLAN = "on_plan"
POST_LLM = "post_llm"
@@ -210,6 +211,17 @@ class EventHandlerInfo(ComponentInfo):
self.component_type = ComponentType.EVENT_HANDLER
@dataclass
class ChatterInfo(ComponentInfo):
"""聊天处理器组件信息"""
chat_type_allow: ChatType = ChatType.ALL # 允许的聊天类型
def __post_init__(self):
super().__post_init__()
self.component_type = ComponentType.CHATTER
@dataclass
class EventInfo(ComponentInfo):
"""事件组件信息"""

View File

@@ -1,7 +1,7 @@
from pathlib import Path
import re
from typing import Dict, List, Optional, Any, Pattern, Tuple, Union, Type
from typing import TYPE_CHECKING, Dict, List, Optional, Any, Pattern, Tuple, Union, Type
from src.common.logger import get_logger
from src.plugin_system.base.component_types import (
@@ -11,14 +11,17 @@ from src.plugin_system.base.component_types import (
CommandInfo,
PlusCommandInfo,
EventHandlerInfo,
ChatterInfo,
PluginInfo,
ComponentType,
)
from src.plugin_system.base.base_command import BaseCommand
from src.plugin_system.base.base_action import BaseAction
from src.plugin_system.base.base_tool import BaseTool
from src.plugin_system.base.base_events_handler import BaseEventHandler
from src.plugin_system.base.plus_command import PlusCommand
from src.plugin_system.base.base_chatter import BaseChatter
logger = get_logger("component_registry")
@@ -31,42 +34,45 @@ class ComponentRegistry:
def __init__(self):
# 命名空间式组件名构成法 f"{component_type}.{component_name}"
self._plus_command_registry: Dict[str, Type[PlusCommand]] = {}
self._components: Dict[str, ComponentInfo] = {}
self._components: Dict[str, 'ComponentInfo'] = {}
"""组件注册表 命名空间式组件名 -> 组件信息"""
self._components_by_type: Dict[ComponentType, Dict[str, ComponentInfo]] = {types: {} for types in ComponentType}
self._components_by_type: Dict['ComponentType', Dict[str, 'ComponentInfo']] = {types: {} for types in ComponentType}
"""类型 -> 组件原名称 -> 组件信息"""
self._components_classes: Dict[
str, Type[Union[BaseCommand, BaseAction, BaseTool, BaseEventHandler, PlusCommand]]
str, Type[Union['BaseCommand', 'BaseAction', 'BaseTool', 'BaseEventHandler', 'PlusCommand', 'BaseChatter']]
] = {}
"""命名空间式组件名 -> 组件类"""
# 插件注册表
self._plugins: Dict[str, PluginInfo] = {}
self._plugins: Dict[str, 'PluginInfo'] = {}
"""插件名 -> 插件信息"""
# Action特定注册表
self._action_registry: Dict[str, Type[BaseAction]] = {}
self._action_registry: Dict[str, Type['BaseAction']] = {}
"""Action注册表 action名 -> action类"""
self._default_actions: Dict[str, ActionInfo] = {}
self._default_actions: Dict[str, 'ActionInfo'] = {}
"""默认动作集即启用的Action集用于重置ActionManager状态"""
# Command特定注册表
self._command_registry: Dict[str, Type[BaseCommand]] = {}
self._command_registry: Dict[str, Type['BaseCommand']] = {}
"""Command类注册表 command名 -> command类"""
self._command_patterns: Dict[Pattern, str] = {}
"""编译后的正则 -> command名"""
# 工具特定注册表
self._tool_registry: Dict[str, Type[BaseTool]] = {} # 工具名 -> 工具类
self._llm_available_tools: Dict[str, Type[BaseTool]] = {} # llm可用的工具名 -> 工具类
self._tool_registry: Dict[str, Type['BaseTool']] = {} # 工具名 -> 工具类
self._llm_available_tools: Dict[str, Type['BaseTool']] = {} # llm可用的工具名 -> 工具类
# EventHandler特定注册表
self._event_handler_registry: Dict[str, Type[BaseEventHandler]] = {}
self._event_handler_registry: Dict[str, Type['BaseEventHandler']] = {}
"""event_handler名 -> event_handler类"""
self._enabled_event_handlers: Dict[str, Type[BaseEventHandler]] = {}
self._enabled_event_handlers: Dict[str, Type['BaseEventHandler']] = {}
"""启用的事件处理器 event_handler名 -> event_handler类"""
self._chatter_registry: Dict[str, Type['BaseChatter']] = {}
"""chatter名 -> chatter类"""
self._enabled_chatter_registry: Dict[str, Type['BaseChatter']] = {}
"""启用的chatter名 -> chatter类"""
logger.info("组件注册中心初始化完成")
# == 注册方法 ==
@@ -93,7 +99,7 @@ class ComponentRegistry:
def register_component(
self,
component_info: ComponentInfo,
component_class: Type[Union[BaseCommand, BaseAction, BaseEventHandler, BaseTool]],
component_class: Type[Union['BaseCommand', 'BaseAction', 'BaseEventHandler', 'BaseTool', 'BaseChatter']],
) -> bool:
"""注册组件
@@ -151,6 +157,10 @@ class ComponentRegistry:
assert isinstance(component_info, EventHandlerInfo)
assert issubclass(component_class, BaseEventHandler)
ret = self._register_event_handler_component(component_info, component_class)
case ComponentType.CHATTER:
assert isinstance(component_info, ChatterInfo)
assert issubclass(component_class, BaseChatter)
ret = self._register_chatter_component(component_info, component_class)
case _:
logger.warning(f"未知组件类型: {component_type}")
@@ -162,7 +172,7 @@ class ComponentRegistry:
)
return True
def _register_action_component(self, action_info: ActionInfo, action_class: Type[BaseAction]) -> bool:
def _register_action_component(self, action_info: 'ActionInfo', action_class: Type['BaseAction']) -> bool:
"""注册Action组件到Action特定注册表"""
if not (action_name := action_info.name):
logger.error(f"Action组件 {action_class.__name__} 必须指定名称")
@@ -182,7 +192,7 @@ class ComponentRegistry:
return True
def _register_command_component(self, command_info: CommandInfo, command_class: Type[BaseCommand]) -> bool:
def _register_command_component(self, command_info: 'CommandInfo', command_class: Type['BaseCommand']) -> bool:
"""注册Command组件到Command特定注册表"""
if not (command_name := command_info.name):
logger.error(f"Command组件 {command_class.__name__} 必须指定名称")
@@ -209,7 +219,7 @@ class ComponentRegistry:
return True
def _register_plus_command_component(
self, plus_command_info: PlusCommandInfo, plus_command_class: Type[PlusCommand]
self, plus_command_info: 'PlusCommandInfo', plus_command_class: Type['PlusCommand']
) -> bool:
"""注册PlusCommand组件到特定注册表"""
plus_command_name = plus_command_info.name
@@ -223,7 +233,7 @@ class ComponentRegistry:
# 创建专门的PlusCommand注册表如果还没有
if not hasattr(self, "_plus_command_registry"):
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
# 设置插件配置
@@ -233,7 +243,7 @@ class ComponentRegistry:
logger.debug(f"已注册PlusCommand组件: {plus_command_name}")
return True
def _register_tool_component(self, tool_info: ToolInfo, tool_class: Type[BaseTool]) -> bool:
def _register_tool_component(self, tool_info: 'ToolInfo', tool_class: Type['BaseTool']) -> bool:
"""注册Tool组件到Tool特定注册表"""
tool_name = tool_info.name
@@ -249,7 +259,7 @@ class ComponentRegistry:
return True
def _register_event_handler_component(
self, handler_info: EventHandlerInfo, handler_class: Type[BaseEventHandler]
self, handler_info: 'EventHandlerInfo', handler_class: Type['BaseEventHandler']
) -> bool:
if not (handler_name := handler_info.name):
logger.error(f"EventHandler组件 {handler_class.__name__} 必须指定名称")
@@ -271,11 +281,38 @@ class ComponentRegistry:
# 使用EventManager进行事件处理器注册
from src.plugin_system.core.event_manager import event_manager
return event_manager.register_event_handler(handler_class,self.get_plugin_config(handler_info.plugin_name) or {})
return event_manager.register_event_handler(
handler_class, self.get_plugin_config(handler_info.plugin_name) or {}
)
def _register_chatter_component(self, chatter_info: 'ChatterInfo', chatter_class: Type['BaseChatter']) -> bool:
"""注册Chatter组件到Chatter特定注册表"""
chatter_name = chatter_info.name
if not chatter_name:
logger.error(f"Chatter组件 {chatter_class.__name__} 必须指定名称")
return False
if not isinstance(chatter_info, ChatterInfo) or not issubclass(chatter_class, BaseChatter):
logger.error(f"注册失败: {chatter_name} 不是有效的Chatter")
return False
chatter_class.plugin_name = chatter_info.plugin_name
# 设置插件配置
chatter_class.plugin_config = self.get_plugin_config(chatter_info.plugin_name) or {}
self._chatter_registry[chatter_name] = chatter_class
if not chatter_info.enabled:
logger.warning(f"Chatter组件 {chatter_name} 未启用")
return True # 未启用,但是也是注册成功
self._enabled_chatter_registry[chatter_name] = chatter_class
logger.debug(f"已注册Chatter组件: {chatter_name}")
return True
# === 组件移除相关 ===
async def remove_component(self, component_name: str, component_type: ComponentType, plugin_name: str) -> bool:
async def remove_component(self, component_name: str, component_type: 'ComponentType', plugin_name: str) -> bool:
target_component_class = self.get_component_class(component_name, component_type)
if not target_component_class:
logger.warning(f"组件 {component_name} 未注册,无法移除")
@@ -323,6 +360,12 @@ class ComponentRegistry:
except Exception as e:
logger.warning(f"移除EventHandler事件订阅时出错: {e}")
case ComponentType.CHATTER:
# 移除Chatter注册
if hasattr(self, '_chatter_registry'):
self._chatter_registry.pop(component_name, None)
logger.debug(f"已移除Chatter组件: {component_name}")
case _:
logger.warning(f"未知的组件类型: {component_type}")
return False
@@ -441,8 +484,8 @@ class ComponentRegistry:
# === 组件查询方法 ===
def get_component_info(
self, component_name: str, component_type: Optional[ComponentType] = None
) -> Optional[ComponentInfo]:
self, component_name: str, component_type: Optional['ComponentType'] = None
) -> Optional['ComponentInfo']:
# sourcery skip: class-extract-method
"""获取组件信息,支持自动命名空间解析
@@ -486,8 +529,8 @@ class ComponentRegistry:
def get_component_class(
self,
component_name: str,
component_type: Optional[ComponentType] = None,
) -> Optional[Union[Type[BaseCommand], Type[BaseAction], Type[BaseEventHandler], Type[BaseTool]]]:
component_type: Optional['ComponentType'] = None,
) -> Optional[Union[Type['BaseCommand'], Type['BaseAction'], Type['BaseEventHandler'], Type['BaseTool']]]:
"""获取组件类,支持自动命名空间解析
Args:
@@ -504,7 +547,7 @@ class ComponentRegistry:
# 2. 如果指定了组件类型,构造命名空间化的名称查找
if component_type:
namespaced_name = f"{component_type.value}.{component_name}"
return self._components_classes.get(namespaced_name)
return self._components_classes.get(namespaced_name) # type: ignore[valid-type]
# 3. 如果没有指定类型,尝试在所有命名空间中查找
candidates = []
@@ -529,22 +572,22 @@ class ComponentRegistry:
# 4. 都没找到
return None
def get_components_by_type(self, component_type: ComponentType) -> Dict[str, ComponentInfo]:
def get_components_by_type(self, component_type: 'ComponentType') -> Dict[str, 'ComponentInfo']:
"""获取指定类型的所有组件"""
return self._components_by_type.get(component_type, {}).copy()
def get_enabled_components_by_type(self, component_type: ComponentType) -> Dict[str, ComponentInfo]:
def get_enabled_components_by_type(self, component_type: 'ComponentType') -> Dict[str, 'ComponentInfo']:
"""获取指定类型的所有启用组件"""
components = self.get_components_by_type(component_type)
return {name: info for name, info in components.items() if info.enabled}
# === Action特定查询方法 ===
def get_action_registry(self) -> Dict[str, Type[BaseAction]]:
def get_action_registry(self) -> Dict[str, Type['BaseAction']]:
"""获取Action注册表"""
return self._action_registry.copy()
def get_registered_action_info(self, action_name: str) -> Optional[ActionInfo]:
def get_registered_action_info(self, action_name: str) -> Optional['ActionInfo']:
"""获取Action信息"""
info = self.get_component_info(action_name, ComponentType.ACTION)
return info if isinstance(info, ActionInfo) else None
@@ -555,11 +598,11 @@ class ComponentRegistry:
# === Command特定查询方法 ===
def get_command_registry(self) -> Dict[str, Type[BaseCommand]]:
def get_command_registry(self) -> Dict[str, Type['BaseCommand']]:
"""获取Command注册表"""
return self._command_registry.copy()
def get_registered_command_info(self, command_name: str) -> Optional[CommandInfo]:
def get_registered_command_info(self, command_name: str) -> Optional['CommandInfo']:
"""获取Command信息"""
info = self.get_component_info(command_name, ComponentType.COMMAND)
return info if isinstance(info, CommandInfo) else None
@@ -568,7 +611,7 @@ class ComponentRegistry:
"""获取Command模式注册表"""
return self._command_patterns.copy()
def find_command_by_text(self, text: str) -> Optional[Tuple[Type[BaseCommand], dict, CommandInfo]]:
def find_command_by_text(self, text: str) -> Optional[Tuple[Type['BaseCommand'], dict, 'CommandInfo']]:
# sourcery skip: use-named-expression, use-next
"""根据文本查找匹配的命令
@@ -595,15 +638,15 @@ class ComponentRegistry:
return None
# === Tool 特定查询方法 ===
def get_tool_registry(self) -> Dict[str, Type[BaseTool]]:
def get_tool_registry(self) -> Dict[str, Type['BaseTool']]:
"""获取Tool注册表"""
return self._tool_registry.copy()
def get_llm_available_tools(self) -> Dict[str, Type[BaseTool]]:
def get_llm_available_tools(self) -> Dict[str, Type['BaseTool']]:
"""获取LLM可用的Tool列表"""
return self._llm_available_tools.copy()
def get_registered_tool_info(self, tool_name: str) -> Optional[ToolInfo]:
def get_registered_tool_info(self, tool_name: str) -> Optional['ToolInfo']:
"""获取Tool信息
Args:
@@ -616,13 +659,13 @@ class ComponentRegistry:
return info if isinstance(info, ToolInfo) else None
# === PlusCommand 特定查询方法 ===
def get_plus_command_registry(self) -> Dict[str, Type[PlusCommand]]:
def get_plus_command_registry(self) -> Dict[str, Type['PlusCommand']]:
"""获取PlusCommand注册表"""
if not hasattr(self, "_plus_command_registry"):
pass
self._plus_command_registry: Dict[str, Type[PlusCommand]] = {}
return self._plus_command_registry.copy()
def get_registered_plus_command_info(self, command_name: str) -> Optional[PlusCommandInfo]:
def get_registered_plus_command_info(self, command_name: str) -> Optional['PlusCommandInfo']:
"""获取PlusCommand信息
Args:
@@ -636,26 +679,44 @@ class ComponentRegistry:
# === EventHandler 特定查询方法 ===
def get_event_handler_registry(self) -> Dict[str, Type[BaseEventHandler]]:
def get_event_handler_registry(self) -> Dict[str, Type['BaseEventHandler']]:
"""获取事件处理器注册表"""
return self._event_handler_registry.copy()
def get_registered_event_handler_info(self, handler_name: str) -> Optional[EventHandlerInfo]:
def get_registered_event_handler_info(self, handler_name: str) -> Optional['EventHandlerInfo']:
"""获取事件处理器信息"""
info = self.get_component_info(handler_name, ComponentType.EVENT_HANDLER)
return info if isinstance(info, EventHandlerInfo) else None
def get_enabled_event_handlers(self) -> Dict[str, Type[BaseEventHandler]]:
def get_enabled_event_handlers(self) -> Dict[str, Type['BaseEventHandler']]:
"""获取启用的事件处理器"""
return self._enabled_event_handlers.copy()
# === Chatter 特定查询方法 ===
def get_chatter_registry(self) -> Dict[str, Type['BaseChatter']]:
"""获取Chatter注册表"""
if not hasattr(self, '_chatter_registry'):
self._chatter_registry: Dict[str, Type[BaseChatter]] = {}
return self._chatter_registry.copy()
def get_enabled_chatter_registry(self) -> Dict[str, Type['BaseChatter']]:
"""获取启用的Chatter注册表"""
if not hasattr(self, '_enabled_chatter_registry'):
self._enabled_chatter_registry: Dict[str, Type[BaseChatter]] = {}
return self._enabled_chatter_registry.copy()
def get_registered_chatter_info(self, chatter_name: str) -> Optional['ChatterInfo']:
"""获取Chatter信息"""
info = self.get_component_info(chatter_name, ComponentType.CHATTER)
return info if isinstance(info, ChatterInfo) else None
# === 插件查询方法 ===
def get_plugin_info(self, plugin_name: str) -> Optional[PluginInfo]:
def get_plugin_info(self, plugin_name: str) -> Optional['PluginInfo']:
"""获取插件信息"""
return self._plugins.get(plugin_name)
def get_all_plugins(self) -> Dict[str, PluginInfo]:
def get_all_plugins(self) -> Dict[str, 'PluginInfo']:
"""获取所有插件"""
return self._plugins.copy()
@@ -663,13 +724,12 @@ class ComponentRegistry:
# """获取所有启用的插件"""
# return {name: info for name, info in self._plugins.items() if info.enabled}
def get_plugin_components(self, plugin_name: str) -> List[ComponentInfo]:
def get_plugin_components(self, plugin_name: str) -> List['ComponentInfo']:
"""获取插件的所有组件"""
plugin_info = self.get_plugin_info(plugin_name)
return plugin_info.components if plugin_info else []
@staticmethod
def get_plugin_config(plugin_name: str) -> dict:
def get_plugin_config(self, plugin_name: str) -> dict:
"""获取插件配置
Args:
@@ -684,19 +744,20 @@ class ComponentRegistry:
plugin_instance = plugin_manager.get_plugin_instance(plugin_name)
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:
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]:
@@ -706,6 +767,7 @@ class ComponentRegistry:
tool_components: int = 0
events_handlers: int = 0
plus_command_components: int = 0
chatter_components: int = 0
for component in self._components.values():
if component.component_type == ComponentType.ACTION:
action_components += 1
@@ -717,12 +779,15 @@ class ComponentRegistry:
events_handlers += 1
elif component.component_type == ComponentType.PLUS_COMMAND:
plus_command_components += 1
elif component.component_type == ComponentType.CHATTER:
chatter_components += 1
return {
"action_components": action_components,
"command_components": command_components,
"tool_components": tool_components,
"event_handlers": events_handlers,
"plus_command_components": plus_command_components,
"chatter_components": chatter_components,
"total_components": len(self._components),
"total_plugins": len(self._plugins),
"components_by_type": {
@@ -730,6 +795,8 @@ class ComponentRegistry:
},
"enabled_components": len([c for c in self._components.values() if c.enabled]),
"enabled_plugins": len([p for p in self._plugins.values() if p.enabled]),
"enabled_components": len([c for c in self._components.values() if c.enabled]),
"enabled_plugins": len([p for p in self._plugins.values() if p.enabled]),
}
# === 组件移除相关 ===

View File

@@ -146,7 +146,9 @@ class EventManager:
logger.info(f"事件 {event_name} 已禁用")
return True
def register_event_handler(self, handler_class: Type[BaseEventHandler], plugin_config: Optional[dict] = None) -> bool:
def register_event_handler(
self, handler_class: Type[BaseEventHandler], plugin_config: Optional[dict] = None
) -> bool:
"""注册事件处理器
Args:
@@ -168,7 +170,7 @@ class EventManager:
# 创建事件处理器实例,传递插件配置
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)
self._event_handlers[handler_name] = handler_instance

View File

@@ -129,9 +129,7 @@ class PluginManager:
self._show_plugin_components(plugin_name)
# 检查并调用 on_plugin_loaded 钩子(如果存在)
if hasattr(plugin_instance, "on_plugin_loaded") and callable(
plugin_instance.on_plugin_loaded
):
if hasattr(plugin_instance, "on_plugin_loaded") and callable(plugin_instance.on_plugin_loaded):
logger.debug(f"为插件 '{plugin_name}' 调用 on_plugin_loaded 钩子")
try:
# 使用 asyncio.create_task 确保它不会阻塞加载流程
@@ -380,13 +378,14 @@ class PluginManager:
tool_count = stats.get("tool_components", 0)
event_handler_count = stats.get("event_handlers", 0)
plus_command_count = stats.get("plus_command_components", 0)
chatter_count = stats.get("chatter_components", 0)
total_components = stats.get("total_components", 0)
# 📋 显示插件加载总览
if total_registered > 0:
logger.info("🎉 插件系统加载完成!")
logger.info(
f"📊 总览: {total_registered}个插件, {total_components}个组件 (Action: {action_count}, Command: {command_count}, Tool: {tool_count}, PlusCommand: {plus_command_count}, EventHandler: {event_handler_count})"
f"📊 总览: {total_registered}个插件, {total_components}个组件 (Action: {action_count}, Command: {command_count}, Tool: {tool_count}, PlusCommand: {plus_command_count}, EventHandler: {event_handler_count}, Chatter: {chatter_count})"
)
# 显示详细的插件列表
@@ -442,6 +441,12 @@ class PluginManager:
if plus_command_components:
plus_command_names = [c.name for c in plus_command_components]
logger.info(f" ⚡ PlusCommand组件: {', '.join(plus_command_names)}")
chatter_components = [
c for c in plugin_info.components if c.component_type == ComponentType.CHATTER
]
if chatter_components:
chatter_names = [c.name for c in chatter_components]
logger.info(f" 🗣️ Chatter组件: {', '.join(chatter_names)}")
if event_handler_components:
event_handler_names = [c.name for c in event_handler_components]
logger.info(f" 📢 EventHandler组件: {', '.join(event_handler_names)}")