docs(comments): 注释中文化 · internal/services/channelbridge(纯替换)
- 只翻注释/文档字符串:剥掉注释后代码行逐字节不变(机械校验只剩允许的行尾注释形态) - 术语对齐既有译法(owner→主人、persona→角色、engage→参与度判定、quiet hours→安静时段、backoff→退避) - 复核:go build 绿 + channelbridge 包测试绿;gofmt 干净
This commit is contained in:
1 parent
61cf80d5ee
commit
093f38d986
28 files changed
+1089
-1089
No files matched your search
@@ -12,12 +12,12 @@ import (
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/user"
|
||||
)
|
||||
|
||||
// This file covers design/22 §2/§7-3/§7-4 from the channel side: which role an
|
||||
// inbound IM turn answers as. The chain asserted is the structural session → the
|
||||
// resolved SessionEnv the loop is driven with → the role named in it.
|
||||
// 本文件从渠道侧覆盖 design/22 §2/§7-3/§7-4:一轮入站 IM 对话
|
||||
// 以哪个角色作答。断言的链路是「结构化会话 → 驱动循环所用的
|
||||
// 已解析 SessionEnv → 其中指定的角色」。
|
||||
|
||||
// personaHistory is the bridge's history store with one bound session role, so the
|
||||
// owner-private mirror can be asserted to follow the main session's role.
|
||||
// personaHistory 是桥接器的历史存储,绑定了一个会话角色,
|
||||
// 以便断言主人私聊的镜像会跟随主会话的角色。
|
||||
type personaHistory struct {
|
||||
*captureHistory
|
||||
personas map[string]string
|
||||
@@ -27,8 +27,8 @@ func (p *personaHistory) SessionPersona(_ context.Context, sessionID string) (st
|
||||
return p.personas[sessionID], nil
|
||||
}
|
||||
|
||||
// envChatter is a Chatter that records the SessionEnv the bridge resolved for the
|
||||
// turn, which is where the role travels (the loop reads it from ctx).
|
||||
// envChatter 是一个 Chatter,记录桥接器为该轮解析出的 SessionEnv,
|
||||
// 角色正是经由它传递(循环从 ctx 读取它)。
|
||||
type envChatter struct {
|
||||
env loop.SessionEnv
|
||||
got bool
|
||||
@@ -40,9 +40,9 @@ func (e *envChatter) Run(ctx context.Context, _ string, _ []model.Message) (*loo
|
||||
return &loop.Result{Text: "在呢"}, nil
|
||||
}
|
||||
|
||||
// personaBridge builds a started bridge whose single telegram account is bound to
|
||||
// channelPersona, over a history store that binds mainSessionPersona to the main
|
||||
// session ("" = unbound).
|
||||
// personaBridge 构建一个已启动的桥接器:其唯一的 telegram 账号绑定到
|
||||
// channelPersona,底层历史存储把 mainSessionPersona 绑定到主
|
||||
// 会话("" = 未绑定)。
|
||||
func personaBridge(t *testing.T, mainSessionPersona, channelPersona string) (*Bridge, *envChatter) {
|
||||
t.Helper()
|
||||
chat := &envChatter{}
|
||||
@@ -63,10 +63,10 @@ func personaBridge(t *testing.T, mainSessionPersona, channelPersona string) (*Br
|
||||
return b, chat
|
||||
}
|
||||
|
||||
// TestInboundOwnerPrivateFollowsMainSessionRole is design/22 §7-3: an owner
|
||||
// private IM chat is mirrored into the main web session, so it must answer as the
|
||||
// role that session is bound to — not as the global default and not as the
|
||||
// account's channel-level role.
|
||||
// TestInboundOwnerPrivateFollowsMainSessionRole 是 design/22 §7-3:主人
|
||||
// 私聊 IM 被镜像进 Web 主会话,因此它必须以该会话绑定的
|
||||
// 角色作答——既不是全局默认角色,也不是
|
||||
// 账号的渠道级角色。
|
||||
func TestInboundOwnerPrivateFollowsMainSessionRole(t *testing.T) {
|
||||
t.Parallel()
|
||||
b, chat := personaBridge(t, "xilian", "yuki")
|
||||
@@ -79,15 +79,15 @@ func TestInboundOwnerPrivateFollowsMainSessionRole(t *testing.T) {
|
||||
if chat.env.PersonaID != "xilian" {
|
||||
t.Fatalf("resolved persona = %q, want the main session's binding (xilian)", chat.env.PersonaID)
|
||||
}
|
||||
// The session binding wins, so the channel binding is never reached here.
|
||||
// 会话绑定胜出,因此这里绝不会走到渠道绑定。
|
||||
if got := b.personaOfAdapter("telegram"); got != "yuki" {
|
||||
t.Fatalf("cached channel persona = %q, want yuki (resolved at connect)", got)
|
||||
}
|
||||
}
|
||||
|
||||
// TestInboundChannelPersonaPrecedence pins the three-state precedence of design/22
|
||||
// §2: the channel-level binding applies only when neither the session nor anything
|
||||
// stronger resolves a role.
|
||||
// TestInboundChannelPersonaPrecedence 钉住 design/22 §2 的三态
|
||||
// 优先级:只有会话以及其他更强的来源都解析不出角色时,
|
||||
// 渠道级绑定才生效。
|
||||
func TestInboundChannelPersonaPrecedence(t *testing.T) {
|
||||
t.Parallel()
|
||||
cases := []struct {
|
||||
@@ -116,9 +116,9 @@ func TestInboundChannelPersonaPrecedence(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestInboundGroupForcesDefaultRole is design/22 §7-4: a group conversation — even
|
||||
// the owner's own messages inside it — keeps the default role even when the account
|
||||
// binds one, so the isolated group session can never be moved into a role's scope.
|
||||
// TestInboundGroupForcesDefaultRole 是 design/22 §7-4:群聊——即使
|
||||
// 群里是主人自己的消息——即使账号绑定了角色也仍用默认
|
||||
// 角色,因此隔离的群会话绝不会被移入某个角色的作用域。
|
||||
func TestInboundGroupForcesDefaultRole(t *testing.T) {
|
||||
t.Parallel()
|
||||
chat := &envChatter{}
|
||||
@@ -148,18 +148,18 @@ func TestInboundGroupForcesDefaultRole(t *testing.T) {
|
||||
if chat.env.PersonaID != "" {
|
||||
t.Fatalf("group conversation persona = %q, want the default role (empty)", chat.env.PersonaID)
|
||||
}
|
||||
// The isolation boundary itself is untouched by role resolution.
|
||||
// 隔离边界本身不受角色解析影响。
|
||||
if chat.env.MemWritable {
|
||||
t.Fatalf("env = %+v, want the read-only restricted lane preserved", chat.env)
|
||||
}
|
||||
}
|
||||
|
||||
// TestResolvePersonaStrangerUsesDefaultRole covers the other restricted lane
|
||||
// directly: a stranger's isolated private conversation is not the owner's mirror,
|
||||
// so both the session binding and the channel binding are skipped (design/22 §7-4).
|
||||
// The pipeline path is asserted for groups above; a stranger message only reaches
|
||||
// the loop when the participation gate admits it (design/12 §6), which is
|
||||
// orthogonal to role resolution and asserted elsewhere.
|
||||
// TestResolvePersonaStrangerUsesDefaultRole 直接覆盖另一条受限通道:
|
||||
// 陌生人的隔离私聊不是主人的镜像,
|
||||
// 因此会话绑定与渠道绑定都被跳过(design/22 §7-4)。
|
||||
// 群聊的流水线路径已在上文断言;陌生人消息只有在参与度
|
||||
// 闸门放行时才会到达循环(design/12 §6),这与角色解析
|
||||
// 正交,已在别处断言。
|
||||
func TestResolvePersonaStrangerUsesDefaultRole(t *testing.T) {
|
||||
t.Parallel()
|
||||
b, err := New(Options{
|
||||
@@ -182,9 +182,9 @@ func TestResolvePersonaStrangerUsesDefaultRole(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestChannelPersonaLookupSplitsAccountName proves the account-level lookup: a
|
||||
// multi-account platform resolves the role of the account that received the
|
||||
// message (platform:confId), not of the platform as a whole.
|
||||
// TestChannelPersonaLookupSplitsAccountName 证明查询是按账号的:
|
||||
// 多账号平台解析的是接收到该消息的账号(platform:confId)
|
||||
// 的角色,而不是整个平台的角色。
|
||||
func TestChannelPersonaLookupSplitsAccountName(t *testing.T) {
|
||||
t.Parallel()
|
||||
var gotPlatform, gotAccount string
|
||||
@@ -219,8 +219,8 @@ func TestChannelPersonaLookupSplitsAccountName(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestRemovedAccountForgetsChannelPersona locks the reload contract: an account
|
||||
// dropped by a reload must not keep answering as its old channel role.
|
||||
// TestRemovedAccountForgetsChannelPersona 锁定重载约定:被
|
||||
// 重载移除的账号绝不能继续以它旧的渠道角色作答。
|
||||
func TestRemovedAccountForgetsChannelPersona(t *testing.T) {
|
||||
t.Parallel()
|
||||
chat := &envChatter{}
|
||||
|
||||
Reference in new issue
Block a user