Files
Cyrene_v2/internal/services/backthink/trigger.go
T
AskaEth 3dc1232bc2
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
docs(comments): 注释中文化 · internal/runtime/model + internal/services/backthink(54 文件,纯替换)
- 只翻注释/文档字符串:`go/scanner` 剥注释后按 token 序列+literal 逐 token 比对,**54/54 文件 SAME**;
  改动文件总行数与 HEAD 漂移 = 0(严格 1:1,无合并/拆行)
- 裁决编号与 design 节号逐字保留(03.4.1/03.4.2/03.4.3/14.4.1/14.4.5/07.4.2-4、design/04 §3.1/§3.2 等);
  `chat_template_kwargs` / `enable_thinking` / `reasoning_effort` / `thinking:{type}` 字段名与形状说明未动
- 存疑译法(已登记):`persona` 在叙事语境用「角色」、标识符语境保留 `persona`(仓库既有模块本身混用);
  `rung`→「级」;`provider` 存在「提供商/提供者」两种落笔(可按需一键统一)
- 复核:build/vet 绿 + 两包测试绿;gofmt 干净;残留英文注释 0 条
- 既有存量(未修,只报告):`model/anthropic_test.go` 612 行 >500;`applyAnthropicEvent` 115 行 >80
2026-10-04 16:27:54 +08:00

118 lines
4.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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}
}
}