feat: AutoZero 通用 Agent 框架(从 AutoGo 五阶段拆分完成)

llm(三协议 Provider)/ session(JSONL 持久化)/ tools(Registry、围栏、
builtin、computer)/ cdp(browser)/ skills / mcp / agent(循环、两级压缩、
编排、审批门控)+ 底座 jsonl/textx/execx/diag/scratch/spill/imagecache。

产品装配代码(config 桥接、schedule 工具、memory/plan/retro/prompt)
留在 AutoGo,宿主接入方式见 MIGRATION.md。
This commit is contained in:
Sakurasan committed 2026-10-26 00:54:46 +08:00
commit d5dac5a6fc
140 files changed
+26497

No files matched your search

+72
View File
@@ -0,0 +1,72 @@
// 模型预设路由(config 的 fallback_model / multimodal_model):
// - 含图回合临时切到多模态模型,回合结束恢复原模型——防"图片打到不支持
// 视觉的模型直接报错"(用户实报的痛点),事后恢复让普通回合仍走首选;
// - 调用失败回落备选模型,粘性切换(切过去就留着)——每回合都先撞一次
// 首选的失败再回落太浪费,粘到 /model 或配置显式切回为止。
//
// 两条都要求 provider 支持 ModelSwitcher + CurrentModeler:不知道现状就
// 不能安全地切换/恢复,宁可路由不生效也不盲切。provider 是共享单例,
// SetModel 与 /model 命令是同一机制、同一并发边界(见 llm 注释)。
package agent
import (
"context"
"errors"
"fmt"
"git.gopher.ink/mirrors2/AutoZero/llm"
)
// routeMultimodal 含图回合切到多模态模型;返回恢复函数(回合结束调用),
// 无需路由时返回 nil。
func (a *Agent) routeMultimodal(hasImages bool) func() {
if !hasImages || a.MultimodalModel == "" {
return nil
}
sw, ok := a.Provider.(llm.ModelSwitcher)
if !ok {
return nil
}
g, ok := a.Provider.(llm.CurrentModeler)
if !ok {
return nil
}
prev := g.CurrentModel()
if prev == a.MultimodalModel {
return nil // 已经在多模态模型上(可能是上一次回落),不必切
}
sw.SetModel(a.MultimodalModel)
if a.Opt.Stderr != nil {
fmt.Fprintf(a.Opt.Stderr, "[model] 本回合含图 → 多模态模型 %s(回合后恢复 %s)\n",
a.MultimodalModel, prev)
}
return func() { sw.SetModel(prev) }
}
// fallbackTo 本步调用失败时决定是否回落备选模型;回落则直接切换(粘性)
// 并返回 true,调用方应重试本步。
//
// 收窄条件(任一命中即不回落):未配置备选;ctx 已取消/超时(用户主动停
// 不重试);错误发生前已有增量文本流出(重试会在回复里叠加重复内容);
// 当前已经在备选模型上(防回环)。任意错误都回落是有意的:备选语义就是
// "首选挂了换人上",凭据错误时备选同样会失败,不会造成重试风暴。
func (a *Agent) fallbackTo(ctx context.Context, err error, streamed bool) bool {
if err == nil || a.FallbackModel == "" || streamed {
return false
}
if ctx.Err() != nil || errors.Is(err, context.Canceled) {
return false
}
sw, ok := a.Provider.(llm.ModelSwitcher)
if !ok {
return false
}
if g, ok := a.Provider.(llm.CurrentModeler); !ok || g.CurrentModel() == a.FallbackModel {
return false
}
sw.SetModel(a.FallbackModel)
if a.Opt.Stderr != nil {
fmt.Fprintf(a.Opt.Stderr, "[model] 调用失败(%v)→ 回落备选模型 %s 重试\n", err, a.FallbackModel)
}
return true
}