package app import ( "context" "encoding/json" "path/filepath" "testing" "time" agentcommand "git-ssh.u1680832.nyat.app/weichen/Agent-Command.git" "git-ssh.u1680832.nyat.app/weichen/Agent-System-Backend.git/internal/cmdbus" "git-ssh.u1680832.nyat.app/weichen/Agent-System-Backend.git/internal/settings" "git-ssh.u1680832.nyat.app/weichen/Agent-System-Backend.git/internal/store" "git-ssh.u1680832.nyat.app/weichen/Agent-System-Backend.git/pkg/extension" ) // WP3-I4:applyCompiled 的注册面摘要——成功注册的命令/意图/技能记入 // CompiledPlugin,失败注册不记录,Register 整体失败保留已成功部分。 func TestApplyCompiledRecordsSummary(t *testing.T) { extension.ResetCompiled() t.Cleanup(extension.ResetCompiled) extension.RegisterCompiled(extension.InProc{ID: "demo", Register: func(reg extension.Registry) error { if err := reg.AddCommandHandler(json.RawMessage(`{"id":"demo.one","title":"一"}`), func(ctx context.Context, h extension.Host, req extension.Request) (any, error) { return "ok", nil }); err != nil { return err } // 重复 id 注册失败:总线拒绝,摘要不记录。 if err := reg.AddCommand(json.RawMessage(`{"id":"demo.one","title":"重复"}`)); err == nil { t.Fatal("duplicate command should fail") } if err := reg.AddIntent(json.RawMessage(`{"id":"demo.go","phrases":["演示"],"command":"demo.one"}`)); err != nil { return err } _ = reg.AddSkill("demo-skill", "# 演示\n技能正文") // WP3-I3:管理区分区声明记入摘要;缺 id/title 的非法规格 fail-closed。 if err := reg.AddAdminZone(json.RawMessage(`{"id":"demo.audit","title":"演示审计","icon":"search","order":20}`)); err != nil { return err } if err := reg.AddAdminZone(json.RawMessage(`{"title":"缺 id"}`)); err == nil { t.Fatal("admin zone without id should fail") } return nil }}) extension.RegisterCompiled(extension.InProc{ID: "broken", Register: func(reg extension.Registry) error { if err := reg.AddCommand(json.RawMessage(`{"id":"broken.cmd","title":"先成功"}`)); err != nil { return err } return reg.AddCommandHandler(json.RawMessage(`not-json`), nil) }}) // 无 Register 的登记不产生条目。 extension.RegisterCompiled(extension.InProc{ID: "empty"}) st, err := store.OpenSQLite(filepath.Join(t.TempDir(), "test.db")) if err != nil { t.Fatal(err) } t.Cleanup(func() { st.Close() }) bus := cmdbus.New(st, nil, func() time.Time { return time.Unix(1700000000, 0).UTC() }) sums := applyCompiled(t.TempDir(), bus, hostcaps{st: st, set: settings.NewService(st)}) if len(sums) != 2 { t.Fatalf("want 2 summaries, got %d: %+v", len(sums), sums) } if sums[0].ID != "demo" { t.Fatalf("sums[0] = %+v", sums[0]) } if len(sums[0].Commands) != 1 || sums[0].Commands[0] != "demo.one" { t.Fatalf("demo commands = %v", sums[0].Commands) } if len(sums[0].Intents) != 1 || sums[0].Intents[0] != "demo.go" { t.Fatalf("demo intents = %v", sums[0].Intents) } if len(sums[0].Skills) != 1 || sums[0].Skills[0] != "demo-skill" { t.Fatalf("demo skills = %v", sums[0].Skills) } // WP3-I3:合法声明记入,非法规格(缺 id)被拒后摘要不受污染。 if len(sums[0].AdminZones) != 1 { t.Fatalf("demo admin zones = %+v", sums[0].AdminZones) } if z := sums[0].AdminZones[0]; z.ID != "demo.audit" || z.Title != "演示审计" || z.Icon != "search" || z.Order != 20 { t.Fatalf("demo admin zone = %+v", z) } // broken:Register 报错但先成功的命令仍在总线,摘要如实保留。 if sums[1].ID != "broken" || len(sums[1].Commands) != 1 || sums[1].Commands[0] != "broken.cmd" { t.Fatalf("broken summary = %+v", sums[1]) } // 摘要与总线一致:记录的命令真实可分发(不是空头衔)。 resp := bus.Dispatch(context.Background(), cmdbus.Request{ID: "demo.one", Owner: "alice", Entrance: "test"}) if resp.Receipt.State != agentcommand.StateCommitted { t.Fatalf("demo.one dispatch = %s (%s)", resp.Receipt.State, resp.Receipt.Reason) } }