diff --git a/src/chat/chat_loop/proactive/proactive_thinker.py b/src/chat/chat_loop/proactive/proactive_thinker.py index d63820710..4abaccebd 100644 --- a/src/chat/chat_loop/proactive/proactive_thinker.py +++ b/src/chat/chat_loop/proactive/proactive_thinker.py @@ -138,20 +138,6 @@ class ProactiveThinker: except Exception as e: logger.error(f"{self.context.log_prefix} 主动思考执行异常: {e}") logger.error(traceback.format_exc()) - - async def _get_reminder_context(self, message_id: str) -> str: - """获取提醒消息的上下文""" - try: - # 只获取那一条消息 - message_record = await db_get(Messages, {"message_id": message_id}, single_result=True) - if message_record: - # 使用 build_readable_messages_with_id 来格式化单条消息 - chat_context_block, _ = build_readable_messages_with_id(messages=[message_record]) - return chat_context_block - return "无法加载相关的聊天记录。" - except Exception as e: - logger.error(f"{self.context.log_prefix} 获取提醒上下文失败: {e}") - return "无法加载相关的聊天记录。" async def _generate_proactive_content_and_send(self, action_result: Dict[str, Any], trigger_event: ProactiveTriggerEvent): diff --git a/src/plugins/built_in/at_user_plugin/plugin.py b/src/plugins/built_in/at_user_plugin/plugin.py index cdaf7163e..7a80b8ab6 100644 --- a/src/plugins/built_in/at_user_plugin/plugin.py +++ b/src/plugins/built_in/at_user_plugin/plugin.py @@ -8,6 +8,7 @@ from src.plugin_system import ( ActionInfo, ActionActivationType, ) +from src.person_info.person_info import get_person_info_manager from src.common.logger import get_logger from src.plugin_system.base.component_types import ChatType @@ -20,16 +21,16 @@ class AtAction(BaseAction): # === 基本信息(必须填写)=== action_name = "at_user" action_description = "发送艾特消息" - activation_type = ActionActivationType.LLM_JUDGE + activation_type = ActionActivationType.LLM_JUDGE # 消息接收时激活(?) parallel_action = False chat_type_allow = ChatType.GROUP # === 功能描述(必须填写)=== - action_parameters = {"user_name": "需要艾特用户的名字", "at_message": "艾特用户时要发送的消息"} + action_parameters = {"user_name": "需要艾特用户的名字", "at_message": "艾特用户时要发送的消,注意消息里不要有@"} action_require = [ - "当用户明确要求你去'叫'、'喊'、'提醒'或'艾特'某人时使用", - "当你判断,为了让特定的人看到消息,需要代表用户去呼叫他/她时使用", - "例如:'你去叫一下张三','提醒一下李四开会'", + "当需要艾特某个用户时使用", + "当你需要提醒特定用户查看消息时使用", + "在回复中需要明确指向某个用户时使用", ] llm_judge_prompt = """ 判定是否需要使用艾特用户动作的条件: @@ -47,43 +48,24 @@ class AtAction(BaseAction): if not user_name or not at_message: logger.warning("艾特用户的动作缺少必要参数。") + await self.store_action_info( + action_build_into_prompt=True, + action_prompt_display=f"执行了艾特用户动作:艾特用户 {user_name} 并发送消息: {at_message},失败了,因为没有提供必要参数", + action_done=False, + ) return False, "缺少必要参数" - from src.plugin_system.apis import send_api - from fuzzywuzzy import process - - group_id = self.chat_stream.group_info.group_id - if not group_id: - return False, "无法获取群组ID" - - response = await send_api.adapter_command_to_stream( - action="get_group_member_list", - params={"group_id": group_id}, - stream_id=self.chat_id, - ) - - if response.get("status") != "ok": - return False, f"获取群成员列表失败: {response.get('message')}" - - member_list = response.get("data", []) - if not member_list: - return False, "群成员列表为空" - - # 使用模糊匹配找到最接近的用户名 - choices = {member["card"] or member["nickname"]: member["user_id"] for member in member_list} - best_match, score = process.extractOne(user_name, choices.keys()) - - if score < 30: # 设置一个匹配度阈值 - logger.info(f"找不到与 '{user_name}' 高度匹配的用户 (最佳匹配: {best_match}, 分数: {score})") + user_info = await get_person_info_manager().get_person_info_by_name(user_name) + if not user_info or not user_info.get("user_id"): + logger.info(f"找不到名为 '{user_name}' 的用户。") return False, "用户不存在" - - user_id = choices[best_match] - user_info = {"user_id": user_id, "user_nickname": best_match} try: + # 使用回复器生成艾特回复,而不是直接发送命令 from src.chat.replyer.default_generator import DefaultReplyer from src.chat.message_receive.chat_stream import get_chat_manager - + + # 获取当前聊天流 chat_manager = get_chat_manager() chat_stream = chat_manager.get_stream(self.chat_id) @@ -91,56 +73,97 @@ class AtAction(BaseAction): logger.error(f"找不到聊天流: {self.stream_id}") return False, "聊天流不存在" + # 创建回复器实例 replyer = DefaultReplyer(chat_stream) + + # 构建回复对象,将艾特消息作为回复目标 + reply_to = f"{user_name}:{at_message}" extra_info = f"你需要艾特用户 {user_name} 并回复他们说: {at_message}" - success, llm_response, _ = await replyer.generate_reply_with_context( - reply_to=f"{user_name}:{at_message}", + # 使用回复器生成回复 + success, llm_response, prompt = await replyer.generate_reply_with_context( + reply_to=reply_to, extra_info=extra_info, - enable_tool=False, + enable_tool=False, # 艾特回复通常不需要工具调用 from_plugin=False ) - if not success or not llm_response: + if success and llm_response: + # 获取生成的回复内容 + reply_content = llm_response.get("content", "") + if reply_content: + # 获取用户QQ号,发送真正的艾特消息 + user_id = user_info.get("user_id") + + # 发送真正的艾特命令,使用回复器生成的智能内容 + await self.send_command( + "SEND_AT_MESSAGE", + args={"qq_id": user_id, "text": reply_content}, + display_message=f"艾特用户 {user_name} 并发送智能回复: {reply_content}", + ) + + await self.store_action_info( + action_build_into_prompt=True, + action_prompt_display=f"执行了艾特用户动作:艾特用户 {user_name} 并发送智能回复: {reply_content}", + action_done=True, + ) + + logger.info(f"成功通过回复器生成智能内容并发送真正的艾特消息给 {user_name}: {reply_content}") + return True, "智能艾特消息发送成功" + else: + logger.warning("回复器生成了空内容") + return False, "回复内容为空" + else: logger.error("回复器生成回复失败") return False, "回复生成失败" - - final_message_raw = llm_response.get("content", "") - if not final_message_raw: - logger.warning("回复器生成了空内容") - return False, "回复内容为空" - - # 对LLM生成的内容进行后处理,解析[SPLIT]标记并将分段消息合并 - from src.chat.utils.utils import process_llm_response - final_message_segments = process_llm_response(final_message_raw, enable_splitter=True, enable_chinese_typo=False) - final_message = " ".join(final_message_segments) - - await self.send_command( - "SEND_AT_MESSAGE", - args={"group_id": self.chat_stream.group_info.group_id, "qq_id": user_id, "text": final_message}, - display_message=f"艾特用户 {user_name} 并发送消息: {final_message}", - ) - - await self.store_action_info( - action_build_into_prompt=True, - action_prompt_display=f"执行了艾特用户动作:艾特用户 {user_name} 并发送消息: {final_message}", - action_done=True, - ) - - logger.info(f"成功发送艾特消息给 {user_name}: {final_message}") - return True, "艾特消息发送成功" except Exception as e: logger.error(f"执行艾特用户动作时发生异常: {e}", exc_info=True) + await self.store_action_info( + action_build_into_prompt=True, + action_prompt_display=f"执行艾特用户动作失败:{str(e)}", + action_done=False, + ) return False, f"执行失败: {str(e)}" +class AtCommand(BaseCommand): + command_name: str = "at_user" + description: str = "通过名字艾特用户" + command_pattern: str = r"/at\s+@?(?P[\S]+)(?:\s+(?P.*))?" + + async def execute(self) -> Tuple[bool, str, bool]: + name = self.matched_groups.get("name") + text = self.matched_groups.get("text", "") + + if not name: + await self.send_text("请指定要艾特的用户名称。") + return False, "缺少用户名称", True + + person_info_manager = get_person_info_manager() + user_info = await person_info_manager.get_person_info_by_name(name) + + if not user_info or not user_info.get("user_id"): + await self.send_text(f"找不到名为 '{name}' 的用户。") + return False, "用户不存在", True + + user_id = user_info.get("user_id") + + await self.send_command( + "SEND_AT_MESSAGE", + args={"qq_id": user_id, "text": text}, + display_message=f"艾特用户 {name} 并发送消息: {text}", + ) + + return True, "艾特消息已发送", True + + @register_plugin class AtUserPlugin(BasePlugin): plugin_name: str = "at_user_plugin" enable_plugin: bool = True dependencies: list[str] = [] - python_dependencies: list[str] = ["fuzzywuzzy", "python-Levenshtein"] + python_dependencies: list[str] = [] config_file_name: str = "config.toml" config_schema: dict = {}