fix(apicompat): scope additional tools parsing

This commit is contained in:
王鹏
2026-07-15 14:31:26 +08:00
parent 2d218fbe61
commit c3a425837c
2 changed files with 35 additions and 4 deletions
@@ -91,16 +91,22 @@ func EffectiveResponsesTools(req *ResponsesRequest) ([]ResponsesTool, error) {
if len(raw) == 0 || raw[0] != '{' { if len(raw) == 0 || raw[0] != '{' {
continue continue
} }
var discriminator struct {
Type string `json:"type"`
}
if err := json.Unmarshal(raw, &discriminator); err != nil {
return nil, fmt.Errorf("parse responses additional tools item: %w", err)
}
if discriminator.Type != "additional_tools" {
continue
}
var item struct { var item struct {
Type string `json:"type"`
Tools []ResponsesTool `json:"tools"` Tools []ResponsesTool `json:"tools"`
} }
if err := json.Unmarshal(raw, &item); err != nil { if err := json.Unmarshal(raw, &item); err != nil {
return nil, fmt.Errorf("parse responses additional tools item: %w", err) return nil, fmt.Errorf("parse responses additional tools item: %w", err)
} }
if item.Type == "additional_tools" { tools = append(tools, item.Tools...)
tools = append(tools, item.Tools...)
}
} }
return tools, nil return tools, nil
} }
@@ -79,6 +79,31 @@ func TestEffectiveResponsesTools_SkipsStringInputItems(t *testing.T) {
assert.Equal(t, "exec", tools[0].Name) assert.Equal(t, "exec", tools[0].Name)
} }
func TestEffectiveResponsesTools_IgnoresMalformedToolsOnNonAdditionalItem(t *testing.T) {
req := &ResponsesRequest{
Input: json.RawMessage(`[
{"type":"message","role":"user","tools":"not-an-array","content":[{"type":"input_text","text":"hello"}]},
{"type":"additional_tools","tools":[{"type":"custom","name":"exec"}]}
]`),
}
tools, err := EffectiveResponsesTools(req)
require.NoError(t, err)
require.Len(t, tools, 1)
assert.Equal(t, "exec", tools[0].Name)
}
func TestEffectiveResponsesTools_RejectsMalformedAdditionalTools(t *testing.T) {
req := &ResponsesRequest{
Input: json.RawMessage(`[{"type":"additional_tools","tools":"not-an-array"}]`),
}
tools, err := EffectiveResponsesTools(req)
require.Error(t, err)
assert.Contains(t, err.Error(), "parse responses additional tools item")
assert.Empty(t, tools)
}
func TestResponsesToChatCompletionsRequest_DropsToolChoiceWhenNoConvertibleTools(t *testing.T) { func TestResponsesToChatCompletionsRequest_DropsToolChoiceWhenNoConvertibleTools(t *testing.T) {
req := &ResponsesRequest{ req := &ResponsesRequest{
Model: "glm-5.2", Model: "glm-5.2",