mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-04 06:12:10 +03:00
fix(antigravity): strip generationConfig.thinkingConfig for Claude models (#2217)
Integrated into release/v3.8.0
This commit is contained in:
@@ -547,6 +547,10 @@ export function openaiToAntigravityRequest(model, body, stream, credentials = nu
|
||||
// Match real Antigravity client: don't send maxOutputTokens when the user
|
||||
// hasn't explicitly specified max_tokens / max_completion_tokens.
|
||||
// The Cloud Code server decides the output limit on its own.
|
||||
// Note: read hasThinking BEFORE stripping thinkingConfig below — for Claude
|
||||
// models the Cloud Code envelope still carries a thinkingBudget set upstream
|
||||
// by applyAntigravityGenerationDefaults, which we must consult here so we
|
||||
// do not accidentally drop the maxOutputTokens it bumped for us.
|
||||
const clientRequestedMaxTokens = body.max_tokens ?? body.max_completion_tokens;
|
||||
const hasThinking = !!envelope.request?.generationConfig?.thinkingConfig?.thinkingBudget;
|
||||
if (
|
||||
@@ -557,6 +561,16 @@ export function openaiToAntigravityRequest(model, body, stream, credentials = nu
|
||||
delete envelope.request.generationConfig.maxOutputTokens;
|
||||
}
|
||||
|
||||
// Claude models on Antigravity use their own native thinking — Gemini's thinkingConfig
|
||||
// is not understood by the Cloud Code Claude endpoint and must be stripped.
|
||||
// applyAntigravityGenerationDefaults (inside wrapInCloudCodeEnvelope) already bumped
|
||||
// maxOutputTokens to thinkingBudget+1 before we get here, so the budget is preserved.
|
||||
// Must run AFTER the hasThinking-derived maxOutputTokens decision above so the
|
||||
// budget is accounted for before the field is removed.
|
||||
if (isClaude && envelope.request?.generationConfig) {
|
||||
delete envelope.request.generationConfig.thinkingConfig;
|
||||
}
|
||||
|
||||
return envelope;
|
||||
}
|
||||
|
||||
|
||||
@@ -756,7 +756,11 @@ test("OpenAI -> Antigravity Claude path sanitizes tool names for Gemini schema",
|
||||
assert.deepEqual(toolResultBlock.response, { result: { ok: true } });
|
||||
});
|
||||
|
||||
test("OpenAI -> Antigravity Claude path applies output cap in generationConfig", () => {
|
||||
test("OpenAI -> Antigravity Claude path applies output cap and strips thinkingConfig", () => {
|
||||
// For Claude on Antigravity, applyAntigravityGenerationDefaults must bump
|
||||
// maxOutputTokens to thinkingBudget+1 BEFORE the envelope strips thinkingConfig
|
||||
// (because Claude on Cloud Code does not understand Gemini's thinkingConfig
|
||||
// shape but still benefits from the larger output cap derived from it).
|
||||
const result = openaiToAntigravityRequest(
|
||||
"claude-3-7-sonnet",
|
||||
{
|
||||
@@ -769,15 +773,14 @@ test("OpenAI -> Antigravity Claude path applies output cap in generationConfig",
|
||||
);
|
||||
|
||||
assert.equal((result as any).request?.generationConfig.maxOutputTokens, 32769);
|
||||
assert.deepEqual((result as any).request?.generationConfig.thinkingConfig, {
|
||||
thinkingBudget: 32768,
|
||||
includeThoughts: true,
|
||||
});
|
||||
// thinkingConfig must be stripped for Claude — Cloud Code Claude endpoint
|
||||
// does not understand the Gemini-shape thinkingConfig field.
|
||||
assert.equal((result as any).request?.generationConfig.thinkingConfig, undefined);
|
||||
assert.equal((result as any).request?.max_tokens, undefined);
|
||||
assert.equal((result as any).request?.thinking, undefined);
|
||||
});
|
||||
|
||||
test("OpenAI -> Antigravity Claude path preserves lower requested output", () => {
|
||||
test("OpenAI -> Antigravity Claude path preserves lower requested output and strips thinkingConfig", () => {
|
||||
const result = openaiToAntigravityRequest(
|
||||
"claude-3-7-sonnet",
|
||||
{
|
||||
@@ -790,10 +793,32 @@ test("OpenAI -> Antigravity Claude path preserves lower requested output", () =>
|
||||
);
|
||||
|
||||
assert.equal((result as any).request?.generationConfig.maxOutputTokens, 32769);
|
||||
assert.deepEqual((result as any).request?.generationConfig.thinkingConfig, {
|
||||
thinkingBudget: 32768,
|
||||
includeThoughts: true,
|
||||
});
|
||||
assert.equal((result as any).request?.generationConfig.thinkingConfig, undefined);
|
||||
assert.equal((result as any).request?.max_tokens, undefined);
|
||||
assert.equal((result as any).request?.thinking, undefined);
|
||||
});
|
||||
|
||||
test("OpenAI -> Antigravity Gemini path preserves thinkingConfig (only Claude is stripped)", () => {
|
||||
// Negative-control for the Claude-thinkingConfig-strip behavior. Gemini models
|
||||
// on Antigravity must still receive thinkingConfig — only Claude needs it removed
|
||||
// (Cloud Code Claude endpoint does not understand the Gemini-shape field).
|
||||
const result = openaiToAntigravityRequest(
|
||||
"gemini-2.5-pro",
|
||||
{
|
||||
messages: [{ role: "user", content: "Summarize this" }],
|
||||
max_completion_tokens: 32000,
|
||||
reasoning_effort: "high",
|
||||
},
|
||||
false,
|
||||
{ projectId: "proj-gemini-thinking" } as any
|
||||
);
|
||||
|
||||
// For Gemini, thinkingConfig must remain in place because the Cloud Code
|
||||
// Gemini endpoint understands and uses it.
|
||||
assert.ok(
|
||||
(result as any).request?.generationConfig.thinkingConfig,
|
||||
"thinkingConfig must be preserved for Gemini models on Antigravity"
|
||||
);
|
||||
assert.equal((result as any).request?.generationConfig.thinkingConfig.thinkingBudget > 0, true);
|
||||
assert.equal((result as any).request?.generationConfig.thinkingConfig.includeThoughts, true);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user