pull/937/head
Bakadax 2025-05-06 11:06:32 +08:00
parent e74ee67376
commit fec9c19b6b
3 changed files with 857 additions and 260 deletions

View File

@ -276,11 +276,13 @@ class ActionPlanner:
time_info = "" time_info = ""
try: try:
if not observation_info or not observation_info.bot_id: return "" if not observation_info or not observation_info.bot_id:
return ""
bot_id_str = str(observation_info.bot_id) bot_id_str = str(observation_info.bot_id)
if hasattr(observation_info, "chat_history") and observation_info.chat_history: if hasattr(observation_info, "chat_history") and observation_info.chat_history:
for msg in reversed(observation_info.chat_history): for msg in reversed(observation_info.chat_history):
if not isinstance(msg, dict): continue if not isinstance(msg, dict):
continue
sender_info = msg.get("user_info", {}) sender_info = msg.get("user_info", {})
sender_id = str(sender_info.get("user_id")) if isinstance(sender_info, dict) else None sender_id = str(sender_info.get("user_id")) if isinstance(sender_info, dict) else None
msg_time = msg.get("time") msg_time = msg.get("time")
@ -289,8 +291,10 @@ class ActionPlanner:
if time_diff < 60.0: if time_diff < 60.0:
time_info = f"提示:你上一条成功发送的消息是在 {time_diff:.1f} 秒前。\n" time_info = f"提示:你上一条成功发送的消息是在 {time_diff:.1f} 秒前。\n"
break break
except AttributeError as e: logger.warning(f"[私聊][{self.private_name}] 获取 Bot 上次发言时间时属性错误: {e}") except AttributeError as e:
except Exception as e: logger.warning(f"[私聊][{self.private_name}] 获取 Bot 上次发言时间时出错: {e}") logger.warning(f"[私聊][{self.private_name}] 获取 Bot 上次发言时间时属性错误: {e}")
except Exception as e:
logger.warning(f"[私聊][{self.private_name}] 获取 Bot 上次发言时间时出错: {e}")
return time_info return time_info
def _get_timeout_context(self, conversation_info: ConversationInfo) -> str: def _get_timeout_context(self, conversation_info: ConversationInfo) -> str:
@ -301,14 +305,18 @@ class ActionPlanner:
if hasattr(conversation_info, "goal_list") and conversation_info.goal_list: if hasattr(conversation_info, "goal_list") and conversation_info.goal_list:
last_goal_item = conversation_info.goal_list[-1] last_goal_item = conversation_info.goal_list[-1]
last_goal_text = "" last_goal_text = ""
if isinstance(last_goal_item, dict): last_goal_text = last_goal_item.get("goal", "") if isinstance(last_goal_item, dict):
elif isinstance(last_goal_item, str): last_goal_text = last_goal_item last_goal_text = last_goal_item.get("goal", "")
elif isinstance(last_goal_item, str):
last_goal_text = last_goal_item
if isinstance(last_goal_text, str) and "分钟," in last_goal_text and "思考接下来要做什么" in last_goal_text: if isinstance(last_goal_text, str) and "分钟," in last_goal_text and "思考接下来要做什么" in last_goal_text:
wait_time_str = last_goal_text.split("分钟,")[0].replace("你等待了","").strip() wait_time_str = last_goal_text.split("分钟,")[0].replace("你等待了","").strip()
timeout_context = f"重要提示:对方已经长时间(约 {wait_time_str} 分钟)没有回复你的消息了,请基于此情况规划下一步。\n" timeout_context = f"重要提示:对方已经长时间(约 {wait_time_str} 分钟)没有回复你的消息了,请基于此情况规划下一步。\n"
logger.debug(f"[私聊][{self.private_name}] 检测到超时目标: {last_goal_text}") logger.debug(f"[私聊][{self.private_name}] 检测到超时目标: {last_goal_text}")
except AttributeError as e: logger.warning(f"[私聊][{self.private_name}] 检查超时目标时属性错误: {e}") except AttributeError as e:
except Exception as e: logger.warning(f"[私聊][{self.private_name}] 检查超时目标时出错: {e}") logger.warning(f"[私聊][{self.private_name}] 检查超时目标时属性错误: {e}")
except Exception as e:
logger.warning(f"[私聊][{self.private_name}] 检查超时目标时出错: {e}")
return timeout_context return timeout_context
def _build_goals_string(self, conversation_info: ConversationInfo) -> str: def _build_goals_string(self, conversation_info: ConversationInfo) -> str:
@ -319,9 +327,11 @@ class ActionPlanner:
if hasattr(conversation_info, "goal_list") and conversation_info.goal_list: if hasattr(conversation_info, "goal_list") and conversation_info.goal_list:
recent_goals = conversation_info.goal_list[-3:] recent_goals = conversation_info.goal_list[-3:]
for goal_item in recent_goals: for goal_item in recent_goals:
goal = "目标内容缺失"; reasoning = "没有明确原因" goal = "目标内容缺失"
reasoning = "没有明确原因"
if isinstance(goal_item, dict): if isinstance(goal_item, dict):
goal = goal_item.get("goal", goal); reasoning = goal_item.get("reasoning", reasoning) goal = goal_item.get("goal", goal)
reasoning = goal_item.get("reasoning", reasoning)
elif isinstance(goal_item, str): goal = goal_item elif isinstance(goal_item, str): goal = goal_item
goal = str(goal) if goal is not None else "目标内容缺失" goal = str(goal) if goal is not None else "目标内容缺失"
reasoning = str(reasoning) if reasoning is not None else "没有明确原因" reasoning = str(reasoning) if reasoning is not None else "没有明确原因"
@ -339,8 +349,8 @@ class ActionPlanner:
try: try:
if hasattr(observation_info, "chat_history_str") and observation_info.chat_history_str: chat_history_text = observation_info.chat_history_str if hasattr(observation_info, "chat_history_str") and observation_info.chat_history_str: chat_history_text = observation_info.chat_history_str
elif hasattr(observation_info, "chat_history") and observation_info.chat_history: elif hasattr(observation_info, "chat_history") and observation_info.chat_history:
history_slice = observation_info.chat_history[-20:] history_slice = observation_info.chat_history[-20:]
chat_history_text = await build_readable_messages(history_slice, replace_bot_name=True, merge_messages=False, timestamp_mode="relative", read_mark=0.0) chat_history_text = await build_readable_messages(history_slice, replace_bot_name=True, merge_messages=False, timestamp_mode="relative", read_mark=0.0)
else: chat_history_text = "还没有聊天记录。\n" else: chat_history_text = "还没有聊天记录。\n"
unread_count = getattr(observation_info, 'new_messages_count', 0) unread_count = getattr(observation_info, 'new_messages_count', 0)
unread_messages = getattr(observation_info, 'unprocessed_messages', []) unread_messages = getattr(observation_info, 'unprocessed_messages', [])

File diff suppressed because it is too large Load Diff

View File

@ -36,11 +36,11 @@ class PFCManager:
await asyncio.sleep(0.5) # 短暂等待,让初始化有机会完成 await asyncio.sleep(0.5) # 短暂等待,让初始化有机会完成
# 再次检查实例是否存在 # 再次检查实例是否存在
if stream_id in self._instances and self._instances[stream_id]._initialized: if stream_id in self._instances and self._instances[stream_id]._initialized:
logger.debug(f"[私聊][{private_name}] 初始化已完成,返回现有实例: {stream_id}") logger.debug(f"[私聊][{private_name}] 初始化已完成,返回现有实例: {stream_id}")
return self._instances[stream_id] return self._instances[stream_id]
else: else:
logger.warning(f"[私聊][{private_name}] 等待后实例仍未初始化完成或不存在。") logger.warning(f"[私聊][{private_name}] 等待后实例仍未初始化完成或不存在。")
return None # 避免返回未完成的实例 return None # 避免返回未完成的实例
# 检查是否已有活动实例 # 检查是否已有活动实例
if stream_id in self._instances: if stream_id in self._instances:
@ -61,8 +61,10 @@ class PFCManager:
logger.warning(f"[私聊][{private_name}] 发现无效或已停止的旧实例,清理并重新创建: {stream_id}") logger.warning(f"[私聊][{private_name}] 发现无效或已停止的旧实例,清理并重新创建: {stream_id}")
await self._cleanup_conversation(instance) await self._cleanup_conversation(instance)
# 从字典中移除,确保下面能创建新的 # 从字典中移除,确保下面能创建新的
if stream_id in self._instances: del self._instances[stream_id] if stream_id in self._instances:
if stream_id in self._initializing: del self._initializing[stream_id] del self._instances[stream_id]
if stream_id in self._initializing:
del self._initializing[stream_id]
# --- 创建并初始化新实例 --- # --- 创建并初始化新实例 ---
@ -88,7 +90,8 @@ class PFCManager:
logger.error(f"[私聊][{private_name}] 初始化未成功完成,无法启动实例 {stream_id}") logger.error(f"[私聊][{private_name}] 初始化未成功完成,无法启动实例 {stream_id}")
# 清理可能部分创建的实例 # 清理可能部分创建的实例
await self._cleanup_conversation(conversation_instance) await self._cleanup_conversation(conversation_instance)
if stream_id in self._instances: del self._instances[stream_id] if stream_id in self._instances:
del self._instances[stream_id]
conversation_instance = None # 返回 None 表示失败 conversation_instance = None # 返回 None 表示失败
except Exception as e: except Exception as e:
@ -97,13 +100,14 @@ class PFCManager:
# 确保清理 # 确保清理
if conversation_instance: if conversation_instance:
await self._cleanup_conversation(conversation_instance) await self._cleanup_conversation(conversation_instance)
if stream_id in self._instances: del self._instances[stream_id] if stream_id in self._instances:
del self._instances[stream_id]
conversation_instance = None # 返回 None conversation_instance = None # 返回 None
finally: finally:
# 确保初始化标记被清除 # 确保初始化标记被清除
if stream_id in self._initializing: if stream_id in self._initializing:
self._initializing[stream_id] = False self._initializing[stream_id] = False
return conversation_instance return conversation_instance
@ -116,9 +120,9 @@ class PFCManager:
await conversation._initialize() # 调用实例自身的初始化方法 await conversation._initialize() # 调用实例自身的初始化方法
# 注意:初始化成功与否由 conversation._initialized 和 conversation.should_continue 标志决定 # 注意:初始化成功与否由 conversation._initialized 和 conversation.should_continue 标志决定
if conversation._initialized: if conversation._initialized:
logger.info(f"[私聊][{private_name}] conversation._initialize() 调用完成,实例标记为已初始化: {stream_id}") logger.info(f"[私聊][{private_name}] conversation._initialize() 调用完成,实例标记为已初始化: {stream_id}")
else: else:
logger.warning(f"[私聊][{private_name}] conversation._initialize() 调用完成,但实例未成功标记为已初始化: {stream_id}") logger.warning(f"[私聊][{private_name}] conversation._initialize() 调用完成,但实例未成功标记为已初始化: {stream_id}")
except Exception as e: except Exception as e:
# _initialize 内部应该处理自己的异常,但这里也捕获以防万一 # _initialize 内部应该处理自己的异常,但这里也捕获以防万一
@ -131,7 +135,8 @@ class PFCManager:
async def _cleanup_conversation(self, conversation: Conversation): async def _cleanup_conversation(self, conversation: Conversation):
"""清理会话实例的资源""" """清理会话实例的资源"""
if not conversation: return if not conversation:
return
stream_id = conversation.stream_id stream_id = conversation.stream_id
private_name = conversation.private_name private_name = conversation.private_name
logger.info(f"[私聊][{private_name}] 开始清理会话实例资源: {stream_id}") logger.info(f"[私聊][{private_name}] 开始清理会话实例资源: {stream_id}")
@ -140,13 +145,13 @@ class PFCManager:
if hasattr(conversation, 'stop') and callable(conversation.stop): if hasattr(conversation, 'stop') and callable(conversation.stop):
await conversation.stop() # stop 方法应处理内部组件的停止 await conversation.stop() # stop 方法应处理内部组件的停止
else: else:
logger.warning(f"[私聊][{private_name}] Conversation 对象缺少 stop 方法,可能无法完全清理资源。") logger.warning(f"[私聊][{private_name}] Conversation 对象缺少 stop 方法,可能无法完全清理资源。")
# 尝试手动停止已知组件 (作为后备) # 尝试手动停止已知组件 (作为后备)
if hasattr(conversation, 'idle_conversation_starter') and conversation.idle_conversation_starter: if hasattr(conversation, 'idle_conversation_starter') and conversation.idle_conversation_starter:
conversation.idle_conversation_starter.stop() conversation.idle_conversation_starter.stop()
if hasattr(conversation, 'observation_info') and conversation.observation_info: if hasattr(conversation, 'observation_info') and conversation.observation_info:
conversation.observation_info.unbind_from_chat_observer() conversation.observation_info.unbind_from_chat_observer()
# ChatObserver 是单例,不在此处停止 # ChatObserver 是单例,不在此处停止
logger.info(f"[私聊][{private_name}] 会话实例 {stream_id} 资源已清理") logger.info(f"[私聊][{private_name}] 会话实例 {stream_id} 资源已清理")
except Exception as e: except Exception as e:
@ -157,12 +162,12 @@ class PFCManager:
"""获取已存在的会话实例 (只读)""" """获取已存在的会话实例 (只读)"""
instance = self._instances.get(stream_id) instance = self._instances.get(stream_id)
if instance and instance._initialized and instance.should_continue: if instance and instance._initialized and instance.should_continue:
# 检查忽略状态 # 检查忽略状态
if (hasattr(instance, "ignore_until_timestamp") and if (hasattr(instance, "ignore_until_timestamp") and
instance.ignore_until_timestamp and instance.ignore_until_timestamp and
time.time() < instance.ignore_until_timestamp): time.time() < instance.ignore_until_timestamp):
return None # 忽略期间不返回 return None # 忽略期间不返回
return instance return instance
return None # 不存在或无效则返回 None return None # 不存在或无效则返回 None
async def remove_conversation(self, stream_id: str): async def remove_conversation(self, stream_id: str):
@ -173,7 +178,8 @@ class PFCManager:
try: try:
# 先从字典中移除引用,防止新的请求获取到正在清理的实例 # 先从字典中移除引用,防止新的请求获取到正在清理的实例
del self._instances[stream_id] del self._instances[stream_id]
if stream_id in self._initializing: del self._initializing[stream_id] if stream_id in self._initializing:
del self._initializing[stream_id]
# 清理资源 # 清理资源
await self._cleanup_conversation(instance_to_remove) await self._cleanup_conversation(instance_to_remove)
logger.info(f"[管理器] 会话实例 {stream_id} 已成功移除并清理") logger.info(f"[管理器] 会话实例 {stream_id} 已成功移除并清理")