Files
Cyrene_v2/internal/runtime/loop/options.go
T
AskaEth 91e8d7a029 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 改动前即未格式化,按铁律保留原样未动。
2026-10-03 22:28:21 +08:00

179 lines
10 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package loop
import (
"context"
"log/slog"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/agent"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/capacity"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/guardrail"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/memory"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/model"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/tool"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/trace"
)
// Options 配置一个 Loop。所有字段都是可选的,nil 会一直被容忍到
// 真正需要该字段的那一步:Run 必须有 agent(否则
// Run 返回 ErrNilAgent);缺少工具 dispatcher 会使被请求的
// 调用以错误形式回灌;缺少 retriever/persona 会跳过记忆
// 注入;缺少 extractor/store 会跳过记忆钩子;缺少
// checkpoint 会跳过持久化;缺少 tracer 会跳过追踪。
type Options struct {
// Agent 是循环的执行单元:一个指令字符串,加上后端
// adapter、可选工具 dispatcher 与可选护栏。它是
// 默认 agent:角色在 Agents 中没有条目的每个 turn(或
// Agents 未设置时的每个 turn)都在它上面运行,
// 因此其指令应是全局默认角色的指令。
Agent *agent.Agent
// Agents 是按角色 agent 池(design/22 §4.2 方案 A):persona id → 承载
// 该角色系统提示词的 agent。循环每一步都为该
// turn 解析出的角色挑选条目,因此切换会话角色即切换
// 提示词,而无需重建循环(Agent 的指令不可变,
// 因此每角色一个 agent 是维持该不变式的方式)。所有条目通常
// 共用同一个 dispatcher/护栏管线/adapter —— 只有指令不同。
// 条目缺失或为 nil、角色未知、池为空,都会回退到
// Agent。为 nil 时保持既有的单角色行为。
Agents map[string]*agent.Agent
// Tools 是用于执行模型所请求调用的工具 dispatcher。为
// nil 时循环回退到 agent 自身的 dispatcher(若有)。
Tools *tool.Dispatcher
// Capacity 非 nil 且启用时,把每轮广告给模型的工具 schema
// 过滤为当前 capacity 状态的允许集
// (design/14 唤醒式能力渐进 §4):循环只向
// 模型暴露允许集 —— 是一个视图,不是硬边界(Invoke 不被拦截,
// 因此紧急调用仍可用)。为 nil(默认)时保持既有
// 行为:每个已注册工具都被广告。
Capacity *capacity.Decider
// OnCapacity 非 nil 时接收循环在判定一轮期间观察到的
// capacity_awaken 迁移事件(design/14 §4),使调用方能把
// 「能力点亮」的进展浮出到前端。为 nil = 空操作。
OnCapacity func(capacity.Event)
// OnAudit 非 nil 时,循环每次在受限(群聊/陌生人)环境中
// 拒绝工具调用都会收到一个 AuditEvent(design/11 §3 §8),
// 使该拒绝进入审计轨迹,且前端可以渲染
// 「xx 工具在群聊被拒」的小字。为 nil 时该拒绝仍会
// 作为软 not_allowed 结果回灌给模型,只是不记录到外部 sink。
OnAudit func(AuditEvent)
// OnTurnEnd 非 nil 时,每个已落定的 turn(返回了 Result 的
// Run)调用一次,携带该 turn 的用户/assistant 文本以及循环
// 绑定的角色,使调用方能推进紧随人格的状态 ——
// design/01 §2 的情绪机与好感度曲线。其返回值
// 记录在 Result.Mood 上并带到持久化的 assistant 消息。
// 为 nil = 循环不上报任何东西,Result.Mood 保持为空。
OnTurnEnd TurnEndHook
// Memory 是用于持久化提取出的条目的长期记忆 store。
Memory *memory.Store
// Retriever 把相关记忆注入上下文,每轮重新评估
//(见 assembleContext),使检索跟上最新对话。
Retriever *memory.Retriever
// WorkingMemory 是每会话滑动窗口,供
// orchestrator 查看;循环不改写它。
WorkingMemory *memory.WorkingMemory
// Extractor 在每一步之后导出要持久化的记忆条目。
Extractor memory.Extractor
// Checkpoint 在每一步持久化循环状态的持久快照,并在之后
// 同一 sessionID 的 Run 中据此恢复被中断的 run
//(design §1 durable execution)。*persist.Store 满足这个窄
// checkpointStore 接口;为 nil 时同时关闭持久化与恢复。
Checkpoint checkpointStore
// Tracer 为每一步、每次 LLM 调用与每次工具调用发出结构化 span。
Tracer *trace.Tracer
// Flow 非 nil 时,把 run 的 trace span 累积成每会话
// flow 图,并在每次 span 迁移时发布 ws.graph_update(design/19
// §1)。为 nil 时关闭实时 flow 可视化。
Flow *FlowPublisher
// Guards 在流式路径上校验请求/响应载荷 —— 该路径
// 绕过了 RunStep。非流式路径上由 agent 在 RunStep 内部
// 运行自己的护栏。
Guards *guardrail.Pipeline
// PersonaID 是循环配置的角色:没有显式 SessionEnv.PersonaID 的
// 每个 turn 都作为它运行(design/22 §2 裁决规则 4)。它
// 界定记忆检索与提取、系统提示词回退以及
// 情绪钩子的作用域。为空则跳过记忆注入/提取。
PersonaID string
// PersonaName 非 nil 时,为上下文的发言人归属把角色 id
// 解析为其显示名(design/22 §7-5):角色声明与
// 边界说明把发言角色称作 "「昔涟」(xilian)" 而不是裸 id,
// 使模型无需自备查表就能跟进「谁说的」。未知角色、
// 空名或 nil 解析器都回退到 id —— 归属绝不
// 因为名字无法解析而消失。
PersonaName func(personaID string) string
// PersonaKnobs 非 nil 时,在每次请求构建开始时为角色
// 解析推理旋钮(design/22 §4.2),使绑定到角色 Y 的会话
// 使用 Y 的思考预算 / 强度 / 广播开关,而不是默认
// 角色的。返回的 ok=false 表示「角色未知」并保持循环
// 配置的默认值(Options.Thinking / ReasoningEffort / ThinkingShowToUser)。
// 经角色 id 解析 —— 而非由调用方按 turn 传值 ——
// 正是让所有路径(gateway、channelbridge、backthink、子代理)都由单一
// 输入落到正确角色旋钮的原因。为 nil 时每个 turn 都保持配置的
// 默认值,即多角色之前的行为。
PersonaKnobs func(personaID string) (LoopKnobs, bool)
// Timezone 是用于渲染每轮「当前时间」系统消息的 IANA
// 时区(如 "Asia/Shanghai")。为空则完全关闭时间注入
// (向后兼容);加载失败的名字同样关闭它。
Timezone string
// MaxRounds 是工具循环上限。非正时选用
// DefaultMaxRounds(8)。
MaxRounds int
// OnStream 非 nil 时把循环切换到流式路径:直接驱动模型
// adapter 的 ChatStream,每个结构化流事件都转发到
// 该回调(model.StreamEvent),使前端能独立渲染
// 正文文本、工具调用以及(最终)推理分段。
OnStream func(model.StreamEvent)
// Thinking 携带注入循环构建的每个模型请求的推理旋钮
//(预算 / 显式开关),在没有按角色取值覆盖它时生效。
// nil 表示「不干预」,即既有行为。它是
// 角色没有解析出旋钮的 turn 的默认值(Options.PersonaKnobs)。
Thinking *model.Thinking
// ReasoningEffort 是注入每个模型请求的兼容 OpenAI 的
// 强度旋钮。为空表示「不干预」。
ReasoningEffort string
// ThinkingShowToUser 控制循环广播的思考帧:nil(默认)
// 保持既有行为并推送它们;显式 false
// 把 thinking_start/delta/end 挡在客户端流之外,而文本与工具
// 帧不受影响。这些帧仍被产出并仍抵达
// 模型/transcript 路径 —— 只有 UI 广播被门控,因此展示与
// 持久化保持解耦(design/04 §3.2)。
ThinkingShowToUser *bool
// ToolExecution 选择一批工具调用如何运行:"parallel"(
// 默认)或 "sequential"。为空表示并行。
ToolExecution string
// ToolParallelism 限制 ToolExecution 为 "parallel" 时并发
// 运行的工调用数。非正时选用 DefaultToolParallelism(4)。
ToolParallelism int
// Hooks 安装可选的按批次/按调用的工具循环钩子。每个字段都
// 容忍 nil;这些保留给「敏感操作代审」(design/11)以及
// 未来的异步工具路径。零值 Hooks 为空操作。
Hooks ToolLoopHooks
// MaxContextTokens 是触发溢出压缩的上下文预算。
// 非正(零值)关闭压缩,保持循环
// 此前的行为。设为正值(如
// DefaultMaxContextTokens)则启用压缩:循环的估算
// 上下文超出预算时,它把更早的轮次摘要成一条前导摘要
// 消息,同时保持近期尾部(含尾部工具结果)
// 完整(design §1.3)。容忍 nil:不设置它不改变任何行为。
MaxContextTokens int
// Compactor 压缩超预算的对话。nil 选用内置的
// 结构化 compactor(不调模型);非 nil 值让调用方注入
// LLM 支持的或自定义的摘要器。它仅在
// MaxContextTokens 为正时被调用。
Compactor Compactor
// Vision 非 nil 时,在 Run 开始时改写携带图像的用户消息,
// 使主模型能对图像进行推理(design/06 §0)。具体
// resolver(vision.MessageResolver)通过 vision Router 决定
// 是保留图像给支持视觉的主模型,还是折叠为
// vision/OCR 工具产出的文字描述("先看图再对话")。为 nil 时
// 图像内容原样保留,直接透传给支持视觉的主模型。
Vision ImageResolver
// TransformContext 非 nil 时,在每个模型步之前立即被调用,
// 传入组装好的消息列表(记忆注入与任何压缩
// 之后)以及当前轮次号(从 1 开始)。它可以投影、过滤
// 或重排模型所见的消息。它是循环中与
// OpenClaw 的 transformContext 等价之物(design §1.3)。为 nil = 不做投影。
TransformContext func(ctx context.Context, messages []model.Message, round int) []model.Message
// Log 是基础 logger。为 nil 时替换为标记来源
// "runtime/loop" 的丢弃 logger。
Log *slog.Logger
}