package backthink import ( "fmt" "git.yeij.top/AskaEth/Cyrene_v2/internal/bus" "git.yeij.top/AskaEth/Cyrene_v2/internal/iot" ) // TriggerKind 归类唤醒一轮思考的原因,好让推送路径套用 // 正确的策略:心跳受门控管辖(60min≤1 / 冷却 / 按风格), // 事件是主人确实想听到的真实信号、绕过频率门。 type TriggerKind int const ( // TriggerHeartbeat 是周期性自主反思。它的主动推送受 // PushGate 限流,使主人绝不会被空洞的反思刷屏。 TriggerHeartbeat TriggerKind = iota // TriggerEvent 是真实事件(IoT 设备变化、提醒、与主人相关的 // 系统事件)。它的推送绕过 PushGate——"该发就发"——只受 // 同一事件去重约束。 TriggerEvent ) // String 返回用于日志与记录的稳定标签。 func (k TriggerKind) String() string { switch k { case TriggerEvent: return "event" case TriggerHeartbeat: return "heartbeat" default: return fmt.Sprintf("triggerkind(%d)", int(k)) } } // 本服务为事件驱动思考订阅的总线主题。它们是 // design/12 §1 定义的契约:一次 IoT 状态变化、一次提醒触发, // 或一次泛化的系统事件。 const ( // SubjectReminderTrigger 是提醒触发所用的总线主题。 SubjectReminderTrigger = "reminder.trigger" // SubjectSystemEvent 是泛化系统事件的总线主题。 SubjectSystemEvent = "system.event" ) // SystemEvent 是调用方可发布到 SubjectSystemEvent 以传达 // 系统通知的可选类型化负载。Import 默认为 Normal。在 // design/12 §6 策略一之下,低价值的系统通知(加入/退出 ping、泛化的 // 平台噪声)被降级为仅登记一条记录,不唤醒 // 一整轮思考;只有高重要度(与主人相关)的系统事件才思考, // 因此繁忙的公开平台无法触发昂贵反思的洪流。 type SystemEvent struct { Summary string Import Importance } // Trigger 描述唤醒一轮思考的原因:来源子系统、 // 可读摘要与事件的估计重要度。 type Trigger struct { Source string Summary string Import Importance // Kind 记录本轮是周期性心跳还是真实事件,好让 // 推送路径能为真实事件绕过频率门(主人要求)。 Kind TriggerKind } // heartbeatTrigger 是周期性、低重要度的触发。低重要度意味着 // 该轮很少打扰用户,遵守 "默认不发送 chat 类型消息"。 func heartbeatTrigger() Trigger { return Trigger{Source: "heartbeat", Summary: "periodic autonomous reflection", Import: ImportanceLow, Kind: TriggerHeartbeat} } // StartupSummary 是启动轮思考(裁决 07.4.4,design/12 §1)的触发摘要。它同时是 // context.go 里切换「拟人化启动消息」专属引导提示词的标识。 const StartupSummary = "process startup" // startupTrigger 是进程启动后的第一轮思考(裁决 07.4.4):不等满一个心跳周期, // 启动立即触发,并引导她以角色口吻产出一条拟人化启动问候(如「我回来啦」)。 // Kind 仍为 TriggerHeartbeat:启动轮的推送与心跳走完全相同的门与限频 // (PushGate / 打扰级联 / 活动门),进程反复重启也不会刷屏主人。 func startupTrigger() Trigger { return Trigger{Source: "startup", Summary: StartupSummary, Import: ImportanceLow, Kind: TriggerHeartbeat} } // triggerForEvent 把总线事件映射为 Trigger。IoT 设备变化按 // 普通重要度处理,提醒触发按高重要度,泛化的 // 系统事件按普通重要度。每个事件都打上 TriggerEvent,因此其 // 主动推送绕过心跳的 PushGate。 func triggerForEvent(e bus.Event) Trigger { switch e.Subject { case iot.DeviceUpdateSubject: if d, ok := e.Payload.(iot.DeviceUpdate); ok { return Trigger{ Source: e.Subject, Summary: fmt.Sprintf("device %s (%s) %s", d.Device.ID, d.Device.Type, d.Action), Import: ImportanceNormal, Kind: TriggerEvent, } } return Trigger{Source: e.Subject, Summary: e.Subject, Import: ImportanceNormal, Kind: TriggerEvent} case SubjectReminderTrigger: return Trigger{Source: e.Subject, Summary: e.Subject, Import: ImportanceHigh, Kind: TriggerEvent} case SubjectSystemEvent: tr := Trigger{Source: e.Subject, Summary: e.Subject, Import: ImportanceNormal, Kind: TriggerEvent} if sy, ok := e.Payload.(SystemEvent); ok { if sy.Summary != "" { tr.Summary = sy.Summary } tr.Import = sy.Import } return tr default: return Trigger{Source: e.Subject, Summary: e.Subject, Import: ImportanceNormal, Kind: TriggerEvent} } }