mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-10-04 00:03:59 +00:00
fix(scheduler)!: 撤掉“优先级=可配置策略表”的错误设计,回归内核内部属性
用户指正:**优先级是内核内部属性**,不是配置项,更不该由插件声明。 我此前把它建模成“策略表 + 字符串解析”,甚至准备接配置中心 (core.agent.priority.<channel>)——方向性错误,故整体撤销。 撤销: - 删除 ParseLevel(字符串解析只服务于“外部可配”这个错误前提) - 删除 AgentConfig.PriorityLookup / Agent.priorityLookup 及 taskLevel 中的查表分支; taskLevel 回归为纯内核内部规则(cli/webui/http→L3,system/_consolidation_→L1, 其余 L1),注释明确“不对外暴露、不做运维可调项” - 设计稿 §3.2 改写为“内核内部属性,不做成配置项”,并删除 §15 里 “ChannelDef.Priority / InjectOptions.Priority 进公开 SDK”这一方向(同属外化) - 未触碰配置中心(registry.go/main.go 的优先级配置一行未加) 同时落地 D6(与本撤销无关、此前遗漏的承诺): - AgentConfig.MaxToolTurns + runTaskSteps 在发起新一轮 LLM 前按 f.Turn 收尾; 0 = 不限;cmd/homed/main.go 从既有 core.agent.max_tool_turns 取值 - 新增 task_test.go 2 项:上限 3 时恰好跑 3 批工具/3 次 LLM 并收尾; 0 = 不限(跑完脚本) 验收:agent 全量 + -race;全仓 build/vet 通过
This commit is contained in:
@ -165,3 +165,74 @@ func TestTaskFrame_UnknownStepFails(t *testing.T) {
|
||||
t.Fatal("未知 step 必须带错误信息")
|
||||
}
|
||||
}
|
||||
|
||||
// D6:工具轮次硬上限——模型不停调用工具时,必须在有限步内收尾。
|
||||
//
|
||||
// 这是审查里定位的 P0(core.agent.max_tool_turns 只定义、从没被读过),
|
||||
// 也是调度器的前提:任务必须可终止。
|
||||
func TestMaxToolTurns_CapsRunawayLoop(t *testing.T) {
|
||||
sh := NewStageHost()
|
||||
sh.RegisterTool("t_loop", sdk.ToolDef{Name: "t_loop", Plugin: "t"}, func(args map[string]interface{}) (interface{}, error) {
|
||||
return "again", nil
|
||||
})
|
||||
|
||||
// 脚本远长于上限:provider 每轮都给下一批工具调用,模拟“永不停止”。
|
||||
script := make([]*agentAPI.CompletionResponse, 0, 20)
|
||||
for i := 0; i < 20; i++ {
|
||||
script = append(script, &agentAPI.CompletionResponse{
|
||||
Content: "继续",
|
||||
ToolCalls: []agentAPI.ToolCall{tc("c1", "t_loop")},
|
||||
})
|
||||
}
|
||||
sp := &scriptProvider{script: script}
|
||||
a := New(AgentConfig{
|
||||
ID: "cap",
|
||||
Provider: sp,
|
||||
ProviderManager: agentAPI.NewProviderManager(),
|
||||
IO: agentIO.NewIOManager(),
|
||||
StageHost: sh,
|
||||
MaxToolTurns: 3,
|
||||
})
|
||||
|
||||
resp, toolsUsed, toolResults, err := a.process("循环", a.stageCtxFromInput("循环", "", ""))
|
||||
if err != nil {
|
||||
t.Fatalf("process 返回错误: %v", err)
|
||||
}
|
||||
if len(toolsUsed) != 3 || len(toolResults) != 3 {
|
||||
t.Fatalf("工具批=%d/%d,期望恰好 3(到上限即止,不多跑第 4 轮)", len(toolsUsed), len(toolResults))
|
||||
}
|
||||
if len(sp.reqs) != 3 {
|
||||
t.Fatalf("LLM 调用=%d,期望 3(上限后不再发起新请求)", len(sp.reqs))
|
||||
}
|
||||
if resp != "继续" {
|
||||
t.Fatalf("响应=%q,期望返回最近一次 LLM 文本", resp)
|
||||
}
|
||||
}
|
||||
|
||||
// 上限为 0 表示不限(显式退出机制)。
|
||||
func TestMaxToolTurns_ZeroMeansUnlimited(t *testing.T) {
|
||||
sh := NewStageHost()
|
||||
sh.RegisterTool("t_loop", sdk.ToolDef{Name: "t_loop", Plugin: "t"}, func(args map[string]interface{}) (interface{}, error) {
|
||||
return "again", nil
|
||||
})
|
||||
sp := &scriptProvider{script: []*agentAPI.CompletionResponse{
|
||||
{Content: "a", ToolCalls: []agentAPI.ToolCall{tc("c1", "t_loop")}},
|
||||
{Content: "b", ToolCalls: []agentAPI.ToolCall{tc("c2", "t_loop")}},
|
||||
{Content: "c"},
|
||||
}}
|
||||
a := New(AgentConfig{
|
||||
ID: "nocap",
|
||||
Provider: sp,
|
||||
ProviderManager: agentAPI.NewProviderManager(),
|
||||
IO: agentIO.NewIOManager(),
|
||||
StageHost: sh,
|
||||
MaxToolTurns: 0,
|
||||
})
|
||||
resp, toolsUsed, _, err := a.process("x", a.stageCtxFromInput("x", "", ""))
|
||||
if err != nil {
|
||||
t.Fatalf("process 返回错误: %v", err)
|
||||
}
|
||||
if len(toolsUsed) != 2 || resp != "c" {
|
||||
t.Fatalf("不限时应跑完脚本:tools=%d resp=%q", len(toolsUsed), resp)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user