diff --git a/internal/util/toolcalls_parse_markup.go b/internal/util/toolcalls_parse_markup.go index b7b2908..355a464 100644 --- a/internal/util/toolcalls_parse_markup.go +++ b/internal/util/toolcalls_parse_markup.go @@ -15,6 +15,7 @@ var antmlArgumentPattern = regexp.MustCompile(`(?is)<(?:[a-z0-9_]+:)?argument\s+ var antmlParametersPattern = regexp.MustCompile(`(?is)<(?:[a-z0-9_]+:)?parameters\s*>\s*(\{.*?\})\s*`) var invokeCallPattern = regexp.MustCompile(`(?is)(.*?)`) var invokeParamPattern = regexp.MustCompile(`(?is)\s*(.*?)\s*`) +var invokeArgumentPattern = regexp.MustCompile(`(?is)\s*(.*?)\s*`) func parseXMLToolCalls(text string) []ParsedToolCall { matches := xmlToolCallPattern.FindAllString(text, -1) @@ -111,6 +112,14 @@ func parseSingleXMLToolCall(block string) (ParsedToolCall, bool) { } } } + if fallback := parseMarkupSingleToolCall("", inner); fallback.Name != "" { + if strings.TrimSpace(name) == "" { + name = fallback.Name + } + if len(params) == 0 && strings.EqualFold(strings.TrimSpace(fallback.Name), strings.TrimSpace(name)) { + params = fallback.Input + } + } if strings.TrimSpace(name) == "" { return ParsedToolCall{}, false } @@ -210,6 +219,23 @@ func parseInvokeFunctionCallStyle(text string) (ParsedToolCall, bool) { input[k] = v } } + for _, am := range invokeArgumentPattern.FindAllStringSubmatch(m[2], -1) { + if len(am) < 3 { + continue + } + key := strings.TrimSpace(am[1]) + raw := strings.TrimSpace(am[2]) + if raw == "" { + continue + } + if key != "" { + input[key] = raw + continue + } + for k, v := range parseToolCallInput(raw) { + input[k] = v + } + } return ParsedToolCall{Name: name, Input: input}, true } diff --git a/internal/util/toolcalls_test.go b/internal/util/toolcalls_test.go index 3ace015..fb5c246 100644 --- a/internal/util/toolcalls_test.go +++ b/internal/util/toolcalls_test.go @@ -271,7 +271,6 @@ func TestParseToolCallsSupportsMultipleAntmlFunctionCalls(t *testing.T) { t.Fatalf("expected canonical names [bash read], got %#v", calls) } } - func TestParseToolCallsDoesNotAcceptMismatchedMarkupTags(t *testing.T) { text := `read_file{"path":"README.md"}` calls := ParseToolCalls(text, []string{"read_file"})