feat: refactor tool definitions to use structured ToolSpec and update related references
This commit is contained in:
+1
-1
Submodule docs updated: 86165abf47...18dc676a5f
@@ -84,12 +84,12 @@ func (s *Service) Run(ctx context.Context, req Request) (*Summary, error) {
|
|||||||
toolDefsByModelName[item.ModelName] = item.ToolCode
|
toolDefsByModelName[item.ModelName] = item.ToolCode
|
||||||
}
|
}
|
||||||
if len(filteredToolDefs) > 0 {
|
if len(filteredToolDefs) > 0 {
|
||||||
summary.ToolCodes = appendIfMissing(summary.ToolCodes, toolx.BuiltinToolSearchToolCode)
|
summary.ToolCodes = appendIfMissing(summary.ToolCodes, toolx.BuiltinToolSearch.Code)
|
||||||
toolDefsByModelName[toolx.BuiltinToolSearchToolName] = toolx.BuiltinToolSearchToolCode
|
toolDefsByModelName[toolx.BuiltinToolSearch.Name] = toolx.BuiltinToolSearch.Code
|
||||||
}
|
}
|
||||||
if req.SelectedSkill != nil {
|
if req.SelectedSkill != nil {
|
||||||
summary.ToolCodes = appendIfMissing(summary.ToolCodes, toolx.BuiltinSkillToolCode)
|
summary.ToolCodes = appendIfMissing(summary.ToolCodes, toolx.BuiltinSkill.Code)
|
||||||
toolDefsByModelName[toolx.BuiltinSkillToolName] = toolx.BuiltinSkillToolCode
|
toolDefsByModelName[toolx.BuiltinSkill.Name] = toolx.BuiltinSkill.Code
|
||||||
}
|
}
|
||||||
for modelName, toolCode := range toolSetStaticToolCodes(req.ToolSet) {
|
for modelName, toolCode := range toolSetStaticToolCodes(req.ToolSet) {
|
||||||
toolCode = strings.TrimSpace(toolCode)
|
toolCode = strings.TrimSpace(toolCode)
|
||||||
@@ -236,8 +236,8 @@ func (s *Service) Resume(ctx context.Context, req ResumeRequest) (*Summary, erro
|
|||||||
toolDefsByModelName[item.ModelName] = item.ToolCode
|
toolDefsByModelName[item.ModelName] = item.ToolCode
|
||||||
}
|
}
|
||||||
if len(toolDefs) > 0 {
|
if len(toolDefs) > 0 {
|
||||||
summary.ToolCodes = appendIfMissing(summary.ToolCodes, toolx.BuiltinToolSearchToolCode)
|
summary.ToolCodes = appendIfMissing(summary.ToolCodes, toolx.BuiltinToolSearch.Code)
|
||||||
toolDefsByModelName[toolx.BuiltinToolSearchToolName] = toolx.BuiltinToolSearchToolCode
|
toolDefsByModelName[toolx.BuiltinToolSearch.Name] = toolx.BuiltinToolSearch.Code
|
||||||
}
|
}
|
||||||
for modelName, toolCode := range toolSetStaticToolCodes(req.ToolSet) {
|
for modelName, toolCode := range toolSetStaticToolCodes(req.ToolSet) {
|
||||||
toolCode = strings.TrimSpace(toolCode)
|
toolCode = strings.TrimSpace(toolCode)
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ func (h *RuntimeTraceHandler) WrapInvokableToolCall(_ context.Context, endpoint
|
|||||||
item.ErrorMessage = err.Error()
|
item.ErrorMessage = err.Error()
|
||||||
}
|
}
|
||||||
h.collector.AddToolItem(item)
|
h.collector.AddToolItem(item)
|
||||||
if metadata, ok := h.resolveToolMetadata(item.ToolName); ok && strings.TrimSpace(metadata.SourceType) == toolx.GraphToolCatalogServerCode {
|
if metadata, ok := h.resolveToolMetadata(item.ToolName); ok && strings.TrimSpace(metadata.SourceType) == toolx.GraphCreateTicketConfirm.ServerCode {
|
||||||
recommendedAction, riskLevel, ticketDraftReady := parseGraphToolOutcome(item.ToolCode, result)
|
recommendedAction, riskLevel, ticketDraftReady := parseGraphToolOutcome(item.ToolCode, result)
|
||||||
h.collector.AddGraphToolItem(GraphToolTraceItem{
|
h.collector.AddGraphToolItem(GraphToolTraceItem{
|
||||||
ToolCode: item.ToolCode,
|
ToolCode: item.ToolCode,
|
||||||
@@ -82,7 +82,7 @@ func (h *RuntimeTraceHandler) WrapInvokableToolCall(_ context.Context, endpoint
|
|||||||
TicketDraftReady: ticketDraftReady,
|
TicketDraftReady: ticketDraftReady,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if metadata, ok := h.resolveToolMetadata(item.ToolName); ok && strings.TrimSpace(metadata.ToolCode) == toolx.BuiltinToolSearchToolCode {
|
if metadata, ok := h.resolveToolMetadata(item.ToolName); ok && strings.TrimSpace(metadata.ToolCode) == toolx.BuiltinToolSearch.Code {
|
||||||
h.collector.AddToolSearchItem(h.buildToolSearchTraceItem(argumentsInJSON, result, err))
|
h.collector.AddToolSearchItem(h.buildToolSearchTraceItem(argumentsInJSON, result, err))
|
||||||
}
|
}
|
||||||
return result, err
|
return result, err
|
||||||
@@ -99,9 +99,9 @@ func parseGraphToolOutcome(toolCode string, result string) (recommendedAction, r
|
|||||||
return "", "", false
|
return "", "", false
|
||||||
}
|
}
|
||||||
switch toolCode {
|
switch toolCode {
|
||||||
case toolx.GraphAnalyzeConversationToolCode:
|
case toolx.GraphAnalyzeConversation.Code:
|
||||||
return strings.TrimSpace(readToolSearchString(payload, "recommendedNextAction")), strings.TrimSpace(readToolSearchString(payload, "riskLevel")), false
|
return strings.TrimSpace(readToolSearchString(payload, "recommendedNextAction")), strings.TrimSpace(readToolSearchString(payload, "riskLevel")), false
|
||||||
case toolx.GraphTriageServiceRequestToolCode:
|
case toolx.GraphTriageServiceRequest.Code:
|
||||||
recommendedAction = strings.TrimSpace(readToolSearchString(payload, "recommendedAction"))
|
recommendedAction = strings.TrimSpace(readToolSearchString(payload, "recommendedAction"))
|
||||||
if analysis, ok := payload["analysis"].(map[string]any); ok {
|
if analysis, ok := payload["analysis"].(map[string]any); ok {
|
||||||
riskLevel = strings.TrimSpace(readToolSearchString(analysis, "riskLevel"))
|
riskLevel = strings.TrimSpace(readToolSearchString(analysis, "riskLevel"))
|
||||||
@@ -124,20 +124,20 @@ func (h *RuntimeTraceHandler) resolveToolMetadata(modelToolName string) (ToolMet
|
|||||||
if modelToolName == "" {
|
if modelToolName == "" {
|
||||||
return ToolMetadata{}, false
|
return ToolMetadata{}, false
|
||||||
}
|
}
|
||||||
if modelToolName == toolx.BuiltinToolSearchToolName {
|
if modelToolName == toolx.BuiltinToolSearch.Name {
|
||||||
return ToolMetadata{
|
return ToolMetadata{
|
||||||
ToolCode: toolx.BuiltinToolSearchToolCode,
|
ToolCode: toolx.BuiltinToolSearch.Code,
|
||||||
ServerCode: toolx.BuiltinToolCatalogServerCode,
|
ServerCode: toolx.BuiltinToolSearch.ServerCode,
|
||||||
ToolName: toolx.BuiltinToolSearchToolName,
|
ToolName: toolx.BuiltinToolSearch.Name,
|
||||||
SourceType: toolx.BuiltinToolCatalogServerCode,
|
SourceType: toolx.BuiltinToolSearch.SourceType,
|
||||||
}, true
|
}, true
|
||||||
}
|
}
|
||||||
if modelToolName == toolx.BuiltinSkillToolName {
|
if modelToolName == toolx.BuiltinSkill.Name {
|
||||||
return ToolMetadata{
|
return ToolMetadata{
|
||||||
ToolCode: toolx.BuiltinSkillToolCode,
|
ToolCode: toolx.BuiltinSkill.Code,
|
||||||
ServerCode: toolx.BuiltinToolCatalogServerCode,
|
ServerCode: toolx.BuiltinSkill.ServerCode,
|
||||||
ToolName: toolx.BuiltinSkillToolName,
|
ToolName: toolx.BuiltinSkill.Name,
|
||||||
SourceType: toolx.BuiltinToolCatalogServerCode,
|
SourceType: toolx.BuiltinSkill.SourceType,
|
||||||
}, true
|
}, true
|
||||||
}
|
}
|
||||||
metadata, ok := h.toolMetadataBy[modelToolName]
|
metadata, ok := h.toolMetadataBy[modelToolName]
|
||||||
|
|||||||
@@ -108,42 +108,22 @@ func (f *AgentFactory) BuildCustomerServiceAgent(ctx context.Context, input Buil
|
|||||||
if modelName == "" || toolCode == "" {
|
if modelName == "" || toolCode == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
serverCode, toolName := "", ""
|
serverCode, toolName, _ := toolx.GetRegisteredToolIdentity(toolCode)
|
||||||
switch toolCode {
|
|
||||||
case toolx.BuiltinToolSearchToolCode:
|
|
||||||
serverCode = toolx.BuiltinToolCatalogServerCode
|
|
||||||
toolName = toolx.BuiltinToolSearchToolName
|
|
||||||
case toolx.GraphTriageServiceRequestToolCode:
|
|
||||||
serverCode = toolx.GraphToolCatalogServerCode
|
|
||||||
toolName = toolx.GraphTriageServiceRequestToolName
|
|
||||||
case toolx.GraphAnalyzeConversationToolCode:
|
|
||||||
serverCode = toolx.GraphToolCatalogServerCode
|
|
||||||
toolName = toolx.GraphAnalyzeConversationToolName
|
|
||||||
case toolx.GraphPrepareTicketDraftToolCode:
|
|
||||||
serverCode = toolx.GraphToolCatalogServerCode
|
|
||||||
toolName = toolx.GraphPrepareTicketDraftToolName
|
|
||||||
case toolx.GraphCreateTicketConfirmToolCode:
|
|
||||||
serverCode = toolx.GraphToolCatalogServerCode
|
|
||||||
toolName = toolx.GraphCreateTicketConfirmToolName
|
|
||||||
case toolx.GraphHandoffConversationToolCode:
|
|
||||||
serverCode = toolx.GraphToolCatalogServerCode
|
|
||||||
toolName = toolx.GraphHandoffConversationToolName
|
|
||||||
}
|
|
||||||
toolMetadataBy[modelName] = einocallbacks.ToolMetadata{
|
toolMetadataBy[modelName] = einocallbacks.ToolMetadata{
|
||||||
ToolCode: toolCode,
|
ToolCode: toolCode,
|
||||||
ServerCode: serverCode,
|
ServerCode: serverCode,
|
||||||
ToolName: toolName,
|
ToolName: toolName,
|
||||||
SourceType: resolveToolSourceType(toolCode),
|
SourceType: toolx.ResolveToolSourceType(toolCode),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if input.SelectedSkill != nil {
|
if input.SelectedSkill != nil {
|
||||||
toolMetadataBy[toolx.BuiltinSkillToolName] = einocallbacks.ToolMetadata{
|
toolMetadataBy[toolx.BuiltinSkill.Name] = einocallbacks.ToolMetadata{
|
||||||
ToolCode: toolx.BuiltinSkillToolCode,
|
ToolCode: toolx.BuiltinSkill.Code,
|
||||||
ServerCode: toolx.BuiltinToolCatalogServerCode,
|
ServerCode: toolx.BuiltinSkill.ServerCode,
|
||||||
ToolName: toolx.BuiltinSkillToolName,
|
ToolName: toolx.BuiltinSkill.Name,
|
||||||
SourceType: toolx.BuiltinToolCatalogServerCode,
|
SourceType: toolx.BuiltinSkill.SourceType,
|
||||||
}
|
}
|
||||||
input.Collector.SetSkillMiddleware(true, toolx.BuiltinSkillToolName)
|
input.Collector.SetSkillMiddleware(true, toolx.BuiltinSkill.Name)
|
||||||
}
|
}
|
||||||
handlers = append(handlers, einocallbacks.NewRuntimeTraceHandler(input.Collector, toolMetadataBy))
|
handlers = append(handlers, einocallbacks.NewRuntimeTraceHandler(input.Collector, toolMetadataBy))
|
||||||
}
|
}
|
||||||
@@ -181,7 +161,7 @@ func (f *AgentFactory) buildSelectedSkillMiddleware(ctx context.Context, selecte
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
toolName := toolx.BuiltinSkillToolName
|
toolName := toolx.BuiltinSkill.Name
|
||||||
return einoskill.NewMiddleware(ctx, &einoskill.Config{
|
return einoskill.NewMiddleware(ctx, &einoskill.Config{
|
||||||
Backend: backend,
|
Backend: backend,
|
||||||
SkillToolName: &toolName,
|
SkillToolName: &toolName,
|
||||||
@@ -189,22 +169,6 @@ func (f *AgentFactory) buildSelectedSkillMiddleware(ctx context.Context, selecte
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveToolSourceType(toolCode string) string {
|
|
||||||
toolCode = strings.TrimSpace(toolCode)
|
|
||||||
switch {
|
|
||||||
case toolCode == toolx.BuiltinToolSearchToolCode:
|
|
||||||
return toolx.BuiltinToolCatalogServerCode
|
|
||||||
case toolCode == toolx.BuiltinSkillToolCode:
|
|
||||||
return toolx.BuiltinToolCatalogServerCode
|
|
||||||
case strings.HasPrefix(toolCode, toolx.GraphToolCatalogServerCode+"/"):
|
|
||||||
return toolx.GraphToolCatalogServerCode
|
|
||||||
case strings.HasPrefix(toolCode, toolx.BuiltinToolCatalogServerCode+"/"):
|
|
||||||
return toolx.BuiltinToolCatalogServerCode
|
|
||||||
default:
|
|
||||||
return "mcp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func assembleAgentInstruction(aiAgent *models.AIAgent, selectedSkill *models.SkillDefinition, toolDefinitions []einoadapter.MCPToolDefinition, extraToolCodes map[string]string) InstructionAssemblyResult {
|
func assembleAgentInstruction(aiAgent *models.AIAgent, selectedSkill *models.SkillDefinition, toolDefinitions []einoadapter.MCPToolDefinition, extraToolCodes map[string]string) InstructionAssemblyResult {
|
||||||
baseInstruction := ""
|
baseInstruction := ""
|
||||||
if aiAgent != nil {
|
if aiAgent != nil {
|
||||||
@@ -222,7 +186,7 @@ func assembleAgentInstruction(aiAgent *models.AIAgent, selectedSkill *models.Ski
|
|||||||
3. 如果当前已有固定内置工具可以完成任务,优先使用固定工具,不要滥用 tool_search。
|
3. 如果当前已有固定内置工具可以完成任务,优先使用固定工具,不要滥用 tool_search。
|
||||||
`))
|
`))
|
||||||
}
|
}
|
||||||
if hasToolCode(extraToolCodes, toolx.GraphTriageServiceRequestToolCode) {
|
if hasToolCode(extraToolCodes, toolx.GraphTriageServiceRequest.Code) {
|
||||||
appendixParts = append(appendixParts, strings.TrimSpace(`
|
appendixParts = append(appendixParts, strings.TrimSpace(`
|
||||||
当你需要判断“继续解答 / 建单 / 转人工”这类复杂升级路径时,优先先调用 triage_service_request 这个 Graph Tool,并遵守以下规则:
|
当你需要判断“继续解答 / 建单 / 转人工”这类复杂升级路径时,优先先调用 triage_service_request 这个 Graph Tool,并遵守以下规则:
|
||||||
1. 该工具会综合当前对话输出 recommendedAction,并在需要建单时附带 ticketDraft。
|
1. 该工具会综合当前对话输出 recommendedAction,并在需要建单时附带 ticketDraft。
|
||||||
@@ -232,7 +196,7 @@ func assembleAgentInstruction(aiAgent *models.AIAgent, selectedSkill *models.Ski
|
|||||||
5. 当升级路径不明确时,优先使用该工具,而不是直接凭主 prompt 做复杂分流判断。
|
5. 当升级路径不明确时,优先使用该工具,而不是直接凭主 prompt 做复杂分流判断。
|
||||||
`))
|
`))
|
||||||
}
|
}
|
||||||
if hasToolCode(extraToolCodes, toolx.GraphPrepareTicketDraftToolCode) {
|
if hasToolCode(extraToolCodes, toolx.GraphPrepareTicketDraft.Code) {
|
||||||
appendixParts = append(appendixParts, strings.TrimSpace(`
|
appendixParts = append(appendixParts, strings.TrimSpace(`
|
||||||
当用户已经表达了建单、投诉、报障、售后处理等诉求,但工单标题、描述或问题整理还比较散乱时,优先调用 prepare_ticket_draft 这个 Graph Tool,并遵守以下规则:
|
当用户已经表达了建单、投诉、报障、售后处理等诉求,但工单标题、描述或问题整理还比较散乱时,优先调用 prepare_ticket_draft 这个 Graph Tool,并遵守以下规则:
|
||||||
1. 该工具用于整理工单草稿,会返回建议标题、建议描述、缺失字段和追问建议。
|
1. 该工具用于整理工单草稿,会返回建议标题、建议描述、缺失字段和追问建议。
|
||||||
@@ -241,7 +205,7 @@ func assembleAgentInstruction(aiAgent *models.AIAgent, selectedSkill *models.Ski
|
|||||||
4. 该工具用于“整理草稿”,不代表已经创建工单。
|
4. 该工具用于“整理草稿”,不代表已经创建工单。
|
||||||
`))
|
`))
|
||||||
}
|
}
|
||||||
if hasToolCode(extraToolCodes, toolx.GraphAnalyzeConversationToolCode) {
|
if hasToolCode(extraToolCodes, toolx.GraphAnalyzeConversation.Code) {
|
||||||
appendixParts = append(appendixParts, strings.TrimSpace(`
|
appendixParts = append(appendixParts, strings.TrimSpace(`
|
||||||
当对话可能涉及投诉升级、退款赔偿、明显负面情绪、是否要建单、是否要转人工等复杂判断时,优先调用 analyze_conversation 这个 Graph Tool,并遵守以下规则:
|
当对话可能涉及投诉升级、退款赔偿、明显负面情绪、是否要建单、是否要转人工等复杂判断时,优先调用 analyze_conversation 这个 Graph Tool,并遵守以下规则:
|
||||||
1. 该工具用于输出结构化摘要、风险信号和下一步建议,不代表实际已经建单或转人工。
|
1. 该工具用于输出结构化摘要、风险信号和下一步建议,不代表实际已经建单或转人工。
|
||||||
@@ -250,7 +214,7 @@ func assembleAgentInstruction(aiAgent *models.AIAgent, selectedSkill *models.Ski
|
|||||||
4. 如果工具建议为 continue_answering,优先继续澄清和解答,不要过早升级动作。
|
4. 如果工具建议为 continue_answering,优先继续澄清和解答,不要过早升级动作。
|
||||||
`))
|
`))
|
||||||
}
|
}
|
||||||
if hasToolCode(extraToolCodes, toolx.GraphCreateTicketConfirmToolCode) {
|
if hasToolCode(extraToolCodes, toolx.GraphCreateTicketConfirm.Code) {
|
||||||
appendixParts = append(appendixParts, strings.TrimSpace(`
|
appendixParts = append(appendixParts, strings.TrimSpace(`
|
||||||
你可以在确认信息充分后调用 create_ticket_with_confirmation 这个 Graph Tool 来创建工单,但必须遵守以下规则:
|
你可以在确认信息充分后调用 create_ticket_with_confirmation 这个 Graph Tool 来创建工单,但必须遵守以下规则:
|
||||||
1. 只有在用户明确表达希望提交工单、投诉、报障、售后处理等诉求时,才考虑调用该工具。
|
1. 只有在用户明确表达希望提交工单、投诉、报障、售后处理等诉求时,才考虑调用该工具。
|
||||||
@@ -260,7 +224,7 @@ func assembleAgentInstruction(aiAgent *models.AIAgent, selectedSkill *models.Ski
|
|||||||
5. 如果用户只是咨询、抱怨或泛泛表达不满,但没有明确要求建单,优先继续澄清,不要主动创建工单。
|
5. 如果用户只是咨询、抱怨或泛泛表达不满,但没有明确要求建单,优先继续澄清,不要主动创建工单。
|
||||||
`))
|
`))
|
||||||
}
|
}
|
||||||
if hasToolCode(extraToolCodes, toolx.GraphHandoffConversationToolCode) {
|
if hasToolCode(extraToolCodes, toolx.GraphHandoffConversation.Code) {
|
||||||
appendixParts = append(appendixParts, strings.TrimSpace(`
|
appendixParts = append(appendixParts, strings.TrimSpace(`
|
||||||
你可以在确认需要人工介入后调用 handoff_to_human 这个 Graph Tool 来转人工,但必须遵守以下规则:
|
你可以在确认需要人工介入后调用 handoff_to_human 这个 Graph Tool 来转人工,但必须遵守以下规则:
|
||||||
1. 只有在用户明确要求人工客服,或你已经判断该问题必须由人工继续处理时,才调用该工具。
|
1. 只有在用户明确要求人工客服,或你已经判断该问题必须由人工继续处理时,才调用该工具。
|
||||||
@@ -311,7 +275,7 @@ func buildSelectedSkillActivationInstruction(skill *models.SkillDefinition) stri
|
|||||||
if desc := strings.TrimSpace(skill.Description); desc != "" {
|
if desc := strings.TrimSpace(skill.Description); desc != "" {
|
||||||
lines = append(lines, fmt.Sprintf("- description: %s", desc))
|
lines = append(lines, fmt.Sprintf("- description: %s", desc))
|
||||||
}
|
}
|
||||||
lines = append(lines, "", "执行要求:", "- 本轮优先处理该技能范围内的问题。", fmt.Sprintf("- 需要专项处理细节时,优先调用 %s 工具加载该技能说明后再继续。", toolx.BuiltinSkillToolName), "- 如果关键信息不足,先向用户追问。", "- 不得调用当前技能未授权的工具。")
|
lines = append(lines, "", "执行要求:", "- 本轮优先处理该技能范围内的问题。", fmt.Sprintf("- 需要专项处理细节时,优先调用 %s 工具加载该技能说明后再继续。", toolx.BuiltinSkill.Name), "- 如果关键信息不足,先向用户追问。", "- 不得调用当前技能未授权的工具。")
|
||||||
return strings.TrimSpace(strings.Join(lines, "\n"))
|
return strings.TrimSpace(strings.Join(lines, "\n"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,24 +59,24 @@ func isAllowedToolCode(toolCode string, allowedToolCodes map[string]struct{}) bo
|
|||||||
if isAlwaysAllowedToolCode(toolCode) {
|
if isAlwaysAllowedToolCode(toolCode) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if strings.TrimSpace(toolCode) == toolx.GraphTriageServiceRequestToolCode {
|
if strings.TrimSpace(toolCode) == toolx.GraphTriageServiceRequest.Code {
|
||||||
if _, ok := allowedToolCodes[toolx.GraphCreateTicketConfirmToolCode]; ok {
|
if _, ok := allowedToolCodes[toolx.GraphCreateTicketConfirm.Code]; ok {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if _, ok := allowedToolCodes[toolx.GraphHandoffConversationToolCode]; ok {
|
if _, ok := allowedToolCodes[toolx.GraphHandoffConversation.Code]; ok {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if strings.TrimSpace(toolCode) == toolx.GraphAnalyzeConversationToolCode {
|
if strings.TrimSpace(toolCode) == toolx.GraphAnalyzeConversation.Code {
|
||||||
if _, ok := allowedToolCodes[toolx.GraphCreateTicketConfirmToolCode]; ok {
|
if _, ok := allowedToolCodes[toolx.GraphCreateTicketConfirm.Code]; ok {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if _, ok := allowedToolCodes[toolx.GraphHandoffConversationToolCode]; ok {
|
if _, ok := allowedToolCodes[toolx.GraphHandoffConversation.Code]; ok {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if strings.TrimSpace(toolCode) == toolx.GraphPrepareTicketDraftToolCode {
|
if strings.TrimSpace(toolCode) == toolx.GraphPrepareTicketDraft.Code {
|
||||||
_, ok := allowedToolCodes[toolx.GraphCreateTicketConfirmToolCode]
|
_, ok := allowedToolCodes[toolx.GraphCreateTicketConfirm.Code]
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
@@ -98,5 +98,5 @@ func makeAllowedToolCodeSet(input []string) map[string]struct{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isAlwaysAllowedToolCode(toolCode string) bool {
|
func isAlwaysAllowedToolCode(toolCode string) bool {
|
||||||
return strings.TrimSpace(toolCode) == toolx.GraphHandoffConversationToolCode
|
return strings.TrimSpace(toolCode) == toolx.GraphHandoffConversation.Code
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -549,7 +549,7 @@ func summaryPrimaryToolCode(summary *Summary) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
toolCode := firstInvokedToolCode(summary)
|
toolCode := firstInvokedToolCode(summary)
|
||||||
if toolCode != toolx.BuiltinToolSearchToolCode {
|
if toolCode != toolx.BuiltinToolSearch.Code {
|
||||||
return toolCode
|
return toolCode
|
||||||
}
|
}
|
||||||
if targetToolCode := firstToolSearchTargetToolCode(summary); targetToolCode != "" {
|
if targetToolCode := firstToolSearchTargetToolCode(summary); targetToolCode != "" {
|
||||||
@@ -611,7 +611,7 @@ func firstGraphToolCode(summary *Summary) string {
|
|||||||
func extractHandoffReason(summary *Summary) string {
|
func extractHandoffReason(summary *Summary) string {
|
||||||
trace := parseRuntimeTraceData(summary.TraceData)
|
trace := parseRuntimeTraceData(summary.TraceData)
|
||||||
for _, item := range trace.GraphTools.Items {
|
for _, item := range trace.GraphTools.Items {
|
||||||
if strings.TrimSpace(item.ToolCode) != toolx.GraphHandoffConversationToolCode {
|
if strings.TrimSpace(item.ToolCode) != toolx.GraphHandoffConversation.Code {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if len(item.Arguments) == 0 {
|
if len(item.Arguments) == 0 {
|
||||||
@@ -628,7 +628,7 @@ func graphPlanReason(summary *Summary) string {
|
|||||||
for _, item := range trace.GraphTools.Items {
|
for _, item := range trace.GraphTools.Items {
|
||||||
toolCode := strings.TrimSpace(item.ToolCode)
|
toolCode := strings.TrimSpace(item.ToolCode)
|
||||||
switch toolCode {
|
switch toolCode {
|
||||||
case toolx.GraphTriageServiceRequestToolCode:
|
case toolx.GraphTriageServiceRequest.Code:
|
||||||
recommendedAction := strings.TrimSpace(item.RecommendedAction)
|
recommendedAction := strings.TrimSpace(item.RecommendedAction)
|
||||||
if recommendedAction == "" {
|
if recommendedAction == "" {
|
||||||
return "graph tool triaged service request"
|
return "graph tool triaged service request"
|
||||||
@@ -637,7 +637,7 @@ func graphPlanReason(summary *Summary) string {
|
|||||||
return "graph tool triaged service request: " + recommendedAction + " with ready ticket draft"
|
return "graph tool triaged service request: " + recommendedAction + " with ready ticket draft"
|
||||||
}
|
}
|
||||||
return "graph tool triaged service request: " + recommendedAction
|
return "graph tool triaged service request: " + recommendedAction
|
||||||
case toolx.GraphAnalyzeConversationToolCode:
|
case toolx.GraphAnalyzeConversation.Code:
|
||||||
recommendedAction := strings.TrimSpace(item.RecommendedAction)
|
recommendedAction := strings.TrimSpace(item.RecommendedAction)
|
||||||
riskLevel := strings.TrimSpace(item.RiskLevel)
|
riskLevel := strings.TrimSpace(item.RiskLevel)
|
||||||
switch {
|
switch {
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ import (
|
|||||||
orderedmap "github.com/wk8/go-ordered-map/v2"
|
orderedmap "github.com/wk8/go-ordered-map/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
var (
|
||||||
AnalyzeConversationToolCode = toolx.GraphAnalyzeConversationToolCode
|
AnalyzeConversationToolCode = toolx.GraphAnalyzeConversation.Code
|
||||||
AnalyzeConversationToolName = toolx.GraphAnalyzeConversationToolName
|
AnalyzeConversationToolName = toolx.GraphAnalyzeConversation.Name
|
||||||
)
|
)
|
||||||
|
|
||||||
type AnalyzeConversationTool struct {
|
type AnalyzeConversationTool struct {
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ import (
|
|||||||
orderedmap "github.com/wk8/go-ordered-map/v2"
|
orderedmap "github.com/wk8/go-ordered-map/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
var (
|
||||||
CreateTicketConfirmToolCode = toolx.GraphCreateTicketConfirmToolCode
|
CreateTicketConfirmToolCode = toolx.GraphCreateTicketConfirm.Code
|
||||||
CreateTicketConfirmToolName = toolx.GraphCreateTicketConfirmToolName
|
CreateTicketConfirmToolName = toolx.GraphCreateTicketConfirm.Name
|
||||||
)
|
)
|
||||||
|
|
||||||
type CreateTicketGraphTool struct {
|
type CreateTicketGraphTool struct {
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ import (
|
|||||||
orderedmap "github.com/wk8/go-ordered-map/v2"
|
orderedmap "github.com/wk8/go-ordered-map/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
var (
|
||||||
HandoffConversationToolCode = toolx.GraphHandoffConversationToolCode
|
HandoffConversationToolCode = toolx.GraphHandoffConversation.Code
|
||||||
HandoffConversationToolName = toolx.GraphHandoffConversationToolName
|
HandoffConversationToolName = toolx.GraphHandoffConversation.Name
|
||||||
)
|
)
|
||||||
|
|
||||||
type HandoffGraphTool struct {
|
type HandoffGraphTool struct {
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ import (
|
|||||||
orderedmap "github.com/wk8/go-ordered-map/v2"
|
orderedmap "github.com/wk8/go-ordered-map/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
var (
|
||||||
PrepareTicketDraftToolCode = toolx.GraphPrepareTicketDraftToolCode
|
PrepareTicketDraftToolCode = toolx.GraphPrepareTicketDraft.Code
|
||||||
PrepareTicketDraftToolName = toolx.GraphPrepareTicketDraftToolName
|
PrepareTicketDraftToolName = toolx.GraphPrepareTicketDraft.Name
|
||||||
)
|
)
|
||||||
|
|
||||||
type PrepareTicketDraftTool struct {
|
type PrepareTicketDraftTool struct {
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ import (
|
|||||||
orderedmap "github.com/wk8/go-ordered-map/v2"
|
orderedmap "github.com/wk8/go-ordered-map/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
var (
|
||||||
ToolSearchToolCode = toolx.BuiltinToolSearchToolCode
|
ToolSearchToolCode = toolx.BuiltinToolSearch.Code
|
||||||
ToolSearchToolName = toolx.BuiltinToolSearchToolName
|
ToolSearchToolName = toolx.BuiltinToolSearch.Name
|
||||||
)
|
)
|
||||||
|
|
||||||
type ToolSearchTool struct {
|
type ToolSearchTool struct {
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ import (
|
|||||||
orderedmap "github.com/wk8/go-ordered-map/v2"
|
orderedmap "github.com/wk8/go-ordered-map/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
var (
|
||||||
TriageServiceRequestToolCode = toolx.GraphTriageServiceRequestToolCode
|
TriageServiceRequestToolCode = toolx.GraphTriageServiceRequest.Code
|
||||||
TriageServiceRequestToolName = toolx.GraphTriageServiceRequestToolName
|
TriageServiceRequestToolName = toolx.GraphTriageServiceRequest.Name
|
||||||
)
|
)
|
||||||
|
|
||||||
type TriageServiceRequestTool struct {
|
type TriageServiceRequestTool struct {
|
||||||
|
|||||||
@@ -177,39 +177,23 @@ func buildAIAgentResponse(item *models.AIAgent) response.AIAgentResponse {
|
|||||||
}
|
}
|
||||||
serverCode := strings.TrimSpace(tool.ServerCode)
|
serverCode := strings.TrimSpace(tool.ServerCode)
|
||||||
toolName := strings.TrimSpace(tool.ToolName)
|
toolName := strings.TrimSpace(tool.ToolName)
|
||||||
if toolCode == toolx.BuiltinToolSearchToolCode {
|
if registeredServerCode, registeredToolName, ok := toolx.GetRegisteredToolIdentity(toolCode); ok {
|
||||||
serverCode = toolx.BuiltinToolCatalogServerCode
|
serverCode = registeredServerCode
|
||||||
toolName = toolx.BuiltinToolSearchToolName
|
toolName = registeredToolName
|
||||||
} else if toolCode == toolx.GraphCreateTicketConfirmToolCode {
|
|
||||||
serverCode = toolx.GraphToolCatalogServerCode
|
|
||||||
toolName = toolx.GraphCreateTicketConfirmToolName
|
|
||||||
} else if toolCode == toolx.GraphHandoffConversationToolCode {
|
|
||||||
serverCode = toolx.GraphToolCatalogServerCode
|
|
||||||
toolName = toolx.GraphHandoffConversationToolName
|
|
||||||
} else if parsedServerCode, parsedToolName := toolx.SplitMCPToolCode(toolCode); parsedServerCode != "" && parsedToolName != "" {
|
} else if parsedServerCode, parsedToolName := toolx.SplitMCPToolCode(toolCode); parsedServerCode != "" && parsedToolName != "" {
|
||||||
serverCode = parsedServerCode
|
serverCode = parsedServerCode
|
||||||
toolName = parsedToolName
|
toolName = parsedToolName
|
||||||
}
|
}
|
||||||
title := strings.TrimSpace(tool.Title)
|
title := strings.TrimSpace(tool.Title)
|
||||||
if title == "" {
|
if title == "" {
|
||||||
switch toolCode {
|
if registeredTitle := toolx.GetRegisteredToolTitle(toolCode); registeredTitle != "" {
|
||||||
case toolx.BuiltinToolSearchToolCode:
|
title = registeredTitle
|
||||||
title = toolx.BuiltinToolSearchToolTitle
|
|
||||||
case toolx.GraphCreateTicketConfirmToolCode:
|
|
||||||
title = toolx.GraphCreateTicketConfirmToolTitle
|
|
||||||
case toolx.GraphHandoffConversationToolCode:
|
|
||||||
title = toolx.GraphHandoffConversationToolTitle
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
description := strings.TrimSpace(tool.Description)
|
description := strings.TrimSpace(tool.Description)
|
||||||
if description == "" {
|
if description == "" {
|
||||||
switch toolCode {
|
if registeredDescription := toolx.GetRegisteredToolDescription(toolCode); registeredDescription != "" {
|
||||||
case toolx.BuiltinToolSearchToolCode:
|
description = registeredDescription
|
||||||
description = toolx.BuiltinToolSearchToolDescription
|
|
||||||
case toolx.GraphCreateTicketConfirmToolCode:
|
|
||||||
description = toolx.GraphCreateTicketConfirmToolDescription
|
|
||||||
case toolx.GraphHandoffConversationToolCode:
|
|
||||||
description = toolx.GraphHandoffConversationToolDescription
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret.DirectTools = append(ret.DirectTools, response.AIAgentMCPToolResponse{
|
ret.DirectTools = append(ret.DirectTools, response.AIAgentMCPToolResponse{
|
||||||
|
|||||||
@@ -1,51 +1,177 @@
|
|||||||
package toolx
|
package toolx
|
||||||
|
|
||||||
const (
|
import "strings"
|
||||||
BuiltinToolCatalogServerCode = "builtin"
|
|
||||||
BuiltinToolSearchToolCode = "builtin/tool_search"
|
type ToolSpec struct {
|
||||||
BuiltinToolSearchToolName = "tool_search"
|
Code string
|
||||||
BuiltinToolSearchToolTitle = "搜索并调用动态工具"
|
ServerCode string
|
||||||
BuiltinToolSearchToolDescription = "用于搜索当前允许使用的 MCP 工具,并在确认目标 toolCode 后动态调用该工具。适合处理长尾工具,不应替代固定内置流程工具。"
|
Name string
|
||||||
BuiltinSkillToolCode = "builtin/skill"
|
Title string
|
||||||
BuiltinSkillToolName = "skill"
|
Description string
|
||||||
BuiltinSkillToolTitle = "加载专项技能说明"
|
SourceType string
|
||||||
BuiltinSkillToolDescription = "用于加载当前命中的专项技能说明文档。仅在本轮已命中 Skill 时可用,适合将专项处理规则按需注入上下文。"
|
AutoInjected bool
|
||||||
GraphToolCatalogServerCode = "graph"
|
Aliases []string
|
||||||
GraphTriageServiceRequestToolCode = "graph/triage_service_request"
|
}
|
||||||
GraphTriageServiceRequestToolName = "triage_service_request"
|
|
||||||
GraphTriageServiceRequestToolTitle = "升级分流判断"
|
var (
|
||||||
GraphTriageServiceRequestToolDescription = "Graph Tool。用于综合分析当前对话,判断应继续解答、整理工单草稿还是转人工,并在需要建单时一并整理工单草稿。"
|
BuiltinToolSearch = ToolSpec{
|
||||||
GraphAnalyzeConversationToolCode = "graph/analyze_conversation"
|
Code: "builtin/tool_search",
|
||||||
GraphAnalyzeConversationToolName = "analyze_conversation"
|
ServerCode: "builtin",
|
||||||
GraphAnalyzeConversationToolTitle = "分析对话风险与摘要"
|
Name: "tool_search",
|
||||||
GraphAnalyzeConversationToolDescription = "Graph Tool。用于整理当前对话摘要、识别风险信号,并给出继续解答、建单或转人工的建议。"
|
Title: "搜索并调用动态工具",
|
||||||
GraphPrepareTicketDraftToolCode = "graph/prepare_ticket_draft"
|
Description: "用于搜索当前允许使用的 MCP 工具,并在确认目标 toolCode 后动态调用该工具。适合处理长尾工具,不应替代固定内置流程工具。",
|
||||||
GraphPrepareTicketDraftToolName = "prepare_ticket_draft"
|
SourceType: "builtin",
|
||||||
GraphPrepareTicketDraftToolTitle = "整理工单草稿"
|
AutoInjected: true,
|
||||||
GraphPrepareTicketDraftToolDescription = "Graph Tool。用于根据当前会话和已收集信息整理工单草稿,输出建议标题、描述、缺失字段和追问建议。"
|
}
|
||||||
GraphCreateTicketConfirmToolCode = "graph/create_ticket_with_confirmation"
|
BuiltinSkill = ToolSpec{
|
||||||
GraphCreateTicketConfirmToolName = "create_ticket_with_confirmation"
|
Code: "builtin/skill",
|
||||||
GraphCreateTicketConfirmToolTitle = "创建工单确认流程"
|
ServerCode: "builtin",
|
||||||
GraphCreateTicketConfirmToolDescription = "Graph Tool。用于封装建单参数整理、用户确认、真正建单和结果返回的确定性流程。"
|
Name: "skill",
|
||||||
GraphHandoffConversationToolCode = "graph/handoff_to_human"
|
Title: "加载专项技能说明",
|
||||||
GraphHandoffConversationToolName = "handoff_to_human"
|
Description: "用于加载当前命中的专项技能说明文档。仅在本轮已命中 Skill 时可用,适合将专项处理规则按需注入上下文。",
|
||||||
GraphHandoffConversationToolTitle = "转人工确认流程"
|
SourceType: "builtin",
|
||||||
GraphHandoffConversationToolDescription = "Graph Tool。用于封装转人工原因整理、用户确认、真正转人工和结果返回的确定性流程。"
|
AutoInjected: true,
|
||||||
BuiltinCreateTicketConfirmToolCode = "builtin/create_ticket_with_confirmation"
|
}
|
||||||
BuiltinCreateTicketConfirmToolName = "create_ticket_with_confirmation"
|
GraphTriageServiceRequest = ToolSpec{
|
||||||
BuiltinCreateTicketConfirmToolTitle = "创建工单并发起确认"
|
Code: "graph/triage_service_request",
|
||||||
BuiltinCreateTicketConfirmToolDescription = "当用户明确要求创建工单,且标题和描述已经整理清楚后调用。工具会先向用户确认,确认后才真正创建工单。"
|
ServerCode: "graph",
|
||||||
|
Name: "triage_service_request",
|
||||||
|
Title: "升级分流判断",
|
||||||
|
Description: "Graph Tool。用于综合分析当前对话,判断应继续解答、整理工单草稿还是转人工,并在需要建单时一并整理工单草稿。",
|
||||||
|
SourceType: "graph",
|
||||||
|
}
|
||||||
|
GraphAnalyzeConversation = ToolSpec{
|
||||||
|
Code: "graph/analyze_conversation",
|
||||||
|
ServerCode: "graph",
|
||||||
|
Name: "analyze_conversation",
|
||||||
|
Title: "分析对话风险与摘要",
|
||||||
|
Description: "Graph Tool。用于整理当前对话摘要、识别风险信号,并给出继续解答、建单或转人工的建议。",
|
||||||
|
SourceType: "graph",
|
||||||
|
}
|
||||||
|
GraphPrepareTicketDraft = ToolSpec{
|
||||||
|
Code: "graph/prepare_ticket_draft",
|
||||||
|
ServerCode: "graph",
|
||||||
|
Name: "prepare_ticket_draft",
|
||||||
|
Title: "整理工单草稿",
|
||||||
|
Description: "Graph Tool。用于根据当前会话和已收集信息整理工单草稿,输出建议标题、描述、缺失字段和追问建议。",
|
||||||
|
SourceType: "graph",
|
||||||
|
}
|
||||||
|
GraphCreateTicketConfirm = ToolSpec{
|
||||||
|
Code: "graph/create_ticket_with_confirmation",
|
||||||
|
ServerCode: "graph",
|
||||||
|
Name: "create_ticket_with_confirmation",
|
||||||
|
Title: "创建工单确认流程",
|
||||||
|
Description: "Graph Tool。用于封装建单参数整理、用户确认、真正建单和结果返回的确定性流程。",
|
||||||
|
SourceType: "graph",
|
||||||
|
Aliases: []string{"builtin/create_ticket_with_confirmation"},
|
||||||
|
}
|
||||||
|
GraphHandoffConversation = ToolSpec{
|
||||||
|
Code: "graph/handoff_to_human",
|
||||||
|
ServerCode: "graph",
|
||||||
|
Name: "handoff_to_human",
|
||||||
|
Title: "转人工确认流程",
|
||||||
|
Description: "Graph Tool。用于封装转人工原因整理、用户确认、真正转人工和结果返回的确定性流程。",
|
||||||
|
SourceType: "graph",
|
||||||
|
}
|
||||||
|
RegisteredToolSpecs = []ToolSpec{
|
||||||
|
BuiltinToolSearch,
|
||||||
|
BuiltinSkill,
|
||||||
|
GraphTriageServiceRequest,
|
||||||
|
GraphAnalyzeConversation,
|
||||||
|
GraphPrepareTicketDraft,
|
||||||
|
GraphCreateTicketConfirm,
|
||||||
|
GraphHandoffConversation,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
toolSpecByCode = buildToolSpecByCode()
|
||||||
|
toolAliasToCanonical = buildToolAliasToCanonical()
|
||||||
|
)
|
||||||
|
|
||||||
|
func buildToolSpecByCode() map[string]ToolSpec {
|
||||||
|
ret := make(map[string]ToolSpec, len(RegisteredToolSpecs))
|
||||||
|
for _, spec := range RegisteredToolSpecs {
|
||||||
|
if strings.TrimSpace(spec.Code) == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ret[spec.Code] = spec
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildToolAliasToCanonical() map[string]string {
|
||||||
|
ret := make(map[string]string)
|
||||||
|
for _, spec := range RegisteredToolSpecs {
|
||||||
|
for _, alias := range spec.Aliases {
|
||||||
|
alias = strings.TrimSpace(alias)
|
||||||
|
if alias == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ret[alias] = spec.Code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func ListRegisteredToolSpecs() []ToolSpec {
|
||||||
|
return append([]ToolSpec(nil), RegisteredToolSpecs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRegisteredToolSpec(toolCode string) (ToolSpec, bool) {
|
||||||
|
toolCode = NormalizeToolCodeAlias(strings.TrimSpace(toolCode))
|
||||||
|
spec, ok := toolSpecByCode[toolCode]
|
||||||
|
return spec, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRegisteredToolTitle(toolCode string) string {
|
||||||
|
spec, ok := GetRegisteredToolSpec(toolCode)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return spec.Title
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRegisteredToolDescription(toolCode string) string {
|
||||||
|
spec, ok := GetRegisteredToolSpec(toolCode)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return spec.Description
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRegisteredToolIdentity(toolCode string) (serverCode, toolName string, ok bool) {
|
||||||
|
spec, ok := GetRegisteredToolSpec(toolCode)
|
||||||
|
if !ok {
|
||||||
|
return "", "", false
|
||||||
|
}
|
||||||
|
return spec.ServerCode, spec.Name, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ResolveToolSourceType(toolCode string) string {
|
||||||
|
if spec, ok := GetRegisteredToolSpec(toolCode); ok {
|
||||||
|
return spec.SourceType
|
||||||
|
}
|
||||||
|
toolCode = strings.TrimSpace(toolCode)
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(toolCode, "graph/"):
|
||||||
|
return "graph"
|
||||||
|
case strings.HasPrefix(toolCode, "builtin/"):
|
||||||
|
return "builtin"
|
||||||
|
default:
|
||||||
|
return "mcp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func IsAutoInjectedToolCode(toolCode string) bool {
|
func IsAutoInjectedToolCode(toolCode string) bool {
|
||||||
return toolCode == BuiltinToolSearchToolCode || toolCode == BuiltinSkillToolCode
|
spec, ok := GetRegisteredToolSpec(toolCode)
|
||||||
|
return ok && spec.AutoInjected
|
||||||
}
|
}
|
||||||
|
|
||||||
func NormalizeToolCodeAlias(toolCode string) string {
|
func NormalizeToolCodeAlias(toolCode string) string {
|
||||||
switch toolCode {
|
toolCode = strings.TrimSpace(toolCode)
|
||||||
case BuiltinCreateTicketConfirmToolCode:
|
if canonical, ok := toolAliasToCanonical[toolCode]; ok {
|
||||||
return GraphCreateTicketConfirmToolCode
|
return canonical
|
||||||
default:
|
|
||||||
return toolCode
|
|
||||||
}
|
}
|
||||||
|
return toolCode
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,15 +106,15 @@ func (s *agentRunLogService) BuildGraphSummary(aiAgentID int64) *AgentRunGraphSu
|
|||||||
return cnd
|
return cnd
|
||||||
}
|
}
|
||||||
return &AgentRunGraphSummary{
|
return &AgentRunGraphSummary{
|
||||||
TriageCount: s.countByGraphTool(buildBaseCnd(), toolx.GraphTriageServiceRequestToolCode),
|
TriageCount: s.countByGraphTool(buildBaseCnd(), toolx.GraphTriageServiceRequest.Code),
|
||||||
TriagePrepareTicket: s.countByGraphToolAndPlanReason(buildBaseCnd(), toolx.GraphTriageServiceRequestToolCode, "%prepare_ticket%"),
|
TriagePrepareTicket: s.countByGraphToolAndPlanReason(buildBaseCnd(), toolx.GraphTriageServiceRequest.Code, "%prepare_ticket%"),
|
||||||
TriagePrepareTicketReady: s.countByGraphToolAndPlanReason(buildBaseCnd(), toolx.GraphTriageServiceRequestToolCode, "%prepare_ticket with ready ticket draft%"),
|
TriagePrepareTicketReady: s.countByGraphToolAndPlanReason(buildBaseCnd(), toolx.GraphTriageServiceRequest.Code, "%prepare_ticket with ready ticket draft%"),
|
||||||
TriageHandoff: s.countByGraphToolAndPlanReason(buildBaseCnd(), toolx.GraphTriageServiceRequestToolCode, "%handoff_to_human%"),
|
TriageHandoff: s.countByGraphToolAndPlanReason(buildBaseCnd(), toolx.GraphTriageServiceRequest.Code, "%handoff_to_human%"),
|
||||||
TriageContinueAnswering: s.countByGraphToolAndPlanReason(buildBaseCnd(), toolx.GraphTriageServiceRequestToolCode, "%continue_answering%"),
|
TriageContinueAnswering: s.countByGraphToolAndPlanReason(buildBaseCnd(), toolx.GraphTriageServiceRequest.Code, "%continue_answering%"),
|
||||||
AnalyzeCount: s.countByGraphTool(buildBaseCnd(), toolx.GraphAnalyzeConversationToolCode),
|
AnalyzeCount: s.countByGraphTool(buildBaseCnd(), toolx.GraphAnalyzeConversation.Code),
|
||||||
PrepareDraftCount: s.countByGraphTool(buildBaseCnd(), toolx.GraphPrepareTicketDraftToolCode),
|
PrepareDraftCount: s.countByGraphTool(buildBaseCnd(), toolx.GraphPrepareTicketDraft.Code),
|
||||||
CreateTicketCount: s.countByGraphTool(buildBaseCnd(), toolx.GraphCreateTicketConfirmToolCode),
|
CreateTicketCount: s.countByGraphTool(buildBaseCnd(), toolx.GraphCreateTicketConfirm.Code),
|
||||||
HandoffCount: s.countByGraphTool(buildBaseCnd(), toolx.GraphHandoffConversationToolCode),
|
HandoffCount: s.countByGraphTool(buildBaseCnd(), toolx.GraphHandoffConversation.Code),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,36 +34,38 @@ type MCPToolCatalogItem struct {
|
|||||||
func (s *toolCatalogService) ListMCPTools(ctx context.Context) ([]MCPToolCatalogItem, error) {
|
func (s *toolCatalogService) ListMCPTools(ctx context.Context) ([]MCPToolCatalogItem, error) {
|
||||||
cfg := config.Current()
|
cfg := config.Current()
|
||||||
ret := make([]MCPToolCatalogItem, 0, 3)
|
ret := make([]MCPToolCatalogItem, 0, 3)
|
||||||
ret = append(ret, MCPToolCatalogItem{
|
for _, toolCode := range []string{
|
||||||
ToolCode: toolx.GraphCreateTicketConfirmToolCode,
|
toolx.GraphCreateTicketConfirm.Code,
|
||||||
ServerCode: toolx.GraphToolCatalogServerCode,
|
toolx.GraphHandoffConversation.Code,
|
||||||
ToolName: toolx.GraphCreateTicketConfirmToolName,
|
} {
|
||||||
SourceType: toolx.GraphToolCatalogServerCode,
|
spec, ok := toolx.GetRegisteredToolSpec(toolCode)
|
||||||
AutoInjected: false,
|
if !ok {
|
||||||
Title: toolx.GraphCreateTicketConfirmToolTitle,
|
continue
|
||||||
Description: toolx.GraphCreateTicketConfirmToolDescription,
|
}
|
||||||
})
|
ret = append(ret, MCPToolCatalogItem{
|
||||||
ret = append(ret, MCPToolCatalogItem{
|
ToolCode: spec.Code,
|
||||||
ToolCode: toolx.GraphHandoffConversationToolCode,
|
ServerCode: spec.ServerCode,
|
||||||
ServerCode: toolx.GraphToolCatalogServerCode,
|
ToolName: spec.Name,
|
||||||
ToolName: toolx.GraphHandoffConversationToolName,
|
SourceType: spec.SourceType,
|
||||||
SourceType: toolx.GraphToolCatalogServerCode,
|
AutoInjected: spec.AutoInjected,
|
||||||
AutoInjected: false,
|
Title: spec.Title,
|
||||||
Title: toolx.GraphHandoffConversationToolTitle,
|
Description: spec.Description,
|
||||||
Description: toolx.GraphHandoffConversationToolDescription,
|
})
|
||||||
})
|
}
|
||||||
if !cfg.MCP.Enabled {
|
if !cfg.MCP.Enabled {
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
ret = append(ret, MCPToolCatalogItem{
|
if spec, ok := toolx.GetRegisteredToolSpec(toolx.BuiltinToolSearch.Code); ok {
|
||||||
ToolCode: toolx.BuiltinToolSearchToolCode,
|
ret = append(ret, MCPToolCatalogItem{
|
||||||
ServerCode: toolx.BuiltinToolCatalogServerCode,
|
ToolCode: spec.Code,
|
||||||
ToolName: toolx.BuiltinToolSearchToolName,
|
ServerCode: spec.ServerCode,
|
||||||
SourceType: toolx.BuiltinToolCatalogServerCode,
|
ToolName: spec.Name,
|
||||||
AutoInjected: true,
|
SourceType: spec.SourceType,
|
||||||
Title: toolx.BuiltinToolSearchToolTitle,
|
AutoInjected: spec.AutoInjected,
|
||||||
Description: toolx.BuiltinToolSearchToolDescription,
|
Title: spec.Title,
|
||||||
})
|
Description: spec.Description,
|
||||||
|
})
|
||||||
|
}
|
||||||
serverCodes := make([]string, 0, len(cfg.MCP.Servers))
|
serverCodes := make([]string, 0, len(cfg.MCP.Servers))
|
||||||
for serverCode, server := range cfg.MCP.Servers {
|
for serverCode, server := range cfg.MCP.Servers {
|
||||||
if !server.Enabled {
|
if !server.Enabled {
|
||||||
@@ -105,7 +107,7 @@ func (s *toolCatalogService) ValidateToolCode(toolCode string) error {
|
|||||||
return errorsx.InvalidParam("toolCode不能为空")
|
return errorsx.InvalidParam("toolCode不能为空")
|
||||||
}
|
}
|
||||||
switch toolCode {
|
switch toolCode {
|
||||||
case toolx.BuiltinToolSearchToolCode, toolx.BuiltinCreateTicketConfirmToolCode, toolx.GraphCreateTicketConfirmToolCode, toolx.GraphHandoffConversationToolCode:
|
case toolx.BuiltinToolSearch.Code, "builtin/create_ticket_with_confirmation", toolx.GraphCreateTicketConfirm.Code, toolx.GraphHandoffConversation.Code:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
serverCode, toolName := toolx.SplitMCPToolCode(toolCode)
|
serverCode, toolName := toolx.SplitMCPToolCode(toolCode)
|
||||||
|
|||||||
Reference in New Issue
Block a user