mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-07 16:48:45 +08:00
Merge pull request #4823 from wucm667/fix/issue-4819-drop-orphan-tool-choice
Supersedes the earlier attempt #4439 by @KnWsdHunter, which its own author closed on 2026-07-20 and which was never merged. This PR discloses that prior work in its description and contributes a broader 6-case test table. Courtesy credit to @KnWsdHunter for the original diagnosis.
This commit is contained in:
@@ -663,7 +663,13 @@ var grokResponsesSupportedToolTypes = map[string]struct{}{
|
||||
|
||||
func sanitizeGrokResponsesTools(body []byte) ([]byte, error) {
|
||||
tools := gjson.GetBytes(body, "tools")
|
||||
if !tools.Exists() || !tools.IsArray() {
|
||||
if !tools.Exists() {
|
||||
if gjson.GetBytes(body, "tool_choice").Exists() {
|
||||
return sjson.DeleteBytes(body, "tool_choice")
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
if !tools.IsArray() {
|
||||
return body, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -209,6 +209,60 @@ func TestPatchGrokResponsesBodyDropsToolChoiceWhenNoSupportedToolsRemain(t *test
|
||||
require.False(t, gjson.GetBytes(patched, "tool_choice").Exists())
|
||||
}
|
||||
|
||||
func TestSanitizeGrokResponsesToolsKeepsToolChoiceOnlyWithSupportedTools(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
body string
|
||||
wantTools bool
|
||||
wantToolChoice bool
|
||||
}{
|
||||
{
|
||||
name: "missing tools with string tool choice",
|
||||
body: `{"input":"hello","tool_choice":"auto"}`,
|
||||
},
|
||||
{
|
||||
name: "missing tools with object tool choice",
|
||||
body: `{"input":"hello","tool_choice":{"type":"function","name":"lookup"}}`,
|
||||
},
|
||||
{
|
||||
name: "empty tools",
|
||||
body: `{"input":"hello","tools":[],"tool_choice":"auto"}`,
|
||||
wantTools: true,
|
||||
},
|
||||
{
|
||||
name: "all tools unsupported",
|
||||
body: `{"input":"hello","tools":[{"type":"namespace","name":"client_tools"}],"tool_choice":"auto"}`,
|
||||
},
|
||||
{
|
||||
name: "supported tool",
|
||||
body: `{"input":"hello","tools":[{"type":"function","name":"lookup"}],"tool_choice":"auto"}`,
|
||||
wantTools: true,
|
||||
wantToolChoice: true,
|
||||
},
|
||||
{
|
||||
name: "malformed non-array tools remain untouched",
|
||||
body: `{"input":"hello","tools":{"type":"function","name":"lookup"},"tool_choice":"auto"}`,
|
||||
wantTools: true,
|
||||
wantToolChoice: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
patched, err := sanitizeGrokResponsesTools([]byte(tt.body))
|
||||
require.NoError(t, err)
|
||||
require.True(t, json.Valid(patched))
|
||||
require.Equal(t, tt.wantTools, gjson.GetBytes(patched, "tools").Exists())
|
||||
require.Equal(t, tt.wantToolChoice, gjson.GetBytes(patched, "tool_choice").Exists())
|
||||
if tt.wantToolChoice {
|
||||
require.Equal(t, "auto", gjson.GetBytes(patched, "tool_choice").String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPatchGrokResponsesBodyPromotesCodexAdditionalTools(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user