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
+45
-55
@@ -33,8 +33,8 @@ import (
|
||||
iotools "git.yeij.top/AskaEth/Cyrene_v2/plugins/tools/io"
|
||||
)
|
||||
|
||||
// buildPersonas loads the persona definitions and registers them, plus the
|
||||
// default character and the owner profile used by channel identity resolution.
|
||||
// buildPersonas 加载人格定义并注册它们,同时注册默认角色与渠道身份识别所用的
|
||||
// 主人档案。
|
||||
func (a *app) buildPersonas() error {
|
||||
a.personas = personareg.New()
|
||||
|
||||
@@ -55,7 +55,7 @@ func (a *app) buildPersonas() error {
|
||||
a.log.Warn("owner profile load skipped", "error", oerr)
|
||||
}
|
||||
|
||||
// Load the default persona explicitly if it was not under the personas dir.
|
||||
// 若默认角色不在 personas 目录下,则显式加载一次。
|
||||
defaultID := "cyrene"
|
||||
if a.owner != nil && a.owner.DefaultPersona != "" {
|
||||
defaultID = a.owner.DefaultPersona
|
||||
@@ -77,8 +77,8 @@ func (a *app) buildPersonas() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// wireMemory builds the long-term memory stack: store, embedding manager, vector
|
||||
// index, project index and the retriever wired into the io knowledge tool.
|
||||
// wireMemory 构建长期记忆栈:store、嵌入管理器、向量索引、项目索引,以及接进
|
||||
// io 知识工具的检索器。
|
||||
func (a *app) wireMemory(ctx context.Context) error {
|
||||
store, err := memory.NewStore(ctx, a.db, a.log)
|
||||
if err != nil {
|
||||
@@ -119,10 +119,9 @@ func (a *app) wireMemory(ctx context.Context) error {
|
||||
func (a *app) wireRuntime() error {
|
||||
a.attachToolPolicyStore()
|
||||
|
||||
// The LLM provider stack is hot-swappable: it loads models.json (or falls
|
||||
// back to .env) and the panel save endpoint reloads it without a restart
|
||||
// (design/04 §3.1). a.modelAdapter stays an Adapter (the runtime stack
|
||||
// implements it) for the channel-bridge review model (design/12 §6 策略四).
|
||||
// LLM 提供商栈可热插拔:它加载 models.json(或回落 .env),面板的保存端点会
|
||||
// 就地重载它而无需重启(design/04 §3.1)。a.modelAdapter 仍保持 Adapter 接口
|
||||
// (运行时栈实现了它),供渠道 bridge 的复审模型使用(design/12 §6 策略四)。
|
||||
modelsPath := runtimeconfig.DefaultPath(resolveDataDir(a.cfg))
|
||||
// 启动即补齐一次(主人裁决):`.env` 只是默认/播种层,models.json 才是面板的
|
||||
// 一等来源——把 `.env` 补齐进面板配置里缺失的键(面板已有的键绝不覆盖,组集合
|
||||
@@ -169,17 +168,16 @@ func (a *app) wireRuntime() error {
|
||||
}
|
||||
|
||||
store := a.memStore
|
||||
// One agent per role, all sharing the dispatcher/guards/adapter above, so a session
|
||||
// can answer as any role (design/22 §4.2 方案 A); the loop picks per turn.
|
||||
// 每个角色一个 agent,共用上面的 dispatcher / 护栏 / 适配器,因此一个会话能以
|
||||
// 任意角色作答(design/22 §4.2 方案 A);具体由 loop 按 turn 选取。
|
||||
agents, defaultAgent := a.personaAgentPool(runtimeStack, a.dispatcher, guards, ag)
|
||||
|
||||
// Spans fan out to the JSONL stderr recorder and — once wireFrontend has built
|
||||
// the gateway — to its observability buffer (cmd/cyrene/observability.go).
|
||||
// span 分两路:一路写 JSONL(stderr 记录器),另一路在 wireFrontend 建好网关后
|
||||
// 进入它的可观测性缓冲(cmd/cyrene/observability.go)。
|
||||
a.traceWriter = newAppTraceWriter()
|
||||
tracer := trace.New(a.traceWriter)
|
||||
// Realtime flow visualization (design/19 §1): the publisher accumulates the
|
||||
// loop's trace spans into a per-session flow graph and publishes
|
||||
// ws.graph_update on each span transition.
|
||||
// 实时链路可视化(design/19 §1):发布器把 loop 的 trace span 累积成按会话的
|
||||
// 链路图,并在每次 span 跃迁时发布 ws.graph_update。
|
||||
//
|
||||
// 图源白名单(裁决 16.4.2):它决定**哪些会话产出实时链路图**,也是后端能提供
|
||||
// 完整链路导图的那一侧 —— 主人 web 会话族("web" 主会话 + "web:<uuid>" 次级会话,
|
||||
@@ -204,15 +202,13 @@ func (a *app) wireRuntime() error {
|
||||
return fmt.Errorf("checkpoint store: %w", perr)
|
||||
}
|
||||
|
||||
// Vision routing: the loop rewrites an image-bearing user message per the
|
||||
// vision Router — a main model that really accepts image input sees the image
|
||||
// directly, otherwise the vision/OCR tool's text description replaces it
|
||||
// (design/06 §0)。
|
||||
// 视觉路由:loop 按 vision Router 改写带图用户消息——真正能收图的主模型直接
|
||||
// 看到图像,否则改用 vision/OCR 工具产出的文字描述替代它(design/06 §0)。
|
||||
//
|
||||
// SupportsVision means "主模型能否收图"(裁决 14.4.1 修语义,C-7), read from the
|
||||
// active models.json group's `multimodal` declaration — NOT from
|
||||
// LLM_VISION_MODEL, which configures the vision *tool's* model. It is read per
|
||||
// call so a panel save/reload takes effect on the next turn.
|
||||
// SupportsVision 指「主模型能否收图」(裁决 14.4.1 修语义,C-7),取自当前生效
|
||||
// 的 models.json 组的 `multimodal` 声明——**不是**取自 LLM_VISION_MODEL,后者配
|
||||
// 的是 vision **工具**用的模型。它按调用读取,因此面板保存/重载在下一个 turn
|
||||
// 即生效。
|
||||
visionRouter := vision.NewRouter(
|
||||
vision.WithVisionTool(visionToolName),
|
||||
vision.WithOCRTool(ocrToolName),
|
||||
@@ -227,15 +223,13 @@ func (a *app) wireRuntime() error {
|
||||
)
|
||||
|
||||
capDecider := a.buildCapacity()
|
||||
// The persona emotion observer (design/01 §2) is built here because it is the
|
||||
// loop's turn-boundary dependency: after every settled turn the bound persona's
|
||||
// emotion machine and affection move, and the returned mood label is written
|
||||
// onto Result.Mood and the assistant message (design/16 §3.3).
|
||||
// 人格情绪观测器(design/01 §2)在此构建,因为它是 loop 的 turn 边界依赖:
|
||||
// 每个 turn 落定后,该 turn 绑定人格的情绪机与好感度都会推进,返回的心情标签
|
||||
// 写进 Result.Mood 与助手消息(design/16 §3.3)。
|
||||
a.emotion = a.buildEmotionObserver()
|
||||
// Reasoning knobs from the default persona (budget / effort / thinking broadcast),
|
||||
// which are also the per-turn defaults: the loop re-resolves them for each turn's
|
||||
// role through PersonaKnobs, so a session bound to another role uses that role's
|
||||
// budget instead.
|
||||
// 推理旋钮取自默认人格(预算 / 强度 / 是否广播思考),它们同时也是按 turn 的
|
||||
// 默认值:loop 会经 PersonaKnobs 按每个 turn 的角色重新解析,因此绑定其他角色
|
||||
// 的会话用的是那个角色的预算。
|
||||
thinking, reasoningEffort, thinkingShow := a.defaultThinkingOptions()
|
||||
|
||||
// 敏感操作代审(design/11 §4;裁决 13.4.3):terminal 这类敏感工具在 loop 的
|
||||
@@ -293,14 +287,12 @@ func (a *app) wireRuntime() error {
|
||||
Bus: a.bus,
|
||||
Memory: store,
|
||||
Tracer: tracer,
|
||||
// A sub-agent dispatched as another role (subagent_spawn `persona`, design/22
|
||||
// §8-2) may only name a role this process can actually run with its own
|
||||
// instructions, i.e. one the pool above has an agent for; anything else is
|
||||
// rejected instead of silently answering in the default role's voice.
|
||||
// 以其他角色派发的子代理(subagent_spawn 的 `persona`,design/22 §8-2)只能
|
||||
// 指名本进程确实能用该角色自己的指令跑起来的角色,即上面那个池子里有 agent
|
||||
// 的角色;其余一律拒绝,而不是默默用默认角色的口吻作答。
|
||||
PersonaExists: personaExists(agents),
|
||||
// The sub-agent's span and its inner llm/tool steps fold into the spawning
|
||||
// session's live graph, so a branch shows up as a swimlane of that session's
|
||||
// flow instead of opening a second graph (design/19 §2).
|
||||
// 子代理的 span 与它内部的 llm/工具步骤并进派生它的那个会话的实时图,因此
|
||||
// 一条分支表现为该会话链路图里的一条泳道,而不是另开第二张图(design/19 §2)。
|
||||
Flow: flowPub,
|
||||
Approver: approver,
|
||||
Logger: logger.WithSource(a.log, "orchestration"),
|
||||
@@ -404,15 +396,14 @@ func (a *app) approvalActor(ctx context.Context) string {
|
||||
return pid
|
||||
}
|
||||
|
||||
// buildCapacity / onCapacity / capacity JSON+TTL parsing live in
|
||||
// wire_capacity.go (AGENTS §10 文件 ≤500 行).
|
||||
// buildCapacity / onCapacity 以及 capacity 的 JSON+TTL 解析都在
|
||||
// wire_capacity.go(AGENTS §10 文件 ≤500 行)。
|
||||
|
||||
// onToolAudit is the loop's OnAudit sink: it forwards a tool call denied by the
|
||||
// design/11 §3 security gate in a group/stranger environment into the gateway
|
||||
// audit trail, so the rejection is "audit 可查" and the frontend can render the
|
||||
// small "xx 工具在群聊被拒" note (design/11 §8). The gateway is built after the
|
||||
// loop (wireFrontend), so the sink reads a.gw at call time — by then the app is
|
||||
// fully assembled and any Run is served through the gateway.
|
||||
// onToolAudit 是 loop 的 OnAudit 出口:它把群聊/陌生人环境里被 design/11 §3 安全闸
|
||||
// 拦下的工具调用转发进网关的审计流水,使这次拒绝「audit 可查」,前端也能渲染那行
|
||||
// 「xx 工具在群聊被拒」小字(design/11 §8)。网关在 loop 之后才建好
|
||||
// (wireFrontend),所以该出口在调用时才读 a.gw——那时应用已装配完整,任何 Run 都
|
||||
// 经网关服务。
|
||||
func (a *app) onToolAudit(ev loop.AuditEvent) {
|
||||
if a.gw == nil {
|
||||
logger.WithSource(a.log, "cmd/cyrene").Warn("loop audit dropped: gateway not ready",
|
||||
@@ -422,18 +413,17 @@ func (a *app) onToolAudit(ev loop.AuditEvent) {
|
||||
a.gw.AuditEvent(ev.Who, ev.What, ev.Result)
|
||||
}
|
||||
|
||||
// parseCapacityToolSets / parseL3CacheTTL live in wire_capacity.go.
|
||||
// parseCapacityToolSets / parseL3CacheTTL 在 wire_capacity.go 里。
|
||||
|
||||
// dbCfgForEmbed returns the DB config used by the vector index, which opens the
|
||||
// same SQLite file as the primary pool.
|
||||
// dbCfgForEmbed 返回向量索引所用的数据库配置——它打开的是与主连接池同一个
|
||||
// SQLite 文件。
|
||||
func (a *app) dbCfgForEmbed() config.DBConfig {
|
||||
cfg := a.cfg.DB
|
||||
cfg.SQLitePath = resolveSQLitePath(a.cfg, resolveDataDir(a.cfg))
|
||||
return cfg
|
||||
}
|
||||
|
||||
// defaultPersonaID returns the id of the default persona, falling back to
|
||||
// "cyrene".
|
||||
// defaultPersonaID 返回默认人格的 id,取不到时回落 "cyrene"。
|
||||
func (a *app) defaultPersonaID() string {
|
||||
if c, ok := a.personas.DefaultCharacter(); ok {
|
||||
return c.PersonaID
|
||||
@@ -441,9 +431,9 @@ func (a *app) defaultPersonaID() string {
|
||||
return "cyrene"
|
||||
}
|
||||
|
||||
// defaultInstructions returns the default persona's system prompt followed by the
|
||||
// personality/values/speechStyle/catchphrase/background sections (design/01
|
||||
// §2.2), falling back to its role text or a minimal instruction when neither is set.
|
||||
// defaultInstructions 返回默认人格的系统提示词,其后依次接 personality / values /
|
||||
// speechStyle / catchphrase / background 各段(design/01 §2.2);两者都取不到时回落
|
||||
// 到该角色的 role 文本或一句最小指令。
|
||||
//
|
||||
// 主人身份说明书**不在这里**(P0-10 收窄后按会话注入,见 personaKnowledgeFor):
|
||||
// 静态拼进指令会让它进入该角色的每一个会话,含群聊与陌生人私聊。
|
||||
|
||||
Reference in new issue
Block a user