docs(cyrene): cmd/cyrene 存量英文注释中文化(22 个非测试文件,仅注释)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

- 四组并行完成: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:
AskaEth committed 2026-10-04 16:58:06 +08:00
1 parent 5c2189efb0
commit 52f08dc343
22 files changed
+455 -586

No files matched your search

+35 -48
View File
@@ -8,9 +8,8 @@ import (
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/model"
)
// Section headers for the persona fields that design/01 §2.2 lists as previously
// inert. They are appended as separate system-prompt sections after the identity
// block so each one can be tuned without touching the identity text.
// 以下段头对应 design/01 §2.2 中此前未被消费的人格字段。它们作为独立的 system
// 提示段追加在身份块之后,使每一段都能单独调优而不必改动身份正文。
const (
personalityHeader = "【性格】"
valuesHeader = "【价值观】"
@@ -19,14 +18,13 @@ const (
backgroundHeader = "【背景】"
)
// personaSection is one appended block: a bracketed header plus its body.
// personaSection 是一个追加块:方括号段头 + 正文。
type personaSection struct {
header string
body string
}
// defaultPersona returns the default character's persona, or false when no
// character/persona is registered.
// defaultPersona 返回默认角色的 persona;没有注册角色/persona 时返回 false。
func (a *app) defaultPersona() (*loader.Persona, bool) {
c, ok := a.personas.DefaultCharacter()
if !ok {
@@ -39,9 +37,8 @@ func (a *app) defaultPersona() (*loader.Persona, bool) {
return p, true
}
// identityInstructionFor returns the persona's identity block — the only part
// injected before design/01 §2.2: identity.systemPrompt, else identity.role, else
// the minimal fallback.
// identityInstructionFor 返回 persona 的身份块 —— design/01 §2.2 之前唯一注入的
// 部分:优先 identity.systemPrompt,其次 identity.role,再退回最小兜底文本。
func identityInstructionFor(p *loader.Persona) string {
if p.Identity.SystemPrompt != "" {
return p.Identity.SystemPrompt
@@ -52,11 +49,10 @@ func identityInstructionFor(p *loader.Persona) string {
return fallbackInstruction
}
// instructionsFromPersona builds the persona's system instruction: the identity
// block, followed by the personality/values/speechStyle/catchphrase/background
// sections that used to have no consumer (design/01 §2.2). Blank fields are
// skipped so no empty section is emitted, and a persona with none of them yields
// exactly the identity block — byte for byte the pre-existing output.
// instructionsFromPersona 构建 persona 的 system 指令:身份块,后接此前无人消费的
// personality/values/speechStyle/catchphrase/background 各段(design/01 §2.2)。
// 空白字段会被跳过,因此不会产生空段;这些字段全空的 persona 产出与身份块完全一致
// —— 与既有输出逐字节相同。
func instructionsFromPersona(p *loader.Persona) string {
base := identityInstructionFor(p)
sections := personaSections(p)
@@ -74,9 +70,8 @@ func instructionsFromPersona(p *loader.Persona) string {
return b.String()
}
// personaSections renders the five optional sections in their fixed order
// (personality → values → speechStyle → catchphrase → background), skipping any
// that is blank.
// personaSections 按固定顺序渲染五个可选段(personality → values → speechStyle
// → catchphrase → background),跳过其中为空的。
func personaSections(p *loader.Persona) []personaSection {
out := make([]personaSection, 0, 5)
appendSection := func(header, body string) {
@@ -93,8 +88,8 @@ func personaSections(p *loader.Persona) []personaSection {
return out
}
// bulletList renders string items as a markdown bullet list, skipping blanks; an
// all-blank list yields "" so its section disappears entirely.
// bulletList 把字符串项渲染成 markdown 无序列表,跳过空白项;全空的列表产出 ""
// 使对应段彻底消失。
func bulletList(items []string) string {
lines := make([]string, 0, len(items))
for _, item := range items {
@@ -105,18 +100,15 @@ func bulletList(items []string) string {
return strings.Join(lines, "\n")
}
// defaultThinkingOptions returns the reasoning knobs the loop should inject for
// the default persona: the thinking directive, the reasoning_effort value and the
// thinking-broadcast switch. It is the default half of the per-role resolution
// the loop performs every turn (Options.PersonaKnobs, see personaKnobs below), so
// the configured default and the per-turn lookup can never drift apart.
// defaultThinkingOptions 返回循环应为默认 persona 注入的推理开关:thinking 指令、
// reasoning_effort 取值与 thinking 广播开关。它是循环每轮所做的按角色解析的默认
// 一半(Options.PersonaKnobs,见下方 personaKnobs),因此配置的默认值与每轮查询
// 永远不会漂移。
//
// The thinking directive is non-nil only when the persona configures something
// that affects the request (a budget, an effort, or an explicit on/off mode).
// showToUser deliberately does NOT create one: it is a presentation switch, and a
// non-nil directive with no switch would enable provider thinking as a side
// effect. All three are zero when no persona is registered, which leaves the
// loop's pre-existing behavior untouched.
// 只有当 persona 配置了会影响请求的内容(预算、effort,或显式的开关模式)时
// thinking 指令才非 nil。showToUser 刻意不产生指令:它只是呈现开关,而一个没有
// 开关的非 nil 指令会顺带打开供应商侧 thinking。未注册 persona 时三者均为零值,
// 循环既有行为不受影响。
func (a *app) defaultThinkingOptions() (*model.Thinking, string, *bool) {
knobs, ok := a.personaKnobs(a.defaultPersonaID())
if !ok {
@@ -125,14 +117,12 @@ func (a *app) defaultThinkingOptions() (*model.Thinking, string, *bool) {
return knobs.Thinking, knobs.ReasoningEffort, knobs.ThinkingShowToUser
}
// personaKnobs resolves a role's reasoning knobs for the loop
// (loop.Options.PersonaKnobs, design/22 §4.2): the loop asks for the role of the
// turn it is about to build a request for, so a session bound to role Y runs with
// Y's thinking budget / effort / broadcast switch instead of the default role's.
// Resolving from the role id rather than pushing a value into every caller's
// SessionEnv means every path — Web REST/WS/voice, IM, backthink, sub-agents —
// gets the right knobs from one input. ok=false means "unknown role", and the loop
// keeps its configured defaults.
// personaKnobs 为循环解析某个角色的推理开关(loop.Options.PersonaKnobs,
// design/22 §4.2):循环会为即将构建请求的那一轮询问其角色,因此绑定角色 Y 的
// 会话运行时用的是 Y 的 thinking 预算 / effort / 广播开关,而不是默认角色的。
// 从角色 id 解析,而不是把取值推入每个调用方的 SessionEnv,意味所有路径 —— Web
// REST/WS/语音、IM、backthink、子代理 —— 都由同一个输入拿到正确的开关。
// ok=false 表示「角色未知」,循环沿用其配置的默认值。
func (a *app) personaKnobs(personaID string) (loop.LoopKnobs, bool) {
if personaID == "" {
return loop.LoopKnobs{}, false
@@ -149,13 +139,11 @@ func (a *app) personaKnobs(personaID string) (loop.LoopKnobs, bool) {
}, true
}
// personaName resolves a role id to its display name for the model context's
// speaker attribution (loop.Options.PersonaName, design/22 §7-5). The loop names a
// speaking role as "「昔涟」(xilian)" instead of a bare id, so the model can follow
// who said what after a session switched roles. An empty or unknown id resolves to
// "" and the loop falls back to the id alone — attribution never disappears just
// because a name could not be resolved, and nothing here is an identity or
// permission input.
// personaName 把角色 id 解析成其展示名,供模型上下文的说话人归属使用
// (loop.Options.PersonaName,design/22 §7-5)。循环把发话角色写成
// 「「昔涟」(xilian)」而不是裸 id,使模型在会话切换角色后仍能跟上谁说了什么。
// id 为空或未知时解析为 "",循环退回只写 id —— 归属不会因为名字解析不出就消失,
// 且这里没有任何身份或权限输入。
func (a *app) personaName(personaID string) string {
if personaID == "" {
return ""
@@ -167,9 +155,8 @@ func (a *app) personaName(personaID string) string {
return strings.TrimSpace(p.Name)
}
// personaThinking maps the persona's `thinking` section onto the model-layer
// knobs (design/01 §2.1 / design/04 §3.2). It returns (nil, "") when nothing
// affects the request.
// personaThinking 把 persona 的 `thinking` 段映射到模型层开关(design/01 §2.1 /
// design/04 §3.2)。没有任何内容影响请求时返回 (nil, "")。
func personaThinking(p *loader.Persona) (*model.Thinking, string) {
effort := strings.TrimSpace(p.Thinking.Effort)
enable := p.Thinking.Enable()