feat: enhance handoff reason extraction and improve trace data handling in run log service

This commit is contained in:
mlogclub
2026-04-14 11:45:55 +08:00
parent 13903baf61
commit 48ad418f06
2 changed files with 46 additions and 24 deletions
+18
View File
@@ -85,6 +85,24 @@ func TestGraphPlanReason(t *testing.T) {
} }
} }
func TestExtractHandoffReason(t *testing.T) {
summary := &Summary{
TraceData: `{
"graphTools": {
"items": [
{
"toolCode":"` + toolx.GraphHandoffConversation.Code + `",
"arguments":{"reason":" 用户明确要求人工处理 "}
}
]
}
}`,
}
if got := extractHandoffReason(summary); got != "用户明确要求人工处理" {
t.Fatalf("unexpected handoff reason: %q", got)
}
}
type fakeErr string type fakeErr string
func (e fakeErr) Error() string { func (e fakeErr) Error() string {
+28 -24
View File
@@ -208,10 +208,14 @@ func extractToolSearchTrace(summary *Summary) string {
return "" return ""
} }
trace := parseRuntimeTraceData(summary.TraceData) trace := parseRuntimeTraceData(summary.TraceData)
if len(trace.ToolSearch.Items) == 0 || len(trace.ToolSearch.Raw) == 0 { if len(trace.ToolSearch.Items) == 0 {
return "" return ""
} }
return string(trace.ToolSearch.Raw) buf, err := json.Marshal(trace.ToolSearch)
if err != nil {
return ""
}
return string(buf)
} }
func extractGraphToolTrace(summary *Summary) string { func extractGraphToolTrace(summary *Summary) string {
@@ -219,10 +223,14 @@ func extractGraphToolTrace(summary *Summary) string {
return "" return ""
} }
trace := parseRuntimeTraceData(summary.TraceData) trace := parseRuntimeTraceData(summary.TraceData)
if len(trace.GraphTools.Items) == 0 || len(trace.GraphTools.Raw) == 0 { if len(trace.GraphTools.Items) == 0 {
return "" return ""
} }
return string(trace.GraphTools.Raw) buf, err := json.Marshal(trace.GraphTools)
if err != nil {
return ""
}
return string(buf)
} }
func firstToolSearchTargetToolCode(summary *Summary) string { func firstToolSearchTargetToolCode(summary *Summary) string {
@@ -262,8 +270,11 @@ func extractHandoffReason(summary *Summary) string {
if len(item.Arguments) == 0 { if len(item.Arguments) == 0 {
return "" return ""
} }
reason, _ := item.Arguments["reason"].(string) var args runtimeTraceHandoffArguments
return strings.TrimSpace(reason) if err := json.Unmarshal(item.Arguments, &args); err != nil {
return ""
}
return strings.TrimSpace(args.Reason)
} }
return "" return ""
} }
@@ -302,41 +313,34 @@ func graphPlanReason(summary *Summary) string {
type runtimeTraceProjection struct { type runtimeTraceProjection struct {
ToolSearch struct { ToolSearch struct {
Raw json.RawMessage `json:"-"`
Items []struct { Items []struct {
TargetToolCode string `json:"targetToolCode"` TargetToolCode string `json:"targetToolCode"`
CandidateToolCodes []string `json:"candidateToolCodes"` CandidateToolCodes []string `json:"candidateToolCodes"`
} `json:"items"` } `json:"items"`
} `json:"toolSearch"` } `json:"toolSearch"`
GraphTools struct { GraphTools struct {
Raw json.RawMessage `json:"-"`
Items []struct { Items []struct {
ToolCode string `json:"toolCode"` ToolCode string `json:"toolCode"`
Arguments map[string]any `json:"arguments"` Arguments json.RawMessage `json:"arguments"`
RecommendedAction string `json:"recommendedAction"` RecommendedAction string `json:"recommendedAction"`
RiskLevel string `json:"riskLevel"` RiskLevel string `json:"riskLevel"`
TicketDraftReady bool `json:"ticketDraftReady"` TicketDraftReady bool `json:"ticketDraftReady"`
} `json:"items"` } `json:"items"`
} `json:"graphTools"` } `json:"graphTools"`
} }
type runtimeTraceHandoffArguments struct {
Reason string `json:"reason"`
}
func parseRuntimeTraceData(raw string) runtimeTraceProjection { func parseRuntimeTraceData(raw string) runtimeTraceProjection {
raw = strings.TrimSpace(raw) raw = strings.TrimSpace(raw)
if raw == "" { if raw == "" {
return runtimeTraceProjection{} return runtimeTraceProjection{}
} }
var payload map[string]json.RawMessage
if err := json.Unmarshal([]byte(raw), &payload); err != nil {
return runtimeTraceProjection{}
}
var trace runtimeTraceProjection var trace runtimeTraceProjection
if toolSearchRaw, ok := payload["toolSearch"]; ok && len(toolSearchRaw) > 0 { if err := json.Unmarshal([]byte(raw), &trace); err != nil {
trace.ToolSearch.Raw = append(json.RawMessage(nil), toolSearchRaw...) return runtimeTraceProjection{}
_ = json.Unmarshal(toolSearchRaw, &trace.ToolSearch)
}
if graphToolsRaw, ok := payload["graphTools"]; ok && len(graphToolsRaw) > 0 {
trace.GraphTools.Raw = append(json.RawMessage(nil), graphToolsRaw...)
_ = json.Unmarshal(graphToolsRaw, &trace.GraphTools)
} }
return trace return trace
} }