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*(?:[a-z0-9_]+:)?parameters>`)
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"})