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
+24
-28
@@ -11,15 +11,15 @@ import (
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/services/gateway"
|
||||
)
|
||||
|
||||
// capacityEmitter is the gateway-facing sink for capacity_awaken broadcasts.
|
||||
// *gateway.Server implements it; tests substitute a fake to capture the args.
|
||||
// capacityEmitter 是面向网关的 capacity_awaken 广播出口。
|
||||
// *gateway.Server 实现它;测试用假实现替换以捕获入参。
|
||||
type capacityEmitter interface {
|
||||
BroadcastCapacityAwaken(sessionID, fromState, toState, tool string)
|
||||
}
|
||||
|
||||
// wireFrontend builds the gateway with the embedded/external SPA filesystem and
|
||||
// the JWT/RBAC authenticator. Session/Persona/Memories are wired to the concrete
|
||||
// managers so the admin/user list endpoints return real data.
|
||||
// wireFrontend 用内嵌/外部 SPA 文件系统与 JWT/RBAC 认证器构建网关。
|
||||
// Session/Persona/Memories 接到具体的管理器上,管理端/用户端的列表接口才会
|
||||
// 返回真实数据。
|
||||
func (a *app) wireFrontend() error {
|
||||
jwt := auth.New(a.cfg.Auth)
|
||||
apiKeys := auth.NewAPIKey(a.cfg.Auth)
|
||||
@@ -35,20 +35,19 @@ func (a *app) wireFrontend() error {
|
||||
a.log.Warn("audit store unavailable, falling back to in-memory", "error", aerr)
|
||||
auditStore = nil
|
||||
}
|
||||
// Opaque refresh tokens (B2) share the primary SQLite handle. A failure here
|
||||
// degrades gracefully: login simply omits refreshToken and /auth/refresh
|
||||
// reports not-configured, rather than failing the whole boot. The store is
|
||||
// held as the interface so a constructor failure leaves it nil (a typed nil
|
||||
// pointer in the interface would be non-nil and panic on first call).
|
||||
// 不透明刷新令牌(B2)与主 SQLite 句柄共用同一连接。这里失败要优雅降级:
|
||||
// 登录只是不下发 refreshToken,/auth/refresh 报「未配置」,而不是让整个
|
||||
// 启动失败。store 以接口形式持有,构造失败就保持 nil(若存成带类型的 nil
|
||||
// 指针,接口值非 nil,首次调用会 panic)。
|
||||
var refreshStore gateway.RefreshGrantStore
|
||||
if store, rerr := auth.NewRefreshStore(context.Background(), a.db, a.log); rerr != nil {
|
||||
a.log.Warn("refresh token store unavailable", "error", rerr)
|
||||
} else {
|
||||
refreshStore = store
|
||||
}
|
||||
// a.history is built in wireAuxiliary so both the channel bridge (wireChannels)
|
||||
// and the gateway share the same persistent store. History was a no-op dependency
|
||||
// before the IM path, so nothing downstream depends on its creation order change.
|
||||
// a.history 在 wireAuxiliary 里构建,让渠道桥(wireChannels)与网关共用同一个
|
||||
// 持久化存储。IM 通路之前 History 是个空转依赖,因此把它的创建顺序提前不会
|
||||
// 影响任何下游。
|
||||
gw, err := gateway.New(a.cfg, gateway.Deps{
|
||||
Log: logger.WithSource(a.log, "gateway"),
|
||||
Auth: jwt,
|
||||
@@ -82,19 +81,17 @@ func (a *app) wireFrontend() error {
|
||||
return fmt.Errorf("gateway: %w", err)
|
||||
}
|
||||
gw.SetVoice(a.voice)
|
||||
a.gw = gw // assign BEFORE wiring hooks below, which capture a.gw / gw (nil-receiver panic otherwise)
|
||||
// Observability trace sink (design/19 §2): now that the gateway exists, its
|
||||
// ring buffer must be fed by the loop's spans, or the admin trace/metrics
|
||||
// endpoints stay empty.
|
||||
a.gw = gw // 必须在下面接线 hook 之前赋值——那些 hook 捕获了 a.gw / gw(否则会 nil 接收者 panic)
|
||||
// 可观测性 trace 出口(design/19 §2):网关已存在,其环形缓冲必须由循环产出的
|
||||
// span 喂养,否则管理端 trace/metrics 接口会一直是空的。
|
||||
wireGatewayTraceSink(a, gw)
|
||||
if a.channelBridge != nil {
|
||||
// Route the channel bridge's owner-private persisted messages into the same
|
||||
// `message_persisted` broadcast the orchestrator uses, so the Web client mirrors
|
||||
// IM messages with one, uniform frame (design/16 §4.4).
|
||||
// 把渠道桥中「主人私聊」持久化的消息接入编排器所用的同一个
|
||||
// `message_persisted` 广播,让 Web 客户端用同一套统一帧来镜像 IM 消息
|
||||
// (design/16 §4.4)。
|
||||
a.channelBridge.SetOnPersisted(a.gw.BroadcastPersisted)
|
||||
// design/16 §4.6 §6: a message dropped by the platform's allow/deny
|
||||
// black-or-white lists is recorded in the gateway audit trail so the
|
||||
// rejection is "audit 可查" even though it never reaches the loop.
|
||||
// design/16 §4.6 §6:被平台白/黑名单(allow/deny)丢弃的消息会记入网关审计
|
||||
// 轨迹,这样即使它从未到达循环,这次拒绝也「audit 可查」。
|
||||
a.channelBridge.SetOnRejected(func(msg adapter.UnifiedMessage, reason string) {
|
||||
a.gw.AuditEvent("bridge:"+msg.Platform, "channel.reject", reason)
|
||||
})
|
||||
@@ -102,11 +99,10 @@ func (a *app) wireFrontend() error {
|
||||
a.capacitySink = gw
|
||||
a.moodSink = gw
|
||||
|
||||
// Wire the backthink proactive sinks now that the gateway hub (active-client
|
||||
// route) and the channel bridge (IM fallback) both exist. They were absent when
|
||||
// backthink.New ran (the hub needs the loop and the bridge needs the loop and the
|
||||
// owner profile, all assembled later), so without this the pusher would resolve
|
||||
// RouteNone. Each setter rebuilds the pusher under the service's lifecycle lock.
|
||||
// 网关 hub(活跃客户端通路)与渠道桥(IM 回落)都已在位,现在接线 backthink 的
|
||||
// 主动推送出口。backthink.New 执行时它们都还不存在(hub 需要循环,桥需要循环与
|
||||
// 主人档案,这些都更晚才组装),若不在此处补接线,推送器会解析出 RouteNone。
|
||||
// 每个 setter 都在服务的生命周期锁下重建推送器。
|
||||
if a.backthink != nil {
|
||||
a.backthink.SetActiveSink(gw)
|
||||
if a.channelBridge != nil {
|
||||
|
||||
Reference in new issue
Block a user