1
This commit is contained in:
@@ -39,6 +39,7 @@ class HeartFChatting:
|
|||||||
"""
|
"""
|
||||||
self.context = HfcContext(chat_id)
|
self.context = HfcContext(chat_id)
|
||||||
self.context.new_message_queue = asyncio.Queue()
|
self.context.new_message_queue = asyncio.Queue()
|
||||||
|
self._processing_lock = asyncio.Lock()
|
||||||
|
|
||||||
self.cycle_tracker = CycleTracker(self.context)
|
self.cycle_tracker = CycleTracker(self.context)
|
||||||
self.response_handler = ResponseHandler(self.context)
|
self.response_handler = ResponseHandler(self.context)
|
||||||
@@ -357,130 +358,130 @@ class HeartFChatting:
|
|||||||
- FOCUS模式:直接处理所有消息并检查退出条件
|
- FOCUS模式:直接处理所有消息并检查退出条件
|
||||||
- NORMAL模式:检查进入FOCUS模式的条件,并通过normal_mode_handler处理消息
|
- NORMAL模式:检查进入FOCUS模式的条件,并通过normal_mode_handler处理消息
|
||||||
"""
|
"""
|
||||||
# --- 核心状态更新 ---
|
async with self._processing_lock:
|
||||||
await self.sleep_manager.update_sleep_state(self.wakeup_manager)
|
# --- 核心状态更新 ---
|
||||||
current_sleep_state = self.sleep_manager.get_current_sleep_state()
|
await self.sleep_manager.update_sleep_state(self.wakeup_manager)
|
||||||
is_sleeping = current_sleep_state == SleepState.SLEEPING
|
current_sleep_state = self.sleep_manager.get_current_sleep_state()
|
||||||
is_in_insomnia = current_sleep_state == SleepState.INSOMNIA
|
is_sleeping = current_sleep_state == SleepState.SLEEPING
|
||||||
|
is_in_insomnia = current_sleep_state == SleepState.INSOMNIA
|
||||||
|
|
||||||
# 核心修复:在睡眠模式(包括失眠)下获取消息时,不过滤命令消息,以确保@消息能被接收
|
# 核心修复:在睡眠模式(包括失眠)下获取消息时,不过滤命令消息,以确保@消息能被接收
|
||||||
filter_command_flag = not (is_sleeping or is_in_insomnia)
|
filter_command_flag = not (is_sleeping or is_in_insomnia)
|
||||||
|
|
||||||
# 从队列中获取所有待处理的新消息
|
# 从队列中获取所有待处理的新消息
|
||||||
recent_messages = []
|
recent_messages = []
|
||||||
while not self.context.new_message_queue.empty():
|
while not self.context.new_message_queue.empty():
|
||||||
recent_messages.append(await self.context.new_message_queue.get())
|
recent_messages.append(await self.context.new_message_queue.get())
|
||||||
|
|
||||||
has_new_messages = bool(recent_messages)
|
has_new_messages = bool(recent_messages)
|
||||||
new_message_count = len(recent_messages)
|
new_message_count = len(recent_messages)
|
||||||
|
|
||||||
# 只有在有新消息时才进行思考循环处理
|
# 只有在有新消息时才进行思考循环处理
|
||||||
if has_new_messages:
|
if has_new_messages:
|
||||||
self.context.last_message_time = time.time()
|
self.context.last_message_time = time.time()
|
||||||
self.context.last_read_time = time.time()
|
self.context.last_read_time = time.time()
|
||||||
|
|
||||||
# --- 专注模式安静群组检查 ---
|
# --- 专注模式安静群组检查 ---
|
||||||
quiet_groups = global_config.chat.focus_mode_quiet_groups
|
quiet_groups = global_config.chat.focus_mode_quiet_groups
|
||||||
if quiet_groups and self.context.chat_stream:
|
if quiet_groups and self.context.chat_stream:
|
||||||
is_group_chat = self.context.chat_stream.group_info is not None
|
is_group_chat = self.context.chat_stream.group_info is not None
|
||||||
if is_group_chat:
|
if is_group_chat:
|
||||||
try:
|
try:
|
||||||
platform = self.context.chat_stream.platform
|
platform = self.context.chat_stream.platform
|
||||||
group_id = self.context.chat_stream.group_info.group_id
|
group_id = self.context.chat_stream.group_info.group_id
|
||||||
|
|
||||||
# 兼容不同QQ适配器的平台名称
|
|
||||||
is_qq_platform = platform in ["qq", "napcat"]
|
|
||||||
|
|
||||||
current_chat_identifier = f"{platform}:{group_id}"
|
|
||||||
config_identifier_for_qq = f"qq:{group_id}"
|
|
||||||
|
|
||||||
is_in_quiet_list = (current_chat_identifier in quiet_groups or
|
|
||||||
(is_qq_platform and config_identifier_for_qq in quiet_groups))
|
|
||||||
|
|
||||||
if is_in_quiet_list:
|
|
||||||
is_mentioned_in_batch = False
|
|
||||||
for msg in recent_messages:
|
|
||||||
if msg.get("is_mentioned"):
|
|
||||||
is_mentioned_in_batch = True
|
|
||||||
break
|
|
||||||
|
|
||||||
if not is_mentioned_in_batch:
|
# 兼容不同QQ适配器的平台名称
|
||||||
logger.info(f"{self.context.log_prefix} 在专注安静模式下,因未被提及而忽略了消息。")
|
is_qq_platform = platform in ["qq", "napcat"]
|
||||||
return True # 消耗消息但不做回复
|
|
||||||
|
current_chat_identifier = f"{platform}:{group_id}"
|
||||||
|
config_identifier_for_qq = f"qq:{group_id}"
|
||||||
|
|
||||||
|
is_in_quiet_list = (current_chat_identifier in quiet_groups or
|
||||||
|
(is_qq_platform and config_identifier_for_qq in quiet_groups))
|
||||||
|
|
||||||
|
if is_in_quiet_list:
|
||||||
|
is_mentioned_in_batch = False
|
||||||
|
for msg in recent_messages:
|
||||||
|
if msg.get("is_mentioned"):
|
||||||
|
is_mentioned_in_batch = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not is_mentioned_in_batch:
|
||||||
|
logger.info(f"{self.context.log_prefix} 在专注安静模式下,因未被提及而忽略了消息。")
|
||||||
|
return True # 消耗消息但不做回复
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"{self.context.log_prefix} 检查专注安静群组时出错: {e}")
|
||||||
|
|
||||||
|
# 处理唤醒度逻辑
|
||||||
|
if current_sleep_state in [SleepState.SLEEPING, SleepState.PREPARING_SLEEP, SleepState.INSOMNIA]:
|
||||||
|
self._handle_wakeup_messages(recent_messages)
|
||||||
|
|
||||||
|
# 再次获取最新状态,因为 handle_wakeup 可能导致状态变为 WOKEN_UP
|
||||||
|
current_sleep_state = self.sleep_manager.get_current_sleep_state()
|
||||||
|
|
||||||
|
if current_sleep_state == SleepState.SLEEPING:
|
||||||
|
# 只有在纯粹的 SLEEPING 状态下才跳过消息处理
|
||||||
|
return True
|
||||||
|
|
||||||
|
if current_sleep_state == SleepState.WOKEN_UP:
|
||||||
|
logger.info(f"{self.context.log_prefix} 从睡眠中被唤醒,将处理积压的消息。")
|
||||||
|
|
||||||
|
# 根据聊天模式处理新消息
|
||||||
|
should_process, interest_value = await self._should_process_messages(recent_messages)
|
||||||
|
if not should_process:
|
||||||
|
# 消息数量不足或兴趣不够,等待
|
||||||
|
await asyncio.sleep(0.5)
|
||||||
|
return True # Skip rest of the logic for this iteration
|
||||||
|
|
||||||
|
# Messages should be processed
|
||||||
|
action_type = await self.cycle_processor.observe(interest_value=interest_value)
|
||||||
|
|
||||||
|
# 尝试触发表达学习
|
||||||
|
if self.context.expression_learner:
|
||||||
|
try:
|
||||||
|
await self.context.expression_learner.trigger_learning_for_chat()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"{self.context.log_prefix} 检查专注安静群组时出错: {e}")
|
logger.error(f"{self.context.log_prefix} 表达学习触发失败: {e}")
|
||||||
|
|
||||||
# 处理唤醒度逻辑
|
# 管理no_reply计数器
|
||||||
if current_sleep_state in [SleepState.SLEEPING, SleepState.PREPARING_SLEEP, SleepState.INSOMNIA]:
|
if action_type != "no_reply":
|
||||||
self._handle_wakeup_messages(recent_messages)
|
self.recent_interest_records.clear()
|
||||||
|
self.context.no_reply_consecutive = 0
|
||||||
|
logger.debug(f"{self.context.log_prefix} 执行了{action_type}动作,重置no_reply计数器")
|
||||||
|
else: # action_type == "no_reply"
|
||||||
|
self.context.no_reply_consecutive += 1
|
||||||
|
self._determine_form_type()
|
||||||
|
|
||||||
# 再次获取最新状态,因为 handle_wakeup 可能导致状态变为 WOKEN_UP
|
# 在一轮动作执行完毕后,增加睡眠压力
|
||||||
current_sleep_state = self.sleep_manager.get_current_sleep_state()
|
if self.context.energy_manager and global_config.sleep_system.enable_insomnia_system:
|
||||||
|
if action_type not in ["no_reply", "no_action"]:
|
||||||
|
self.context.energy_manager.increase_sleep_pressure()
|
||||||
|
|
||||||
if current_sleep_state == SleepState.SLEEPING:
|
# 如果成功观察,增加能量值并重置累积兴趣值
|
||||||
# 只有在纯粹的 SLEEPING 状态下才跳过消息处理
|
self.context.energy_value += 1 / global_config.chat.focus_value
|
||||||
return True
|
# 重置累积兴趣值,因为消息已经被成功处理
|
||||||
|
self.context.breaking_accumulated_interest = 0.0
|
||||||
if current_sleep_state == SleepState.WOKEN_UP:
|
|
||||||
logger.info(f"{self.context.log_prefix} 从睡眠中被唤醒,将处理积压的消息。")
|
|
||||||
|
|
||||||
# 根据聊天模式处理新消息
|
|
||||||
should_process, interest_value = await self._should_process_messages(recent_messages)
|
|
||||||
if not should_process:
|
|
||||||
# 消息数量不足或兴趣不够,等待
|
|
||||||
await asyncio.sleep(0.5)
|
|
||||||
return True # Skip rest of the logic for this iteration
|
|
||||||
|
|
||||||
# Messages should be processed
|
|
||||||
action_type = await self.cycle_processor.observe(interest_value=interest_value)
|
|
||||||
|
|
||||||
# 尝试触发表达学习
|
|
||||||
if self.context.expression_learner:
|
|
||||||
try:
|
|
||||||
await self.context.expression_learner.trigger_learning_for_chat()
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"{self.context.log_prefix} 表达学习触发失败: {e}")
|
|
||||||
|
|
||||||
# 管理no_reply计数器
|
|
||||||
if action_type != "no_reply":
|
|
||||||
self.recent_interest_records.clear()
|
|
||||||
self.context.no_reply_consecutive = 0
|
|
||||||
logger.debug(f"{self.context.log_prefix} 执行了{action_type}动作,重置no_reply计数器")
|
|
||||||
else: # action_type == "no_reply"
|
|
||||||
self.context.no_reply_consecutive += 1
|
|
||||||
self._determine_form_type()
|
|
||||||
|
|
||||||
# 在一轮动作执行完毕后,增加睡眠压力
|
|
||||||
if self.context.energy_manager and global_config.sleep_system.enable_insomnia_system:
|
|
||||||
if action_type not in ["no_reply", "no_action"]:
|
|
||||||
self.context.energy_manager.increase_sleep_pressure()
|
|
||||||
|
|
||||||
# 如果成功观察,增加能量值并重置累积兴趣值
|
|
||||||
self.context.energy_value += 1 / global_config.chat.focus_value
|
|
||||||
# 重置累积兴趣值,因为消息已经被成功处理
|
|
||||||
self.context.breaking_accumulated_interest = 0.0
|
|
||||||
logger.info(
|
|
||||||
f"{self.context.log_prefix} 能量值增加,当前能量值:{self.context.energy_value:.1f},重置累积兴趣值"
|
|
||||||
)
|
|
||||||
|
|
||||||
# 更新上一帧的睡眠状态
|
|
||||||
self.context.was_sleeping = is_sleeping
|
|
||||||
|
|
||||||
# --- 重新入睡逻辑 ---
|
|
||||||
# 如果被吵醒了,并且在一定时间内没有新消息,则尝试重新入睡
|
|
||||||
if self.sleep_manager.get_current_sleep_state() == SleepState.WOKEN_UP and not has_new_messages:
|
|
||||||
re_sleep_delay = global_config.sleep_system.re_sleep_delay_minutes * 60
|
|
||||||
# 使用 last_message_time 来判断空闲时间
|
|
||||||
if time.time() - self.context.last_message_time > re_sleep_delay:
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"{self.context.log_prefix} 已被唤醒且超过 {re_sleep_delay / 60} 分钟无新消息,尝试重新入睡。"
|
f"{self.context.log_prefix} 能量值增加,当前能量值:{self.context.energy_value:.1f},重置累积兴趣值"
|
||||||
)
|
)
|
||||||
self.sleep_manager.reset_sleep_state_after_wakeup()
|
|
||||||
|
|
||||||
# 保存HFC上下文状态
|
# 更新上一帧的睡眠状态
|
||||||
self.context.save_context_state()
|
self.context.was_sleeping = is_sleeping
|
||||||
|
|
||||||
return has_new_messages
|
# --- 重新入睡逻辑 ---
|
||||||
|
# 如果被吵醒了,并且在一定时间内没有新消息,则尝试重新入睡
|
||||||
|
if self.sleep_manager.get_current_sleep_state() == SleepState.WOKEN_UP and not has_new_messages:
|
||||||
|
re_sleep_delay = global_config.sleep_system.re_sleep_delay_minutes * 60
|
||||||
|
# 使用 last_message_time 来判断空闲时间
|
||||||
|
if time.time() - self.context.last_message_time > re_sleep_delay:
|
||||||
|
logger.info(
|
||||||
|
f"{self.context.log_prefix} 已被唤醒且超过 {re_sleep_delay / 60} 分钟无新消息,尝试重新入睡。"
|
||||||
|
)
|
||||||
|
self.sleep_manager.reset_sleep_state_after_wakeup()
|
||||||
|
|
||||||
|
# 保存HFC上下文状态
|
||||||
|
self.context.save_context_state()
|
||||||
|
return has_new_messages
|
||||||
|
|
||||||
def _handle_wakeup_messages(self, messages):
|
def _handle_wakeup_messages(self, messages):
|
||||||
"""
|
"""
|
||||||
|
|||||||
Reference in New Issue
Block a user