Details (original message): Integrate the agent-intent gate: plugin intent overlays rebuild the registry (fail-closed, keeps previous snapshot), HITL free-input pivots on matched foreign intents; unit and e2e tests; pin logging-system and error-code-system submodules.
68 lines
1.9 KiB
Go
68 lines
1.9 KiB
Go
package intentgate
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"testing"
|
|
)
|
|
|
|
func raw(t *testing.T, v any) json.RawMessage {
|
|
t.Helper()
|
|
b, err := json.Marshal(v)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return b
|
|
}
|
|
|
|
// spec 采用 agent-intent overlay 形态(matcher 嵌套)。
|
|
func demoSpec(t *testing.T) json.RawMessage {
|
|
return raw(t, map[string]any{
|
|
"id": "demo.show", "domain": "demo", "version": 1,
|
|
"description": "示例意图",
|
|
"matcher": map[string]any{"includes_any": []string{"示例", "演示"}},
|
|
})
|
|
}
|
|
|
|
func TestGateMatchAndFallback(t *testing.T) {
|
|
g := New()
|
|
if _, id := g.Match(context.Background(), "任意"); id != "" || g.Enabled() {
|
|
t.Error("empty gate should passthrough")
|
|
}
|
|
if err := g.Rebuild(context.Background(), []json.RawMessage{demoSpec(t)}); err != nil {
|
|
t.Fatalf("rebuild: %v", err)
|
|
}
|
|
if !g.Enabled() || g.SpecCount() != 1 {
|
|
t.Fatalf("enabled=%v specs=%d", g.Enabled(), g.SpecCount())
|
|
}
|
|
branch, top := g.Match(context.Background(), "来个示例看看")
|
|
if branch != "matched" || top != "demo.show" {
|
|
t.Errorf("want matched/demo_intent, got %s/%s", branch, top)
|
|
}
|
|
branch, _ = g.Match(context.Background(), "完全无关的一句话")
|
|
if branch != "fallback" {
|
|
t.Errorf("want fallback, got %s", branch)
|
|
}
|
|
}
|
|
|
|
// fail-closed:坏 spec 保留上一快照。
|
|
func TestGateFailClosed(t *testing.T) {
|
|
g := New()
|
|
if err := g.Rebuild(context.Background(), []json.RawMessage{demoSpec(t)}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := g.Rebuild(context.Background(), []json.RawMessage{json.RawMessage(`{"id":`)}); err == nil {
|
|
t.Error("broken spec should error")
|
|
}
|
|
if !g.Enabled() || g.SpecCount() != 1 {
|
|
t.Error("previous snapshot must be kept on failed rebuild")
|
|
}
|
|
// 空重建 = 显式清空(卸载全部插件意图)。
|
|
if err := g.Rebuild(context.Background(), nil); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if g.Enabled() {
|
|
t.Error("empty rebuild should disable gate")
|
|
}
|
|
}
|