Files
Cyrene_v2/internal/runtime/orchestration/options.go
T
AskaEth eb1828ee7a
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
docs(comments): 注释中文化 · internal/runtime/orchestration(29 文件,纯替换)
- 只翻注释/文档字符串:剥离注释后代码行逐字节不变(机械校验只剩允许的行尾注释形态)
- 裁决编号与 design 节号(02.4.3 / 11.4.2 / design/05 §9 等)逐字保留
- 复核:go build 绿;orchestration 及其子包(audit/comm)测试绿;gofmt 干净
2026-10-04 13:30:04 +08:00

125 lines
5.2 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 orchestration
import (
"log/slog"
"time"
"git.yeij.top/AskaEth/Cyrene_v2/internal/bus"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/loop"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/memory"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/orchestration/audit"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/orchestration/comm"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/trace"
)
// 编排层的默认值。
const (
// DefaultMaxParallel 是 Options.MaxParallel 为非正数时同时运行的子代理
// 数量上限。
DefaultMaxParallel = 4
// defaultAgentID 是 Options.AgentID 为空、且必须由 Bus 构建探针时所用的
// comm 探针身份。
defaultAgentID = "orchestrator"
)
// Options 配置由 New 构建的 Scheduler。所有字段都可选;每个为 nil 的依赖都优雅
// 降级(缺 Loop 使子代理快速失败,缺 Comm 跳过进度事件,缺 Approver 使 Approve
// 报错,等等)。
type Options struct {
// MaxParallel 限制同时执行的子代理数量。超出的子代理排队直到有空位。
// 非正数则选用 DefaultMaxParallel(4)。
MaxParallel int
// PerAgentTimeout 约束每个子代理的运行时限。超时后该子代理被中止
// (状态 aborted)。非正数表示不设时限。
PerAgentTimeout time.Duration
// Loop 是执行模板:用于运行每个子代理的 *loop.Loop。它必须能安全地并发调用
// Run(如 loop.Loop 自身文档所述);模板的 agent/tools/guardrails/persona
// 适用于每个子代理。为 nil 时子代理以 ErrNoRunner 快速失败。
Loop *loop.Loop
// Bus 是进程内事件总线,用于发布进度事件;Comm 为 nil 时也由它构建默认
// comm 探针。为 nil 时不发布任何事件。
Bus bus.Bus
// Comm 是用于发布进度事件的 comm 探针。为 nil 时,用 Bus(Bus 非 nil 时)
// 构建一个绑定到 AgentID 的探针。
Comm *comm.Probe
// Memory 是 SinkMemory 所用的长期记忆存储。可选。
Memory *memory.Store
// Tracer 为每次运行发射一个子代理 span(kind subagent)。可选。
Tracer *trace.Tracer
// Flow 非 nil 时接收子代理 span 的状态转移,使派生出的分支出现在
// AgentSpec.ParentSession 所指会话的流程图里(design/19 §2)。
// *loop.FlowPublisher 是生产实现。可选:sink 为 nil 时子代理分支不被可视化
// (子代理自身的内部 span 仍会经循环的 flow 分支折进父图)。
Flow FlowSpanSink
// Approver 记录由 Approve 触发的敏感操作「代审」。策略判断属于上层。可选。
Approver *audit.Approver
// PersonaExists 报告某个角色 id 能否以自身指令运行,即 Loop 背后的按角色
// agent 池(loop.Options.Agents)里是否有它的条目(design/22 §8-2)。它把守
// AgentSpec.PersonaID:指名了一个它返回 false 的 id 的派发会被拒绝并返回
// ErrUnknownPersona,而不是按默认角色的提示词运行。为 nil 意味着「本部署不认识
// 任何角色」,因此指名角色的派发同样被拒 —— 关键是绝不悄悄替调用方做决定。
// 省略 persona 的派发不受它影响。
PersonaExists func(personaID string) bool
// Logger 是基础 logger。为 nil 时替换为标注了来源 "orchestration" 的
// 丢弃式 logger。
Logger *slog.Logger
// AgentID 是 comm 探针身份。为空且必须由 Bus 构建探针时,使用
// "orchestrator"。
AgentID string
}
// FlowSpanSink 把一个 span 的状态转移折进会话的实时流程图,使实时可视化展示在飞的
// 工作(design/19 §1)。*loop.FlowPublisher 是生产实现;测试替换为捕获式假实现。
// 该接口让编排层除了已有的循环模板之外,不必再依赖那个具体发布器。
type FlowSpanSink interface {
// SpanStarted 为一个刚刚开始的 span 登记运行中的占位节点。
SpanStarted(sessionID string, sp *trace.Span)
// SpanFinished 把一个刚结束的 span 折进会话图。
SpanFinished(sessionID string, sp *trace.Span)
}
// wrapLoop 把 *loop.Loop 适配成 runner 接口;模板为 nil 时替换为空操作 runner
// (快速失败)。
func wrapLoop(l *loop.Loop) runner {
if l == nil {
return noopRunner{}
}
return l
}
// scopedRunner 挑选执行 sub 的 runner:没有工具白名单时按原样运行已配置的模板
// (缺省全开,继承主 agent 全量工具集);有白名单时,为 *loop.Loop 模板经
// WithToolWhitelist 派生出只放行所列工具的新模板(design/05 §7 裁决 02.4.1)。
// 非 loop 的 runner(测试注入的 mock)原样返回 —— 白名单仍随运行上下文传递,它可经
// loop.ToolWhitelistFrom 自行读取。
func (s *Scheduler) scopedRunner(sub *SubAgent) runner {
if len(sub.ToolWhitelist) == 0 {
return s.runner
}
if lp, ok := s.runner.(*loop.Loop); ok {
return lp.WithToolWhitelist(sub.ToolWhitelist)
}
return s.runner
}
// effectiveTimeout 解析某个子代理运行时所受的时限:正的按调用覆盖优先;否则套用
// 调度器的 PerAgentTimeout(非正 = 无期限)。
func effectiveTimeout(override, schedulerDefault time.Duration) time.Duration {
if override > 0 {
return override
}
return schedulerDefault
}