docs(runtime): internal/runtime/loop 44 个文件注释改中文(逐行 1:1,代码零字节改动)

主人 2026-10-03 拍板「注释一律中文」;本模块按长期分批协议(一个模块一次派工)执行。
注释行数 1329 → 1329 逐行 1:1(含中文 33 → 1304);行尾注释 5 条一并译。
校验:机械校验(非注释改动行)= 空;独立 Go AST 程序(剥注释复渲)证明 44/44 文件代码全等;
全树 go test ./... 58 包 ok / 0 FAIL;交叉编译绿。
gofmt:capacity_loop_test.go / flow.go 改动前即未格式化,按铁律保留原样未动。
This commit is contained in:
AskaEth committed 2026-10-03 22:28:21 +08:00
1 parent 355f81d04a
commit 91e8d7a029
44 files changed
+1315 -1315

No files matched your search

+36 -36
View File
@@ -10,22 +10,22 @@ import (
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/model"
)
// This file covers design/22 §7-5 from the model's side: a conversation whose
// assistant messages were spoken by different roles must reach the provider with
// that attribution visible, without a single character being added to a message
// body and without disturbing the assembled prompt's established order.
// 本文件从模型一侧覆盖 design/22 §7-5:一段其 assistant 消息
// 由不同角色说出的对话,必须在归属可见的情况下抵达 provider,
// 且不向消息正文添加任何一个字符,
// 也不打乱组装好的提示词的既定顺序。
// speakerMsg builds one conversation message labelled with the role that spoke
// it, exactly the way the gateway's transcript seeding labels an assistant turn
// (model.Message.SenderName carries the speaking role id).
// speakerMsg 构建一条标注了说出它的角色的对话消息,
// 与 gateway 的 transcript 播种标注 assistant 轮的方式完全一致
// (model.Message.SenderName 携带发言角色 id)。
func speakerMsg(role model.Role, personaID, text string) model.Message {
m := model.TextMessage(role, text)
m.SenderName = personaID
return m
}
// attributedLoop builds a two-role loop: instructions say which role answered, and
// the name resolver mirrors the persona registry's id→display-name mapping.
// attributedLoop 构建一个双角色循环:指令说明是哪个角色作答,
// 名字解析器镜像 persona registry 的 id→显示名映射。
func attributedLoop(t *testing.T, ad model.Adapter) *Loop {
t.Helper()
xilian := personaAgent(t, "你是昔涟。", ad)
@@ -39,8 +39,8 @@ func attributedLoop(t *testing.T, ad model.Adapter) *Loop {
})
}
// seedMemory writes one persona-scoped memory item for personaID so the round's
// retrieval has something to inject.
// seedMemory 为 personaID 写入一条按人格作用域的记忆条目,使该轮的
// 检索有东西可注入。
func seedMemory(t *testing.T, store *memory.Store, personaID, content string) {
t.Helper()
if _, err := store.Add(context.Background(), memory.MemoryItem{
@@ -51,7 +51,7 @@ func seedMemory(t *testing.T, store *memory.Store, personaID, content string) {
}
}
// systemTexts returns the text of every system message of req, in order.
// systemTexts 按顺序返回 req 中每条系统消息的文本。
func systemTexts(req model.Request) []string {
out := make([]string, 0, len(req.Messages))
for _, m := range req.Messages {
@@ -62,8 +62,8 @@ func systemTexts(req model.Request) []string {
return out
}
// indexOfSystemContaining returns the index of the first message whose text
// contains want, or -1.
// indexOfSystemContaining 返回文本包含 want 的第一条消息的索引,
// 没有则返回 -1。
func indexOfSystemContaining(req model.Request, want string) int {
for i, m := range req.Messages {
if strings.Contains(messageText(m), want) {
@@ -73,12 +73,12 @@ func indexOfSystemContaining(req model.Request, want string) int {
return -1
}
// TestAttribution_SpeakersReachTheModelRequest is the acceptance case of
// design/22 §7-5: the session now speaks as Y while the context still holds
// utterances by X. The request the adapter receives must (a) open with Y's own
// instructions, (b) declare which role is answering, (c) mark where the speaker
// changed so "第 N 条是谁说的" is decidable, and (d) leave every message body
// untouched — the attribution travels only in system messages.
// TestAttribution_SpeakersReachTheModelRequest 是 design/22 §7-5 的
// 验收用例:会话现在以 Y 发言,而上下文中仍留有
// X 说过的话。适配器收到的请求必须 (a) 以 Y 自己的
// 指令开头,(b) 声明哪个角色在作答,(c) 标出发言人
// 何处变化,使「第 N 条是谁说的」可判定,且 (d) 保持每条消息正文
// 不动 —— 归属只在系统消息中传递。
func TestAttribution_SpeakersReachTheModelRequest(t *testing.T) {
t.Parallel()
ad := &mockAdapter{chat: []mgResp{{resp: model.Response{Content: "在呢"}}}}
@@ -96,14 +96,14 @@ func TestAttribution_SpeakersReachTheModelRequest(t *testing.T) {
}
req := lastChatRequest(t, ad)
// (a) the role that answers now still owns the first system message.
// (a) 现在作答的角色仍然拥有第一条系统消息。
if got := messageText(req.Messages[0]); got != "你是由纪。" {
t.Fatalf("first system = %q, want the bound role's instructions", got)
}
sys := systemTexts(req)
// instructions + the role-context segment + one boundary note per speaker
// stretch (X's two assistant turns are one stretch).
// instructions + 角色上下文片段 + 每个发言人片段一条边界说明
// (X 的两个 assistant 轮是一个片段)。
if len(sys) != 4 {
t.Fatalf("system messages = %d (%q), want 4 (instructions + role context + two speaker boundaries)", len(sys), sys)
}
@@ -128,8 +128,8 @@ func TestAttribution_SpeakersReachTheModelRequest(t *testing.T) {
t.Fatalf("system[3] = %q, want Y's own boundary note naming the answering role", sys[3])
}
// (c) the boundary sits directly before the first utterance it covers, and the
// second X utterance inherits the same speaker without a second note.
// (c) 边界就位于它所覆盖的第一句话之前,且
// 第二句 X 的话继承同一发言人,无需第二条说明。
firstX := indexOfSystemContaining(req, "我记住了")
if firstX < 0 || req.Messages[firstX-1].Role != model.RoleSystem {
t.Fatalf("X's first utterance at %d is not preceded by a boundary note (%+v)", firstX, req.Messages)
@@ -137,14 +137,14 @@ func TestAttribution_SpeakersReachTheModelRequest(t *testing.T) {
if idx := indexOfSystemContaining(req, "「昔涟」(xilian)"); idx > firstX {
t.Fatalf("X boundary at %d must precede its utterance at %d", idx, firstX)
}
// The answering role's own history is re-opened by its own boundary note.
// 作答角色自己的历史由它自己的边界说明重新开启。
self := indexOfSystemContaining(req, "我在呢")
if self < 0 || !strings.Contains(messageText(req.Messages[self-1]), "来自你自己") {
t.Fatalf("Y's utterance is not preceded by its self boundary: %+v", req.Messages)
}
// (d) no body was rewritten: user text stays verbatim and carries no metadata,
// and the assistant's own words are unchanged.
// (d) 没有任何正文被改写:用户文本保持逐字且不携带元数据,
// 且 assistant 自己的话也未变。
var users []string
for _, m := range req.Messages {
if m.Role != model.RoleUser {
@@ -167,10 +167,10 @@ func TestAttribution_SpeakersReachTheModelRequest(t *testing.T) {
}
}
// TestAssembleContext_AttributionKeepsBlockOrder pins the placement rule: the role
// declaration is added AFTER the established leading blocks (time, working memory,
// memory) and immediately before the conversation, so the memory/time block order
// and the instructions-first rule are untouched.
// TestAssembleContext_AttributionKeepsBlockOrder 钉住放置规则:角色
// 声明被加在既定的前导块(时间、工作记忆、
// 记忆)之后、紧邻对话之前,因此记忆/时间块的顺序
// 与指令优先规则不受影响。
func TestAssembleContext_AttributionKeepsBlockOrder(t *testing.T) {
t.Parallel()
store := newTestMemoryStore(t)
@@ -217,10 +217,10 @@ func TestAssembleContext_AttributionKeepsBlockOrder(t *testing.T) {
}
}
// TestAttribution_UnlabeledConversationIsUntouched locks the backward-compatible
// half: a caller that labels nothing (every single-role path, IM, backthink, the
// autonomous passes) gets exactly the prompt it had before, with no role segment
// and no boundary notes.
// TestAttribution_UnlabeledConversationIsUntouched 钉住向后兼容的
// 那一半:什么都不标注的调用方(每条单角色路径、IM、backthink、
// 自主流程)拿到与从前完全一样的提示词,没有角色片段
// 也没有边界说明。
func TestAttribution_UnlabeledConversationIsUntouched(t *testing.T) {
t.Parallel()
ad := &mockAdapter{chat: []mgResp{{resp: model.Response{Content: "done"}}}}