feat: implement tool search tracing and logging in agent run logs
This commit is contained in:
@@ -6,6 +6,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"cs-agent/internal/pkg/toolx"
|
||||
|
||||
einotool "github.com/cloudwego/eino/components/tool"
|
||||
|
||||
"github.com/cloudwego/eino/adk"
|
||||
@@ -56,10 +58,25 @@ func (h *RuntimeTraceHandler) WrapInvokableToolCall(_ context.Context, endpoint
|
||||
item.ErrorMessage = err.Error()
|
||||
}
|
||||
h.collector.AddToolItem(item)
|
||||
if metadata, ok := h.resolveToolMetadata(item.ToolName); ok && strings.TrimSpace(metadata.ToolCode) == toolx.BuiltinToolSearchToolCode {
|
||||
h.collector.AddToolSearchItem(buildToolSearchTraceItem(argumentsInJSON, result, err))
|
||||
}
|
||||
return result, err
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (h *RuntimeTraceHandler) resolveToolMetadata(modelToolName string) (ToolMetadata, bool) {
|
||||
if h == nil || h.toolMetadataBy == nil {
|
||||
return ToolMetadata{}, false
|
||||
}
|
||||
modelToolName = strings.TrimSpace(modelToolName)
|
||||
if modelToolName == "" {
|
||||
return ToolMetadata{}, false
|
||||
}
|
||||
metadata, ok := h.toolMetadataBy[modelToolName]
|
||||
return metadata, ok
|
||||
}
|
||||
|
||||
func parseToolArguments(argumentsInJSON string) map[string]any {
|
||||
argumentsInJSON = strings.TrimSpace(argumentsInJSON)
|
||||
if argumentsInJSON == "" {
|
||||
@@ -83,3 +100,62 @@ func previewToolText(text string, limit int) string {
|
||||
}
|
||||
return string(runes[:limit]) + "..."
|
||||
}
|
||||
|
||||
func buildToolSearchTraceItem(argumentsInJSON string, result string, runErr error) ToolSearchTraceItem {
|
||||
item := ToolSearchTraceItem{
|
||||
Status: "ok",
|
||||
}
|
||||
args := parseToolArguments(argumentsInJSON)
|
||||
item.Query = strings.TrimSpace(readToolSearchString(args, "query"))
|
||||
item.TargetToolCode = strings.TrimSpace(readToolSearchString(args, "toolCode"))
|
||||
if item.TargetToolCode != "" {
|
||||
item.Action = "invoke"
|
||||
item.TargetServerCode, item.TargetToolName = toolx.SplitMCPToolCode(item.TargetToolCode)
|
||||
} else {
|
||||
item.Action = "search"
|
||||
}
|
||||
if runErr != nil {
|
||||
item.Status = "error"
|
||||
item.ErrorMessage = runErr.Error()
|
||||
return item
|
||||
}
|
||||
payload := make(map[string]any)
|
||||
if err := json.Unmarshal([]byte(strings.TrimSpace(result)), &payload); err != nil {
|
||||
return item
|
||||
}
|
||||
candidateItems, _ := payload["candidates"].([]any)
|
||||
item.CandidateToolCodes = extractCandidateToolCodes(candidateItems)
|
||||
return item
|
||||
}
|
||||
|
||||
func readToolSearchString(data map[string]any, key string) string {
|
||||
if len(data) == 0 {
|
||||
return ""
|
||||
}
|
||||
value, ok := data[key]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
text, _ := value.(string)
|
||||
return text
|
||||
}
|
||||
|
||||
func extractCandidateToolCodes(items []any) []string {
|
||||
if len(items) == 0 {
|
||||
return nil
|
||||
}
|
||||
ret := make([]string, 0, len(items))
|
||||
for _, item := range items {
|
||||
payload, ok := item.(map[string]any)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
toolCode, _ := payload["toolCode"].(string)
|
||||
toolCode = strings.TrimSpace(toolCode)
|
||||
if toolCode == "" {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, toolCode)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -39,3 +39,13 @@ func (c *RuntimeTraceCollector) AddToolItem(item ToolTraceItem) {
|
||||
c.Data.Tools.Count++
|
||||
c.Data.Tools.Items = append(c.Data.Tools.Items, item)
|
||||
}
|
||||
|
||||
func (c *RuntimeTraceCollector) AddToolSearchItem(item ToolSearchTraceItem) {
|
||||
if c == nil {
|
||||
return
|
||||
}
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
c.Data.ToolSearch.Count++
|
||||
c.Data.ToolSearch.Items = append(c.Data.ToolSearch.Items, item)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,17 @@ type ToolTraceItem struct {
|
||||
ErrorMessage string `json:"errorMessage,omitempty"`
|
||||
}
|
||||
|
||||
type ToolSearchTraceItem struct {
|
||||
Action string `json:"action,omitempty"`
|
||||
Query string `json:"query,omitempty"`
|
||||
TargetToolCode string `json:"targetToolCode,omitempty"`
|
||||
TargetServerCode string `json:"targetServerCode,omitempty"`
|
||||
TargetToolName string `json:"targetToolName,omitempty"`
|
||||
CandidateToolCodes []string `json:"candidateToolCodes,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
ErrorMessage string `json:"errorMessage,omitempty"`
|
||||
}
|
||||
|
||||
type RetrieverTraceItem struct {
|
||||
Query string `json:"query,omitempty"`
|
||||
KnowledgeBaseID int64 `json:"knowledgeBaseId,omitempty"`
|
||||
@@ -47,6 +58,10 @@ type RuntimeTraceData struct {
|
||||
Count int `json:"count,omitempty"`
|
||||
Items []ToolTraceItem `json:"items,omitempty"`
|
||||
} `json:"tools"`
|
||||
ToolSearch struct {
|
||||
Count int `json:"count,omitempty"`
|
||||
Items []ToolSearchTraceItem `json:"items,omitempty"`
|
||||
} `json:"toolSearch"`
|
||||
Output struct {
|
||||
ReplyText string `json:"replyText,omitempty"`
|
||||
FinishReason string `json:"finishReason,omitempty"`
|
||||
|
||||
Reference in New Issue
Block a user