feat: add support for Graph Tools in AIAgent model and related services
This commit is contained in:
@@ -73,16 +73,23 @@ func (c *toolCatalog) parseSkillAllowedToolCodes(skill *models.SkillDefinition)
|
||||
}
|
||||
|
||||
func (c *toolCatalog) parseAgentAllowedToolCodes(aiAgent *models.AIAgent) []string {
|
||||
if aiAgent == nil || strings.TrimSpace(aiAgent.AllowedMCPTools) == "" {
|
||||
if aiAgent == nil {
|
||||
return nil
|
||||
}
|
||||
items, err := toolx.ParseAgentMCPToolsJSON(aiAgent.AllowedMCPTools)
|
||||
if err != nil {
|
||||
return nil
|
||||
ret := make([]string, 0)
|
||||
if raw := strings.TrimSpace(aiAgent.AllowedMCPTools); raw != "" {
|
||||
items, err := toolx.ParseAgentMCPToolsJSON(raw)
|
||||
if err == nil {
|
||||
for _, item := range items {
|
||||
ret = append(ret, item.ToolCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
ret := make([]string, 0, len(items))
|
||||
for _, item := range items {
|
||||
ret = append(ret, item.ToolCode)
|
||||
if raw := strings.TrimSpace(aiAgent.AllowedGraphTools); raw != "" {
|
||||
var graphTools []string
|
||||
if err := json.Unmarshal([]byte(raw), &graphTools); err == nil {
|
||||
ret = append(ret, graphTools...)
|
||||
}
|
||||
}
|
||||
return toolx.NormalizeToolCodes(ret)
|
||||
}
|
||||
|
||||
@@ -131,6 +131,7 @@ func buildAIAgentResponse(item *models.AIAgent) response.AIAgentResponse {
|
||||
Skills: make([]response.AIAgentSkillResponse, 0),
|
||||
Teams: make([]response.AIAgentTeamResponse, 0),
|
||||
DirectTools: make([]response.AIAgentMCPToolResponse, 0),
|
||||
GraphTools: make([]string, 0),
|
||||
SortNo: item.SortNo,
|
||||
Remark: item.Remark,
|
||||
CreatedAt: item.CreatedAt.Format("2006-01-02 15:04:05"),
|
||||
@@ -175,6 +176,10 @@ func buildAIAgentResponse(item *models.AIAgent) response.AIAgentResponse {
|
||||
if toolx.IsAutoInjectedToolCode(toolCode) {
|
||||
continue
|
||||
}
|
||||
if toolx.IsAgentDirectGraphToolCode(toolCode) {
|
||||
ret.GraphTools = appendGraphToolCodeIfMissing(ret.GraphTools, toolCode)
|
||||
continue
|
||||
}
|
||||
serverCode := strings.TrimSpace(tool.ServerCode)
|
||||
toolName := strings.TrimSpace(tool.ToolName)
|
||||
if registeredServerCode, registeredToolName, ok := toolx.GetRegisteredToolIdentity(toolCode); ok {
|
||||
@@ -207,5 +212,30 @@ func buildAIAgentResponse(item *models.AIAgent) response.AIAgentResponse {
|
||||
}
|
||||
}
|
||||
}
|
||||
if raw := strings.TrimSpace(item.AllowedGraphTools); raw != "" {
|
||||
var graphTools []string
|
||||
if err := json.Unmarshal([]byte(raw), &graphTools); err == nil {
|
||||
for _, toolCode := range graphTools {
|
||||
toolCode = toolx.NormalizeToolCodeAlias(strings.TrimSpace(toolCode))
|
||||
if !toolx.IsAgentDirectGraphToolCode(toolCode) {
|
||||
continue
|
||||
}
|
||||
ret.GraphTools = appendGraphToolCodeIfMissing(ret.GraphTools, toolCode)
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func appendGraphToolCodeIfMissing(items []string, toolCode string) []string {
|
||||
toolCode = strings.TrimSpace(toolCode)
|
||||
if toolCode == "" {
|
||||
return items
|
||||
}
|
||||
for _, item := range items {
|
||||
if strings.TrimSpace(item) == toolCode {
|
||||
return items
|
||||
}
|
||||
}
|
||||
return append(items, toolCode)
|
||||
}
|
||||
|
||||
@@ -514,6 +514,7 @@ type AIAgent struct {
|
||||
KnowledgeIDs string `gorm:"type:varchar(500);not null;default:''"` // KnowledgeIDs 为绑定的知识库ID列表,按顺序表示优先级。
|
||||
SkillIDs string `gorm:"type:varchar(500);not null;default:''"` // SkillIDs 为绑定的技能ID列表,按顺序表示允许路由的范围。
|
||||
AllowedMCPTools string `gorm:"type:text"` // AllowedMCPTools 为允许 direct tool 路由的 MCP 工具白名单配置JSON。
|
||||
AllowedGraphTools string `gorm:"type:text"` // AllowedGraphTools 为允许 Graph Tool 的白名单配置JSON。
|
||||
SortNo int `gorm:"type:int;not null;default:0;index"` // SortNo 为后台展示排序号。
|
||||
Remark string `gorm:"type:text"` // Remark 为备注。
|
||||
AuditFields
|
||||
|
||||
@@ -56,6 +56,7 @@ type CreateAIAgentRequest struct {
|
||||
KnowledgeIDs []int64 `json:"knowledgeIds"`
|
||||
SkillIDs []int64 `json:"skillIds"`
|
||||
DirectTools []AIAgentMCPToolRequest `json:"directTools"`
|
||||
GraphTools []string `json:"graphTools"`
|
||||
Remark string `json:"remark"`
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@ type AIAgentResponse struct {
|
||||
SkillIDs []int64 `json:"skillIds"`
|
||||
Skills []AIAgentSkillResponse `json:"skills"`
|
||||
DirectTools []AIAgentMCPToolResponse `json:"directTools"`
|
||||
GraphTools []string `json:"graphTools"`
|
||||
SortNo int `json:"sortNo"`
|
||||
Remark string `json:"remark"`
|
||||
CreatedAt string `json:"createdAt"`
|
||||
|
||||
@@ -281,6 +281,12 @@ func IsAgentDirectToolCode(toolCode string) bool {
|
||||
return ok && spec.DirectAccess
|
||||
}
|
||||
|
||||
func IsAgentDirectGraphToolCode(toolCode string) bool {
|
||||
toolCode = NormalizeToolCodeAlias(strings.TrimSpace(toolCode))
|
||||
spec, ok := GetRegisteredToolSpec(toolCode)
|
||||
return ok && spec.DirectAccess && spec.SourceType == enums.ToolSourceTypeGraph
|
||||
}
|
||||
|
||||
func NormalizeToolCodeAlias(toolCode string) string {
|
||||
toolCode = strings.TrimSpace(toolCode)
|
||||
if canonical, ok := toolAliasToCanonical[toolCode]; ok {
|
||||
|
||||
@@ -105,6 +105,7 @@ func (s *aIAgentService) UpdateAIAgent(req request.UpdateAIAgentRequest, operato
|
||||
"knowledge_ids": item.KnowledgeIDs,
|
||||
"skill_ids": item.SkillIDs,
|
||||
"allowed_mcp_tools": item.AllowedMCPTools,
|
||||
"allowed_graph_tools": item.AllowedGraphTools,
|
||||
"remark": item.Remark,
|
||||
"update_user_id": operator.UserID,
|
||||
"update_user_name": operator.Username,
|
||||
@@ -179,6 +180,10 @@ func (s *aIAgentService) buildAIAgentModel(id int64, req request.CreateAIAgentRe
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
graphTools, err := s.normalizeGraphTools(req.GraphTools)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
directToolsJSON := ""
|
||||
if len(directTools) > 0 {
|
||||
buf, marshalErr := json.Marshal(directTools)
|
||||
@@ -187,6 +192,14 @@ func (s *aIAgentService) buildAIAgentModel(id int64, req request.CreateAIAgentRe
|
||||
}
|
||||
directToolsJSON = string(buf)
|
||||
}
|
||||
graphToolsJSON := ""
|
||||
if len(graphTools) > 0 {
|
||||
buf, marshalErr := json.Marshal(graphTools)
|
||||
if marshalErr != nil {
|
||||
return nil, errorsx.InvalidParam("Graph Tools 配置格式不合法")
|
||||
}
|
||||
graphToolsJSON = string(buf)
|
||||
}
|
||||
return &models.AIAgent{
|
||||
Name: name,
|
||||
Description: strings.TrimSpace(req.Description),
|
||||
@@ -201,6 +214,7 @@ func (s *aIAgentService) buildAIAgentModel(id int64, req request.CreateAIAgentRe
|
||||
KnowledgeIDs: utils.JoinInt64s(knowledgeIDs),
|
||||
SkillIDs: utils.JoinInt64s(skillIDs),
|
||||
AllowedMCPTools: directToolsJSON,
|
||||
AllowedGraphTools: graphToolsJSON,
|
||||
Remark: strings.TrimSpace(req.Remark),
|
||||
}, nil
|
||||
}
|
||||
@@ -289,6 +303,9 @@ func (s *aIAgentService) normalizeDirectTools(input []request.AIAgentMCPToolRequ
|
||||
if toolx.IsAutoInjectedToolCode(strings.TrimSpace(normalized.ToolCode)) {
|
||||
continue
|
||||
}
|
||||
if toolx.ResolveToolSourceType(normalized.ToolCode) != enums.ToolSourceTypeMCP {
|
||||
return nil, errorsx.InvalidParam("Direct Tools 仅允许配置 MCP 工具")
|
||||
}
|
||||
if err := ToolCatalogService.ValidateToolCode(normalized.ToolCode); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -302,6 +319,29 @@ func (s *aIAgentService) normalizeDirectTools(input []request.AIAgentMCPToolRequ
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (s *aIAgentService) normalizeGraphTools(input []string) ([]string, error) {
|
||||
if len(input) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
ret := make([]string, 0, len(input))
|
||||
seen := make(map[string]struct{})
|
||||
for _, item := range input {
|
||||
toolCode := toolx.NormalizeToolCodeAlias(strings.TrimSpace(item))
|
||||
if toolCode == "" {
|
||||
continue
|
||||
}
|
||||
if !toolx.IsAgentDirectGraphToolCode(toolCode) {
|
||||
return nil, errorsx.InvalidParam("Graph Tools 仅允许配置 Graph Tool")
|
||||
}
|
||||
if _, exists := seen[toolCode]; exists {
|
||||
continue
|
||||
}
|
||||
seen[toolCode] = struct{}{}
|
||||
ret = append(ret, toolCode)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (s *aIAgentService) UpdateSort(ids []int64) error {
|
||||
return sqls.WithTransaction(func(ctx *sqls.TxContext) error {
|
||||
for i, id := range ids {
|
||||
|
||||
Reference in New Issue
Block a user