diff --git a/src/chat/message_receive/bot.py b/src/chat/message_receive/bot.py index dc6634f65..544dec94f 100644 --- a/src/chat/message_receive/bot.py +++ b/src/chat/message_receive/bot.py @@ -659,6 +659,41 @@ class ChatBot: group_name = getattr(group_info, "group_name", None) group_platform = getattr(group_info, "platform", None) + # 准备 additional_config,将 format_info 嵌入其中 + additional_config_str = None + try: + import orjson + + additional_config_data = {} + + # 首先获取adapter传递的additional_config + if hasattr(message_info, 'additional_config') and message_info.additional_config: + if isinstance(message_info.additional_config, dict): + additional_config_data = message_info.additional_config.copy() + elif isinstance(message_info.additional_config, str): + try: + additional_config_data = orjson.loads(message_info.additional_config) + except Exception as e: + logger.warning(f"无法解析 additional_config JSON: {e}") + additional_config_data = {} + + # 然后添加format_info到additional_config中 + if hasattr(message_info, 'format_info') and message_info.format_info: + try: + format_info_dict = message_info.format_info.to_dict() + additional_config_data["format_info"] = format_info_dict + logger.debug(f"[bot.py] 嵌入 format_info 到 additional_config: {format_info_dict}") + except Exception as e: + logger.warning(f"将 format_info 转换为字典失败: {e}") + else: + logger.warning(f"[bot.py] [问题] 消息缺少 format_info: message_id={message_id}") + + # 序列化为JSON字符串 + if additional_config_data: + additional_config_str = orjson.dumps(additional_config_data).decode("utf-8") + except Exception as e: + logger.error(f"准备 additional_config 失败: {e}") + # 创建数据库消息对象 db_message = DatabaseMessages( message_id=message_id, @@ -674,6 +709,7 @@ class ChatBot: is_notify=bool(message.is_notify), is_public_notice=bool(message.is_public_notice), notice_type=message.notice_type, + additional_config=additional_config_str, user_id=user_id, user_nickname=user_nickname, user_cardname=user_cardname, diff --git a/src/chat/message_receive/chat_stream.py b/src/chat/message_receive/chat_stream.py index d3d418648..1cc3e548b 100644 --- a/src/chat/message_receive/chat_stream.py +++ b/src/chat/message_receive/chat_stream.py @@ -213,8 +213,8 @@ class ChatStream: priority_info=json.dumps(getattr(message, "priority_info", None)) if getattr(message, "priority_info", None) else None, - # 额外配置 - additional_config=getattr(message_info, "additional_config", None), + # 额外配置 - 需要将 format_info 嵌入到 additional_config 中 + additional_config=self._prepare_additional_config(message_info), # 用户信息 user_id=str(getattr(user_info, "user_id", "")), user_nickname=getattr(user_info, "user_nickname", ""), @@ -253,8 +253,59 @@ class ChatStream: f"interest_value: {db_message.interest_value}" ) + def _prepare_additional_config(self, message_info) -> str | None: + """ + 准备 additional_config,将 format_info 嵌入其中 + + 这个方法模仿 storage.py 中的逻辑,确保 DatabaseMessages 中的 additional_config + 包含 format_info,使得 action_modifier 能够正确获取适配器支持的消息类型 + + Args: + message_info: BaseMessageInfo 对象 + + Returns: + str | None: JSON 字符串格式的 additional_config,如果为空则返回 None + """ + import orjson + + # 首先获取adapter传递的additional_config + additional_config_data = {} + if hasattr(message_info, 'additional_config') and message_info.additional_config: + if isinstance(message_info.additional_config, dict): + additional_config_data = message_info.additional_config.copy() + elif isinstance(message_info.additional_config, str): + # 如果是字符串,尝试解析 + try: + additional_config_data = orjson.loads(message_info.additional_config) + except Exception as e: + logger.warning(f"无法解析 additional_config JSON: {e}") + additional_config_data = {} + + # 然后添加format_info到additional_config中 + if hasattr(message_info, 'format_info') and message_info.format_info: + try: + format_info_dict = message_info.format_info.to_dict() + additional_config_data["format_info"] = format_info_dict + logger.debug(f"嵌入 format_info 到 additional_config: {format_info_dict}") + except Exception as e: + logger.warning(f"将 format_info 转换为字典失败: {e}") + else: + logger.warning(f"[问题] 消息缺少 format_info: message_id={getattr(message_info, 'message_id', 'unknown')}") + logger.warning("[问题] 这可能导致 Action 无法正确检查适配器支持的类型") + + # 序列化为JSON字符串 + if additional_config_data: + try: + return orjson.dumps(additional_config_data).decode("utf-8") + except Exception as e: + logger.error(f"序列化 additional_config 失败: {e}") + return None + return None + def _safe_get_actions(self, message: "MessageRecv") -> list | None: """安全获取消息的actions字段""" + import json + try: actions = getattr(message, "actions", None) if actions is None: @@ -263,8 +314,6 @@ class ChatStream: # 如果是字符串,尝试解析为JSON if isinstance(actions, str): try: - import json - actions = json.loads(actions) except json.JSONDecodeError: logger.warning(f"无法解析actions JSON字符串: {actions}") diff --git a/src/chat/message_receive/optimized_chat_stream.py b/src/chat/message_receive/optimized_chat_stream.py index bc59631e6..2f7059a3e 100644 --- a/src/chat/message_receive/optimized_chat_stream.py +++ b/src/chat/message_receive/optimized_chat_stream.py @@ -230,7 +230,7 @@ class OptimizedChatStream: priority_info=json.dumps(getattr(message, "priority_info", None)) if getattr(message, "priority_info", None) else None, - additional_config=getattr(message_info, "additional_config", None), + additional_config=self._prepare_additional_config(message_info), user_id=str(getattr(user_info, "user_id", "")), user_nickname=getattr(user_info, "user_nickname", ""), user_cardname=getattr(user_info, "user_cardname", None), @@ -342,8 +342,59 @@ class OptimizedChatStream: return instance + def _prepare_additional_config(self, message_info) -> str | None: + """ + 准备 additional_config,将 format_info 嵌入其中 + + 这个方法模仿 storage.py 中的逻辑,确保 DatabaseMessages 中的 additional_config + 包含 format_info,使得 action_modifier 能够正确获取适配器支持的消息类型 + + Args: + message_info: BaseMessageInfo 对象 + + Returns: + str | None: JSON 字符串格式的 additional_config,如果为空则返回 None + """ + import orjson + + # 首先获取adapter传递的additional_config + additional_config_data = {} + if hasattr(message_info, 'additional_config') and message_info.additional_config: + if isinstance(message_info.additional_config, dict): + additional_config_data = message_info.additional_config.copy() + elif isinstance(message_info.additional_config, str): + # 如果是字符串,尝试解析 + try: + additional_config_data = orjson.loads(message_info.additional_config) + except Exception as e: + logger.warning(f"无法解析 additional_config JSON: {e}") + additional_config_data = {} + + # 然后添加format_info到additional_config中 + if hasattr(message_info, 'format_info') and message_info.format_info: + try: + format_info_dict = message_info.format_info.to_dict() + additional_config_data["format_info"] = format_info_dict + logger.debug(f"嵌入 format_info 到 additional_config: {format_info_dict}") + except Exception as e: + logger.warning(f"将 format_info 转换为字典失败: {e}") + else: + logger.warning(f"[问题] 消息缺少 format_info: message_id={getattr(message_info, 'message_id', 'unknown')}") + logger.warning("[问题] 这可能导致 Action 无法正确检查适配器支持的类型") + + # 序列化为JSON字符串 + if additional_config_data: + try: + return orjson.dumps(additional_config_data).decode("utf-8") + except Exception as e: + logger.error(f"序列化 additional_config 失败: {e}") + return None + return None + def _safe_get_actions(self, message: "MessageRecv") -> list | None: """安全获取消息的actions字段""" + import json + try: actions = getattr(message, "actions", None) if actions is None: @@ -351,8 +402,6 @@ class OptimizedChatStream: if isinstance(actions, str): try: - import json - actions = json.loads(actions) except json.JSONDecodeError: logger.warning(f"无法解析actions JSON字符串: {actions}") diff --git a/src/chat/message_receive/storage.py b/src/chat/message_receive/storage.py index 6b03bb1dd..174001411 100644 --- a/src/chat/message_receive/storage.py +++ b/src/chat/message_receive/storage.py @@ -100,16 +100,22 @@ class MessageStorage: priority_info_json = orjson.dumps(priority_info).decode("utf-8") if priority_info else None # 准备additional_config,包含format_info和其他配置 - additional_config_data = {} + additional_config_data = None - # 保存format_info到additional_config中 + # 首先获取adapter传递的additional_config + if hasattr(message.message_info, 'additional_config') and message.message_info.additional_config: + additional_config_data = message.message_info.additional_config.copy() # 避免修改原始对象 + else: + additional_config_data = {} + + # 然后添加format_info到additional_config中 if hasattr(message.message_info, 'format_info') and message.message_info.format_info: format_info_dict = message.message_info.format_info.to_dict() additional_config_data["format_info"] = format_info_dict - - # 合并adapter传递的其他additional_config - if hasattr(message.message_info, 'additional_config') and message.message_info.additional_config: - additional_config_data.update(message.message_info.additional_config) + logger.debug(f"保存format_info: {format_info_dict}") + else: + logger.warning(f"[问题] 消息缺少format_info: message_id={getattr(message.message_info, 'message_id', 'unknown')}") + logger.warning("[问题] 这可能导致Action无法正确检查适配器支持的类型") # 序列化为JSON字符串以便存储 additional_config_json = orjson.dumps(additional_config_data).decode("utf-8") if additional_config_data else None diff --git a/src/chat/planner_actions/action_modifier.py b/src/chat/planner_actions/action_modifier.py index 69fc902de..d48af9761 100644 --- a/src/chat/planner_actions/action_modifier.py +++ b/src/chat/planner_actions/action_modifier.py @@ -223,12 +223,32 @@ class ActionModifier: list[str]: 支持的输出类型列表 """ # 检查additional_config是否存在且不为空 - if (chat_context.current_message - and hasattr(chat_context.current_message, "additional_config") - and chat_context.current_message.additional_config): + additional_config = None + has_additional_config = False + # 先检查 current_message 是否存在 + if not chat_context.current_message: + logger.warning(f"{self.log_prefix} [问题] chat_context.current_message 为 None,无法获取适配器支持的类型") + return ["text", "emoji"] # 返回基础类型 + + if hasattr(chat_context.current_message, "additional_config"): + additional_config = chat_context.current_message.additional_config + + # 更准确的非空判断 + if additional_config is not None: + if isinstance(additional_config, str) and additional_config.strip(): + has_additional_config = True + elif isinstance(additional_config, dict): + # 字典存在就可以,即使为空也可能有format_info字段 + has_additional_config = True + else: + logger.warning(f"{self.log_prefix} [问题] current_message 没有 additional_config 属性") + + logger.debug(f"{self.log_prefix} [调试] has_additional_config: {has_additional_config}") + + if has_additional_config: try: - additional_config = chat_context.current_message.additional_config + logger.debug(f"{self.log_prefix} [调试] 开始解析 additional_config") format_info = None # 处理additional_config可能是字符串或字典的情况 @@ -237,8 +257,7 @@ class ActionModifier: try: config = orjson.loads(additional_config) format_info = config.get("format_info") - except (orjson.JSONDecodeError, AttributeError, TypeError): - logger.debug("无法解析additional_config JSON字符串") + except (orjson.JSONDecodeError, AttributeError, TypeError) as e: format_info = None elif isinstance(additional_config, dict): @@ -247,7 +266,6 @@ class ActionModifier: # 如果找到了format_info,从中提取支持的类型 if format_info: - # 优先检查accept_format字段 if "accept_format" in format_info: accept_format = format_info["accept_format"] if isinstance(accept_format, str): @@ -258,11 +276,13 @@ class ActionModifier: accept_format = list(accept_format) if hasattr(accept_format, "__iter__") else [] # 合并基础类型和适配器特定类型 - return list(set(accept_format)) + result = list(set(accept_format)) + return result # 备用检查content_format字段 elif "content_format" in format_info: content_format = format_info["content_format"] + logger.debug(f"{self.log_prefix} [调试] 找到 content_format: {content_format}") if isinstance(content_format, str): content_format = [content_format] elif isinstance(content_format, list): @@ -270,10 +290,25 @@ class ActionModifier: else: content_format = list(content_format) if hasattr(content_format, "__iter__") else [] - return list(set(content_format)) - + result = list(set(content_format)) + return result + else: + logger.warning(f"{self.log_prefix} [问题] additional_config 中没有 format_info 字段") except Exception as e: - logger.debug(f"解析适配器格式信息失败,使用默认支持类型: {e}") + logger.error(f"{self.log_prefix} [问题] 解析适配器格式信息失败: {e}", exc_info=True) + else: + logger.warning(f"{self.log_prefix} [问题] additional_config 不存在或为空") + + # 如果无法获取格式信息,返回默认支持的基础类型 + default_types = ["text", "emoji"] + logger.warning( + f"{self.log_prefix} [问题] 无法从适配器获取支持的消息类型,使用默认类型: {default_types}" + ) + logger.warning( + f"{self.log_prefix} [问题] 这可能导致某些 Action 被错误地过滤。" + f"请检查适配器是否正确设置了 format_info。" + ) + return default_types async def _get_deactivated_actions_by_type(