fix(translator): route Gemini thinking through reasoning_effort on OpenAI-compatible wire
This commit is contained in:
@@ -105,12 +105,16 @@ export function extractThinking(body) {
|
|||||||
// at the call-site where intent is snapshotted before format translation.
|
// at the call-site where intent is snapshotted before format translation.
|
||||||
export const captureThinking = extractThinking;
|
export const captureThinking = extractThinking;
|
||||||
|
|
||||||
// Resolve thinking format: provider override > capability > derive(targetFormat).
|
const NATIVE_ONLY_FORMATS = new Set(["gemini-level", "gemini-budget", "claude-budget", "claude-adaptive", "kiro"]);
|
||||||
|
|
||||||
function resolveFormat(targetFormat, model, provider) {
|
function resolveFormat(targetFormat, model, provider) {
|
||||||
const providerFmt = provider ? PROVIDERS[provider]?.thinkingFormat : null;
|
const providerFmt = provider ? PROVIDERS[provider]?.thinkingFormat : null;
|
||||||
if (providerFmt) return providerFmt;
|
if (providerFmt) return providerFmt;
|
||||||
const caps = getCapabilitiesForModel(provider, model);
|
const caps = getCapabilitiesForModel(provider, model);
|
||||||
if (caps.thinkingFormat) return caps.thinkingFormat;
|
const isOpenAIWire = targetFormat === "openai" || targetFormat === "openai-responses";
|
||||||
|
if (caps.thinkingFormat && !(isOpenAIWire && NATIVE_ONLY_FORMATS.has(caps.thinkingFormat))) {
|
||||||
|
return caps.thinkingFormat;
|
||||||
|
}
|
||||||
return FORMAT_TO_NATIVE[targetFormat] || "openai";
|
return FORMAT_TO_NATIVE[targetFormat] || "openai";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -220,6 +220,26 @@ describe("applyThinking per provider format", () => {
|
|||||||
const out = apply("openai", "gpt-5.6-sol", { reasoning_effort: "max" }, "kiro");
|
const out = apply("openai", "gpt-5.6-sol", { reasoning_effort: "max" }, "kiro");
|
||||||
expect(out.reasoning_effort).toBe("xhigh");
|
expect(out.reasoning_effort).toBe("xhigh");
|
||||||
});
|
});
|
||||||
|
it.each([
|
||||||
|
["gemini-3.5-flash-lite"],
|
||||||
|
["gemini-3.7-flash"],
|
||||||
|
["gemini-3-pro"],
|
||||||
|
])("Gemini 3.x model %s (gemini-level) over a custom OpenAI-compatible provider → reasoning_effort, not generationConfig (regression: #3718)", (model) => {
|
||||||
|
const out = apply("openai", model, { reasoning_effort: "medium" }, "my-custom-gemini-openai");
|
||||||
|
expect(out.reasoning_effort).toBe("medium");
|
||||||
|
expect(out.generationConfig).toBeUndefined();
|
||||||
|
expect(out.thinkingConfig).toBeUndefined();
|
||||||
|
});
|
||||||
|
it("Gemini 2.5 model (gemini-budget) over a custom OpenAI-compatible provider → reasoning_effort, not generationConfig (regression: #3718)", () => {
|
||||||
|
const out = apply("openai", "gemini-2.5-flash", { reasoning_effort: "high" }, "my-custom-gemini-openai");
|
||||||
|
expect(out.reasoning_effort).toBe("high");
|
||||||
|
expect(out.generationConfig).toBeUndefined();
|
||||||
|
expect(out.thinkingConfig).toBeUndefined();
|
||||||
|
});
|
||||||
|
it("Gemini model over its native format (antigravity/gemini-cli/vertex) still gets generationConfig", () => {
|
||||||
|
const out = apply("gemini-cli", "gemini-3.5-flash-lite", { reasoning_effort: "medium" }, "gemini-cli");
|
||||||
|
expect(out.generationConfig.thinkingConfig.thinkingLevel).toBe("medium");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("extractReasoningText (response shapes)", () => {
|
describe("extractReasoningText (response shapes)", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user