feat: enhance graph tool handling by adding recommended action, risk level, and ticket draft readiness
This commit is contained in:
@@ -65,17 +65,21 @@ func (h *RuntimeTraceHandler) WrapInvokableToolCall(_ context.Context, endpoint
|
||||
}
|
||||
h.collector.AddToolItem(item)
|
||||
if metadata, ok := h.resolveToolMetadata(item.ToolName); ok && strings.TrimSpace(metadata.SourceType) == toolx.GraphToolCatalogServerCode {
|
||||
recommendedAction, riskLevel, ticketDraftReady := parseGraphToolOutcome(item.ToolCode, result)
|
||||
h.collector.AddGraphToolItem(GraphToolTraceItem{
|
||||
ToolCode: item.ToolCode,
|
||||
ToolName: item.ToolName,
|
||||
Arguments: item.Arguments,
|
||||
ResultPreview: item.ResultPreview,
|
||||
ResultReduced: item.ResultReduced,
|
||||
OriginalChars: item.OriginalChars,
|
||||
KeptChars: item.KeptChars,
|
||||
LatencyMs: item.LatencyMs,
|
||||
Status: item.Status,
|
||||
ErrorMessage: item.ErrorMessage,
|
||||
ToolCode: item.ToolCode,
|
||||
ToolName: item.ToolName,
|
||||
Arguments: item.Arguments,
|
||||
ResultPreview: item.ResultPreview,
|
||||
ResultReduced: item.ResultReduced,
|
||||
OriginalChars: item.OriginalChars,
|
||||
KeptChars: item.KeptChars,
|
||||
LatencyMs: item.LatencyMs,
|
||||
Status: item.Status,
|
||||
ErrorMessage: item.ErrorMessage,
|
||||
RecommendedAction: recommendedAction,
|
||||
RiskLevel: riskLevel,
|
||||
TicketDraftReady: ticketDraftReady,
|
||||
})
|
||||
}
|
||||
if metadata, ok := h.resolveToolMetadata(item.ToolName); ok && strings.TrimSpace(metadata.ToolCode) == toolx.BuiltinToolSearchToolCode {
|
||||
@@ -85,6 +89,33 @@ func (h *RuntimeTraceHandler) WrapInvokableToolCall(_ context.Context, endpoint
|
||||
}, nil
|
||||
}
|
||||
|
||||
func parseGraphToolOutcome(toolCode string, result string) (recommendedAction, riskLevel string, ticketDraftReady bool) {
|
||||
toolCode = strings.TrimSpace(toolCode)
|
||||
if toolCode == "" || strings.TrimSpace(result) == "" {
|
||||
return "", "", false
|
||||
}
|
||||
payload := make(map[string]any)
|
||||
if err := json.Unmarshal([]byte(strings.TrimSpace(result)), &payload); err != nil {
|
||||
return "", "", false
|
||||
}
|
||||
switch toolCode {
|
||||
case toolx.GraphAnalyzeConversationToolCode:
|
||||
return strings.TrimSpace(readToolSearchString(payload, "recommendedNextAction")), strings.TrimSpace(readToolSearchString(payload, "riskLevel")), false
|
||||
case toolx.GraphTriageServiceRequestToolCode:
|
||||
recommendedAction = strings.TrimSpace(readToolSearchString(payload, "recommendedAction"))
|
||||
if analysis, ok := payload["analysis"].(map[string]any); ok {
|
||||
riskLevel = strings.TrimSpace(readToolSearchString(analysis, "riskLevel"))
|
||||
}
|
||||
if ticketDraft, ok := payload["ticketDraft"].(map[string]any); ok {
|
||||
ready, _ := ticketDraft["ready"].(bool)
|
||||
ticketDraftReady = ready
|
||||
}
|
||||
return recommendedAction, riskLevel, ticketDraftReady
|
||||
default:
|
||||
return "", "", false
|
||||
}
|
||||
}
|
||||
|
||||
func (h *RuntimeTraceHandler) resolveToolMetadata(modelToolName string) (ToolMetadata, bool) {
|
||||
if h == nil || h.toolMetadataBy == nil {
|
||||
return ToolMetadata{}, false
|
||||
|
||||
@@ -26,16 +26,19 @@ type ToolSearchTraceItem struct {
|
||||
}
|
||||
|
||||
type GraphToolTraceItem struct {
|
||||
ToolCode string `json:"toolCode"`
|
||||
ToolName string `json:"toolName"`
|
||||
Arguments map[string]any `json:"arguments,omitempty"`
|
||||
ResultPreview string `json:"resultPreview,omitempty"`
|
||||
ResultReduced bool `json:"resultReduced,omitempty"`
|
||||
OriginalChars int `json:"originalChars,omitempty"`
|
||||
KeptChars int `json:"keptChars,omitempty"`
|
||||
LatencyMs int64 `json:"latencyMs,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
ErrorMessage string `json:"errorMessage,omitempty"`
|
||||
ToolCode string `json:"toolCode"`
|
||||
ToolName string `json:"toolName"`
|
||||
Arguments map[string]any `json:"arguments,omitempty"`
|
||||
ResultPreview string `json:"resultPreview,omitempty"`
|
||||
ResultReduced bool `json:"resultReduced,omitempty"`
|
||||
OriginalChars int `json:"originalChars,omitempty"`
|
||||
KeptChars int `json:"keptChars,omitempty"`
|
||||
LatencyMs int64 `json:"latencyMs,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
ErrorMessage string `json:"errorMessage,omitempty"`
|
||||
RecommendedAction string `json:"recommendedAction,omitempty"`
|
||||
RiskLevel string `json:"riskLevel,omitempty"`
|
||||
TicketDraftReady bool `json:"ticketDraftReady,omitempty"`
|
||||
}
|
||||
|
||||
type RetrieverTraceItem struct {
|
||||
|
||||
@@ -360,13 +360,21 @@ func buildRunLogPlan(summary *Summary) (plannedAction, plannedToolCode, planReas
|
||||
}
|
||||
if summary.Interrupted {
|
||||
if graphToolCode := firstGraphToolCode(summary); graphToolCode != "" {
|
||||
return "graph", graphToolCode, "graph tool interrupted and is waiting for user confirmation"
|
||||
reason := graphPlanReason(summary)
|
||||
if reason == "" {
|
||||
reason = "graph tool interrupted and is waiting for user confirmation"
|
||||
}
|
||||
return "graph", graphToolCode, reason
|
||||
}
|
||||
return "tool", summaryPrimaryToolCode(summary), "agent interrupted and is waiting for user confirmation"
|
||||
}
|
||||
if len(summary.InvokedToolCodes) > 0 {
|
||||
if graphToolCode := firstGraphToolCode(summary); graphToolCode != "" {
|
||||
return "graph", graphToolCode, "agent invoked graph tool"
|
||||
reason := graphPlanReason(summary)
|
||||
if reason == "" {
|
||||
reason = "agent invoked graph tool"
|
||||
}
|
||||
return "graph", graphToolCode, reason
|
||||
}
|
||||
toolCode := summaryPrimaryToolCode(summary)
|
||||
reason := "agent invoked MCP tool"
|
||||
@@ -615,6 +623,38 @@ func extractHandoffReason(summary *Summary) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func graphPlanReason(summary *Summary) string {
|
||||
trace := parseRuntimeTraceData(summary.TraceData)
|
||||
for _, item := range trace.GraphTools.Items {
|
||||
toolCode := strings.TrimSpace(item.ToolCode)
|
||||
switch toolCode {
|
||||
case toolx.GraphTriageServiceRequestToolCode:
|
||||
recommendedAction := strings.TrimSpace(item.RecommendedAction)
|
||||
if recommendedAction == "" {
|
||||
return "graph tool triaged service request"
|
||||
}
|
||||
if item.TicketDraftReady {
|
||||
return "graph tool triaged service request: " + recommendedAction + " with ready ticket draft"
|
||||
}
|
||||
return "graph tool triaged service request: " + recommendedAction
|
||||
case toolx.GraphAnalyzeConversationToolCode:
|
||||
recommendedAction := strings.TrimSpace(item.RecommendedAction)
|
||||
riskLevel := strings.TrimSpace(item.RiskLevel)
|
||||
switch {
|
||||
case recommendedAction != "" && riskLevel != "":
|
||||
return "graph tool analyzed conversation: " + recommendedAction + " (" + riskLevel + " risk)"
|
||||
case recommendedAction != "":
|
||||
return "graph tool analyzed conversation: " + recommendedAction
|
||||
case riskLevel != "":
|
||||
return "graph tool analyzed conversation (" + riskLevel + " risk)"
|
||||
default:
|
||||
return "graph tool analyzed conversation"
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type runtimeTraceProjection struct {
|
||||
ToolSearch struct {
|
||||
Raw json.RawMessage `json:"-"`
|
||||
@@ -626,8 +666,11 @@ type runtimeTraceProjection struct {
|
||||
GraphTools struct {
|
||||
Raw json.RawMessage `json:"-"`
|
||||
Items []struct {
|
||||
ToolCode string `json:"toolCode"`
|
||||
Arguments map[string]any `json:"arguments"`
|
||||
ToolCode string `json:"toolCode"`
|
||||
Arguments map[string]any `json:"arguments"`
|
||||
RecommendedAction string `json:"recommendedAction"`
|
||||
RiskLevel string `json:"riskLevel"`
|
||||
TicketDraftReady bool `json:"ticketDraftReady"`
|
||||
} `json:"items"`
|
||||
} `json:"graphTools"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user