mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-21 05:21:20 +00:00
Merge pull request #6674 from wuji-labs/fix/antigravity-toolconfig-always-present
fix(antigravity): always set toolConfig for reasoning models without tools
This commit is contained in:
@@ -148,21 +148,20 @@ func TransformClaudeToGeminiWithOptions(claudeReq *ClaudeRequest, projectID, map
|
||||
}
|
||||
|
||||
// 针对 Gemini Reasoning 模型(如 gemini-3.1-pro-high等)过滤强制空 ToolConfig
|
||||
isReasoning := IsGeminiReasoningModel(targetModel)
|
||||
if !isReasoning || len(tools) > 0 {
|
||||
// 总是设置 toolConfig,与官方客户端一致
|
||||
innerRequest.ToolConfig = &GeminiToolConfig{
|
||||
FunctionCallingConfig: &GeminiFunctionCallingConfig{
|
||||
Mode: "VALIDATED",
|
||||
},
|
||||
}
|
||||
// 内置工具(googleSearch)与函数调用混用时,上游要求显式开启
|
||||
// includeServerSideToolInvocations,否则返回 400(issue #5709)。
|
||||
// 与 raw 透传路的 enableMixedGeminiToolInvocations 注入保持同一语义。
|
||||
if hasMixedToolInvocations(tools) {
|
||||
enabled := true
|
||||
innerRequest.ToolConfig.IncludeServerSideToolInvocations = &enabled
|
||||
}
|
||||
// toolConfig must always be present: upstream rejects requests without it,
|
||||
// including reasoning models called without any tools.
|
||||
// 总是设置 toolConfig,与官方客户端一致
|
||||
innerRequest.ToolConfig = &GeminiToolConfig{
|
||||
FunctionCallingConfig: &GeminiFunctionCallingConfig{
|
||||
Mode: "VALIDATED",
|
||||
},
|
||||
}
|
||||
// 内置工具(googleSearch)与函数调用混用时,上游要求显式开启
|
||||
// includeServerSideToolInvocations,否则返回 400(issue #5709)。
|
||||
// 与 raw 透传路的 enableMixedGeminiToolInvocations 注入保持同一语义。
|
||||
if hasMixedToolInvocations(tools) {
|
||||
enabled := true
|
||||
innerRequest.ToolConfig.IncludeServerSideToolInvocations = &enabled
|
||||
}
|
||||
|
||||
if systemInstruction != nil {
|
||||
|
||||
@@ -621,3 +621,38 @@ func TestGeminiToolConfig_IncludeServerSideToolInvocations(t *testing.T) {
|
||||
require.NotContains(t, raw, "includeServerSideToolInvocations")
|
||||
})
|
||||
}
|
||||
|
||||
// TestToolConfigAlwaysPresent ensures toolConfig is always emitted, including for
|
||||
// reasoning models without any tools: upstream rejects requests that omit it.
|
||||
func TestToolConfigAlwaysPresent(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
model string
|
||||
tools []ClaudeTool
|
||||
}{
|
||||
{name: "reasoning model without tools", model: "gemini-3.1-pro-high"},
|
||||
{name: "reasoning model with tools", model: "gemini-3.1-pro-high", tools: []ClaudeTool{{
|
||||
Name: "web_search",
|
||||
Description: "Search the web",
|
||||
InputSchema: map[string]any{"type": "object", "properties": map[string]any{}},
|
||||
}}},
|
||||
{name: "non-reasoning model without tools", model: "gemini-3.1-pro"},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
claudeReq := &ClaudeRequest{
|
||||
Model: tc.model,
|
||||
Messages: []ClaudeMessage{{Role: "user", Content: json.RawMessage(`"Hello"`)}},
|
||||
Tools: tc.tools,
|
||||
}
|
||||
body, err := TransformClaudeToGeminiWithOptions(claudeReq, "project-1", tc.model, DefaultTransformOptions())
|
||||
require.NoError(t, err)
|
||||
|
||||
var req V1InternalRequest
|
||||
require.NoError(t, json.Unmarshal(body, &req))
|
||||
require.NotNil(t, req.Request.ToolConfig, "toolConfig must be present")
|
||||
require.NotNil(t, req.Request.ToolConfig.FunctionCallingConfig)
|
||||
require.Equal(t, "VALIDATED", req.Request.ToolConfig.FunctionCallingConfig.Mode)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user