diff --git a/scripts/log_viewer.py b/scripts/log_viewer.py index 30f9cebf0..248919fa8 100644 --- a/scripts/log_viewer.py +++ b/scripts/log_viewer.py @@ -1183,4 +1183,3 @@ def main(): if __name__ == "__main__": main() - diff --git a/scripts/log_viewer_optimized.py b/scripts/log_viewer_optimized.py index b4ae6e066..c970022c4 100644 --- a/scripts/log_viewer_optimized.py +++ b/scripts/log_viewer_optimized.py @@ -370,7 +370,6 @@ class VirtualLogDisplay: self.text_widget.tag_add(tag_name, f"{start_pos}+{tag_info[1]}c", f"{start_pos}+{tag_info[2]}c") - class AsyncLogLoader: """异步日志加载器""" diff --git a/src/chat/focus_chat/heartFC_sender.py b/src/chat/focus_chat/heartFC_sender.py index 3cb4e3a2e..0efcf16d8 100644 --- a/src/chat/focus_chat/heartFC_sender.py +++ b/src/chat/focus_chat/heartFC_sender.py @@ -99,7 +99,6 @@ class HeartFCSender: message.build_reply() logger.debug(f"[{chat_id}] 选择回复引用消息: {message.processed_plain_text[:20]}...") - await message.process() if typing: @@ -110,7 +109,6 @@ class HeartFCSender: ) await asyncio.sleep(typing_time) - sent_msg = await send_message(message) if not sent_msg: return False diff --git a/src/chat/focus_chat/planners/action_manager.py b/src/chat/focus_chat/planners/action_manager.py index ec53227f6..8dec6889a 100644 --- a/src/chat/focus_chat/planners/action_manager.py +++ b/src/chat/focus_chat/planners/action_manager.py @@ -14,7 +14,7 @@ ActionInfo = Dict[str, Any] class ActionManager: """ 动作管理器,用于管理各种类型的动作 - + 现在统一使用新插件系统,简化了原有的新旧兼容逻辑。 """ diff --git a/src/chat/focus_chat/planners/base_planner.py b/src/chat/focus_chat/planners/base_planner.py index 0201da63d..0492039e1 100644 --- a/src/chat/focus_chat/planners/base_planner.py +++ b/src/chat/focus_chat/planners/base_planner.py @@ -12,7 +12,9 @@ class BasePlanner(ABC): self.action_manager = action_manager @abstractmethod - async def plan(self, all_plan_info: List[InfoBase], running_memorys: List[Dict[str, Any]], loop_start_time: float) -> Dict[str, Any]: + async def plan( + self, all_plan_info: List[InfoBase], running_memorys: List[Dict[str, Any]], loop_start_time: float + ) -> Dict[str, Any]: """ 规划下一步行动 diff --git a/src/chat/focus_chat/planners/modify_actions.py b/src/chat/focus_chat/planners/modify_actions.py index 1c0bb72bf..2e3b84a1b 100644 --- a/src/chat/focus_chat/planners/modify_actions.py +++ b/src/chat/focus_chat/planners/modify_actions.py @@ -242,7 +242,7 @@ class ActionModifier: for action_name, action_info in actions_with_info.items(): activation_type = action_info.get("focus_activation_type", "always") - + print(f"action_name: {action_name}, activation_type: {activation_type}") # 现在统一是字符串格式的激活类型值 diff --git a/src/chat/focus_chat/planners/planner_simple.py b/src/chat/focus_chat/planners/planner_simple.py index 95c5a0d8c..3970a73ac 100644 --- a/src/chat/focus_chat/planners/planner_simple.py +++ b/src/chat/focus_chat/planners/planner_simple.py @@ -82,7 +82,9 @@ class ActionPlanner(BasePlanner): request_type="focus.planner", # 用于动作规划 ) - async def plan(self, all_plan_info: List[InfoBase], running_memorys: List[Dict[str, Any]], loop_start_time: float) -> Dict[str, Any]: + async def plan( + self, all_plan_info: List[InfoBase], running_memorys: List[Dict[str, Any]], loop_start_time: float + ) -> Dict[str, Any]: """ 规划器 (Planner): 使用LLM根据上下文决定做出什么动作。 @@ -243,7 +245,7 @@ class ActionPlanner(BasePlanner): if selected_expressions: action_data["selected_expressions"] = selected_expressions logger.debug(f"{self.log_prefix} 传递{len(selected_expressions)}个选中的表达方式到action_data") - + action_data["loop_start_time"] = loop_start_time # 对于reply动作不需要额外处理,因为相关字段已经在上面的循环中添加到action_data diff --git a/src/chat/focus_chat/replyer/default_generator.py b/src/chat/focus_chat/replyer/default_generator.py index 6f2f13673..34b4476c9 100644 --- a/src/chat/focus_chat/replyer/default_generator.py +++ b/src/chat/focus_chat/replyer/default_generator.py @@ -71,7 +71,7 @@ def init_prompt(): """, "default_generator_private_prompt", ) - + Prompt( """ 你可以参考你的以下的语言习惯,如果情景合适就使用,不要盲目使用,不要生硬使用,而是结合到表达中: @@ -156,7 +156,7 @@ class DefaultReplyer: await self.heart_fc_sender.register_thinking(thinking_message) return None - + async def generate_reply_with_context( self, reply_data: Dict[str, Any], @@ -166,8 +166,6 @@ class DefaultReplyer: (已整合原 HeartFCGenerator 的功能) """ try: - - # 3. 构建 Prompt with Timer("构建Prompt", {}): # 内部计时器,可选保留 prompt = await self.build_prompt_reply_context( @@ -206,13 +204,13 @@ class DefaultReplyer: reply_seg = ("text", str) reply_set.append(reply_seg) - return True , reply_set + return True, reply_set except Exception as e: logger.error(f"{self.log_prefix}回复生成意外失败: {e}") traceback.print_exc() return False, None - + async def rewrite_reply_with_context( self, reply_data: Dict[str, Any], @@ -221,8 +219,6 @@ class DefaultReplyer: 表达器 (Expressor): 核心逻辑,负责生成回复文本。 """ try: - - reply_to = reply_data.get("reply_to", "") raw_reply = reply_data.get("raw_reply", "") reason = reply_data.get("reason", "") @@ -275,24 +271,20 @@ class DefaultReplyer: logger.error(f"{self.log_prefix}回复生成意外失败: {e}") traceback.print_exc() return False, None - - - - async def build_prompt_reply_context( self, reply_data=None, ) -> str: chat_stream = self.chat_stream - + is_group_chat = bool(chat_stream.group_info) - + identity = reply_data.get("identity", "") extra_info_block = reply_data.get("extra_info_block", "") relation_info_block = reply_data.get("relation_info_block", "") reply_to = reply_data.get("reply_to", "none") - + sender = "" target = "" if ":" in reply_to or ":" in reply_to: @@ -301,7 +293,6 @@ class DefaultReplyer: if len(parts) == 2: sender = parts[0].strip() target = parts[1].strip() - message_list_before_now = get_raw_msg_before_timestamp_with_chat( chat_id=chat_stream.stream_id, @@ -379,9 +370,7 @@ class DefaultReplyer: # logger.debug("开始构建 focus prompt") if sender: - reply_target_block = ( - f"现在{sender}说的:{target}。引起了你的注意,你想要在群里发言或者回复这条消息。" - ) + reply_target_block = f"现在{sender}说的:{target}。引起了你的注意,你想要在群里发言或者回复这条消息。" elif target: reply_target_block = f"现在{target}引起了你的注意,你想要在群里发言或者回复这条消息。" else: @@ -436,9 +425,6 @@ class DefaultReplyer: raw_reply, reply_to, ) -> str: - - - sender = "" target = "" if ":" in reply_to or ":" in reply_to: @@ -447,9 +433,9 @@ class DefaultReplyer: if len(parts) == 2: sender = parts[0].strip() target = parts[1].strip() - + chat_stream = self.chat_stream - + is_group_chat = bool(chat_stream.group_info) message_list_before_now = get_raw_msg_before_timestamp_with_chat( @@ -608,23 +594,22 @@ class DefaultReplyer: ) try: - if (bot_message.is_private_message() or - bot_message.reply.processed_plain_text != "[System Trigger Context]" or - mark_head): + if ( + bot_message.is_private_message() + or bot_message.reply.processed_plain_text != "[System Trigger Context]" + or mark_head + ): set_reply = False else: set_reply = True - + if not mark_head: mark_head = True typing = False else: typing = True - - - sent_msg = await self.heart_fc_sender.send_message( - bot_message, typing=typing, set_reply=set_reply - ) + + sent_msg = await self.heart_fc_sender.send_message(bot_message, typing=typing, set_reply=set_reply) reply_message_ids.append(part_message_id) # 记录我们生成的ID @@ -652,7 +637,7 @@ class DefaultReplyer: is_emoji: bool, thinking_start_time: float, display_message: str, - anchor_message: MessageRecv = None + anchor_message: MessageRecv = None, ) -> MessageSending: """构建单个发送消息""" diff --git a/src/chat/heart_flow/observation/chatting_observation.py b/src/chat/heart_flow/observation/chatting_observation.py index d88e5ad6e..3c180e13f 100644 --- a/src/chat/heart_flow/observation/chatting_observation.py +++ b/src/chat/heart_flow/observation/chatting_observation.py @@ -16,6 +16,7 @@ from src.common.logger import get_logger from src.chat.heart_flow.utils_chat import get_chat_type_and_target_info from src.chat.message_receive.chat_stream import get_chat_manager from src.person_info.person_info import get_person_info_manager + logger = get_logger("observation") # 定义提示模板 @@ -71,7 +72,7 @@ class ChattingObservation(Observation): self.oldest_messages = [] self.oldest_messages_str = "" - self.last_observe_time = datetime.now().timestamp() -1 + self.last_observe_time = datetime.now().timestamp() - 1 print(f"last_observe_time: {self.last_observe_time}") initial_messages = get_raw_msg_before_timestamp_with_chat(self.chat_id, self.last_observe_time, 10) self.last_observe_time = initial_messages[-1]["time"] if initial_messages else self.last_observe_time @@ -159,10 +160,9 @@ class ChattingObservation(Observation): "processed_plain_text": find_msg.get("processed_plain_text"), } find_rec_msg = MessageRecv(message_dict) - + find_rec_msg.update_chat_stream(get_chat_manager().get_or_create_stream(self.chat_id)) - - + return find_rec_msg async def observe(self): diff --git a/src/chat/message_receive/chat_stream.py b/src/chat/message_receive/chat_stream.py index bf6ea3c8a..fc251f4ff 100644 --- a/src/chat/message_receive/chat_stream.py +++ b/src/chat/message_receive/chat_stream.py @@ -171,7 +171,7 @@ class ChatManager: # 使用MD5生成唯一ID key = "_".join(components) return hashlib.md5(key.encode()).hexdigest() - + def get_stream_id(self, platform: str, chat_id: str, is_group: bool = True) -> str: """获取聊天流ID""" if is_group: diff --git a/src/plugin_system/apis/__init__.py b/src/plugin_system/apis/__init__.py index eb3930279..cfcf9b7e7 100644 --- a/src/plugin_system/apis/__init__.py +++ b/src/plugin_system/apis/__init__.py @@ -15,7 +15,7 @@ from src.plugin_system.apis import ( message_api, person_api, send_api, - utils_api + utils_api, ) # 导出所有API模块,使它们可以通过 apis.xxx 方式访问 @@ -29,5 +29,5 @@ __all__ = [ "message_api", "person_api", "send_api", - "utils_api" + "utils_api", ] diff --git a/src/plugin_system/apis/chat_api.py b/src/plugin_system/apis/chat_api.py index f07613f23..23a5a3be0 100644 --- a/src/plugin_system/apis/chat_api.py +++ b/src/plugin_system/apis/chat_api.py @@ -6,7 +6,7 @@ from src.plugin_system.apis import chat_api streams = chat_api.get_all_group_streams() chat_type = chat_api.get_stream_type(stream) - + 或者: from src.plugin_system.apis.chat_api import ChatManager as chat streams = chat.get_all_group_streams() @@ -24,14 +24,14 @@ logger = get_logger("chat_api") class ChatManager: """聊天管理器 - 专门负责聊天信息的查询和管理""" - + @staticmethod def get_all_streams(platform: str = "qq") -> List[ChatStream]: """获取所有聊天流 - + Args: platform: 平台筛选,默认为"qq" - + Returns: List[ChatStream]: 聊天流列表 """ @@ -44,14 +44,14 @@ class ChatManager: except Exception as e: logger.error(f"[ChatAPI] 获取聊天流失败: {e}") return streams - + @staticmethod def get_group_streams(platform: str = "qq") -> List[ChatStream]: """获取所有群聊聊天流 - + Args: platform: 平台筛选,默认为"qq" - + Returns: List[ChatStream]: 群聊聊天流列表 """ @@ -64,14 +64,14 @@ class ChatManager: except Exception as e: logger.error(f"[ChatAPI] 获取群聊流失败: {e}") return streams - + @staticmethod def get_private_streams(platform: str = "qq") -> List[ChatStream]: """获取所有私聊聊天流 - + Args: platform: 平台筛选,默认为"qq" - + Returns: List[ChatStream]: 私聊聊天流列表 """ @@ -84,15 +84,15 @@ class ChatManager: except Exception as e: logger.error(f"[ChatAPI] 获取私聊流失败: {e}") return streams - + @staticmethod def get_stream_by_group_id(group_id: str, platform: str = "qq") -> Optional[ChatStream]: """根据群ID获取聊天流 - + Args: group_id: 群聊ID platform: 平台,默认为"qq" - + Returns: Optional[ChatStream]: 聊天流对象,如果未找到返回None """ @@ -109,15 +109,15 @@ class ChatManager: except Exception as e: logger.error(f"[ChatAPI] 查找群聊流失败: {e}") return None - + @staticmethod def get_stream_by_user_id(user_id: str, platform: str = "qq") -> Optional[ChatStream]: """根据用户ID获取私聊流 - + Args: user_id: 用户ID platform: 平台,默认为"qq" - + Returns: Optional[ChatStream]: 聊天流对象,如果未找到返回None """ @@ -134,74 +134,78 @@ class ChatManager: except Exception as e: logger.error(f"[ChatAPI] 查找私聊流失败: {e}") return None - + @staticmethod def get_stream_type(chat_stream: ChatStream) -> str: """获取聊天流类型 - + Args: chat_stream: 聊天流对象 - + Returns: str: 聊天类型 ("group", "private", "unknown") """ if not chat_stream: return "unknown" - + if hasattr(chat_stream, "group_info"): return "group" if chat_stream.group_info else "private" return "unknown" - + @staticmethod def get_stream_info(chat_stream: ChatStream) -> Dict[str, Any]: """获取聊天流详细信息 - + Args: chat_stream: 聊天流对象 - + Returns: Dict[str, Any]: 聊天流信息字典 """ if not chat_stream: return {} - + try: info = { "stream_id": chat_stream.stream_id, "platform": chat_stream.platform, "type": ChatManager.get_stream_type(chat_stream), } - + if chat_stream.group_info: - info.update({ - "group_id": chat_stream.group_info.group_id, - "group_name": getattr(chat_stream.group_info, "group_name", "未知群聊"), - }) - + info.update( + { + "group_id": chat_stream.group_info.group_id, + "group_name": getattr(chat_stream.group_info, "group_name", "未知群聊"), + } + ) + if chat_stream.user_info: - info.update({ - "user_id": chat_stream.user_info.user_id, - "user_name": chat_stream.user_info.user_nickname, - }) - + info.update( + { + "user_id": chat_stream.user_info.user_id, + "user_name": chat_stream.user_info.user_nickname, + } + ) + return info except Exception as e: logger.error(f"[ChatAPI] 获取聊天流信息失败: {e}") return {} - + @staticmethod def get_recent_messages_from_obs(observations: List[Any], count: int = 5) -> List[Dict[str, Any]]: """从观察对象获取最近的消息 - + Args: observations: 观察对象列表 count: 要获取的消息数量 - + Returns: List[Dict]: 消息列表,每个消息包含发送者、内容等信息 """ messages = [] - + try: if observations and len(observations) > 0: obs = observations[0] @@ -219,13 +223,13 @@ class ChatManager: logger.debug(f"[ChatAPI] 获取到 {len(messages)} 条最近消息") except Exception as e: logger.error(f"[ChatAPI] 获取最近消息失败: {e}") - + return messages - + @staticmethod def get_streams_summary() -> Dict[str, int]: """获取聊天流统计摘要 - + Returns: Dict[str, int]: 包含各种统计信息的字典 """ @@ -233,14 +237,14 @@ class ChatManager: all_streams = ChatManager.get_all_streams() group_streams = ChatManager.get_group_streams() private_streams = ChatManager.get_private_streams() - + summary = { "total_streams": len(all_streams), "group_streams": len(group_streams), "private_streams": len(private_streams), "qq_streams": len([s for s in all_streams if s.platform == "qq"]), } - + logger.debug(f"[ChatAPI] 聊天流统计: {summary}") return summary except Exception as e: @@ -252,6 +256,7 @@ class ChatManager: # 模块级别的便捷函数 - 类似 requests.get(), requests.post() 的设计 # ============================================================================= + def get_all_streams(platform: str = "qq") -> List[ChatStream]: """获取所有聊天流的便捷函数""" return ChatManager.get_all_streams(platform) @@ -289,4 +294,4 @@ def get_stream_info(chat_stream: ChatStream) -> Dict[str, Any]: def get_streams_summary() -> Dict[str, int]: """获取聊天流统计摘要的便捷函数""" - return ChatManager.get_streams_summary() \ No newline at end of file + return ChatManager.get_streams_summary() diff --git a/src/plugin_system/apis/config_api.py b/src/plugin_system/apis/config_api.py index a2f8870dd..80b9d2645 100644 --- a/src/plugin_system/apis/config_api.py +++ b/src/plugin_system/apis/config_api.py @@ -19,6 +19,7 @@ logger = get_logger("config_api") # 配置访问API函数 # ============================================================================= + def get_global_config(key: str, default: Any = None) -> Any: """ 安全地从全局配置中获取一个值。 @@ -34,7 +35,7 @@ def get_global_config(key: str, default: Any = None) -> Any: # 支持嵌套键访问 keys = key.split(".") current = global_config - + try: for k in keys: if hasattr(current, k): @@ -79,6 +80,7 @@ def get_plugin_config(plugin_config: dict, key: str, default: Any = None) -> Any # 用户信息API函数 # ============================================================================= + async def get_user_id_by_person_name(person_name: str) -> tuple[str, str]: """根据用户名获取用户ID diff --git a/src/plugin_system/apis/database_api.py b/src/plugin_system/apis/database_api.py index ccde040bf..3921443df 100644 --- a/src/plugin_system/apis/database_api.py +++ b/src/plugin_system/apis/database_api.py @@ -18,6 +18,7 @@ logger = get_logger("database_api") # 通用数据库查询API函数 # ============================================================================= + async def db_query( model_class: Type[Model], query_type: str = "get", @@ -202,9 +203,7 @@ async def db_save( # 如果提供了key_field和key_value,尝试更新现有记录 if key_field and key_value is not None: # 查找现有记录 - existing_records = list( - model_class.select().where(getattr(model_class, key_field) == key_value).limit(1) - ) + existing_records = list(model_class.select().where(getattr(model_class, key_field) == key_value).limit(1)) if existing_records: # 更新现有记录 @@ -307,9 +306,9 @@ async def store_action_info( action_name: str = "", ) -> Union[Dict[str, Any], None]: """存储动作信息到数据库 - + 将Action执行的相关信息保存到ActionRecords表中,用于后续的记忆和上下文构建。 - + Args: chat_stream: 聊天流对象,包含聊天相关信息 action_build_into_prompt: 是否将此动作构建到提示中 @@ -318,11 +317,11 @@ async def store_action_info( thinking_id: 关联的思考ID action_data: 动作数据字典 action_name: 动作名称 - + Returns: Dict[str, Any]: 保存的记录数据 None: 如果保存失败 - + 示例: record = await database_api.store_action_info( chat_stream=chat_stream, @@ -338,7 +337,7 @@ async def store_action_info( import time import json from src.common.database.database_model import ActionRecords - + # 构建动作记录数据 record_data = { "action_id": thinking_id or str(int(time.time() * 1000000)), # 使用thinking_id或生成唯一ID @@ -349,38 +348,39 @@ async def store_action_info( "action_build_into_prompt": action_build_into_prompt, "action_prompt_display": action_prompt_display, } - + # 从chat_stream获取聊天信息 if chat_stream: - record_data.update({ - "chat_id": getattr(chat_stream, 'stream_id', ''), - "chat_info_stream_id": getattr(chat_stream, 'stream_id', ''), - "chat_info_platform": getattr(chat_stream, 'platform', ''), - }) + record_data.update( + { + "chat_id": getattr(chat_stream, "stream_id", ""), + "chat_info_stream_id": getattr(chat_stream, "stream_id", ""), + "chat_info_platform": getattr(chat_stream, "platform", ""), + } + ) else: # 如果没有chat_stream,设置默认值 - record_data.update({ - "chat_id": "", - "chat_info_stream_id": "", - "chat_info_platform": "", - }) - + record_data.update( + { + "chat_id": "", + "chat_info_stream_id": "", + "chat_info_platform": "", + } + ) + # 使用已有的db_save函数保存记录 saved_record = await db_save( - ActionRecords, - data=record_data, - key_field="action_id", - key_value=record_data["action_id"] + ActionRecords, data=record_data, key_field="action_id", key_value=record_data["action_id"] ) - + if saved_record: logger.info(f"[DatabaseAPI] 成功存储动作信息: {action_name} (ID: {record_data['action_id']})") else: logger.error(f"[DatabaseAPI] 存储动作信息失败: {action_name}") - + return saved_record - + except Exception as e: logger.error(f"[DatabaseAPI] 存储动作信息时发生错误: {e}") traceback.print_exc() - return None \ No newline at end of file + return None diff --git a/src/plugin_system/apis/emoji_api.py b/src/plugin_system/apis/emoji_api.py index 5cf2d6d2b..3fdcf1b55 100644 --- a/src/plugin_system/apis/emoji_api.py +++ b/src/plugin_system/apis/emoji_api.py @@ -20,35 +20,36 @@ logger = get_logger("emoji_api") # 表情包获取API函数 # ============================================================================= + async def get_by_description(description: str) -> Optional[Tuple[str, str, str]]: """根据描述选择表情包 - + Args: description: 表情包的描述文本,例如"开心"、"难过"、"愤怒"等 - + Returns: Optional[Tuple[str, str, str]]: (base64编码, 表情包描述, 匹配的情感标签) 或 None """ try: logger.info(f"[EmojiAPI] 根据描述获取表情包: {description}") - + emoji_manager = get_emoji_manager() emoji_result = await emoji_manager.get_emoji_for_text(description) - + if not emoji_result: logger.warning(f"[EmojiAPI] 未找到匹配描述 '{description}' 的表情包") return None - + emoji_path, emoji_description, matched_emotion = emoji_result emoji_base64 = image_path_to_base64(emoji_path) - + if not emoji_base64: logger.error(f"[EmojiAPI] 无法将表情包文件转换为base64: {emoji_path}") return None - + logger.info(f"[EmojiAPI] 成功获取表情包: {emoji_description}, 匹配情感: {matched_emotion}") return emoji_base64, emoji_description, matched_emotion - + except Exception as e: logger.error(f"[EmojiAPI] 获取表情包失败: {e}") return None @@ -56,43 +57,44 @@ async def get_by_description(description: str) -> Optional[Tuple[str, str, str]] async def get_random() -> Optional[Tuple[str, str, str]]: """随机获取表情包 - + Returns: Optional[Tuple[str, str, str]]: (base64编码, 表情包描述, 随机情感标签) 或 None """ try: logger.info("[EmojiAPI] 随机获取表情包") - + emoji_manager = get_emoji_manager() all_emojis = emoji_manager.emoji_objects - + if not all_emojis: logger.warning("[EmojiAPI] 没有可用的表情包") return None - + # 过滤有效表情包 valid_emojis = [emoji for emoji in all_emojis if not emoji.is_deleted] if not valid_emojis: logger.warning("[EmojiAPI] 没有有效的表情包") return None - + # 随机选择 import random + selected_emoji = random.choice(valid_emojis) emoji_base64 = image_path_to_base64(selected_emoji.full_path) - + if not emoji_base64: logger.error(f"[EmojiAPI] 无法转换表情包为base64: {selected_emoji.full_path}") return None - + matched_emotion = random.choice(selected_emoji.emotion) if selected_emoji.emotion else "随机表情" - + # 记录使用次数 emoji_manager.record_usage(selected_emoji.hash) - + logger.info(f"[EmojiAPI] 成功获取随机表情包: {selected_emoji.description}") return emoji_base64, selected_emoji.description, matched_emotion - + except Exception as e: logger.error(f"[EmojiAPI] 获取随机表情包失败: {e}") return None @@ -100,44 +102,45 @@ async def get_random() -> Optional[Tuple[str, str, str]]: async def get_by_emotion(emotion: str) -> Optional[Tuple[str, str, str]]: """根据情感标签获取表情包 - + Args: emotion: 情感标签,如"happy"、"sad"、"angry"等 - + Returns: Optional[Tuple[str, str, str]]: (base64编码, 表情包描述, 匹配的情感标签) 或 None """ try: logger.info(f"[EmojiAPI] 根据情感获取表情包: {emotion}") - + emoji_manager = get_emoji_manager() all_emojis = emoji_manager.emoji_objects - + # 筛选匹配情感的表情包 matching_emojis = [] for emoji_obj in all_emojis: if not emoji_obj.is_deleted and emotion.lower() in [e.lower() for e in emoji_obj.emotion]: matching_emojis.append(emoji_obj) - + if not matching_emojis: logger.warning(f"[EmojiAPI] 未找到匹配情感 '{emotion}' 的表情包") return None - + # 随机选择匹配的表情包 import random + selected_emoji = random.choice(matching_emojis) emoji_base64 = image_path_to_base64(selected_emoji.full_path) - + if not emoji_base64: logger.error(f"[EmojiAPI] 无法转换表情包为base64: {selected_emoji.full_path}") return None - + # 记录使用次数 emoji_manager.record_usage(selected_emoji.hash) - + logger.info(f"[EmojiAPI] 成功获取情感表情包: {selected_emoji.description}") return emoji_base64, selected_emoji.description, emotion - + except Exception as e: logger.error(f"[EmojiAPI] 根据情感获取表情包失败: {e}") return None @@ -147,9 +150,10 @@ async def get_by_emotion(emotion: str) -> Optional[Tuple[str, str, str]]: # 表情包信息查询API函数 # ============================================================================= + def get_count() -> int: """获取表情包数量 - + Returns: int: 当前可用的表情包数量 """ @@ -163,7 +167,7 @@ def get_count() -> int: def get_info() -> dict: """获取表情包系统信息 - + Returns: dict: 包含表情包数量、最大数量等信息 """ @@ -181,18 +185,18 @@ def get_info() -> dict: def get_emotions() -> list: """获取所有可用的情感标签 - + Returns: list: 所有表情包的情感标签列表(去重) """ try: emoji_manager = get_emoji_manager() emotions = set() - + for emoji_obj in emoji_manager.emoji_objects: if not emoji_obj.is_deleted and emoji_obj.emotion: emotions.update(emoji_obj.emotion) - + return sorted(list(emotions)) except Exception as e: logger.error(f"[EmojiAPI] 获取情感标签失败: {e}") @@ -201,18 +205,18 @@ def get_emotions() -> list: def get_descriptions() -> list: """获取所有表情包描述 - + Returns: list: 所有可用表情包的描述列表 """ try: emoji_manager = get_emoji_manager() descriptions = [] - + for emoji_obj in emoji_manager.emoji_objects: if not emoji_obj.is_deleted and emoji_obj.description: descriptions.append(emoji_obj.description) - + return descriptions except Exception as e: logger.error(f"[EmojiAPI] 获取表情包描述失败: {e}") diff --git a/src/plugin_system/apis/generator_api.py b/src/plugin_system/apis/generator_api.py index fdc29a06d..21cdcd3a3 100644 --- a/src/plugin_system/apis/generator_api.py +++ b/src/plugin_system/apis/generator_api.py @@ -16,22 +16,22 @@ from src.chat.message_receive.chat_stream import get_chat_manager logger = get_logger("generator_api") - # ============================================================================= # 回复器获取API函数 # ============================================================================= + def get_replyer(chat_stream=None, platform: str = None, chat_id: str = None, is_group: bool = True) -> DefaultReplyer: """获取回复器对象 - + 优先使用chat_stream,如果没有则使用platform和chat_id组合 - + Args: chat_stream: 聊天流对象(优先) platform: 平台名称,如"qq" chat_id: 聊天ID(群ID或用户ID) is_group: 是否为群聊 - + Returns: Optional[Any]: 回复器对象,如果获取失败则返回None """ @@ -40,7 +40,7 @@ def get_replyer(chat_stream=None, platform: str = None, chat_id: str = None, is_ if chat_stream: logger.debug("[GeneratorAPI] 使用聊天流获取回复器") return DefaultReplyer(chat_stream=chat_stream) - + # 使用平台和ID组合 if platform and chat_id: logger.debug("[GeneratorAPI] 使用平台和ID获取回复器") @@ -48,7 +48,7 @@ def get_replyer(chat_stream=None, platform: str = None, chat_id: str = None, is_ if not chat_manager: logger.warning("[GeneratorAPI] 无法获取聊天管理器") return None - + # 查找对应的聊天流 target_stream = None for _stream_id, stream in chat_manager.streams.items(): @@ -61,29 +61,31 @@ def get_replyer(chat_stream=None, platform: str = None, chat_id: str = None, is_ if str(stream.user_info.user_id) == str(chat_id): target_stream = stream break - + return DefaultReplyer(chat_stream=target_stream) - + logger.warning("[GeneratorAPI] 缺少必要参数,无法获取回复器") return None - + except Exception as e: logger.error(f"[GeneratorAPI] 获取回复器失败: {e}") return None + # ============================================================================= # 回复生成API函数 # ============================================================================= + async def generate_reply( chat_stream=None, action_data: Dict[str, Any] = None, platform: str = None, chat_id: str = None, - is_group: bool = True + is_group: bool = True, ) -> Tuple[bool, List[Tuple[str, Any]]]: """生成回复 - + Args: chat_stream: 聊天流对象(优先) action_data: 动作数据 @@ -94,7 +96,7 @@ async def generate_reply( platform: 平台名称(备用) chat_id: 聊天ID(备用) is_group: 是否为群聊(备用) - + Returns: Tuple[bool, List[Tuple[str, Any]]]: (是否成功, 回复集合) """ @@ -104,41 +106,42 @@ async def generate_reply( if not replyer: logger.error("[GeneratorAPI] 无法获取回复器") return False, [] - + logger.info("[GeneratorAPI] 开始生成回复") - + # 调用回复器生成回复 success, reply_set = await replyer.generate_reply_with_context( reply_data=action_data or {}, ) - + if success: logger.info(f"[GeneratorAPI] 回复生成成功,生成了 {len(reply_set)} 个回复项") else: logger.warning("[GeneratorAPI] 回复生成失败") - + return success, reply_set or [] - + except Exception as e: logger.error(f"[GeneratorAPI] 生成回复时出错: {e}") return False, [] + async def rewrite_reply( chat_stream=None, reply_data: Dict[str, Any] = None, platform: str = None, chat_id: str = None, - is_group: bool = True + is_group: bool = True, ) -> Tuple[bool, List[Tuple[str, Any]]]: """重写回复 - + Args: chat_stream: 聊天流对象(优先) action_data: 动作数据 platform: 平台名称(备用) chat_id: 聊天ID(备用) is_group: 是否为群聊(备用) - + Returns: Tuple[bool, List[Tuple[str, Any]]]: (是否成功, 回复集合) """ @@ -148,23 +151,21 @@ async def rewrite_reply( if not replyer: logger.error("[GeneratorAPI] 无法获取回复器") return False, [] - + logger.info("[GeneratorAPI] 开始重写回复") - + # 调用回复器重写回复 success, reply_set = await replyer.rewrite_reply_with_context( reply_data=reply_data or {}, ) - + if success: logger.info(f"[GeneratorAPI] 重写回复成功,生成了 {len(reply_set)} 个回复项") else: logger.warning("[GeneratorAPI] 重写回复失败") - + return success, reply_set or [] - + except Exception as e: logger.error(f"[GeneratorAPI] 重写回复时出错: {e}") return False, [] - - diff --git a/src/plugin_system/apis/llm_api.py b/src/plugin_system/apis/llm_api.py index 1fb2f11a2..b87306990 100644 --- a/src/plugin_system/apis/llm_api.py +++ b/src/plugin_system/apis/llm_api.py @@ -19,6 +19,7 @@ logger = get_logger("llm_api") # LLM模型API函数 # ============================================================================= + def get_available_models() -> Dict[str, Any]: """获取所有可用的模型配置 diff --git a/src/plugin_system/apis/message_api.py b/src/plugin_system/apis/message_api.py index 106fa56bc..a4241ab53 100644 --- a/src/plugin_system/apis/message_api.py +++ b/src/plugin_system/apis/message_api.py @@ -32,18 +32,19 @@ from src.chat.utils.chat_message_builder import ( # 消息查询API函数 # ============================================================================= + def get_messages_by_time( start_time: float, end_time: float, limit: int = 0, limit_mode: str = "latest" ) -> List[Dict[str, Any]]: """ 获取指定时间范围内的消息 - + Args: start_time: 开始时间戳 end_time: 结束时间戳 limit: 限制返回的消息数量,0为不限制 limit_mode: 当limit>0时生效,'earliest'表示获取最早的记录,'latest'表示获取最新的记录 - + Returns: 消息列表 """ @@ -55,14 +56,14 @@ def get_messages_by_time_in_chat( ) -> List[Dict[str, Any]]: """ 获取指定聊天中指定时间范围内的消息 - + Args: chat_id: 聊天ID start_time: 开始时间戳 end_time: 结束时间戳 limit: 限制返回的消息数量,0为不限制 limit_mode: 当limit>0时生效,'earliest'表示获取最早的记录,'latest'表示获取最新的记录 - + Returns: 消息列表 """ @@ -74,14 +75,14 @@ def get_messages_by_time_in_chat_inclusive( ) -> List[Dict[str, Any]]: """ 获取指定聊天中指定时间范围内的消息(包含边界) - + Args: chat_id: 聊天ID start_time: 开始时间戳(包含) end_time: 结束时间戳(包含) limit: 限制返回的消息数量,0为不限制 limit_mode: 当limit>0时生效,'earliest'表示获取最早的记录,'latest'表示获取最新的记录 - + Returns: 消息列表 """ @@ -98,7 +99,7 @@ def get_messages_by_time_in_chat_for_users( ) -> List[Dict[str, Any]]: """ 获取指定聊天中指定用户在指定时间范围内的消息 - + Args: chat_id: 聊天ID start_time: 开始时间戳 @@ -106,7 +107,7 @@ def get_messages_by_time_in_chat_for_users( person_ids: 用户ID列表 limit: 限制返回的消息数量,0为不限制 limit_mode: 当limit>0时生效,'earliest'表示获取最早的记录,'latest'表示获取最新的记录 - + Returns: 消息列表 """ @@ -118,13 +119,13 @@ def get_random_chat_messages( ) -> List[Dict[str, Any]]: """ 随机选择一个聊天,返回该聊天在指定时间范围内的消息 - + Args: start_time: 开始时间戳 end_time: 结束时间戳 limit: 限制返回的消息数量,0为不限制 limit_mode: 当limit>0时生效,'earliest'表示获取最早的记录,'latest'表示获取最新的记录 - + Returns: 消息列表 """ @@ -136,14 +137,14 @@ def get_messages_by_time_for_users( ) -> List[Dict[str, Any]]: """ 获取指定用户在所有聊天中指定时间范围内的消息 - + Args: start_time: 开始时间戳 end_time: 结束时间戳 person_ids: 用户ID列表 limit: 限制返回的消息数量,0为不限制 limit_mode: 当limit>0时生效,'earliest'表示获取最早的记录,'latest'表示获取最新的记录 - + Returns: 消息列表 """ @@ -153,11 +154,11 @@ def get_messages_by_time_for_users( def get_messages_before_time(timestamp: float, limit: int = 0) -> List[Dict[str, Any]]: """ 获取指定时间戳之前的消息 - + Args: timestamp: 时间戳 limit: 限制返回的消息数量,0为不限制 - + Returns: 消息列表 """ @@ -167,29 +168,27 @@ def get_messages_before_time(timestamp: float, limit: int = 0) -> List[Dict[str, def get_messages_before_time_in_chat(chat_id: str, timestamp: float, limit: int = 0) -> List[Dict[str, Any]]: """ 获取指定聊天中指定时间戳之前的消息 - + Args: chat_id: 聊天ID timestamp: 时间戳 limit: 限制返回的消息数量,0为不限制 - + Returns: 消息列表 """ return get_raw_msg_before_timestamp_with_chat(chat_id, timestamp, limit) -def get_messages_before_time_for_users( - timestamp: float, person_ids: list, limit: int = 0 -) -> List[Dict[str, Any]]: +def get_messages_before_time_for_users(timestamp: float, person_ids: list, limit: int = 0) -> List[Dict[str, Any]]: """ 获取指定用户在指定时间戳之前的消息 - + Args: timestamp: 时间戳 person_ids: 用户ID列表 limit: 限制返回的消息数量,0为不限制 - + Returns: 消息列表 """ @@ -197,20 +196,17 @@ def get_messages_before_time_for_users( def get_recent_messages( - chat_id: str, - hours: float = 24.0, - limit: int = 100, - limit_mode: str = "latest" + chat_id: str, hours: float = 24.0, limit: int = 100, limit_mode: str = "latest" ) -> List[Dict[str, Any]]: """ 获取指定聊天中最近一段时间的消息 - + Args: chat_id: 聊天ID hours: 最近多少小时,默认24小时 limit: 限制返回的消息数量,默认100条 limit_mode: 当limit>0时生效,'earliest'表示获取最早的记录,'latest'表示获取最新的记录 - + Returns: 消息列表 """ @@ -223,35 +219,32 @@ def get_recent_messages( # 消息计数API函数 # ============================================================================= -def count_new_messages( - chat_id: str, start_time: float = 0.0, end_time: Optional[float] = None -) -> int: + +def count_new_messages(chat_id: str, start_time: float = 0.0, end_time: Optional[float] = None) -> int: """ 计算指定聊天中从开始时间到结束时间的新消息数量 - + Args: chat_id: 聊天ID start_time: 开始时间戳 end_time: 结束时间戳,如果为None则使用当前时间 - + Returns: 新消息数量 """ return num_new_messages_since(chat_id, start_time, end_time) -def count_new_messages_for_users( - chat_id: str, start_time: float, end_time: float, person_ids: list -) -> int: +def count_new_messages_for_users(chat_id: str, start_time: float, end_time: float, person_ids: list) -> int: """ 计算指定聊天中指定用户从开始时间到结束时间的新消息数量 - + Args: chat_id: 聊天ID start_time: 开始时间戳 end_time: 结束时间戳 person_ids: 用户ID列表 - + Returns: 新消息数量 """ @@ -262,6 +255,7 @@ def count_new_messages_for_users( # 消息格式化API函数 # ============================================================================= + def build_readable_messages_to_str( messages: List[Dict[str, Any]], replace_bot_name: bool = True, @@ -273,7 +267,7 @@ def build_readable_messages_to_str( ) -> str: """ 将消息列表构建成可读的字符串 - + Args: messages: 消息列表 replace_bot_name: 是否将机器人的名称替换为"你" @@ -282,7 +276,7 @@ def build_readable_messages_to_str( read_mark: 已读标记时间戳,用于分割已读和未读消息 truncate: 是否截断长消息 show_actions: 是否显示动作记录 - + Returns: 格式化后的可读字符串 """ @@ -300,29 +294,27 @@ async def build_readable_messages_with_details( ) -> Tuple[str, List[Tuple[float, str, str]]]: """ 将消息列表构建成可读的字符串,并返回详细信息 - + Args: messages: 消息列表 replace_bot_name: 是否将机器人的名称替换为"你" merge_messages: 是否合并连续消息 timestamp_mode: 时间戳显示模式,'relative'或'absolute' truncate: 是否截断长消息 - + Returns: 格式化后的可读字符串和详细信息元组列表(时间戳, 昵称, 内容) """ - return await build_readable_messages_with_list( - messages, replace_bot_name, merge_messages, timestamp_mode, truncate - ) + return await build_readable_messages_with_list(messages, replace_bot_name, merge_messages, timestamp_mode, truncate) async def get_person_ids_from_messages(messages: List[Dict[str, Any]]) -> List[str]: """ 从消息列表中提取不重复的用户ID列表 - + Args: messages: 消息列表 - + Returns: 用户ID列表 """ diff --git a/src/plugin_system/apis/person_api.py b/src/plugin_system/apis/person_api.py index 85ad8a70f..ae108211c 100644 --- a/src/plugin_system/apis/person_api.py +++ b/src/plugin_system/apis/person_api.py @@ -18,16 +18,17 @@ logger = get_logger("person_api") # 个人信息API函数 # ============================================================================= + def get_person_id(platform: str, user_id: int) -> str: """根据平台和用户ID获取person_id - + Args: platform: 平台名称,如 "qq", "telegram" 等 user_id: 用户ID - + Returns: str: 唯一的person_id(MD5哈希值) - + 示例: person_id = person_api.get_person_id("qq", 123456) """ @@ -40,15 +41,15 @@ def get_person_id(platform: str, user_id: int) -> str: async def get_person_value(person_id: str, field_name: str, default: Any = None) -> Any: """根据person_id和字段名获取某个值 - + Args: person_id: 用户的唯一标识ID field_name: 要获取的字段名,如 "nickname", "impression" 等 default: 当字段不存在或获取失败时返回的默认值 - + Returns: Any: 字段值或默认值 - + 示例: nickname = await person_api.get_person_value(person_id, "nickname", "未知用户") impression = await person_api.get_person_value(person_id, "impression") @@ -64,18 +65,18 @@ async def get_person_value(person_id: str, field_name: str, default: Any = None) async def get_person_values(person_id: str, field_names: list, default_dict: dict = None) -> dict: """批量获取用户信息字段值 - + Args: person_id: 用户的唯一标识ID field_names: 要获取的字段名列表 default_dict: 默认值字典,键为字段名,值为默认值 - + Returns: dict: 字段名到值的映射字典 - + 示例: values = await person_api.get_person_values( - person_id, + person_id, ["nickname", "impression", "know_times"], {"nickname": "未知用户", "know_times": 0} ) @@ -83,11 +84,11 @@ async def get_person_values(person_id: str, field_names: list, default_dict: dic try: person_info_manager = get_person_info_manager() values = await person_info_manager.get_values(person_id, field_names) - + # 如果获取成功,返回结果 if values: return values - + # 如果获取失败,构建默认值字典 result = {} if default_dict: @@ -96,9 +97,9 @@ async def get_person_values(person_id: str, field_names: list, default_dict: dic else: for field in field_names: result[field] = None - + return result - + except Exception as e: logger.error(f"[PersonAPI] 批量获取用户信息失败: person_id={person_id}, fields={field_names}, error={e}") # 返回默认值字典 @@ -114,14 +115,14 @@ async def get_person_values(person_id: str, field_names: list, default_dict: dic async def is_person_known(platform: str, user_id: int) -> bool: """判断是否认识某个用户 - + Args: platform: 平台名称 user_id: 用户ID - + Returns: bool: 是否认识该用户 - + 示例: known = await person_api.is_person_known("qq", 123456) """ @@ -135,13 +136,13 @@ async def is_person_known(platform: str, user_id: int) -> bool: def get_person_id_by_name(person_name: str) -> str: """根据用户名获取person_id - + Args: person_name: 用户名 - + Returns: str: person_id,如果未找到返回空字符串 - + 示例: person_id = person_api.get_person_id_by_name("张三") """ diff --git a/src/plugin_system/apis/send_api.py b/src/plugin_system/apis/send_api.py index 66734c7c7..6ccede4ff 100644 --- a/src/plugin_system/apis/send_api.py +++ b/src/plugin_system/apis/send_api.py @@ -31,6 +31,7 @@ logger = get_logger("send_api") # 内部实现函数(不暴露给外部) # ============================================================================= + async def _send_to_target( message_type: str, content: str, @@ -41,7 +42,7 @@ async def _send_to_target( storage_message: bool = True, ) -> bool: """向指定目标发送消息的内部实现 - + Args: message_type: 消息类型,如"text"、"image"、"emoji"等 content: 消息内容 @@ -49,41 +50,41 @@ async def _send_to_target( display_message: 显示消息 typing: 是否显示正在输入 reply_to: 回复消息的格式,如"发送者:消息内容" - + Returns: bool: 是否发送成功 """ try: logger.info(f"[SendAPI] 发送{message_type}消息到 {stream_id}") - + # 查找目标聊天流 target_stream = get_chat_manager().get_stream(stream_id) if not target_stream: logger.error(f"[SendAPI] 未找到聊天流: {stream_id}") return False - + # 创建发送器 heart_fc_sender = HeartFCSender() - + # 生成消息ID current_time = time.time() message_id = f"send_api_{int(current_time * 1000)}" - + # 构建机器人用户信息 bot_user_info = UserInfo( user_id=global_config.bot.qq_account, user_nickname=global_config.bot.nickname, platform=target_stream.platform, ) - + # 创建消息段 message_segment = Seg(type=message_type, data=content) - + # 处理回复消息 anchor_message = None if reply_to: anchor_message = await _find_reply_message(target_stream, reply_to) - + # 构建发送消息对象 bot_message = MessageSending( message_id=message_id, @@ -97,19 +98,19 @@ async def _send_to_target( is_emoji=(message_type == "emoji"), thinking_start_time=current_time, ) - + # 发送消息 sent_msg = await heart_fc_sender.send_message( bot_message, typing=typing, set_reply=(anchor_message is not None), storage_message=storage_message ) - + if sent_msg: logger.info(f"[SendAPI] 成功发送消息到 {stream_id}") return True else: logger.error("[SendAPI] 发送消息失败") return False - + except Exception as e: logger.error(f"[SendAPI] 发送消息时出错: {e}") traceback.print_exc() @@ -118,11 +119,11 @@ async def _send_to_target( async def _find_reply_message(target_stream, reply_to: str) -> Optional[MessageRecv]: """查找要回复的消息 - + Args: target_stream: 目标聊天流 reply_to: 回复格式,如"发送者:消息内容"或"发送者:消息内容" - + Returns: Optional[MessageRecv]: 找到的消息,如果没找到则返回None """ @@ -139,20 +140,20 @@ async def _find_reply_message(target_stream, reply_to: str) -> Optional[MessageR if len(parts) != 2: logger.warning(f"[SendAPI] reply_to格式不正确: {reply_to}") return None - + sender = parts[0].strip() text = parts[1].strip() - + # 获取聊天流的最新20条消息 reverse_talking_message = get_raw_msg_before_timestamp_with_chat( - target_stream.stream_id, + target_stream.stream_id, time.time(), # 当前时间之前的消息 - 20 # 最新的20条消息 + 20, # 最新的20条消息 ) - + # 反转列表,使最新的消息在前面 reverse_talking_message = list(reversed(reverse_talking_message)) - + find_msg = None for message in reverse_talking_message: user_id = message["user_id"] @@ -198,20 +199,20 @@ async def _find_reply_message(target_stream, reply_to: str) -> Optional[MessageR "format_info": format_info, "template_info": template_info, } - + message_dict = { "message_info": message_info, "raw_message": find_msg.get("processed_plain_text"), "detailed_plain_text": find_msg.get("processed_plain_text"), "processed_plain_text": find_msg.get("processed_plain_text"), } - + find_rec_msg = MessageRecv(message_dict) find_rec_msg.update_chat_stream(target_stream) - + logger.info(f"[SendAPI] 找到匹配的回复消息,发送者: {sender}") return find_rec_msg - + except Exception as e: logger.error(f"[SendAPI] 查找回复消息时出错: {e}") traceback.print_exc() @@ -222,34 +223,49 @@ async def _find_reply_message(target_stream, reply_to: str) -> Optional[MessageR # 公共API函数 - 预定义类型的发送函数 # ============================================================================= -async def text_to_group(text: str, group_id: str, platform: str = "qq", typing: bool = False, reply_to: str = "", storage_message: bool = True) -> bool: + +async def text_to_group( + text: str, + group_id: str, + platform: str = "qq", + typing: bool = False, + reply_to: str = "", + storage_message: bool = True, +) -> bool: """向群聊发送文本消息 - + Args: text: 要发送的文本内容 group_id: 群聊ID platform: 平台,默认为"qq" typing: 是否显示正在输入 reply_to: 回复消息,格式为"发送者:消息内容" - + Returns: bool: 是否发送成功 """ stream_id = get_chat_manager().get_stream_id(platform, group_id, True) - + return await _send_to_target("text", text, stream_id, "", typing, reply_to, storage_message) -async def text_to_user(text: str, user_id: str, platform: str = "qq", typing: bool = False, reply_to: str = "", storage_message: bool = True) -> bool: +async def text_to_user( + text: str, + user_id: str, + platform: str = "qq", + typing: bool = False, + reply_to: str = "", + storage_message: bool = True, +) -> bool: """向用户发送私聊文本消息 - + Args: text: 要发送的文本内容 user_id: 用户ID platform: 平台,默认为"qq" typing: 是否显示正在输入 reply_to: 回复消息,格式为"发送者:消息内容" - + Returns: bool: 是否发送成功 """ @@ -259,12 +275,12 @@ async def text_to_user(text: str, user_id: str, platform: str = "qq", typing: bo async def emoji_to_group(emoji_base64: str, group_id: str, platform: str = "qq", storage_message: bool = True) -> bool: """向群聊发送表情包 - + Args: emoji_base64: 表情包的base64编码 group_id: 群聊ID platform: 平台,默认为"qq" - + Returns: bool: 是否发送成功 """ @@ -274,12 +290,12 @@ async def emoji_to_group(emoji_base64: str, group_id: str, platform: str = "qq", async def emoji_to_user(emoji_base64: str, user_id: str, platform: str = "qq", storage_message: bool = True) -> bool: """向用户发送表情包 - + Args: emoji_base64: 表情包的base64编码 user_id: 用户ID platform: 平台,默认为"qq" - + Returns: bool: 是否发送成功 """ @@ -289,12 +305,12 @@ async def emoji_to_user(emoji_base64: str, user_id: str, platform: str = "qq", s async def image_to_group(image_base64: str, group_id: str, platform: str = "qq", storage_message: bool = True) -> bool: """向群聊发送图片 - + Args: image_base64: 图片的base64编码 group_id: 群聊ID platform: 平台,默认为"qq" - + Returns: bool: 是否发送成功 """ @@ -304,40 +320,42 @@ async def image_to_group(image_base64: str, group_id: str, platform: str = "qq", async def image_to_user(image_base64: str, user_id: str, platform: str = "qq", storage_message: bool = True) -> bool: """向用户发送图片 - + Args: image_base64: 图片的base64编码 user_id: 用户ID platform: 平台,默认为"qq" - + Returns: bool: 是否发送成功 """ stream_id = get_chat_manager().get_stream_id(platform, user_id, False) return await _send_to_target("image", image_base64, stream_id, "", typing=False) + async def command_to_group(command: str, group_id: str, platform: str = "qq", storage_message: bool = True) -> bool: """向群聊发送命令 - + Args: command: 命令 group_id: 群聊ID platform: 平台,默认为"qq" - + Returns: bool: 是否发送成功 """ stream_id = get_chat_manager().get_stream_id(platform, group_id, True) return await _send_to_target("command", command, stream_id, "", typing=False, storage_message=storage_message) + async def command_to_user(command: str, user_id: str, platform: str = "qq", storage_message: bool = True) -> bool: """向用户发送命令 - + Args: command: 命令 user_id: 用户ID platform: 平台,默认为"qq" - + Returns: bool: 是否发送成功 """ @@ -349,18 +367,19 @@ async def command_to_user(command: str, user_id: str, platform: str = "qq", stor # 通用发送函数 - 支持任意消息类型 # ============================================================================= + async def custom_to_group( - message_type: str, - content: str, - group_id: str, - platform: str = "qq", + message_type: str, + content: str, + group_id: str, + platform: str = "qq", display_message: str = "", typing: bool = False, reply_to: str = "", - storage_message: bool = True + storage_message: bool = True, ) -> bool: """向群聊发送自定义类型消息 - + Args: message_type: 消息类型,如"text"、"image"、"emoji"、"video"、"file"等 content: 消息内容(通常是base64编码或文本) @@ -369,7 +388,7 @@ async def custom_to_group( display_message: 显示消息 typing: 是否显示正在输入 reply_to: 回复消息,格式为"发送者:消息内容" - + Returns: bool: 是否发送成功 """ @@ -378,17 +397,17 @@ async def custom_to_group( async def custom_to_user( - message_type: str, - content: str, - user_id: str, - platform: str = "qq", + message_type: str, + content: str, + user_id: str, + platform: str = "qq", display_message: str = "", typing: bool = False, reply_to: str = "", - storage_message: bool = True + storage_message: bool = True, ) -> bool: """向用户发送自定义类型消息 - + Args: message_type: 消息类型,如"text"、"image"、"emoji"、"video"、"file"等 content: 消息内容(通常是base64编码或文本) @@ -397,7 +416,7 @@ async def custom_to_user( display_message: 显示消息 typing: 是否显示正在输入 reply_to: 回复消息,格式为"发送者:消息内容" - + Returns: bool: 是否发送成功 """ @@ -414,10 +433,10 @@ async def custom_message( display_message: str = "", typing: bool = False, reply_to: str = "", - storage_message: bool = True + storage_message: bool = True, ) -> bool: """发送自定义消息的通用接口 - + Args: message_type: 消息类型,如"text"、"image"、"emoji"、"video"、"file"、"audio"等 content: 消息内容 @@ -427,19 +446,19 @@ async def custom_message( display_message: 显示消息 typing: 是否显示正在输入 reply_to: 回复消息,格式为"发送者:消息内容" - + Returns: bool: 是否发送成功 - + 示例: # 发送视频到群聊 await send_api.custom_message("video", video_base64, "123456", True) - + # 发送文件到用户 await send_api.custom_message("file", file_base64, "987654", False) - + # 发送音频到群聊并回复特定消息 await send_api.custom_message("audio", audio_base64, "123456", True, reply_to="张三:你好") """ stream_id = get_chat_manager().get_stream_id(platform, target_id, is_group) - return await _send_to_target(message_type, content, stream_id, display_message, typing, reply_to, storage_message) \ No newline at end of file + return await _send_to_target(message_type, content, stream_id, display_message, typing, reply_to, storage_message) diff --git a/src/plugin_system/apis/utils_api.py b/src/plugin_system/apis/utils_api.py index f29b6ee85..1e5858b3f 100644 --- a/src/plugin_system/apis/utils_api.py +++ b/src/plugin_system/apis/utils_api.py @@ -24,6 +24,7 @@ logger = get_logger("utils_api") # 文件操作API函数 # ============================================================================= + def get_plugin_path(caller_frame=None) -> str: """获取调用者插件的路径 @@ -106,6 +107,7 @@ def write_json_file(file_path: str, data: Any, indent: int = 2) -> bool: # 时间相关API函数 # ============================================================================= + def get_timestamp() -> int: """获取当前时间戳 @@ -156,6 +158,7 @@ def parse_time(time_str: str, format_str: str = "%Y-%m-%d %H:%M:%S") -> int: # 其他工具函数 # ============================================================================= + def generate_unique_id() -> str: """生成唯一ID diff --git a/src/plugin_system/base/base_action.py b/src/plugin_system/base/base_action.py index c25893742..b0cd2d194 100644 --- a/src/plugin_system/base/base_action.py +++ b/src/plugin_system/base/base_action.py @@ -2,7 +2,7 @@ from abc import ABC, abstractmethod from typing import Tuple, Optional from src.common.logger import get_logger from src.plugin_system.base.component_types import ActionActivationType, ChatMode, ActionInfo, ComponentType -from src.plugin_system.apis import send_api, database_api,message_api +from src.plugin_system.apis import send_api, database_api, message_api import time import asyncio @@ -59,7 +59,7 @@ class BaseAction(ABC): self.thinking_id = thinking_id self.log_prefix = log_prefix self.shutting_down = shutting_down - + # 保存插件配置 self.plugin_config = plugin_config or {} @@ -83,11 +83,10 @@ class BaseAction(ABC): # ============================================================================= # 便捷属性 - 直接在初始化时获取常用聊天信息(带类型注解) # ============================================================================= - - + # 获取聊天流对象 self.chat_stream = chat_stream or kwargs.get("chat_stream") - + self.chat_id = self.chat_stream.stream_id # 初始化基础信息(带类型注解) self.is_group: bool = False @@ -97,28 +96,30 @@ class BaseAction(ABC): self.target_id: Optional[str] = None self.group_name: Optional[str] = None self.user_nickname: Optional[str] = None - + # 如果有聊天流,提取所有信息 if self.chat_stream: - self.platform = getattr(self.chat_stream, 'platform', None) - + self.platform = getattr(self.chat_stream, "platform", None) + # 获取群聊信息 # print(self.chat_stream) # print(self.chat_stream.group_info) if self.chat_stream.group_info: self.is_group = True self.group_id = str(self.chat_stream.group_info.group_id) - self.group_name = getattr(self.chat_stream.group_info, 'group_name', None) + self.group_name = getattr(self.chat_stream.group_info, "group_name", None) else: self.is_group = False self.user_id = str(self.chat_stream.user_info.user_id) - self.user_nickname = getattr(self.chat_stream.user_info, 'user_nickname', None) - + self.user_nickname = getattr(self.chat_stream.user_info, "user_nickname", None) + # 设置目标ID(群聊用群ID,私聊用户ID) self.target_id = self.group_id if self.is_group else self.user_id logger.debug(f"{self.log_prefix} Action组件初始化完成") - logger.debug(f"{self.log_prefix} 聊天信息: 类型={'群聊' if self.is_group else '私聊'}, 平台={self.platform}, 目标={self.target_id}") + logger.debug( + f"{self.log_prefix} 聊天信息: 类型={'群聊' if self.is_group else '私聊'}, 平台={self.platform}, 目标={self.target_id}" + ) def _get_activation_type_value(self, attr_name: str, default: str) -> str: """获取激活类型的字符串值""" @@ -138,10 +139,9 @@ class BaseAction(ABC): return attr.value return str(attr) - async def wait_for_new_message(self, timeout: int = 1200) -> Tuple[bool, str]: """等待新消息或超时 - + 在loop_start_time之后等待新消息,如果没有新消息且没有超时,就一直等待。 使用message_api检查self.chat_id对应的聊天中是否有新消息。 @@ -155,7 +155,7 @@ class BaseAction(ABC): # 获取循环开始时间,如果没有则使用当前时间 loop_start_time = self.action_data.get("loop_start_time", time.time()) logger.info(f"{self.log_prefix} 开始等待新消息... (最长等待: {timeout}秒, 从时间点: {loop_start_time})") - + # 确保有有效的chat_id if not self.chat_id: logger.error(f"{self.log_prefix} 等待新消息失败: 没有有效的chat_id") @@ -166,17 +166,15 @@ class BaseAction(ABC): # 检查关闭标志 # shutting_down = self.get_action_context("shutting_down", False) # if shutting_down: - # logger.info(f"{self.log_prefix} 等待新消息时检测到关闭信号,中断等待") - # return False, "" + # logger.info(f"{self.log_prefix} 等待新消息时检测到关闭信号,中断等待") + # return False, "" # 检查新消息 current_time = time.time() new_message_count = message_api.count_new_messages( - chat_id=self.chat_id, - start_time=loop_start_time, - end_time=current_time + chat_id=self.chat_id, start_time=loop_start_time, end_time=current_time ) - + if new_message_count > 0: logger.info(f"{self.log_prefix} 检测到{new_message_count}条新消息,聊天ID: {self.chat_id}") return True, "" @@ -186,7 +184,7 @@ class BaseAction(ABC): if elapsed_time > timeout: logger.warning(f"{self.log_prefix} 等待新消息超时({timeout}秒),聊天ID: {self.chat_id}") return False, "" - + # 每30秒记录一次等待状态 if int(elapsed_time) % 15 == 0 and int(elapsed_time) > 0: logger.debug(f"{self.log_prefix} 已等待{int(elapsed_time)}秒,继续等待新消息...") @@ -234,7 +232,7 @@ class BaseAction(ABC): """ # 导入send_api from src.plugin_system.apis import send_api - + if not self.target_id or not self.platform: logger.error(f"{self.log_prefix} 缺少发送消息所需的信息") return False @@ -255,7 +253,7 @@ class BaseAction(ABC): """ # 导入send_api from src.plugin_system.apis import send_api - + if not self.target_id or not self.platform: logger.error(f"{self.log_prefix} 缺少发送消息所需的信息") return False @@ -278,7 +276,7 @@ class BaseAction(ABC): """ # 导入send_api from src.plugin_system.apis import send_api - + if not self.target_id or not self.platform: logger.error(f"{self.log_prefix} 缺少发送消息所需的信息") return False @@ -289,7 +287,7 @@ class BaseAction(ABC): target_id=self.target_id, is_group=self.is_group, platform=self.platform, - typing=typing + typing=typing, ) async def store_action_info( @@ -299,7 +297,7 @@ class BaseAction(ABC): action_done: bool = True, ) -> None: """存储动作信息到数据库 - + Args: action_build_into_prompt: 是否构建到提示中 action_prompt_display: 显示的action提示信息 @@ -315,7 +313,9 @@ class BaseAction(ABC): action_name=self.action_name, ) - async def send_command(self, command_name: str, args: dict = None, display_message: str = None, storage_message: bool = True) -> bool: + async def send_command( + self, command_name: str, args: dict = None, display_message: str = None, storage_message: bool = True + ) -> bool: """发送命令消息 使用和send_text相同的方式通过MessageAPI发送命令 @@ -338,7 +338,7 @@ class BaseAction(ABC): command=command_data, group_id=str(self.group_id), platform=self.platform, - storage_message=storage_message + storage_message=storage_message, ) else: # 私聊 @@ -346,7 +346,7 @@ class BaseAction(ABC): command=command_data, user_id=str(self.user_id), platform=self.platform, - storage_message=storage_message + storage_message=storage_message, ) if success: @@ -433,11 +433,11 @@ class BaseAction(ABC): def get_action_context(self, key: str, default=None): """获取action上下文信息 - + Args: key: 上下文键名 default: 默认值 - + Returns: Any: 上下文值或默认值 """ @@ -445,17 +445,17 @@ class BaseAction(ABC): def get_config(self, key: str, default=None): """获取插件配置值,支持嵌套键访问 - + Args: key: 配置键名,支持嵌套访问如 "section.subsection.key" default: 默认值 - + Returns: Any: 配置值或默认值 """ if not self.plugin_config: return default - + # 支持嵌套键访问 keys = key.split(".") current = self.plugin_config diff --git a/src/plugin_system/base/base_command.py b/src/plugin_system/base/base_command.py index 63550b52b..4c5cb1ee0 100644 --- a/src/plugin_system/base/base_command.py +++ b/src/plugin_system/base/base_command.py @@ -22,7 +22,7 @@ class BaseCommand(ABC): command_name: str = "" command_description: str = "" - + # 默认命令设置(子类可以覆盖) command_pattern: str = "" command_help: str = "" @@ -63,17 +63,17 @@ class BaseCommand(ABC): def get_config(self, key: str, default=None): """获取插件配置值,支持嵌套键访问 - + Args: key: 配置键名,支持嵌套访问如 "section.subsection.key" default: 默认值 - + Returns: Any: 配置值或默认值 """ if not self.plugin_config: return default - + # 支持嵌套键访问 keys = key.split(".") current = self.plugin_config @@ -97,19 +97,15 @@ class BaseCommand(ABC): if chat_stream.group_info: # 群聊 - + await send_api.text_to_group( - text=content, - group_id=str(chat_stream.group_info.group_id), - platform=chat_stream.platform + text=content, group_id=str(chat_stream.group_info.group_id), platform=chat_stream.platform ) else: # 私聊 - + await send_api.text_to_user( - text=content, - user_id=str(chat_stream.user_info.user_id), - platform=chat_stream.platform + text=content, user_id=str(chat_stream.user_info.user_id), platform=chat_stream.platform ) async def send_type( @@ -131,6 +127,7 @@ class BaseCommand(ABC): if chat_stream.group_info: # 群聊 from src.plugin_system.apis import send_api + return await send_api.custom_message( message_type=message_type, content=content, @@ -142,6 +139,7 @@ class BaseCommand(ABC): else: # 私聊 from src.plugin_system.apis import send_api + return await send_api.custom_message( message_type=message_type, content=content, @@ -172,6 +170,7 @@ class BaseCommand(ABC): if chat_stream.group_info: # 群聊 from src.plugin_system.apis import send_api + success = await send_api.custom_message( message_type="command", content=command_data, @@ -182,6 +181,7 @@ class BaseCommand(ABC): else: # 私聊 from src.plugin_system.apis import send_api + success = await send_api.custom_message( message_type="command", content=command_data, diff --git a/src/plugin_system/core/component_registry.py b/src/plugin_system/core/component_registry.py index 47611817c..5457a396e 100644 --- a/src/plugin_system/core/component_registry.py +++ b/src/plugin_system/core/component_registry.py @@ -54,7 +54,7 @@ class ComponentRegistry: """ component_name = component_info.name component_type = component_info.component_type - plugin_name = getattr(component_info, 'plugin_name', 'unknown') + plugin_name = getattr(component_info, "plugin_name", "unknown") # 🔥 系统级别自动区分:为不同类型的组件添加命名空间前缀 if component_type == ComponentType.ACTION: @@ -68,8 +68,8 @@ class ComponentRegistry: # 检查命名空间化的名称是否冲突 if namespaced_name in self._components: existing_info = self._components[namespaced_name] - existing_plugin = getattr(existing_info, 'plugin_name', 'unknown') - + existing_plugin = getattr(existing_info, "plugin_name", "unknown") + logger.warning( f"组件冲突: {component_type.value}组件 '{component_name}' " f"已被插件 '{existing_plugin}' 注册,跳过插件 '{plugin_name}' 的注册" @@ -116,18 +116,18 @@ class ComponentRegistry: def get_component_info(self, component_name: str, component_type: ComponentType = None) -> Optional[ComponentInfo]: """获取组件信息,支持自动命名空间解析 - + Args: component_name: 组件名称,可以是原始名称或命名空间化的名称 component_type: 组件类型,如果提供则优先在该类型中查找 - + Returns: Optional[ComponentInfo]: 组件信息或None """ # 1. 如果已经是命名空间化的名称,直接查找 - if '.' in component_name: + if "." in component_name: return self._components.get(component_name) - + # 2. 如果指定了组件类型,构造命名空间化的名称查找 if component_type: if component_type == ComponentType.ACTION: @@ -136,9 +136,9 @@ class ComponentRegistry: namespaced_name = f"command.{component_name}" else: namespaced_name = f"{component_type.value}.{component_name}" - + return self._components.get(namespaced_name) - + # 3. 如果没有指定类型,尝试在所有命名空间中查找 candidates = [] for namespace_prefix in ["action", "command"]: @@ -146,7 +146,7 @@ class ComponentRegistry: component_info = self._components.get(namespaced_name) if component_info: candidates.append((namespace_prefix, namespaced_name, component_info)) - + if len(candidates) == 1: # 只有一个匹配,直接返回 return candidates[0][2] @@ -154,28 +154,27 @@ class ComponentRegistry: # 多个匹配,记录警告并返回第一个 namespaces = [ns for ns, _, _ in candidates] logger.warning( - f"组件名称 '{component_name}' 在多个命名空间中存在: {namespaces}," - f"使用第一个匹配项: {candidates[0][1]}" + f"组件名称 '{component_name}' 在多个命名空间中存在: {namespaces},使用第一个匹配项: {candidates[0][1]}" ) return candidates[0][2] - + # 4. 都没找到 return None def get_component_class(self, component_name: str, component_type: ComponentType = None) -> Optional[Type]: """获取组件类,支持自动命名空间解析 - + Args: component_name: 组件名称,可以是原始名称或命名空间化的名称 component_type: 组件类型,如果提供则优先在该类型中查找 - + Returns: Optional[Type]: 组件类或None """ # 1. 如果已经是命名空间化的名称,直接查找 - if '.' in component_name: + if "." in component_name: return self._component_classes.get(component_name) - + # 2. 如果指定了组件类型,构造命名空间化的名称查找 if component_type: if component_type == ComponentType.ACTION: @@ -184,9 +183,9 @@ class ComponentRegistry: namespaced_name = f"command.{component_name}" else: namespaced_name = f"{component_type.value}.{component_name}" - + return self._component_classes.get(namespaced_name) - + # 3. 如果没有指定类型,尝试在所有命名空间中查找 candidates = [] for namespace_prefix in ["action", "command"]: @@ -194,7 +193,7 @@ class ComponentRegistry: component_class = self._component_classes.get(namespaced_name) if component_class: candidates.append((namespace_prefix, namespaced_name, component_class)) - + if len(candidates) == 1: # 只有一个匹配,直接返回 namespace, full_name, cls = candidates[0] @@ -204,11 +203,10 @@ class ComponentRegistry: # 多个匹配,记录警告并返回第一个 namespaces = [ns for ns, _, _ in candidates] logger.warning( - f"组件名称 '{component_name}' 在多个命名空间中存在: {namespaces}," - f"使用第一个匹配项: {candidates[0][1]}" + f"组件名称 '{component_name}' 在多个命名空间中存在: {namespaces},使用第一个匹配项: {candidates[0][1]}" ) return candidates[0][2] - + # 4. 都没找到 return None @@ -262,7 +260,6 @@ class ComponentRegistry: """ for pattern, command_class in self._command_patterns.items(): - match = pattern.match(text) if match: command_name = None @@ -271,7 +268,7 @@ class ComponentRegistry: if cls == command_class: command_name = name break - + # 检查命令是否启用 if command_name: command_info = self.get_command_info(command_name) @@ -346,15 +343,19 @@ class ComponentRegistry: component_info = self.get_component_info(component_name, component_type) if not component_info: return False - + # 根据组件类型构造正确的命名空间化名称 if component_info.component_type == ComponentType.ACTION: - namespaced_name = f"action.{component_name}" if '.' not in component_name else component_name + namespaced_name = f"action.{component_name}" if "." not in component_name else component_name elif component_info.component_type == ComponentType.COMMAND: - namespaced_name = f"command.{component_name}" if '.' not in component_name else component_name + namespaced_name = f"command.{component_name}" if "." not in component_name else component_name else: - namespaced_name = f"{component_info.component_type.value}.{component_name}" if '.' not in component_name else component_name - + namespaced_name = ( + f"{component_info.component_type.value}.{component_name}" + if "." not in component_name + else component_name + ) + if namespaced_name in self._components: self._components[namespaced_name].enabled = True # 如果是Action,更新默认动作集 @@ -370,15 +371,19 @@ class ComponentRegistry: component_info = self.get_component_info(component_name, component_type) if not component_info: return False - + # 根据组件类型构造正确的命名空间化名称 if component_info.component_type == ComponentType.ACTION: - namespaced_name = f"action.{component_name}" if '.' not in component_name else component_name + namespaced_name = f"action.{component_name}" if "." not in component_name else component_name elif component_info.component_type == ComponentType.COMMAND: - namespaced_name = f"command.{component_name}" if '.' not in component_name else component_name + namespaced_name = f"command.{component_name}" if "." not in component_name else component_name else: - namespaced_name = f"{component_info.component_type.value}.{component_name}" if '.' not in component_name else component_name - + namespaced_name = ( + f"{component_info.component_type.value}.{component_name}" + if "." not in component_name + else component_name + ) + if namespaced_name in self._components: self._components[namespaced_name].enabled = False # 如果是Action,从默认动作集中移除 diff --git a/src/plugins/built_in/core_actions/plugin.py b/src/plugins/built_in/core_actions/plugin.py index 5c1b048c9..dfd6e82b7 100644 --- a/src/plugins/built_in/core_actions/plugin.py +++ b/src/plugins/built_in/core_actions/plugin.py @@ -38,9 +38,7 @@ class ReplyAction(BaseAction): action_description = "参与聊天回复,发送文本进行表达" # 动作参数定义 - action_parameters = { - "reply_to": "你要回复的对方的发言内容,格式:(用户名:发言内容),可以为none" - } + action_parameters = {"reply_to": "你要回复的对方的发言内容,格式:(用户名:发言内容),可以为none"} # 动作使用场景 action_require = ["你想要闲聊或者随便附和", "有人提到你", "如果你刚刚进行了回复,不要对同一个话题重复回应"] @@ -53,45 +51,40 @@ class ReplyAction(BaseAction): logger.info(f"{self.log_prefix} 决定回复: {self.reasoning}") start_time = self.action_data.get("loop_start_time", time.time()) - + try: - success, reply_set = await generator_api.generate_reply( chat_stream=self.chat_stream, action_data=self.action_data, platform=self.platform, chat_id=self.chat_id, - is_group=self.is_group + is_group=self.is_group, ) # 检查从start_time以来的新消息数量 # 获取动作触发时间或使用默认值 current_time = time.time() new_message_count = message_api.count_new_messages( - chat_id=self.chat_id, - start_time=start_time, - end_time=current_time + chat_id=self.chat_id, start_time=start_time, end_time=current_time ) - + # 根据新消息数量决定是否使用reply_to need_reply = new_message_count >= 4 - logger.info(f"{self.log_prefix} 从{start_time}到{current_time}共有{new_message_count}条新消息,{'使用' if need_reply else '不使用'}reply_to") + logger.info( + f"{self.log_prefix} 从{start_time}到{current_time}共有{new_message_count}条新消息,{'使用' if need_reply else '不使用'}reply_to" + ) # 构建回复文本 - reply_text = "" + reply_text = "" first_reply = False for reply_seg in reply_set: data = reply_seg[1] if not first_reply and need_reply: - await self.send_text( - content=data, - reply_to=self.action_data.get("reply_to", "") - ) + await self.send_text(content=data, reply_to=self.action_data.get("reply_to", "")) else: await self.send_text(content=data) first_reply = True reply_text += data - # 存储动作记录 await self.store_action_info( @@ -110,7 +103,6 @@ class ReplyAction(BaseAction): return False, f"回复失败: {str(e)}" - class NoReplyAction(BaseAction): """不回复动作,继承时会等待新消息或超时""" @@ -168,7 +160,7 @@ class NoReplyAction(BaseAction): except Exception as e: logger.error(f"{self.log_prefix} 不回复动作执行失败: {e}") - return False, f"不回复动作执行失败: {e}" + return False, f"不回复动作执行失败: {e}" @classmethod def reset_consecutive_count(cls): @@ -218,17 +210,17 @@ class EmojiAction(BaseAction): # 1. 根据描述选择表情包 description = self.action_data.get("description", "") emoji_result = await emoji_api.get_by_description(description) - + if not emoji_result: logger.warning(f"{self.log_prefix} 未找到匹配描述 '{description}' 的表情包") return False, f"未找到匹配 '{description}' 的表情包" - + emoji_base64, emoji_description, matched_emotion = emoji_result logger.info(f"{self.log_prefix} 找到表情包: {emoji_description}, 匹配情感: {matched_emotion}") - + # 使用BaseAction的便捷方法发送表情包 success = await self.send_emoji(emoji_base64) - + if not success: logger.error(f"{self.log_prefix} 表情包发送失败") return False, "表情包发送失败" @@ -430,10 +422,6 @@ class CoreActionsPlugin(BasePlugin): return components - - - - # class DeepReplyAction(BaseAction): # """回复动作 - 参与聊天回复""" @@ -467,42 +455,39 @@ class CoreActionsPlugin(BasePlugin): # chatting_observation = self._get_chatting_observation() # if not chatting_observation: # return False, "未找到聊天观察" - + # talking_message_str = chatting_observation.talking_message_str # # 处理回复目标 # chat_stream = self.api.get_service("chat_stream") # anchor_message = await create_empty_anchor_message(chat_stream.platform, chat_stream.group_info, chat_stream) - - + # llm_model = self.api.get_available_models().replyer_1 - + # prompt = f""" # {talking_message_str} # 在上面的聊天中,你对{self.action_data.get("topic", "")}感兴趣,形成深刻观点,请你思考,总结成一份学术论文,APA标准格式 # """ - + # success, response, reasoning, model_name = await self.api.generate_with_model(prompt, llm_model) - + # print(prompt) # print(f"DeepReplyAction: {response}") - + # # prompt = f""" # # {talking_message_str} # # 在上面的聊天中,你对{self.action_data.get("topic", "")}感兴趣,请你思考 # # """ - + # extra_info_block = self.action_data.get("extra_info_block", "") # extra_info_block += response # # extra_info_block += f"\n--------------------------------\n注意,这是最重要的内容!!!!!你现在可以用比较长的篇幅来表达你的观点,不要只回复一个字或者几个字\n由于你进入了深度思考模式,所以下方聊天记录的回复要求不再适用,请你自由的表达,不论字数长短限制\n\n--------------------------------\n注意,你现在可以用比较长的篇幅来表达你的观点,不要只回复一个字或者几个字\n由于你进入了深度思考模式,所以下方聊天记录的回复要求不再适用,请你自由的表达,不论字数长短限制\n" # # extra_info_block += f"\n--------------------------------\n注意,优先关注这句!!!!你现在可以用比较长的篇幅来表达你的观点,不要只回复一个字或者几个字\n由于你进入了深度思考模式,所以下方聊天记录的回复要求不再适用,请你自由的表达,不论字数长短限制\n\n--------------------------------\n注意,你现在可以用比较长的篇幅来表达你的观点,不要只回复一个字或者几个字\n由于你进入了深度思考模式,所以其他的回复要求不再适用,请你自由的表达,不论字数长短限制\n" # self.action_data["extra_info_block"] = extra_info_block - - # # 获取回复器服务 # # replyer = self.api.get_service("replyer") @@ -558,4 +543,4 @@ class CoreActionsPlugin(BasePlugin): # for reply in reply_set: # data = reply[1] # reply_text += data -# return reply_text \ No newline at end of file +# return reply_text diff --git a/src/plugins/built_in/mute_plugin/plugin.py b/src/plugins/built_in/mute_plugin/plugin.py index 3c2036897..4e664f944 100644 --- a/src/plugins/built_in/mute_plugin/plugin.py +++ b/src/plugins/built_in/mute_plugin/plugin.py @@ -26,6 +26,7 @@ from src.plugin_system.base.base_command import BaseCommand from src.plugin_system.base.component_types import ComponentInfo, ActionActivationType, ChatMode from src.plugin_system.base.config_types import ConfigField from src.common.logger import get_logger + # 导入配置API(可选的简便方法) from src.plugin_system.apis import person_api, generator_api @@ -140,28 +141,28 @@ class MuteAction(BaseAction): # 获取用户ID person_id = person_api.get_person_id_by_name(target) - user_id = await person_api.get_person_value(person_id,"user_id") + user_id = await person_api.get_person_value(person_id, "user_id") if not user_id: error_msg = f"未找到用户 {target} 的ID" await self.send_text(f"找不到 {target} 这个人呢~") logger.error(f"{self.log_prefix} {error_msg}") return False, error_msg - + # 格式化时长显示 enable_formatting = self.get_config("mute.enable_duration_formatting", True) time_str = self._format_duration(duration_int) if enable_formatting else f"{duration_int}秒" # 获取模板化消息 message = self._get_template_message(target, time_str, reason) - - result_status,result_message = await generator_api.rewrite_reply( + + result_status, result_message = await generator_api.rewrite_reply( chat_stream=self.chat_stream, reply_data={ "raw_reply": message, "reason": reason, - } + }, ) - + if result_status: for reply_seg in result_message: data = reply_seg[1] @@ -169,9 +170,7 @@ class MuteAction(BaseAction): # 发送群聊禁言命令 success = await self.send_command( - command_name="GROUP_BAN", - args={"qq_id": str(user_id), "duration": str(duration_int)}, - storage_message=False + command_name="GROUP_BAN", args={"qq_id": str(user_id), "duration": str(duration_int)}, storage_message=False ) if success: @@ -186,15 +185,13 @@ class MuteAction(BaseAction): else: error_msg = "发送禁言命令失败" logger.error(f"{self.log_prefix} {error_msg}") - + await self.send_text("执行禁言动作失败") return False, error_msg def _get_template_message(self, target: str, duration_str: str, reason: str) -> str: """获取模板化的禁言消息""" - templates = self.get_config( - "mute.templates" - ) + templates = self.get_config("mute.templates") template = random.choice(templates) return template.format(target=target, duration=duration_str, reason=reason)