增强聊天管理器和数据库API,添加自动注册和异步清理功能,优化模型转换为字典的逻辑

This commit is contained in:
Windpicker-owo
2025-11-20 16:48:18 +08:00
parent 03c80a08fb
commit 6ecf5a36f2
5 changed files with 215 additions and 74 deletions

View File

@@ -18,6 +18,7 @@ class ChatterManager:
self.action_manager = action_manager
self.chatter_classes: dict[ChatType, list[type]] = {}
self.instances: dict[str, BaseChatter] = {}
self._auto_registered = False
# 管理器统计
self.stats = {
@@ -40,6 +41,12 @@ class ChatterManager:
except Exception as e:
logger.warning(f"自动注册chatter组件时发生错误: {e}")
def _ensure_chatter_registry(self):
"""确保聊天处理器注册表已初始化"""
if not self.chatter_classes and not self._auto_registered:
self._auto_register_from_component_registry()
self._auto_registered = True
def register_chatter(self, chatter_class: type):
"""注册聊天处理器类"""
for chat_type in chatter_class.chat_types:
@@ -84,73 +91,97 @@ class ChatterManager:
del self.instances[stream_id]
logger.info(f"清理不活跃聊天流实例: {stream_id}")
def _schedule_unread_cleanup(self, stream_id: str):
"""异步清理未读消息计数"""
try:
from src.chat.message_manager.message_manager import message_manager
except Exception as import_error:
logger.error("加载 message_manager 失败", stream_id=stream_id, error=import_error)
return
async def _clear_unread():
try:
await message_manager.clear_stream_unread_messages(stream_id)
logger.debug("清理未读消息完成", stream_id=stream_id)
except Exception as clear_error:
logger.error("清理未读消息失败", stream_id=stream_id, error=clear_error)
try:
asyncio.create_task(_clear_unread(), name=f"clear-unread-{stream_id}")
except RuntimeError as runtime_error:
logger.error("schedule unread cleanup failed", stream_id=stream_id, error=runtime_error)
async def process_stream_context(self, stream_id: str, context: "StreamContext") -> dict:
"""处理流上下文"""
chat_type = context.chat_type
logger.debug(f"处理流 {stream_id},聊天类型: {chat_type.value}")
if not self.chatter_classes:
self._auto_register_from_component_registry()
chat_type_value = chat_type.value
logger.debug("处理流上下文", stream_id=stream_id, chat_type=chat_type_value)
self._ensure_chatter_registry()
# 获取适合该聊天类型的chatter
chatter_class = self.get_chatter_class(chat_type)
if not chatter_class:
# 如果没有找到精确匹配尝试查找支持ALL类型的chatter
from src.plugin_system.base.component_types import ChatType
all_chatter_class = self.get_chatter_class(ChatType.ALL)
if all_chatter_class:
chatter_class = all_chatter_class
logger.info(f"{stream_id} 使用通用chatter (类型: {chat_type.value})")
logger.info(
"回退到通用聊天处理器",
stream_id=stream_id,
requested_type=chat_type_value,
fallback=ChatType.ALL.value,
)
else:
raise ValueError(f"No chatter registered for chat type {chat_type}")
if stream_id not in self.instances:
self.instances[stream_id] = chatter_class(stream_id=stream_id, action_manager=self.action_manager)
logger.info(f"创建新的聊天流实例: {stream_id} 使用 {chatter_class.__name__} (类型: {chat_type.value})")
stream_instance = self.instances.get(stream_id)
if stream_instance is None:
stream_instance = chatter_class(stream_id=stream_id, action_manager=self.action_manager)
self.instances[stream_id] = stream_instance
logger.info(
"创建聊天处理器实例",
stream_id=stream_id,
chatter_class=chatter_class.__name__,
chat_type=chat_type_value,
)
self.stats["streams_processed"] += 1
try:
result = await self.instances[stream_id].execute(context)
# 检查执行结果是否真正成功
result = await stream_instance.execute(context)
success = result.get("success", False)
if success:
self.stats["successful_executions"] += 1
# 只有真正成功时才清空未读消息
try:
from src.chat.message_manager.message_manager import message_manager
await message_manager.clear_stream_unread_messages(stream_id)
logger.debug(f"{stream_id} 处理成功,已清空未读消息")
except Exception as clear_e:
logger.error(f"清除流 {stream_id} 未读消息时发生错误: {clear_e}")
self._schedule_unread_cleanup(stream_id)
else:
self.stats["failed_executions"] += 1
logger.warning(f"{stream_id} 处理失败,不清空未读消息")
logger.warning("聊天处理器执行失败", stream_id=stream_id)
# 记录处理结果
actions_count = result.get("actions_count", 0)
logger.debug(f"{stream_id} 处理完成: 成功={success}, 动作数={actions_count}")
logger.debug(
"聊天处理器执行完成",
stream_id=stream_id,
success=success,
actions_count=actions_count,
)
return result
except asyncio.CancelledError:
self.stats["failed_executions"] += 1
logger.info(f" {stream_id} 处理被取消")
context.triggering_user_id = None # 清除触发用户ID
# 确保清理 processing_message_id 以防止重复回复检测失效
logger.info("流处理被取消", stream_id=stream_id)
context.triggering_user_id = None
context.processing_message_id = None
raise
except Exception as e:
except Exception as e: # noqa: BLE001
self.stats["failed_executions"] += 1
logger.error(f"处理流 {stream_id} 时发生错误: {e}")
context.triggering_user_id = None # 清除触发用户ID
# 确保清理 processing_message_id
logger.error("处理流时出错", stream_id=stream_id, error=e)
context.triggering_user_id = None
context.processing_message_id = None
raise
finally:
# 清除触发用户ID所有情况下都需要
context.triggering_user_id = None
def get_stats(self) -> dict[str, Any]:
"""获取管理器统计信息"""
stats = self.stats.copy()