docs(cyrene): cmd/cyrene 存量英文注释中文化(22 个非测试文件,仅注释)
- 四组并行完成:main/wire*.go、wire_capacity|channels|runtime、channels|persona_*|emotion|observability、 voice|plugins|stream|skills|vision|subagent_tool|extractor|mcp|sessionread_tool|terminal_tool。 - 机械校验(git diff -U0 去 // 行与空行)仅剩 wire_frontend.go:84 一处行尾注释:代码前缀 「\ta.gw = gw 」经 cat -A 与 HEAD 逐字节比对一致(allow 清单已声明)。 - 验收:隔离 worktree(HEAD + 本批 patch)go build/vet 绿、全树 58 包 ok、 linux/amd64 + darwin/arm64 交叉编译绿;gofmt -l 干净。 - 备注:整树两次红均为负载敏感 flake(backthink / orchestration 的 timeout 类用例单独 -count=20 全过)。
This commit is contained in:
1 parent
5c2189efb0
commit
52f08dc343
22 files changed
+455
-586
No files matched your search
+33
-42
@@ -9,52 +9,45 @@ import (
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/loop"
|
||||
)
|
||||
|
||||
// This file wires the persona emotion state machine (design/01 §2: 情绪状态机 +
|
||||
// 好感度曲线 follow the persona/character, never a behavior mode) into the agent
|
||||
// loop's turn boundary. The loop stays emotion-agnostic: it reports each settled
|
||||
// turn and carries the returned mood label onto Result.Mood, which the
|
||||
// persistence layer writes onto the assistant message (design/16 §3.3).
|
||||
// 本文件把 persona 情绪状态机(design/01 §2:情绪状态机 + 好感度曲线跟随
|
||||
// persona/角色,绝不跟随行为模式)接到 agent 循环的轮次边界上。循环保持与情绪无关:
|
||||
// 它上报每个已结算轮次,并把返回的心情标签带到 Result.Mood,由持久化层写到助手消息上
|
||||
// (design/16 §3.3)。
|
||||
//
|
||||
// Scope of this milestone (A1) — what is wired end to end:
|
||||
// - every settled owner turn advances the bound persona's emotion machine and
|
||||
// affection (in-memory, persona-keyed by the registry's emotion Manager);
|
||||
// - the resulting mood rides the assistant message into chat_messages and the
|
||||
// `message_persisted` frame, and each *change* is broadcast as a `mood` frame.
|
||||
// 本里程碑(A1)端到端接通的范围:
|
||||
// - 每个已结算的主人轮次推进所绑定 persona 的情绪状态机与好感度(内存态,按 persona
|
||||
// 为键,由 registry 的 emotion Manager 持有);
|
||||
// - 由此得到的心情随助手消息进入 chat_messages 与 `message_persisted` 帧,而每次
|
||||
// *变化* 都作为 `mood` 帧广播。
|
||||
//
|
||||
// Not wired (design/01 does not specify it): the mood is not yet injected back
|
||||
// into the system prompt, so it does not steer the reply text, and the emotion
|
||||
// state is not persisted across restarts (design/01 requires neither; the state
|
||||
// resets to the persona's configured initialState on boot).
|
||||
// 未接通(design/01 未作规定):心情尚未反注入 system 提示,因此不会左右回复文本;
|
||||
// 情绪状态也不跨重启持久化(design/01 两者都不要求;启动时状态重置为 persona 配置的
|
||||
// initialState)。
|
||||
|
||||
// moodEmitter is the gateway-facing sink for `mood` broadcasts. *gateway.Server
|
||||
// implements it (BroadcastMood); held as an interface so the composition root
|
||||
// stays unit-testable with a fake sink, mirroring capacityEmitter.
|
||||
// moodEmitter 是面向 gateway 的 `mood` 广播出口。*gateway.Server 实现它
|
||||
// (BroadcastMood);这里持有接口是为了让组合根能用假实现做单元测试,与
|
||||
// capacityEmitter 一致。
|
||||
type moodEmitter interface {
|
||||
BroadcastMood(personaID, mood string, affection int)
|
||||
}
|
||||
|
||||
// buildEmotionObserver assembles the persona emotion observer: the registry's
|
||||
// emotion Manager supplies each persona's machine and affection, the registry
|
||||
// supplies the persona's configured affection step (好感度曲线), and every change
|
||||
// is pushed to the Web UI through publishMood.
|
||||
// buildEmotionObserver 装配 persona 情绪观察者:registry 的 emotion Manager 提供
|
||||
// 每个 persona 的状态机与好感度,registry 提供 persona 配置的好感度步长
|
||||
// (好感度曲线),每次变化都经 publishMood 推送到 Web UI。
|
||||
func (a *app) buildEmotionObserver() *emotion.Observer {
|
||||
return emotion.NewObserver(a.personas.Emotions(), a.personas.AffectionStep, a.publishMood)
|
||||
}
|
||||
|
||||
// onTurnEnd is the loop's turn-boundary hook (design/01 §2): a settled turn is
|
||||
// applied to the persona the loop is bound to, and the mood after the turn is
|
||||
// returned for the assistant message. An absent persona id falls back to the
|
||||
// default persona, matching how the loop is bound.
|
||||
// onTurnEnd 是循环的轮次边界钩子(design/01 §2):已结算的轮次被施加到循环所绑定的
|
||||
// persona 上,并把该轮之后的心情返回给助手消息。persona id 缺失时退回默认 persona,
|
||||
// 与循环的绑定方式一致。
|
||||
//
|
||||
// Two gates keep this to real conversation turns:
|
||||
// - only the user-facing conversation lane (the Web main session and its
|
||||
// sub-sessions; IM owner-private chat rides the main session, design/16 §4.4)
|
||||
// moves the mood. Autonomous and delegated loop calls — background thinking
|
||||
// (sess-backthink), sub-agent work, isolated IM sessions — are not turns of
|
||||
// the owner's conversation, so they must not rewrite her mood;
|
||||
// - a restricted (group/stranger) conversation is read-only: the observer
|
||||
// refuses the write, so a third party can never move her mood or affection
|
||||
// (design/02 §3, design/11 §2).
|
||||
// 两道闸门确保只有真实对话轮次才触发:
|
||||
// - 只有面向用户的对话车道(Web 主会话及其子会话;IM 主人私聊走主会话,
|
||||
// design/16 §4.4)会推动心情。自主与委派的循环调用 —— 后台思考(sess-backthink)、
|
||||
// 子代理工作、隔离的 IM 会话 —— 不是主人对话的轮次,因此不得改写她的心情;
|
||||
// - 受限(群聊/陌生人)对话是只读的:观察者拒绝写入,因此第三方永远无法左右她的
|
||||
// 心情或好感度(design/02 §3、design/11 §2)。
|
||||
func (a *app) onTurnEnd(end loop.TurnEnd) string {
|
||||
if a.emotion == nil || !isConversationLane(end.SessionID) {
|
||||
return ""
|
||||
@@ -66,18 +59,16 @@ func (a *app) onTurnEnd(end loop.TurnEnd) string {
|
||||
return string(a.emotion.Observe(personaID, end.UserText, !end.Env.Restricted()))
|
||||
}
|
||||
|
||||
// isConversationLane reports whether a session belongs to the owner's live
|
||||
// conversation: the fixed main session "web" and its "web:<uuid>" sub-sessions
|
||||
// (design/16 §2.1 — IM owner-private chat is routed into the main session).
|
||||
// isConversationLane 报告某会话是否属于主人的实时对话:固定的主会话 "web" 及其
|
||||
// "web:<uuid>" 子会话(design/16 §2.1 —— IM 主人私聊被路由进主会话)。
|
||||
func isConversationLane(sessionID string) bool {
|
||||
return sessionID == history.MainSessionID || strings.HasPrefix(sessionID, history.MainSessionID+":")
|
||||
}
|
||||
|
||||
// publishMood broadcasts one emotion change as a `mood` frame (design/07 §3,
|
||||
// design/01 §2) so the Web 心情 badge follows the persona without a refresh. It is
|
||||
// called only when the mood actually changed, so the frame stays news rather than
|
||||
// per-turn noise. The sink is read at call time because the gateway is built after
|
||||
// the loop; before it exists the change is logged and dropped.
|
||||
// publishMood 把一次情绪变化作为 `mood` 帧广播(design/07 §3、design/01 §2),
|
||||
// 使 Web 的心情徽标无需刷新即可跟随 persona。它只在心情确实变化时调用,因此该帧
|
||||
// 是新闻而不是每轮噪声。出口在调用时读取,因为 gateway 构建在循环之后;它还不存在
|
||||
// 时该变化只记日志并丢弃。
|
||||
func (a *app) publishMood(update emotion.Update) {
|
||||
log := logger.WithSource(a.log, "cmd/cyrene")
|
||||
if a.moodSink == nil {
|
||||
|
||||
Reference in new issue
Block a user