Unify agent topology and subagent memory logging

This commit is contained in:
lpf
2026-03-06 15:14:58 +08:00
parent 86691f75d0
commit cc04d9ab3a
27 changed files with 1408 additions and 791 deletions

View File

@@ -108,106 +108,6 @@ func TestHandleSubagentRuntimeUpsertConfigSubagent(t *testing.T) {
}
}
func TestHandleSubagentRuntimeDraftConfigSubagent(t *testing.T) {
manager := tools.NewSubagentManager(nil, t.TempDir(), nil, nil)
loop := &AgentLoop{
subagentManager: manager,
subagentRouter: tools.NewSubagentRouter(manager),
}
out, err := loop.HandleSubagentRuntime(context.Background(), "draft_config_subagent", map[string]interface{}{
"description": "创建一个负责回归测试和验证修复结果的子代理",
})
if err != nil {
t.Fatalf("draft config subagent failed: %v", err)
}
payload, ok := out.(map[string]interface{})
if !ok {
t.Fatalf("unexpected payload type: %T", out)
}
draft, ok := payload["draft"].(map[string]interface{})
if !ok {
t.Fatalf("expected draft payload, got %#v", payload["draft"])
}
if draft["role"] == "" || draft["agent_id"] == "" {
t.Fatalf("expected draft role and agent_id, got %#v", draft)
}
}
func TestHandleSubagentRuntimePendingDraftsAndClear(t *testing.T) {
manager := tools.NewSubagentManager(nil, t.TempDir(), nil, nil)
loop := &AgentLoop{
subagentManager: manager,
subagentRouter: tools.NewSubagentRouter(manager),
pendingSubagentDraft: map[string]map[string]interface{}{"main": {"agent_id": "tester", "role": "testing"}},
}
out, err := loop.HandleSubagentRuntime(context.Background(), "pending_drafts", nil)
if err != nil {
t.Fatalf("pending drafts failed: %v", err)
}
payload, ok := out.(map[string]interface{})
if !ok {
t.Fatalf("unexpected payload type: %T", out)
}
items, ok := payload["items"].([]map[string]interface{})
if !ok || len(items) != 1 {
t.Fatalf("expected one pending draft, got %#v", payload["items"])
}
out, err = loop.HandleSubagentRuntime(context.Background(), "clear_pending_draft", map[string]interface{}{"session_key": "main"})
if err != nil {
t.Fatalf("clear pending draft failed: %v", err)
}
payload, ok = out.(map[string]interface{})
if !ok || payload["ok"] != true {
t.Fatalf("unexpected clear payload: %#v", out)
}
if loop.loadPendingSubagentDraft("main") != nil {
t.Fatalf("expected pending draft to be cleared")
}
}
func TestHandleSubagentRuntimeConfirmPendingDraft(t *testing.T) {
workspace := t.TempDir()
configPath := filepath.Join(workspace, "config.json")
cfg := config.DefaultConfig()
cfg.Agents.Router.Enabled = true
cfg.Agents.Subagents["main"] = config.SubagentConfig{
Enabled: true,
Type: "router",
Role: "orchestrator",
SystemPromptFile: "agents/main/AGENT.md",
}
if err := config.SaveConfig(configPath, cfg); err != nil {
t.Fatalf("save config failed: %v", err)
}
runtimecfg.Set(cfg)
t.Cleanup(func() { runtimecfg.Set(config.DefaultConfig()) })
manager := tools.NewSubagentManager(nil, workspace, nil, nil)
loop := &AgentLoop{
configPath: configPath,
subagentManager: manager,
subagentRouter: tools.NewSubagentRouter(manager),
pendingSubagentDraft: map[string]map[string]interface{}{"main": {"agent_id": "tester", "role": "testing", "type": "worker", "system_prompt_file": "agents/tester/AGENT.md"}},
}
out, err := loop.HandleSubagentRuntime(context.Background(), "confirm_pending_draft", map[string]interface{}{"session_key": "main"})
if err != nil {
t.Fatalf("confirm pending draft failed: %v", err)
}
payload, ok := out.(map[string]interface{})
if !ok || payload["ok"] != true {
t.Fatalf("unexpected confirm payload: %#v", out)
}
reloaded, err := config.LoadConfig(configPath)
if err != nil {
t.Fatalf("reload config failed: %v", err)
}
if _, ok := reloaded.Agents.Subagents["tester"]; !ok {
t.Fatalf("expected tester subagent to be persisted")
}
}
func TestHandleSubagentRuntimeRegistryAndToggleEnabled(t *testing.T) {
workspace := t.TempDir()
configPath := filepath.Join(workspace, "config.json")