mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-17 20:52:15 +03:00
fix(antigravity): unblock Gemini and Claude reasoning capabilities (#10376)
* fix(antigravity): unblock Gemini and Claude reasoning capabilities * fix(antigravity): align two unit tests with unblocked Gemini/Claude reasoning The PR unblocks Antigravity Gemini/Claude reasoning (removed from REASONING_UNSUPPORTED_PATTERNS, mirroring model-capabilities-registry.test.ts). models-catalog-combo-metadata and services-branch-hardening still asserted the pre-PR deny contract; align them to the new verified behavior. No production code changed. Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com> --------- Co-authored-by: adevwithpurpose <adevwithpurpose@users.noreply.github.com> Co-authored-by: Chewji9875 <Chewji9875@users.noreply.github.com> Co-authored-by: diegosouzapw <diegosouza.pw@gmail.com>
This commit is contained in:
@@ -47,13 +47,6 @@ const TOOL_CALLING_UNSUPPORTED_PATTERNS: string[] = [
|
||||
"stable-diffusion",
|
||||
];
|
||||
const REASONING_UNSUPPORTED_PATTERNS = [
|
||||
"antigravity/claude-sonnet-4-6",
|
||||
"antigravity/claude-sonnet-4-5",
|
||||
"antigravity/claude-sonnet-4",
|
||||
// Non-Claude antigravity models don't support thinking params (#1361)
|
||||
"antigravity/gemini-",
|
||||
"antigravity/gpt-oss-",
|
||||
"antigravity/gemini-3",
|
||||
"antigravity/tab_",
|
||||
// Specialty / non-chat surfaces (#8016)
|
||||
"whisper",
|
||||
|
||||
130
tests/unit/antigravity-thinking-config-preservation.test.ts
Normal file
130
tests/unit/antigravity-thinking-config-preservation.test.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import {
|
||||
getResolvedModelCapabilities,
|
||||
supportsReasoning,
|
||||
} from "../../src/lib/modelCapabilities.ts";
|
||||
import { applyThinkingBudget } from "../../open-sse/services/thinkingBudget.ts";
|
||||
import { translateRequest } from "../../open-sse/translator/index.ts";
|
||||
import { FORMATS } from "../../open-sse/translator/formats.ts";
|
||||
|
||||
test("antigravity reasoning capabilities: Gemini and Claude models support reasoning", () => {
|
||||
const geminiModels = [
|
||||
"antigravity/gemini-3-flash-agent",
|
||||
"antigravity/gemini-pro-agent",
|
||||
"antigravity/gemini-3.1-pro-low",
|
||||
"antigravity/claude-sonnet-4-6",
|
||||
"antigravity/claude-opus-4-6-thinking",
|
||||
];
|
||||
|
||||
for (const modelId of geminiModels) {
|
||||
const isReasoning = supportsReasoning(modelId);
|
||||
assert.equal(isReasoning, true, `supportsReasoning should be true for ${modelId}`);
|
||||
|
||||
const caps = getResolvedModelCapabilities(modelId);
|
||||
assert.equal(caps.reasoning, true, `caps.reasoning should be true for ${modelId}`);
|
||||
assert.equal(
|
||||
caps.supportsThinking,
|
||||
true,
|
||||
`caps.supportsThinking should be true for ${modelId}`
|
||||
);
|
||||
}
|
||||
|
||||
// Passthrough / unlisted Gemini model should still heuristically resolve reasoning
|
||||
assert.equal(supportsReasoning("antigravity/gemini-2.5-pro"), true);
|
||||
const gemini25Caps = getResolvedModelCapabilities("antigravity/gemini-2.5-pro");
|
||||
assert.equal(gemini25Caps.reasoning, true);
|
||||
|
||||
// Non-reasoning models like tab completion should return false
|
||||
assert.equal(supportsReasoning("antigravity/tab_flash_lite"), false);
|
||||
const tabCaps = getResolvedModelCapabilities("antigravity/tab_flash_lite");
|
||||
assert.equal(tabCaps.reasoning, false);
|
||||
});
|
||||
|
||||
test("antigravity request pipeline: applyThinkingBudget preserves reasoning params", () => {
|
||||
const req: Record<string, unknown> = {
|
||||
model: "antigravity/gemini-pro-agent",
|
||||
messages: [{ role: "user", content: "Solve math problem" }],
|
||||
reasoning_effort: "max",
|
||||
};
|
||||
|
||||
const processed = applyThinkingBudget(req);
|
||||
assert.equal(
|
||||
(processed as Record<string, unknown>).reasoning_effort,
|
||||
"max",
|
||||
"reasoning_effort must not be stripped"
|
||||
);
|
||||
});
|
||||
|
||||
test("antigravity translator: translates reasoning_effort into Gemini thinkingConfig", () => {
|
||||
const inputReq = {
|
||||
model: "antigravity/gemini-pro-agent",
|
||||
messages: [{ role: "user", content: "Solve math problem" }],
|
||||
reasoning_effort: "max",
|
||||
};
|
||||
|
||||
const translated = translateRequest(
|
||||
FORMATS.OPENAI,
|
||||
FORMATS.ANTIGRAVITY,
|
||||
"antigravity/gemini-pro-agent",
|
||||
inputReq,
|
||||
true,
|
||||
null,
|
||||
"antigravity"
|
||||
);
|
||||
|
||||
const generationConfig = (
|
||||
translated as { request?: { generationConfig?: Record<string, unknown> } }
|
||||
)?.request?.generationConfig;
|
||||
|
||||
assert.ok(generationConfig, "generationConfig must exist in Cloud Code envelope");
|
||||
assert.ok(
|
||||
generationConfig.thinkingConfig,
|
||||
"thinkingConfig must exist in generationConfig for Gemini reasoning models"
|
||||
);
|
||||
assert.equal(
|
||||
(generationConfig.thinkingConfig as { includeThoughts?: boolean }).includeThoughts,
|
||||
true
|
||||
);
|
||||
assert.equal(
|
||||
typeof (generationConfig.thinkingConfig as { thinkingBudget?: number }).thinkingBudget,
|
||||
"number"
|
||||
);
|
||||
assert.ok(
|
||||
(generationConfig.thinkingConfig as { thinkingBudget: number }).thinkingBudget > 0,
|
||||
"thinkingBudget should be positive"
|
||||
);
|
||||
});
|
||||
|
||||
test("antigravity translator: Claude models bump maxOutputTokens and strip raw thinkingConfig", () => {
|
||||
const inputReq = {
|
||||
model: "antigravity/claude-sonnet-4-6",
|
||||
messages: [{ role: "user", content: "Explain quantum mechanics" }],
|
||||
reasoning_effort: "high",
|
||||
};
|
||||
|
||||
const translated = translateRequest(
|
||||
FORMATS.OPENAI,
|
||||
FORMATS.ANTIGRAVITY,
|
||||
"antigravity/claude-sonnet-4-6",
|
||||
inputReq,
|
||||
true,
|
||||
null,
|
||||
"antigravity"
|
||||
);
|
||||
|
||||
const generationConfig = (
|
||||
translated as { request?: { generationConfig?: Record<string, unknown> } }
|
||||
)?.request?.generationConfig;
|
||||
|
||||
assert.ok(generationConfig, "generationConfig must exist in Cloud Code envelope");
|
||||
assert.equal(
|
||||
generationConfig.thinkingConfig,
|
||||
undefined,
|
||||
"raw thinkingConfig must be stripped for Claude models on Antigravity"
|
||||
);
|
||||
assert.ok(
|
||||
(generationConfig.maxOutputTokens as number) >= 16384,
|
||||
"maxOutputTokens should be preserved/bumped for Claude reasoning"
|
||||
);
|
||||
});
|
||||
@@ -165,7 +165,7 @@ test("Antigravity Gemini 3.5 upstream IDs share the Flash capability profile", (
|
||||
const capabilities = modelCapabilities.getResolvedModelCapabilities(`antigravity/${modelId}`);
|
||||
assert.equal(capabilities.contextWindow, 1048576, modelId);
|
||||
assert.equal(capabilities.maxOutputTokens, 65536, modelId);
|
||||
assert.equal(capabilities.supportsThinking, false, modelId);
|
||||
assert.equal(capabilities.supportsThinking, true, modelId);
|
||||
assert.equal(capabilities.supportsTools, true, modelId);
|
||||
assert.equal(capabilities.supportsVision, true, modelId);
|
||||
}
|
||||
@@ -184,7 +184,7 @@ test("Antigravity Gemini 3.7 and 3.6 tier IDs share the Flash capability profile
|
||||
const capabilities = modelCapabilities.getResolvedModelCapabilities(`antigravity/${modelId}`);
|
||||
assert.equal(capabilities.contextWindow, 1048576, modelId);
|
||||
assert.equal(capabilities.maxOutputTokens, 65536, modelId);
|
||||
assert.equal(capabilities.supportsThinking, false, modelId);
|
||||
assert.equal(capabilities.supportsThinking, true, modelId);
|
||||
assert.equal(capabilities.supportsTools, true, modelId);
|
||||
assert.equal(capabilities.supportsVision, true, modelId);
|
||||
}
|
||||
|
||||
@@ -87,18 +87,18 @@ test("single-target combo respects registry reasoning overrides before specs", a
|
||||
assert.equal(Object.hasOwn(capabilities, "effort_tiers"), false);
|
||||
});
|
||||
|
||||
test("single-target combo respects resolved reasoning deny patterns", async () => {
|
||||
test("single-target combo reflects unblocked Antigravity Gemini reasoning", async () => {
|
||||
await providersDb.createProviderConnection({
|
||||
provider: "antigravity",
|
||||
authType: "oauth",
|
||||
name: "antigravity-gemini-no-thinking-combo",
|
||||
name: "antigravity-gemini-reasoning-combo",
|
||||
accessToken: "antigravity-test-token",
|
||||
isActive: true,
|
||||
testStatus: "active",
|
||||
providerSpecificData: {},
|
||||
});
|
||||
await combosDb.createCombo({
|
||||
name: "antigravity-gemini-no-thinking-combo",
|
||||
name: "antigravity-gemini-reasoning-combo",
|
||||
strategy: "auto",
|
||||
models: ["antigravity/gemini-3.1-pro-high"],
|
||||
});
|
||||
@@ -107,13 +107,13 @@ test("single-target combo respects resolved reasoning deny patterns", async () =
|
||||
new Request("http://localhost/api/v1/models")
|
||||
);
|
||||
const body = (await response.json()) as { data: Array<Record<string, unknown>> };
|
||||
const combo = body.data.find((item) => item.id === "antigravity-gemini-no-thinking-combo");
|
||||
const combo = body.data.find((item) => item.id === "antigravity-gemini-reasoning-combo");
|
||||
|
||||
assert.equal(response.status, 200);
|
||||
assert.ok(combo);
|
||||
const capabilities = combo.capabilities as Record<string, unknown>;
|
||||
assert.equal(capabilities.reasoning, false);
|
||||
assert.equal(capabilities.thinking, false);
|
||||
assert.equal(capabilities.supportsThinking, false);
|
||||
assert.equal(Object.hasOwn(capabilities, "effort_tiers"), false);
|
||||
assert.equal(capabilities.reasoning, true);
|
||||
assert.equal(capabilities.thinking, true);
|
||||
assert.equal(capabilities.supportsThinking, true);
|
||||
assert.equal(Object.hasOwn(capabilities, "effort_tiers"), true);
|
||||
});
|
||||
|
||||
@@ -113,8 +113,8 @@ test("model capability helpers cover denylist, empty input and default-safe path
|
||||
);
|
||||
|
||||
assert.equal(modelCapabilities.supportsReasoning(""), true);
|
||||
assert.equal(modelCapabilities.supportsReasoning("antigravity/claude-sonnet-4-6"), false);
|
||||
assert.equal(modelCapabilities.supportsReasoning("antigravity/claude-sonnet-4"), false);
|
||||
assert.equal(modelCapabilities.supportsReasoning("antigravity/claude-sonnet-4-6"), true);
|
||||
assert.equal(modelCapabilities.supportsReasoning("antigravity/claude-sonnet-4"), true);
|
||||
assert.equal(modelCapabilities.supportsReasoning("openai/nonexistent-default-safe-model"), true);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user