feat: enhance tooling management with static and dynamic tool code handling

This commit is contained in:
mlogclub
2026-04-11 22:50:35 +08:00
parent e6d0fa2ba2
commit be17807152
4 changed files with 102 additions and 7 deletions
@@ -97,6 +97,7 @@ func (s *Service) Run(ctx context.Context, req Request) (*Summary, error) {
toolDefsByModelName[modelName] = toolCode
}
collector.Data.Input.ToolCodes = append(collector.Data.Input.ToolCodes, summary.ToolCodes...)
collector.SetTooling(staticToolCodeList(req.ToolSet), definitionToolCodes(filteredToolDefs), len(filteredToolDefs) > 0)
collector.Data.Model.Provider = string(req.AIConfig.Provider)
collector.Data.Model.Name = req.AIConfig.ModelName
@@ -250,6 +251,7 @@ func (s *Service) Resume(ctx context.Context, req ResumeRequest) (*Summary, erro
toolDefsByModelName[modelName] = toolCode
}
collector.Data.Input.ToolCodes = append(collector.Data.Input.ToolCodes, summary.ToolCodes...)
collector.SetTooling(staticToolCodeList(req.ToolSet), definitionToolCodes(toolDefs), len(toolDefs) > 0)
collector.Data.Model.Provider = string(req.AIConfig.Provider)
collector.Data.Model.Name = req.AIConfig.ModelName
agent, err := s.agentFactory.BuildCustomerServiceAgent(ctx, factory.BuildCustomerServiceAgentInput{
@@ -559,3 +561,34 @@ func toolSetStaticToolCodes(toolSet *registry.ToolSet) map[string]string {
}
return toolSet.StaticToolCodes
}
func definitionToolCodes(definitions []adapter.MCPToolDefinition) []string {
if len(definitions) == 0 {
return nil
}
ret := make([]string, 0, len(definitions))
for _, item := range definitions {
toolCode := strings.TrimSpace(item.ToolCode)
if toolCode == "" {
continue
}
ret = append(ret, toolCode)
}
return ret
}
func staticToolCodeList(toolSet *registry.ToolSet) []string {
toolCodes := toolSetStaticToolCodes(toolSet)
if len(toolCodes) == 0 {
return nil
}
ret := make([]string, 0, len(toolCodes))
for _, toolCode := range toolCodes {
toolCode = strings.TrimSpace(toolCode)
if toolCode == "" {
continue
}
ret = append(ret, toolCode)
}
return ret
}
@@ -122,12 +122,19 @@ func previewToolText(text string, limit int) string {
}
func (h *RuntimeTraceHandler) buildToolSearchTraceItem(argumentsInJSON string, result string, runErr error) ToolSearchTraceItem {
item := ToolSearchTraceItem{
Action: "search",
Status: "ok",
}
item := ToolSearchTraceItem{Status: "ok"}
args := parseToolArguments(argumentsInJSON)
item.Query = strings.TrimSpace(readToolSearchString(args, "regex_pattern"))
item.Query = strings.TrimSpace(firstNonBlank(
readToolSearchString(args, "query"),
readToolSearchString(args, "regex_pattern"),
))
item.TargetToolCode = strings.TrimSpace(readToolSearchString(args, "toolCode"))
item.TargetServerCode, item.TargetToolName = toolx.SplitMCPToolCode(item.TargetToolCode)
if item.TargetToolCode != "" {
item.Action = "invoke"
} else {
item.Action = "search"
}
if runErr != nil {
item.Status = "error"
item.ErrorMessage = runErr.Error()
@@ -137,8 +144,7 @@ func (h *RuntimeTraceHandler) buildToolSearchTraceItem(argumentsInJSON string, r
if err := json.Unmarshal([]byte(strings.TrimSpace(result)), &payload); err != nil {
return item
}
selectedTools, _ := payload["selectedTools"].([]any)
item.CandidateToolCodes = h.extractSelectedToolCodes(selectedTools)
item.CandidateToolCodes = h.extractCandidateToolCodes(payload)
return item
}
@@ -154,6 +160,29 @@ func readToolSearchString(data map[string]any, key string) string {
return text
}
func firstNonBlank(values ...string) string {
for _, value := range values {
value = strings.TrimSpace(value)
if value != "" {
return value
}
}
return ""
}
func (h *RuntimeTraceHandler) extractCandidateToolCodes(payload map[string]any) []string {
if len(payload) == 0 {
return nil
}
if items, ok := payload["selectedTools"].([]any); ok {
return h.extractSelectedToolCodes(items)
}
if items, ok := payload["candidates"].([]any); ok {
return h.extractCandidateObjects(items)
}
return nil
}
func (h *RuntimeTraceHandler) extractSelectedToolCodes(items []any) []string {
if len(items) == 0 {
return nil
@@ -179,3 +208,22 @@ func (h *RuntimeTraceHandler) extractSelectedToolCodes(items []any) []string {
}
return ret
}
func (h *RuntimeTraceHandler) extractCandidateObjects(items []any) []string {
if len(items) == 0 {
return nil
}
ret := make([]string, 0, len(items))
for _, item := range items {
obj, ok := item.(map[string]any)
if !ok {
continue
}
toolCode := strings.TrimSpace(readToolSearchString(obj, "toolCode"))
if toolCode == "" {
continue
}
ret = append(ret, toolCode)
}
return ret
}
@@ -30,6 +30,17 @@ func (c *RuntimeTraceCollector) Marshal() string {
return string(buf)
}
func (c *RuntimeTraceCollector) SetTooling(staticToolCodes []string, dynamicToolCodes []string, toolSearchEnabled bool) {
if c == nil {
return
}
c.mu.Lock()
defer c.mu.Unlock()
c.Data.Input.StaticToolCodes = append([]string(nil), staticToolCodes...)
c.Data.Input.DynamicToolCodes = append([]string(nil), dynamicToolCodes...)
c.Data.Input.ToolSearchEnabled = toolSearchEnabled
}
func (c *RuntimeTraceCollector) AddToolItem(item ToolTraceItem) {
if c == nil {
return
@@ -58,6 +58,9 @@ type RuntimeTraceData struct {
HistoryMessageCount int `json:"historyMessageCount,omitempty"`
KnowledgeBaseIDs []int64 `json:"knowledgeBaseIds,omitempty"`
ToolCodes []string `json:"toolCodes,omitempty"`
StaticToolCodes []string `json:"staticToolCodes,omitempty"`
DynamicToolCodes []string `json:"dynamicToolCodes,omitempty"`
ToolSearchEnabled bool `json:"toolSearchEnabled,omitempty"`
CurrentUserMessagePreview string `json:"currentUserMessagePreview,omitempty"`
} `json:"input"`
Retriever struct {