- 四组并行完成: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 全过)。
51 lines
2.4 KiB
Go
51 lines
2.4 KiB
Go
package main
|
||
|
||
import (
|
||
"time"
|
||
|
||
"git.yeij.top/AskaEth/Cyrene_v2/internal/logger"
|
||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/orchestration"
|
||
)
|
||
|
||
// defaultSubagentTimeout 在别处都未配置时,约束单个子代理的整轮运行。
|
||
// DevDocs/design/05-子代理.md §7 要求有超时与防失控上限;调度器两者都已实现
|
||
// (PerAgentTimeout、Abort/CancelAll),因此生产必须给出一个值,否则每代理超时
|
||
// 形同虚设(调度器里的 0 表示「无超时」)。该值刻意给得宽松 —— 子代理与任何循环
|
||
// 一样最多跑 8 轮工具 —— 并且是 SUBAGENT_TIMEOUT_SEC 之后的兜底(裁决 02.4.4:
|
||
// 默认 10min,可配置;subagentToolTimeout 解析出生效值)。
|
||
const defaultSubagentTimeout = 10 * time.Minute
|
||
|
||
// subagentToolTimeout 解析分派工具的默认子代理超时:SUBAGENT_TIMEOUT_SEC 为正时
|
||
// 以它为准,否则采用代码里的 10 分钟默认值(design/05 §7 裁决 02.4.4)。每次分派
|
||
// 传入的 timeout_seconds 参数仍会在工具层按次覆盖此值。
|
||
func (a *app) subagentToolTimeout() time.Duration {
|
||
if a.cfg != nil && a.cfg.Subagent.TimeoutSec > 0 {
|
||
return time.Duration(a.cfg.Subagent.TimeoutSec) * time.Second
|
||
}
|
||
return defaultSubagentTimeout
|
||
}
|
||
|
||
// wireSubagentTool 向分发器注册子代理分派工具,让 agent 在运行时终于能触达编排层
|
||
// (在此之前 (*orchestration.Scheduler).Spawn 没有生产调用方,design/05 只是库)。
|
||
//
|
||
// 该能力以默认的可达性标记(两者皆 false)注册,从而保持仅主人可用:design/11 §3 的
|
||
// 策略引擎会对群聊/陌生人会话隐藏其 schema,循环的安全门也会在那里拒绝调用。
|
||
// design/05 §6/§7 未给群聊/陌生人分派后台 agent 的许可,且能生成子代理属于重操作,
|
||
// 因此刻意选择安全默认值,而不是让它被意外开启。
|
||
func (a *app) wireSubagentTool() {
|
||
log := logger.WithSource(a.log, "cmd/cyrene")
|
||
if a.scheduler == nil {
|
||
log.Warn("sub-agent tool skipped: no scheduler")
|
||
return
|
||
}
|
||
spawner := orchestration.NewSpawnTool(a.scheduler,
|
||
orchestration.WithSpawnLogger(a.log),
|
||
orchestration.WithSpawnTimeout(a.subagentToolTimeout()))
|
||
if err := a.dispatcher.Register(spawner); err != nil {
|
||
log.Warn("sub-agent tool register skipped", "error", err)
|
||
return
|
||
}
|
||
log.Info("sub-agent tool registered", "tool", orchestration.SpawnToolName,
|
||
"owner_only", true)
|
||
}
|