diff --git a/src/chat/chat_loop/heartFC_chat.py b/src/chat/chat_loop/heartFC_chat.py index dbfe541e9..6ca4dc916 100644 --- a/src/chat/chat_loop/heartFC_chat.py +++ b/src/chat/chat_loop/heartFC_chat.py @@ -242,10 +242,16 @@ class HeartFChatting: # 处理唤醒度逻辑 if is_sleeping: self._handle_wakeup_messages(recent_messages) - # 如果处于失眠状态,则无视睡眠时间,继续处理消息 - # 否则,如果仍然在睡眠(没被吵醒),则跳过本轮处理 - if not self.context.is_in_insomnia and schedule_manager.is_sleeping(self.wakeup_manager): + # 再次检查睡眠状态,因为_handle_wakeup_messages可能会触发唤醒 + current_is_sleeping = schedule_manager.is_sleeping(self.wakeup_manager) + + if not self.context.is_in_insomnia and current_is_sleeping: + # 仍然在睡眠,跳过本轮的消息处理 return has_new_messages + else: + # 从睡眠中被唤醒,需要继续处理本轮消息 + logger.info(f"{self.context.log_prefix} 从睡眠中被唤醒,将处理积压的消息。") + self.context.last_wakeup_time = time.time() # 根据聊天模式处理新消息 if self.context.loop_mode == ChatMode.FOCUS: @@ -266,6 +272,15 @@ class HeartFChatting: # 更新上一帧的睡眠状态 self.context.was_sleeping = is_sleeping + # --- 重新入睡逻辑 --- + # 如果被吵醒了,并且在一定时间内没有新消息,则尝试重新入睡 + if schedule_manager._is_woken_up and not has_new_messages: + re_sleep_delay = global_config.wakeup_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} 分钟无新消息,尝试重新入睡。") + schedule_manager.reset_wakeup_state() + # 保存HFC上下文状态 self.context.save_context_state() diff --git a/src/chat/chat_loop/hfc_context.py b/src/chat/chat_loop/hfc_context.py index 8383b2ea1..767ee60bc 100644 --- a/src/chat/chat_loop/hfc_context.py +++ b/src/chat/chat_loop/hfc_context.py @@ -49,6 +49,7 @@ class HfcContext: # 失眠状态 self.is_in_insomnia: bool = False self.insomnia_end_time: float = 0.0 + self.last_wakeup_time: float = 0.0 # 被吵醒的时间 self.last_message_time = time.time() self.last_read_time = time.time() - 10 @@ -92,6 +93,7 @@ class HfcContext: "sleep_pressure": self.sleep_pressure, "is_in_insomnia": self.is_in_insomnia, "insomnia_end_time": self.insomnia_end_time, + "last_wakeup_time": self.last_wakeup_time, } local_storage[self._get_storage_key()] = state logger = get_logger("hfc_context") diff --git a/src/chat/chat_loop/wakeup_manager.py b/src/chat/chat_loop/wakeup_manager.py index 9c7c50ade..37fd755aa 100644 --- a/src/chat/chat_loop/wakeup_manager.py +++ b/src/chat/chat_loop/wakeup_manager.py @@ -188,6 +188,10 @@ class WakeUpManager: from src.mood.mood_manager import mood_manager mood_manager.set_angry_from_wakeup(self.context.stream_id) + # 通知日程管理器重置睡眠状态 + from src.schedule.schedule_manager import schedule_manager + schedule_manager.reset_sleep_state_after_wakeup() + logger.info(f"{self.context.log_prefix} 唤醒度达到阈值({self.wakeup_threshold}),被吵醒进入愤怒状态!") def get_angry_prompt_addition(self) -> str: diff --git a/src/schedule/schedule_manager.py b/src/schedule/schedule_manager.py index ec5b3c63e..82578046d 100644 --- a/src/schedule/schedule_manager.py +++ b/src/schedule/schedule_manager.py @@ -138,6 +138,7 @@ class ScheduleManager: self._last_sleep_check_date: Optional[datetime.date] = None self._last_fully_slept_log_time: float = 0 self._is_in_voluntary_delay: bool = False # 新增:标记是否处于主动延迟睡眠状态 + self._is_woken_up: bool = False # 新增:标记是否被吵醒 self._load_sleep_state() @@ -453,14 +454,15 @@ class ScheduleManager: self._is_preparing_sleep = False self._sleep_buffer_end_time = None self._is_in_voluntary_delay = False + self._is_woken_up = False # 离开睡眠时间,重置唤醒状态 self._save_sleep_state() return False # --- 处理唤醒状态 --- - if wakeup_manager and wakeup_manager.is_in_angry_state(): + if self._is_woken_up: current_timestamp = now.timestamp() if current_timestamp - self.last_sleep_log_time > self.sleep_log_interval: - logger.info(f"在休眠活动 '{activity}' 期间,但已被唤醒。") + logger.info(f"在休眠活动 '{activity}' 期间,但已被唤醒,保持清醒状态。") self.last_sleep_log_time = current_timestamp return False @@ -502,6 +504,16 @@ class ScheduleManager: self.last_sleep_log_time = current_timestamp return True + def reset_sleep_state_after_wakeup(self): + """被唤醒后重置睡眠状态""" + if self._is_preparing_sleep or self.is_sleeping(): + logger.info("被唤醒,重置所有睡眠准备状态,恢复清醒!") + self._is_preparing_sleep = False + self._sleep_buffer_end_time = None + self._is_in_voluntary_delay = False + self._is_woken_up = True # 标记为已被唤醒 + self._save_sleep_state() + def _is_in_theoretical_sleep_time(self, now_time: time) -> (bool, Optional[str]): """检查当前时间是否落在日程表的任何一个睡眠活动中""" sleep_keywords = ["休眠", "睡觉", "梦乡"] @@ -600,6 +612,7 @@ class ScheduleManager: "total_delayed_minutes_today": self._total_delayed_minutes_today, "last_sleep_check_date_str": self._last_sleep_check_date.isoformat() if self._last_sleep_check_date else None, "is_in_voluntary_delay": self._is_in_voluntary_delay, + "is_woken_up": self._is_woken_up, } local_storage["schedule_sleep_state"] = state logger.debug(f"已保存睡眠状态: {state}") @@ -619,6 +632,7 @@ class ScheduleManager: self._total_delayed_minutes_today = state.get("total_delayed_minutes_today", 0) self._is_in_voluntary_delay = state.get("is_in_voluntary_delay", False) + self._is_woken_up = state.get("is_woken_up", False) date_str = state.get("last_sleep_check_date_str") if date_str: @@ -628,6 +642,15 @@ class ScheduleManager: except Exception as e: logger.warning(f"加载睡眠状态失败,将使用默认值: {e}") + def reset_wakeup_state(self): + """重置被唤醒的状态,允许重新尝试入睡""" + if self._is_woken_up: + logger.info("重置唤醒状态,将重新尝试入睡。") + self._is_woken_up = False + self._is_preparing_sleep = False # 允许重新进入弹性睡眠判断 + self._sleep_buffer_end_time = None + self._save_sleep_state() + def _validate_schedule_with_pydantic(self, schedule_data) -> bool: """使用Pydantic验证日程数据格式和完整性""" try: