From 7bdd462ed5cf82dc70b23b8e7b4ef56e792b4d5c Mon Sep 17 00:00:00 2001 From: mlogclub Date: Tue, 14 Apr 2026 10:43:26 +0800 Subject: [PATCH] feat: refactor agent factory to use AgentHandlerService and add buildInstructionTraceSummary helper --- .../internal/impl/factory/agent_factory.go | 52 +++++---------- .../impl/factory/agent_handler_service.go | 65 +++++++++++++++++++ .../internal/impl/factory/tool_helpers.go | 11 ++++ 3 files changed, 92 insertions(+), 36 deletions(-) create mode 100644 internal/ai/runtime/internal/impl/factory/agent_handler_service.go diff --git a/internal/ai/runtime/internal/impl/factory/agent_factory.go b/internal/ai/runtime/internal/impl/factory/agent_factory.go index fc6d8d1..fd93b14 100644 --- a/internal/ai/runtime/internal/impl/factory/agent_factory.go +++ b/internal/ai/runtime/internal/impl/factory/agent_factory.go @@ -9,10 +9,8 @@ import ( einocallbacks "cs-agent/internal/ai/runtime/internal/impl/callbacks" "cs-agent/internal/ai/runtime/registry" "cs-agent/internal/models" - "cs-agent/internal/pkg/toolx" "github.com/cloudwego/eino/adk" - einotoolsearch "github.com/cloudwego/eino/adk/middlewares/dynamictool/toolsearch" einobasetool "github.com/cloudwego/eino/components/tool" "github.com/cloudwego/eino/compose" ) @@ -21,7 +19,7 @@ type AgentFactory struct { chatModelFactory *ChatModelFactory toolFactory *ToolFactory instructionService *InstructionService - skillMiddleware *SkillMiddlewareService + handlerService *AgentHandlerService } // BuildCustomerServiceAgentInput 定义客服 Agent 的装配输入。 @@ -58,7 +56,7 @@ func NewAgentFactory() *AgentFactory { chatModelFactory: NewChatModelFactory(), toolFactory: NewToolFactory(), instructionService: NewInstructionService(nil, nil, nil, nil, nil), - skillMiddleware: NewSkillMiddlewareService(), + handlerService: NewAgentHandlerService(nil), } } @@ -77,40 +75,22 @@ func (f *AgentFactory) BuildCustomerServiceAgent(ctx context.Context, input Buil } allTools := make([]einobasetool.BaseTool, 0, len(input.StaticTools)) allTools = append(allTools, input.StaticTools...) - handlers := make([]adk.ChatModelAgentMiddleware, 0, 2) - if len(dynamicTools) > 0 { - toolSearchHandler, toolSearchErr := einotoolsearch.New(ctx, &einotoolsearch.Config{ - DynamicTools: dynamicTools, - }) - if toolSearchErr != nil { - return nil, toolSearchErr - } - handlers = append(handlers, toolSearchHandler) - } - if input.SelectedSkill != nil { - skillHandler, skillErr := f.skillMiddleware.Build(ctx, input.SelectedSkill, input.InstructionToolDefinitions) - if skillErr != nil { - return nil, skillErr - } - handlers = append(handlers, skillHandler) - } - if input.Collector != nil { - toolMetadataBy := buildRuntimeTraceToolMetadata(input.DynamicMCPToolDefinitions, input.StaticToolMetadata, input.SelectedSkill) - if input.SelectedSkill != nil { - input.Collector.SetSkillMiddleware(true, toolx.BuiltinSkill.Name) - } - handlers = append(handlers, einocallbacks.NewRuntimeTraceHandler(input.Collector, toolMetadataBy)) - } instructionResult := f.instructionService.Build(input.AIAgent, input.SelectedSkill, input.InstructionToolDefinitions, input.StaticToolCodes) - if input.Collector != nil { - input.Collector.SetInstructionSummary(einocallbacks.InstructionTraceSummary{ - SectionTitles: append([]string(nil), instructionResult.Summary.SectionTitles...), - HasProjectRule: instructionResult.Summary.HasProjectRule, - HasGovernanceRule: instructionResult.Summary.HasGovernanceRule, - HasAgentRule: instructionResult.Summary.HasAgentRule, - HasSkillRule: instructionResult.Summary.HasSkillRule, - HasToolRule: instructionResult.Summary.HasToolRule, + handlers := make([]adk.ChatModelAgentMiddleware, 0, 3) + if f.handlerService != nil { + builtHandlers, err := f.handlerService.Build(ctx, BuildAgentHandlersInput{ + SelectedSkill: input.SelectedSkill, + InstructionToolDefinitions: input.InstructionToolDefinitions, + DynamicToolDefinitions: input.DynamicMCPToolDefinitions, + DynamicTools: dynamicTools, + StaticToolMetadata: input.StaticToolMetadata, + Collector: input.Collector, + InstructionSummary: buildInstructionTraceSummary(instructionResult.Summary), }) + if err != nil { + return nil, err + } + handlers = append(handlers, builtHandlers...) } inner, err := adk.NewChatModelAgent(ctx, &adk.ChatModelAgentConfig{ Name: strings.TrimSpace(input.AIAgent.Name), diff --git a/internal/ai/runtime/internal/impl/factory/agent_handler_service.go b/internal/ai/runtime/internal/impl/factory/agent_handler_service.go new file mode 100644 index 0000000..fcdfae5 --- /dev/null +++ b/internal/ai/runtime/internal/impl/factory/agent_handler_service.go @@ -0,0 +1,65 @@ +package factory + +import ( + "context" + + einoadapter "cs-agent/internal/ai/runtime/internal/impl/adapter" + einocallbacks "cs-agent/internal/ai/runtime/internal/impl/callbacks" + "cs-agent/internal/ai/runtime/registry" + "cs-agent/internal/models" + "cs-agent/internal/pkg/toolx" + + "github.com/cloudwego/eino/adk" + einotoolsearch "github.com/cloudwego/eino/adk/middlewares/dynamictool/toolsearch" + einobasetool "github.com/cloudwego/eino/components/tool" +) + +type AgentHandlerService struct { + skillMiddleware *SkillMiddlewareService +} + +type BuildAgentHandlersInput struct { + SelectedSkill *models.SkillDefinition + InstructionToolDefinitions []einoadapter.MCPToolDefinition + DynamicToolDefinitions []einoadapter.MCPToolDefinition + DynamicTools []einobasetool.BaseTool + StaticToolMetadata map[string]registry.ToolMetadata + Collector *einocallbacks.RuntimeTraceCollector + InstructionSummary einocallbacks.InstructionTraceSummary +} + +func NewAgentHandlerService(skillMiddleware *SkillMiddlewareService) *AgentHandlerService { + if skillMiddleware == nil { + skillMiddleware = NewSkillMiddlewareService() + } + return &AgentHandlerService{skillMiddleware: skillMiddleware} +} + +func (s *AgentHandlerService) Build(ctx context.Context, input BuildAgentHandlersInput) ([]adk.ChatModelAgentMiddleware, error) { + handlers := make([]adk.ChatModelAgentMiddleware, 0, 3) + if len(input.DynamicTools) > 0 { + toolSearchHandler, err := einotoolsearch.New(ctx, &einotoolsearch.Config{ + DynamicTools: input.DynamicTools, + }) + if err != nil { + return nil, err + } + handlers = append(handlers, toolSearchHandler) + } + if input.SelectedSkill != nil { + skillHandler, err := s.skillMiddleware.Build(ctx, input.SelectedSkill, input.InstructionToolDefinitions) + if err != nil { + return nil, err + } + handlers = append(handlers, skillHandler) + } + if input.Collector != nil { + toolMetadataBy := buildRuntimeTraceToolMetadata(input.DynamicToolDefinitions, input.StaticToolMetadata, input.SelectedSkill) + if input.SelectedSkill != nil { + input.Collector.SetSkillMiddleware(true, toolx.BuiltinSkill.Name) + } + input.Collector.SetInstructionSummary(input.InstructionSummary) + handlers = append(handlers, einocallbacks.NewRuntimeTraceHandler(input.Collector, toolMetadataBy)) + } + return handlers, nil +} diff --git a/internal/ai/runtime/internal/impl/factory/tool_helpers.go b/internal/ai/runtime/internal/impl/factory/tool_helpers.go index 1b306c1..7aaaf50 100644 --- a/internal/ai/runtime/internal/impl/factory/tool_helpers.go +++ b/internal/ai/runtime/internal/impl/factory/tool_helpers.go @@ -10,6 +10,17 @@ import ( "cs-agent/internal/pkg/toolx" ) +func buildInstructionTraceSummary(summary InstructionAssemblySummary) einocallbacks.InstructionTraceSummary { + return einocallbacks.InstructionTraceSummary{ + SectionTitles: append([]string(nil), summary.SectionTitles...), + HasProjectRule: summary.HasProjectRule, + HasGovernanceRule: summary.HasGovernanceRule, + HasAgentRule: summary.HasAgentRule, + HasSkillRule: summary.HasSkillRule, + HasToolRule: summary.HasToolRule, + } +} + func buildRuntimeTraceToolMetadata( dynamicToolDefinitions []einoadapter.MCPToolDefinition, staticToolMetadata map[string]registry.ToolMetadata,