Files
Agent-System-Backend/internal/app/compiled_list_test.go
T
weichen 62bfc6068a
ci / vet-and-test (pull_request) Successful in 46s
Declare admin-zone sections from compiled plugins (surface 2.9.0)
Why: the admin zone could not host plugin-declared partitions - KTD4
requires the RDM audit partition to be reachable by RDM domain admins and
base superadmins without hardcoding RDM into the base AdminZone.
Evidence: go test ./internal/app ./internal/server ./pkg/extension green
incl. new admin-zone recording/endpoint tests; surface snapshot test
green after surface.txt update; CI (Dev composite) is authoritative.
Impact: extension surface 2.8.0 -> 2.9.0 (Registry.AddAdminZone +
AdminZoneSpec, fail-closed on invalid specs); applyCompiled records
declarations into the plugin summary; new authenticated GET
/api/admin-zone/sections returns the flattened, ordered declaration list.
Entry visibility stays metadata-only - data capability remains enforced
by each section's own command surface (fail-closed).
Refs: WP3-I3/KTD4; task card feature-adminzone-plugin-sections.
2026-10-12 02:28:51 +00:00

93 lines
3.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package app
import (
"context"
"encoding/json"
"path/filepath"
"testing"
"time"
agentcommand "agent-command"
"agent-system-backend/internal/cmdbus"
"agent-system-backend/internal/settings"
"agent-system-backend/internal/store"
"agent-system-backend/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)
}
}