Support toolCall XML tags and XML child arguments in DetectToolCalls

This commit is contained in:
Luxferre
2026-09-07 14:45:51 +03:00
parent 16c4ed1e91
commit e505f44f4a
2 changed files with 55 additions and 0 deletions
+39
View File
@@ -658,7 +658,10 @@ type ToolTagPair struct {
var ToolTagPairs = []ToolTagPair{
{Start: "<tool_call>", End: "</tool_call>"},
{Start: "<tool_calls>", End: "</tool_calls>"},
{Start: "<toolCall>", End: "</toolCall>"},
{Start: "<toolCalls>", End: "</toolCalls>"},
{Start: "<function_call>", End: "</function_call>"},
{Start: "<functionCall>", End: "</functionCall>"},
{Start: "[TOOL_CALLS]", End: "[/TOOL_CALLS]"},
}
@@ -903,6 +906,36 @@ func parseXMLToolCall(block string) ([]ToolCall, bool) {
}
}
if argsStr != "" && !json.Valid([]byte(argsStr)) {
reTagOpen := regexp.MustCompile(`<([a-zA-Z0-9_-]+)>`)
openMatches := reTagOpen.FindAllStringSubmatchIndex(argsStr, -1)
if len(openMatches) > 0 {
xmlMap := make(map[string]interface{})
for _, match := range openMatches {
tagName := argsStr[match[2]:match[3]]
closeTag := "</" + tagName + ">"
closeIdx := strings.Index(argsStr[match[1]:], closeTag)
if closeIdx != -1 {
v := strings.TrimSpace(argsStr[match[1] : match[1]+closeIdx])
if num, err := strconv.ParseFloat(v, 64); err == nil && !strings.HasPrefix(v, "0") {
xmlMap[tagName] = num
} else if v == "true" {
xmlMap[tagName] = true
} else if v == "false" {
xmlMap[tagName] = false
} else {
xmlMap[tagName] = v
}
}
}
if len(xmlMap) > 0 {
if b, err := json.Marshal(xmlMap); err == nil {
argsStr = string(b)
}
}
}
}
if fnName != "" {
if argsStr == "" {
argsStr = "{}"
@@ -976,6 +1009,12 @@ func DetectToolCalls(content string) ([]ToolCall, string, bool) {
}
if len(calls) > 0 {
remaining = strings.TrimSpace(remaining)
if remaining == "```xml" || remaining == "```" || remaining == "```json" {
remaining = ""
}
reEmptyFence := regexp.MustCompile("(?m)^```(?:xml|json)?\\s*\\n?\\s*```\\s*$")
remaining = strings.TrimSpace(reEmptyFence.ReplaceAllString(remaining, ""))
return calls, remaining, true
}