diff --git a/internal/intentgate/gate.go b/internal/intentgate/gate.go index 81f8ec5..68e04d7 100644 --- a/internal/intentgate/gate.go +++ b/internal/intentgate/gate.go @@ -26,9 +26,25 @@ type MatchResult struct { Missing []SlotQuestion // Commands 是库层展开的命令列表(I1);Router 消费它做唯一裁决。 // guard_hit/expectation_hit 被折叠为 fallback 时为空。 - Commands []agentintent.Command + Commands []Command } +// 命令类型经闸门投影(别名):生态库按边界规则只许本包导入, +// Router/runmgr 等消费方只依赖本包表面。 +type ( + Command = agentintent.Command + ActionRef = agentintent.ActionRef +) + +const ( + CommandStart = agentintent.CommandStart + ActionAuto = agentintent.ActionAuto + ActionCommand = agentintent.ActionCommand + ActionWorkflow = agentintent.ActionWorkflow + ActionBlueprint = agentintent.ActionBlueprint + ActionHandler = agentintent.ActionHandler +) + type Gate struct { mu sync.RWMutex reg *agentintent.Registry diff --git a/internal/route/route.go b/internal/route/route.go index 4b5347f..2d12269 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -19,8 +19,6 @@ package route import ( - agentintent "agent-intent/intent" - "agent-system-backend/internal/intentgate" core "agent-system-core" ) @@ -64,14 +62,14 @@ func Decide(res intentgate.MatchResult, env Env) Decision { if res.Branch != "matched" { return d } - var start *agentintent.Command + var start *intentgate.Command for i := range res.Commands { - if res.Commands[i].Kind == agentintent.CommandStart { + if res.Commands[i].Kind == intentgate.CommandStart { start = &res.Commands[i] break } } - action := agentintent.ActionRef{Kind: agentintent.ActionAuto, ID: res.ID} + action := intentgate.ActionRef{Kind: intentgate.ActionAuto, ID: res.ID} if start != nil { d.StartFound = true action = start.Action @@ -80,13 +78,13 @@ func Decide(res intentgate.MatchResult, env Env) Decision { } } switch action.Kind { - case agentintent.ActionCommand: + case intentgate.ActionCommand: if env.HasCommand != nil && env.HasCommand(action.ID) { d.Kind, d.CommandID = KindCommand, action.ID return d } d.Reason = "声明的命令不存在:" + action.ID - case agentintent.ActionWorkflow: + case intentgate.ActionWorkflow: if env.WorkflowFor != nil { if def, ok := env.WorkflowFor(action.ID); ok { d.Kind, d.Workflow = KindWorkflow, def @@ -94,7 +92,7 @@ func Decide(res intentgate.MatchResult, env Env) Decision { } } d.Reason = "声明的工作流未注册:" + action.ID - case agentintent.ActionBlueprint: + case intentgate.ActionBlueprint: if env.SquadReady { d.Kind, d.Blueprint = KindSquad, action.ID return d diff --git a/internal/route/route_test.go b/internal/route/route_test.go index cb2913d..8c66a9c 100644 --- a/internal/route/route_test.go +++ b/internal/route/route_test.go @@ -3,19 +3,17 @@ package route import ( "testing" - agentintent "agent-intent/intent" - - "agent-system-backend/internal/intentgate" + "agent-system-backend/internal/intentgate" core "agent-system-core" ) -func startCmd(action agentintent.ActionRef) agentintent.Command { - return agentintent.Command{Kind: agentintent.CommandStart, Action: action} +func startCmd(action intentgate.ActionRef) intentgate.Command { + return intentgate.Command{Kind: intentgate.CommandStart, Action: action} } func TestDecideAutoPrefersCommandThenWorkflow(t *testing.T) { in := intentgate.MatchResult{Branch: "matched", ID: "demo.x", - Commands: []agentintent.Command{startCmd(agentintent.ActionRef{Kind: agentintent.ActionAuto, ID: "demo.x"})}} + Commands: []intentgate.Command{startCmd(intentgate.ActionRef{Kind: intentgate.ActionAuto, ID: "demo.x"})}} d := Decide(in, Env{HasCommand: func(string) bool { return true }}) if d.Kind != KindCommand || d.CommandID != "demo.x" { t.Fatalf("auto command = %+v", d) @@ -36,26 +34,26 @@ func TestDecideAutoPrefersCommandThenWorkflow(t *testing.T) { func TestDecideExplicitKinds(t *testing.T) { mk := func(kind, id string) intentgate.MatchResult { return intentgate.MatchResult{Branch: "matched", ID: "demo.x", - Commands: []agentintent.Command{startCmd(agentintent.ActionRef{Kind: kind, ID: id})}} + Commands: []intentgate.Command{startCmd(intentgate.ActionRef{Kind: kind, ID: id})}} } - if d := Decide(mk(agentintent.ActionCommand, "cmd-1"), Env{HasCommand: func(id string) bool { return id == "cmd-1" }}); d.Kind != KindCommand || d.CommandID != "cmd-1" { + if d := Decide(mk(intentgate.ActionCommand, "cmd-1"), Env{HasCommand: func(id string) bool { return id == "cmd-1" }}); d.Kind != KindCommand || d.CommandID != "cmd-1" { t.Fatalf("explicit command = %+v", d) } - d := Decide(mk(agentintent.ActionCommand, "nope"), Env{ + d := Decide(mk(intentgate.ActionCommand, "nope"), Env{ WorkflowFor: func(string) (core.WorkflowDef, bool) { return core.WorkflowDef{ID: "wf"}, true }, }) if d.Kind != KindTurn || d.Reason == "" { t.Fatalf("unresolvable command = %+v", d) } - if d := Decide(mk(agentintent.ActionWorkflow, "wf-1"), Env{ + if d := Decide(mk(intentgate.ActionWorkflow, "wf-1"), Env{ WorkflowFor: func(id string) (core.WorkflowDef, bool) { return core.WorkflowDef{ID: id}, true }, }); d.Kind != KindWorkflow || d.Workflow.ID != "wf-1" { t.Fatalf("explicit workflow = %+v", d) } - if d := Decide(mk(agentintent.ActionBlueprint, "bp-1"), Env{SquadReady: true}); d.Kind != KindSquad || d.Blueprint != "bp-1" { + if d := Decide(mk(intentgate.ActionBlueprint, "bp-1"), Env{SquadReady: true}); d.Kind != KindSquad || d.Blueprint != "bp-1" { t.Fatalf("blueprint = %+v", d) } - if d := Decide(mk(agentintent.ActionBlueprint, "bp-1"), Env{}); d.Kind != KindTurn || d.Reason == "" { + if d := Decide(mk(intentgate.ActionBlueprint, "bp-1"), Env{}); d.Kind != KindTurn || d.Reason == "" { t.Fatalf("blueprint without squad = %+v", d) } } @@ -73,9 +71,9 @@ func TestDecideNonMatchedAndLegacyFallback(t *testing.T) { func TestSlotsFromStartCommand(t *testing.T) { in := intentgate.MatchResult{Branch: "matched", ID: "demo.x", - Commands: []agentintent.Command{{ - Kind: agentintent.CommandStart, - Action: agentintent.ActionRef{Kind: agentintent.ActionAuto, ID: "demo.x"}, + Commands: []intentgate.Command{{ + Kind: intentgate.CommandStart, + Action: intentgate.ActionRef{Kind: intentgate.ActionAuto, ID: "demo.x"}, Slots: map[string]string{"topic": "电机"}, }}} d := Decide(in, Env{HasCommand: func(string) bool { return true }})