refactor(schedule): 重构睡眠系统为状态机模型
将原有的睡眠、失眠、唤醒等分散的布尔标记逻辑重构为一个统一的睡眠状态机(SleepState),以提高代码的可读性、可维护性和可扩展性。 主要变更: - 引入 `SleepState` 枚举,包含 `AWAKE`, `INSOMNIA`, `PREPARING_SLEEP`, `SLEEPING`, `WOKEN_UP` 状态。 - 在 `ScheduleManager` 中实现 `_update_sleep_state` 作为核心状态机,统一管理所有状态转换。 - 将原有的失眠判断逻辑从 `WakeUpManager` 移至 `ScheduleManager` 的状态机内部,与弹性睡眠决策合并,简化了模块职责。 - `heartFC_chat.py` 中的聊天循环现在直接查询 `ScheduleManager` 的当前状态,而不是处理多个独立的布尔值,使逻辑更清晰。 - 删除了 `WakeUpManager` 中与失眠相关的配置和方法,因为它现在由 `ScheduleManager` 统一管理。 - 删除了配置中已废弃的 `enable_is_sleep` 选项。
This commit is contained in:
@@ -8,7 +8,7 @@ from src.config.config import global_config
|
||||
from src.person_info.relationship_builder_manager import relationship_builder_manager
|
||||
from src.chat.express.expression_learner import expression_learner_manager
|
||||
from src.plugin_system.base.component_types import ChatMode
|
||||
from src.schedule.schedule_manager import schedule_manager
|
||||
from src.schedule.schedule_manager import schedule_manager, SleepState
|
||||
from src.plugin_system.apis import message_api
|
||||
|
||||
from .hfc_context import HfcContext
|
||||
@@ -196,30 +196,14 @@ class HeartFChatting:
|
||||
- FOCUS模式:直接处理所有消息并检查退出条件
|
||||
- NORMAL模式:检查进入FOCUS模式的条件,并通过normal_mode_handler处理消息
|
||||
"""
|
||||
is_sleeping = schedule_manager.is_sleeping(self.wakeup_manager)
|
||||
|
||||
# --- 失眠状态管理 ---
|
||||
if self.context.is_in_insomnia and time.time() > self.context.insomnia_end_time:
|
||||
# 失眠状态结束
|
||||
self.context.is_in_insomnia = False
|
||||
await self.proactive_thinker.trigger_goodnight_thinking()
|
||||
|
||||
if is_sleeping and not self.context.was_sleeping:
|
||||
# 刚刚进入睡眠状态,进行一次入睡检查
|
||||
if self.wakeup_manager and self.wakeup_manager.check_for_insomnia():
|
||||
# 触发失眠
|
||||
self.context.is_in_insomnia = True
|
||||
duration = global_config.sleep_system.insomnia_duration_minutes * 60
|
||||
self.context.insomnia_end_time = time.time() + duration
|
||||
|
||||
# 判断失眠原因并触发思考
|
||||
reason = "random"
|
||||
if self.context.sleep_pressure < global_config.sleep_system.sleep_pressure_threshold:
|
||||
reason = "low_pressure"
|
||||
await self.proactive_thinker.trigger_insomnia_thinking(reason)
|
||||
# --- 核心状态更新 ---
|
||||
await schedule_manager._update_sleep_state(self.wakeup_manager)
|
||||
current_sleep_state = schedule_manager.get_current_sleep_state()
|
||||
is_sleeping = current_sleep_state == SleepState.SLEEPING
|
||||
is_in_insomnia = current_sleep_state == SleepState.INSOMNIA
|
||||
|
||||
# 核心修复:在睡眠模式(包括失眠)下获取消息时,不过滤命令消息,以确保@消息能被接收
|
||||
filter_command_flag = not is_sleeping
|
||||
filter_command_flag = not (is_sleeping or is_in_insomnia)
|
||||
|
||||
recent_messages = message_api.get_messages_by_time_in_chat(
|
||||
chat_id=self.context.stream_id,
|
||||
@@ -239,16 +223,17 @@ class HeartFChatting:
|
||||
self.context.last_read_time = time.time()
|
||||
|
||||
# 处理唤醒度逻辑
|
||||
if is_sleeping:
|
||||
if current_sleep_state in [SleepState.SLEEPING, SleepState.PREPARING_SLEEP, SleepState.INSOMNIA]:
|
||||
self._handle_wakeup_messages(recent_messages)
|
||||
# 再次检查睡眠状态,因为_handle_wakeup_messages可能会触发唤醒
|
||||
current_is_sleeping = schedule_manager.is_sleeping(self.wakeup_manager)
|
||||
|
||||
if not self.context.is_in_insomnia and current_is_sleeping:
|
||||
# 仍然在睡眠,跳过本轮的消息处理
|
||||
# 再次获取最新状态,因为 handle_wakeup 可能导致状态变为 WOKEN_UP
|
||||
current_sleep_state = schedule_manager.get_current_sleep_state()
|
||||
|
||||
if current_sleep_state == SleepState.SLEEPING:
|
||||
# 只有在纯粹的 SLEEPING 状态下才跳过消息处理
|
||||
return has_new_messages
|
||||
else:
|
||||
# 从睡眠中被唤醒,需要继续处理本轮消息
|
||||
|
||||
if current_sleep_state == SleepState.WOKEN_UP:
|
||||
logger.info(f"{self.context.log_prefix} 从睡眠中被唤醒,将处理积压的消息。")
|
||||
self.context.last_wakeup_time = time.time()
|
||||
|
||||
|
||||
@@ -41,13 +41,6 @@ class WakeUpManager:
|
||||
self.enabled = sleep_config.enable
|
||||
self.angry_prompt = sleep_config.angry_prompt
|
||||
|
||||
# 失眠系统参数
|
||||
self.insomnia_enabled = sleep_config.enable_insomnia_system
|
||||
self.sleep_pressure_threshold = sleep_config.sleep_pressure_threshold
|
||||
self.deep_sleep_threshold = sleep_config.deep_sleep_threshold
|
||||
self.insomnia_chance_low_pressure = sleep_config.insomnia_chance_low_pressure
|
||||
self.insomnia_chance_normal_pressure = sleep_config.insomnia_chance_normal_pressure
|
||||
|
||||
self._load_wakeup_state()
|
||||
|
||||
def _get_storage_key(self) -> str:
|
||||
@@ -220,39 +213,4 @@ class WakeUpManager:
|
||||
"wakeup_threshold": self.wakeup_threshold,
|
||||
"is_angry": self.is_angry,
|
||||
"angry_remaining_time": max(0, self.angry_duration - (time.time() - self.angry_start_time)) if self.is_angry else 0
|
||||
}
|
||||
|
||||
def check_for_insomnia(self) -> bool:
|
||||
"""
|
||||
在尝试入睡时检查是否会失眠
|
||||
|
||||
Returns:
|
||||
bool: 如果失眠则返回 True,否则返回 False
|
||||
"""
|
||||
if not self.insomnia_enabled:
|
||||
return False
|
||||
|
||||
import random
|
||||
|
||||
pressure = self.context.sleep_pressure
|
||||
|
||||
# 压力过高,深度睡眠,极难失眠
|
||||
if pressure > self.deep_sleep_threshold:
|
||||
return False
|
||||
|
||||
# 根据睡眠压力决定失眠概率
|
||||
from src.schedule.schedule_manager import schedule_manager
|
||||
if pressure < self.sleep_pressure_threshold:
|
||||
# 压力不足型失眠
|
||||
if schedule_manager._is_in_voluntary_delay:
|
||||
logger.debug(f"{self.context.log_prefix} 处于主动延迟睡眠期间,跳过压力不足型失眠判断。")
|
||||
elif random.random() < self.insomnia_chance_low_pressure:
|
||||
logger.info(f"{self.context.log_prefix} 睡眠压力不足 ({pressure:.1f}),触发失眠!")
|
||||
return True
|
||||
else:
|
||||
# 压力正常,随机失眠
|
||||
if random.random() < self.insomnia_chance_normal_pressure:
|
||||
logger.info(f"{self.context.log_prefix} 睡眠压力正常 ({pressure:.1f}),触发随机失眠!")
|
||||
return True
|
||||
|
||||
return False
|
||||
}
|
||||
Reference in New Issue
Block a user