package toolcall import "strings" func normalizeDSMLToolCallMarkup(text string) (string, bool) { if text == "" { return "", true } hasDSML, hasCanonical := toolMarkupStylesOutsideIgnored(text) if hasDSML && hasCanonical { return text, false } if !hasDSML { return text, true } return replaceDSMLToolMarkupOutsideIgnored(text), true } var dsmlToolMarkupAliases = []struct { from string to string }{ {"<|dsml|tool_calls", "", ""}, {"<|dsml|invoke", "", ""}, {"<|dsml|parameter", "", ""}, } var canonicalToolMarkupPrefixes = []string{ "", "", "", } func toolMarkupStylesOutsideIgnored(text string) (hasDSML, hasCanonical bool) { lower := strings.ToLower(text) for i := 0; i < len(text); { next, advanced, blocked := skipXMLIgnoredSection(lower, i) if blocked { return hasDSML, hasCanonical } if advanced { i = next continue } if hasPrefixAt(lower, i, canonicalToolMarkupPrefixes) { hasCanonical = true } for _, alias := range dsmlToolMarkupAliases { if strings.HasPrefix(lower[i:], alias.from) { hasDSML = true break } } if hasDSML && hasCanonical { return true, true } i++ } return hasDSML, hasCanonical } func replaceDSMLToolMarkupOutsideIgnored(text string) string { lower := strings.ToLower(text) var b strings.Builder b.Grow(len(text)) for i := 0; i < len(text); { next, advanced, blocked := skipXMLIgnoredSection(lower, i) if blocked { b.WriteString(text[i:]) break } if advanced { b.WriteString(text[i:next]) i = next continue } replaced := false for _, alias := range dsmlToolMarkupAliases { if strings.HasPrefix(lower[i:], alias.from) { b.WriteString(alias.to) i += len(alias.from) replaced = true break } } if replaced { continue } b.WriteByte(text[i]) i++ } return b.String() } func hasPrefixAt(text string, idx int, prefixes []string) bool { for _, prefix := range prefixes { if strings.HasPrefix(text[idx:], prefix) { return true } } return false }