fix(providers): strip XML tool call artifacts from response content
Minimax (and potentially other providers) embed raw XML like <minimax:toolcall> in response Content alongside structured tool_calls. Strip these before returning to prevent leaking internal data to users. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
d614e1f887
commit
7d283d640c
2 changed files with 37 additions and 1 deletions
|
|
@ -23,7 +23,14 @@ func NewHTTPProvider(apiKey, apiBase, proxy string) *HTTPProvider {
|
|||
}
|
||||
|
||||
func (p *HTTPProvider) Chat(ctx context.Context, messages []Message, tools []ToolDefinition, model string, options map[string]interface{}) (*LLMResponse, error) {
|
||||
return p.delegate.Chat(ctx, messages, tools, model, options)
|
||||
resp, err := p.delegate.Chat(ctx, messages, tools, model, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Strip provider-specific XML tool call artifacts (e.g. minimax)
|
||||
// that leak into Content alongside structured tool_calls.
|
||||
resp.Content = stripXMLToolCalls(resp.Content)
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (p *HTTPProvider) GetDefaultModel() string {
|
||||
|
|
|
|||
|
|
@ -56,6 +56,35 @@ func extractToolCallsFromText(text string) []ToolCall {
|
|||
return result
|
||||
}
|
||||
|
||||
// stripXMLToolCalls removes XML tool call blocks (e.g. <minimax:toolcall>...</minimax:toolcall>)
|
||||
// from response text. Some providers embed raw XML tool calls in Content alongside
|
||||
// structured tool_calls; this prevents them from leaking to users.
|
||||
func stripXMLToolCalls(text string) string {
|
||||
// Match <vendor:toolcall>...</vendor:toolcall> blocks (any namespace prefix)
|
||||
idx := strings.Index(text, ":toolcall>")
|
||||
if idx == -1 {
|
||||
return text
|
||||
}
|
||||
// Find the opening tag start: scan backwards for '<'
|
||||
tagStart := strings.LastIndex(text[:idx], "<")
|
||||
if tagStart == -1 {
|
||||
return text
|
||||
}
|
||||
// Extract namespace (e.g. "minimax" from "<minimax:toolcall>")
|
||||
ns := text[tagStart+1 : idx]
|
||||
closeTag := "</" + ns + ":toolcall>"
|
||||
closeIdx := strings.Index(text, closeTag)
|
||||
if closeIdx == -1 {
|
||||
return text
|
||||
}
|
||||
cleaned := text[:tagStart] + text[closeIdx+len(closeTag):]
|
||||
// Recursively strip if there are more blocks
|
||||
if strings.Contains(cleaned, ":toolcall>") {
|
||||
cleaned = stripXMLToolCalls(cleaned)
|
||||
}
|
||||
return strings.TrimSpace(cleaned)
|
||||
}
|
||||
|
||||
// stripToolCallsFromText removes tool call JSON from response text.
|
||||
func stripToolCallsFromText(text string) string {
|
||||
start := strings.Index(text, `{"tool_calls"`)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue