feat: Intercept and format tool calls, including unknown ones, from model responses in the OpenAI adapter, preventing raw JSON leaks and improving stream finalization.

This commit is contained in:
CJACK
2026-02-16 16:24:21 +08:00
parent 6a6f380987
commit ac57cabc80
4 changed files with 306 additions and 6 deletions

View File

@@ -52,6 +52,20 @@ func ParseToolCalls(text string, availableToolNames []string) []ParsedToolCall {
}
out = append(out, tc)
}
// If the model clearly emitted tool_calls JSON but all names are outside the
// declared set, keep the parsed calls as a fallback so upper layers can still
// intercept structured tool output instead of leaking raw JSON to users.
if len(out) == 0 && len(parsed) > 0 {
for _, tc := range parsed {
if tc.Name == "" {
continue
}
if tc.Input == nil {
tc.Input = map[string]any{}
}
out = append(out, tc)
}
}
return out
}

View File

@@ -41,11 +41,14 @@ func TestParseToolCallsWithFunctionArgumentsString(t *testing.T) {
}
}
func TestParseToolCallsRejectUnknown(t *testing.T) {
func TestParseToolCallsKeepsUnknownAsFallback(t *testing.T) {
text := `{"tool_calls":[{"name":"unknown","input":{}}]}`
calls := ParseToolCalls(text, []string{"search"})
if len(calls) != 0 {
t.Fatalf("expected 0 calls, got %d", len(calls))
if len(calls) != 1 {
t.Fatalf("expected fallback 1 call, got %d", len(calls))
}
if calls[0].Name != "unknown" {
t.Fatalf("unexpected name: %s", calls[0].Name)
}
}