feat: refactor agent factory and introduce helper functions for tool metadata and instruction assembly
This commit is contained in:
@@ -96,38 +96,8 @@ func (f *AgentFactory) BuildCustomerServiceAgent(ctx context.Context, input Buil
|
|||||||
handlers = append(handlers, skillHandler)
|
handlers = append(handlers, skillHandler)
|
||||||
}
|
}
|
||||||
if input.Collector != nil {
|
if input.Collector != nil {
|
||||||
toolMetadataBy := make(map[string]einocallbacks.ToolMetadata, len(input.DynamicMCPToolDefinitions)+len(input.StaticToolMetadata))
|
toolMetadataBy := buildRuntimeTraceToolMetadata(input.DynamicMCPToolDefinitions, input.StaticToolMetadata, input.SelectedSkill)
|
||||||
for _, item := range input.DynamicMCPToolDefinitions {
|
|
||||||
toolMetadataBy[item.ModelName] = einocallbacks.ToolMetadata{
|
|
||||||
ToolCode: item.ToolCode,
|
|
||||||
ServerCode: item.ServerCode,
|
|
||||||
ToolName: item.ToolName,
|
|
||||||
SourceType: "mcp",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for modelName, metadata := range input.StaticToolMetadata {
|
|
||||||
modelName = strings.TrimSpace(modelName)
|
|
||||||
metadata.ToolCode = strings.TrimSpace(metadata.ToolCode)
|
|
||||||
metadata.ServerCode = strings.TrimSpace(metadata.ServerCode)
|
|
||||||
metadata.ToolName = strings.TrimSpace(metadata.ToolName)
|
|
||||||
metadata.SourceType = strings.TrimSpace(metadata.SourceType)
|
|
||||||
if modelName == "" || metadata.ToolCode == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
toolMetadataBy[modelName] = einocallbacks.ToolMetadata{
|
|
||||||
ToolCode: metadata.ToolCode,
|
|
||||||
ServerCode: metadata.ServerCode,
|
|
||||||
ToolName: metadata.ToolName,
|
|
||||||
SourceType: metadata.SourceType,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if input.SelectedSkill != nil {
|
if input.SelectedSkill != nil {
|
||||||
toolMetadataBy[toolx.BuiltinSkill.Name] = einocallbacks.ToolMetadata{
|
|
||||||
ToolCode: toolx.BuiltinSkill.Code,
|
|
||||||
ServerCode: toolx.BuiltinSkill.ServerCode,
|
|
||||||
ToolName: toolx.BuiltinSkill.Name,
|
|
||||||
SourceType: toolx.BuiltinSkill.SourceType,
|
|
||||||
}
|
|
||||||
input.Collector.SetSkillMiddleware(true, toolx.BuiltinSkill.Name)
|
input.Collector.SetSkillMiddleware(true, toolx.BuiltinSkill.Name)
|
||||||
}
|
}
|
||||||
handlers = append(handlers, einocallbacks.NewRuntimeTraceHandler(input.Collector, toolMetadataBy))
|
handlers = append(handlers, einocallbacks.NewRuntimeTraceHandler(input.Collector, toolMetadataBy))
|
||||||
@@ -179,11 +149,7 @@ func assembleAgentInstruction(aiAgent *models.AIAgent, selectedSkill *models.Ski
|
|||||||
if aiAgent != nil {
|
if aiAgent != nil {
|
||||||
baseInstruction = strings.TrimSpace(aiAgent.SystemPrompt)
|
baseInstruction = strings.TrimSpace(aiAgent.SystemPrompt)
|
||||||
}
|
}
|
||||||
appendixParts := make([]string, 0, 2)
|
appendixParts := buildInstructionAppendices(selectedSkill, toolDefinitions, extraToolCodes)
|
||||||
if skillInstruction := buildSelectedSkillActivationInstruction(selectedSkill); skillInstruction != "" {
|
|
||||||
appendixParts = append(appendixParts, skillInstruction)
|
|
||||||
}
|
|
||||||
appendixParts = append(appendixParts, toolx.BuildToolAppendices(len(toolDefinitions) > 0, extraToolCodes)...)
|
|
||||||
return NewInstructionAssembler().Assemble(InstructionAssemblerInput{
|
return NewInstructionAssembler().Assemble(InstructionAssemblerInput{
|
||||||
AgentInstruction: baseInstruction,
|
AgentInstruction: baseInstruction,
|
||||||
SkillInstruction: firstAppendixPart(appendixParts),
|
SkillInstruction: firstAppendixPart(appendixParts),
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
package factory
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
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"
|
||||||
|
)
|
||||||
|
|
||||||
|
func buildRuntimeTraceToolMetadata(
|
||||||
|
dynamicToolDefinitions []einoadapter.MCPToolDefinition,
|
||||||
|
staticToolMetadata map[string]registry.ToolMetadata,
|
||||||
|
selectedSkill *models.SkillDefinition,
|
||||||
|
) map[string]einocallbacks.ToolMetadata {
|
||||||
|
ret := make(map[string]einocallbacks.ToolMetadata, len(dynamicToolDefinitions)+len(staticToolMetadata)+1)
|
||||||
|
for _, item := range dynamicToolDefinitions {
|
||||||
|
modelName := strings.TrimSpace(item.ModelName)
|
||||||
|
if modelName == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ret[modelName] = einocallbacks.ToolMetadata{
|
||||||
|
ToolCode: strings.TrimSpace(item.ToolCode),
|
||||||
|
ServerCode: strings.TrimSpace(item.ServerCode),
|
||||||
|
ToolName: strings.TrimSpace(item.ToolName),
|
||||||
|
SourceType: "mcp",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for modelName, metadata := range staticToolMetadata {
|
||||||
|
modelName = strings.TrimSpace(modelName)
|
||||||
|
metadata.ToolCode = strings.TrimSpace(metadata.ToolCode)
|
||||||
|
metadata.ServerCode = strings.TrimSpace(metadata.ServerCode)
|
||||||
|
metadata.ToolName = strings.TrimSpace(metadata.ToolName)
|
||||||
|
metadata.SourceType = strings.TrimSpace(metadata.SourceType)
|
||||||
|
if modelName == "" || metadata.ToolCode == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ret[modelName] = einocallbacks.ToolMetadata{
|
||||||
|
ToolCode: metadata.ToolCode,
|
||||||
|
ServerCode: metadata.ServerCode,
|
||||||
|
ToolName: metadata.ToolName,
|
||||||
|
SourceType: metadata.SourceType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if selectedSkill != nil {
|
||||||
|
ret[toolx.BuiltinSkill.Name] = einocallbacks.ToolMetadata{
|
||||||
|
ToolCode: toolx.BuiltinSkill.Code,
|
||||||
|
ServerCode: toolx.BuiltinSkill.ServerCode,
|
||||||
|
ToolName: toolx.BuiltinSkill.Name,
|
||||||
|
SourceType: toolx.BuiltinSkill.SourceType,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildInstructionAppendices(selectedSkill *models.SkillDefinition, toolDefinitions []einoadapter.MCPToolDefinition, extraToolCodes map[string]string) []string {
|
||||||
|
appendixParts := make([]string, 0, 2)
|
||||||
|
if skillInstruction := buildSelectedSkillActivationInstruction(selectedSkill); skillInstruction != "" {
|
||||||
|
appendixParts = append(appendixParts, skillInstruction)
|
||||||
|
}
|
||||||
|
toolCodes := make([]string, 0, len(toolDefinitions)+len(extraToolCodes))
|
||||||
|
for _, item := range toolDefinitions {
|
||||||
|
toolCodes = append(toolCodes, item.ToolCode)
|
||||||
|
}
|
||||||
|
for _, item := range extraToolCodes {
|
||||||
|
toolCodes = append(toolCodes, item)
|
||||||
|
}
|
||||||
|
appendixParts = append(appendixParts, toolx.BuildToolAppendicesForCodes(len(toolDefinitions) > 0, toolCodes)...)
|
||||||
|
return appendixParts
|
||||||
|
}
|
||||||
@@ -279,7 +279,12 @@ func NormalizeToolCodeAlias(toolCode string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func BuildToolAppendices(hasDynamicMCPTools bool, toolCodes map[string]string) []string {
|
func BuildToolAppendices(hasDynamicMCPTools bool, toolCodes map[string]string) []string {
|
||||||
|
return BuildToolAppendicesForCodes(hasDynamicMCPTools, toolCodesFromMap(toolCodes))
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildToolAppendicesForCodes(hasDynamicMCPTools bool, toolCodes []string) []string {
|
||||||
ret := make([]string, 0, len(toolCodes)+1)
|
ret := make([]string, 0, len(toolCodes)+1)
|
||||||
|
normalizedToolCodes := NormalizeToolCodes(toolCodes)
|
||||||
if hasDynamicMCPTools && strings.TrimSpace(BuiltinToolSearch.Appendix) != "" {
|
if hasDynamicMCPTools && strings.TrimSpace(BuiltinToolSearch.Appendix) != "" {
|
||||||
ret = append(ret, BuiltinToolSearch.Appendix)
|
ret = append(ret, BuiltinToolSearch.Appendix)
|
||||||
}
|
}
|
||||||
@@ -290,7 +295,7 @@ func BuildToolAppendices(hasDynamicMCPTools bool, toolCodes map[string]string) [
|
|||||||
if spec.Code == BuiltinToolSearch.Code {
|
if spec.Code == BuiltinToolSearch.Code {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if hasToolCode(toolCodes, spec.Code) {
|
if containsNormalizedToolCode(normalizedToolCodes, spec.Code) {
|
||||||
ret = append(ret, spec.Appendix)
|
ret = append(ret, spec.Appendix)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -330,18 +335,33 @@ func IsImpliedAllowedToolCode(toolCode string, allowedToolCodes map[string]struc
|
|||||||
}
|
}
|
||||||
|
|
||||||
func hasToolCode(toolCodes map[string]string, target string) bool {
|
func hasToolCode(toolCodes map[string]string, target string) bool {
|
||||||
|
return containsNormalizedToolCode(toolCodesFromMap(toolCodes), target)
|
||||||
|
}
|
||||||
|
|
||||||
|
func containsNormalizedToolCode(toolCodes []string, target string) bool {
|
||||||
target = strings.TrimSpace(target)
|
target = strings.TrimSpace(target)
|
||||||
if target == "" || len(toolCodes) == 0 {
|
if target == "" || len(toolCodes) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, item := range toolCodes {
|
for _, item := range NormalizeToolCodes(toolCodes) {
|
||||||
if NormalizeToolCodeAlias(strings.TrimSpace(item)) == target {
|
if item == target {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toolCodesFromMap(toolCodes map[string]string) []string {
|
||||||
|
if len(toolCodes) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
ret := make([]string, 0, len(toolCodes))
|
||||||
|
for _, item := range toolCodes {
|
||||||
|
ret = append(ret, item)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
func NormalizeToolCodes(items []string) []string {
|
func NormalizeToolCodes(items []string) []string {
|
||||||
if len(items) == 0 {
|
if len(items) == 0 {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
Reference in New Issue
Block a user