cleanup: make smallOptions rely on variants (#27390)

This commit is contained in:
Aiden Cline
2026-05-13 18:30:36 -05:00
committed by GitHub
parent 55e0af1405
commit df3895d74f
2 changed files with 75 additions and 42 deletions
+6 -27
View File
@@ -617,14 +617,6 @@ function googleThinkingBudgetMax(apiId: string) {
return 24_576 return 24_576
} }
function googleSmallThinkingConfig(apiId: string) {
const levels = googleThinkingLevelEfforts(apiId)
if (apiId.toLowerCase().includes("gemini-3")) {
return { thinkingLevel: levels.includes("minimal") ? "minimal" : levels.includes("low") ? "low" : "high" }
}
return { thinkingBudget: googleThinkingBudgetMax(apiId) === 32_768 ? 128 : 0 }
}
export function variants(model: Provider.Model): Record<string, Record<string, any>> { export function variants(model: Provider.Model): Record<string, Record<string, any>> {
if (!model.capabilities.reasoning) return {} if (!model.capabilities.reasoning) return {}
@@ -1184,40 +1176,27 @@ export function options(input: {
} }
export function smallOptions(model: Provider.Model) { export function smallOptions(model: Provider.Model) {
const small = Object.values(model.variants ?? {})[0] ?? {}
if ( if (
model.providerID === "openai" || model.providerID === "openai" ||
model.api.npm === "@ai-sdk/openai" || model.api.npm === "@ai-sdk/openai" ||
model.api.npm === "@ai-sdk/github-copilot" model.api.npm === "@ai-sdk/github-copilot"
) { ) {
if (model.api.id.includes("gpt-5")) { const base = { store: false }
if (model.api.id.includes("-chat")) { return mergeDeep(base, small)
if (gpt5Version(model.api.id) === undefined) return { store: false }
return { store: false, reasoningEffort: "medium" }
}
if (model.api.id.includes("search-api")) return { store: false }
if (model.api.id.includes("5.") || model.api.id.includes("5-mini")) {
return { store: false, reasoningEffort: "low" }
}
return { store: false, reasoningEffort: "minimal" }
}
return { store: false }
}
if (model.providerID === "google") {
// gemini-3 uses thinkingLevel, gemini-2.5 uses thinkingBudget
return { thinkingConfig: googleSmallThinkingConfig(model.api.id) }
} }
if (model.providerID === "openrouter" || model.providerID === "llmgateway") { if (model.providerID === "openrouter" || model.providerID === "llmgateway") {
if (model.api.id.includes("google")) { if (Object.keys(small).length === 0 && model.api.id.includes("google")) {
return { reasoning: { enabled: false } } return { reasoning: { enabled: false } }
} }
return { reasoningEffort: "minimal" }
} }
if (model.providerID === "venice") { if (model.providerID === "venice") {
if (Object.keys(small).length > 0) return small
return { veniceParameters: { disableThinking: true } } return { veniceParameters: { disableThinking: true } }
} }
return {} return small
} }
// Maps model ID prefix to provider slug used in providerOptions. // Maps model ID prefix to provider slug used in providerOptions.
@@ -3602,8 +3602,8 @@ describe("ProviderTransform.variants", () => {
}) })
describe("ProviderTransform.smallOptions - gpt-5 chat/search", () => { describe("ProviderTransform.smallOptions - gpt-5 chat/search", () => {
const createModel = (apiId: string) => const createModel = (apiId: string) => {
({ const model = {
id: `openai/${apiId}`, id: `openai/${apiId}`,
providerID: "openai", providerID: "openai",
api: { api: {
@@ -3611,13 +3611,43 @@ describe("ProviderTransform.smallOptions - gpt-5 chat/search", () => {
url: "https://api.openai.com", url: "https://api.openai.com",
npm: "@ai-sdk/openai", npm: "@ai-sdk/openai",
}, },
}) as any capabilities: { reasoning: true },
limit: { output: 64_000 },
release_date: "2026-01-01",
} as any
model.variants = ProviderTransform.variants(model)
return model
}
for (const testCase of [ for (const testCase of [
{ id: "gpt-5-chat-latest", options: { store: false } }, { id: "gpt-5-chat-latest", options: { store: false } },
{ id: "gpt-5.1-chat-latest", options: { store: false, reasoningEffort: "medium" } }, {
{ id: "gpt-5.2-chat-latest", options: { store: false, reasoningEffort: "medium" } }, id: "gpt-5.1-chat-latest",
{ id: "gpt-5-search-api", options: { store: false } }, options: {
store: false,
reasoningEffort: "medium",
reasoningSummary: "auto",
include: ["reasoning.encrypted_content"],
},
},
{
id: "gpt-5.2-chat-latest",
options: {
store: false,
reasoningEffort: "medium",
reasoningSummary: "auto",
include: ["reasoning.encrypted_content"],
},
},
{
id: "gpt-5-search-api",
options: {
store: false,
reasoningEffort: "none",
reasoningSummary: "auto",
include: ["reasoning.encrypted_content"],
},
},
]) { ]) {
test(`${testCase.id} returns only supported small options`, () => { test(`${testCase.id} returns only supported small options`, () => {
expect(ProviderTransform.smallOptions(createModel(testCase.id))).toEqual(testCase.options) expect(ProviderTransform.smallOptions(createModel(testCase.id))).toEqual(testCase.options)
@@ -3626,8 +3656,8 @@ describe("ProviderTransform.smallOptions - gpt-5 chat/search", () => {
}) })
describe("ProviderTransform.smallOptions - google thinking controls", () => { describe("ProviderTransform.smallOptions - google thinking controls", () => {
const createGoogleModel = (apiId: string) => const createGoogleModel = (apiId: string) => {
({ const model = {
id: `google/${apiId}`, id: `google/${apiId}`,
providerID: "google", providerID: "google",
api: { api: {
@@ -3635,20 +3665,44 @@ describe("ProviderTransform.smallOptions - google thinking controls", () => {
url: "https://generativelanguage.googleapis.com", url: "https://generativelanguage.googleapis.com",
npm: "@ai-sdk/google", npm: "@ai-sdk/google",
}, },
}) as any capabilities: { reasoning: true },
limit: { output: 64_000 },
} as any
model.variants = ProviderTransform.variants(model)
return model
}
for (const testCase of [ for (const testCase of [
{ id: "gemini-3-pro-preview", options: { thinkingConfig: { thinkingLevel: "low" } } }, { id: "gemini-3-pro-preview", options: { thinkingConfig: { includeThoughts: true, thinkingLevel: "low" } } },
{ id: "gemini-3-flash-preview", options: { thinkingConfig: { thinkingLevel: "minimal" } } }, { id: "gemini-3-flash-preview", options: { thinkingConfig: { includeThoughts: true, thinkingLevel: "minimal" } } },
{ id: "gemini-3.1-flash-image-preview", options: { thinkingConfig: { thinkingLevel: "minimal" } } }, {
{ id: "gemini-3-pro-image-preview", options: { thinkingConfig: { thinkingLevel: "high" } } }, id: "gemini-3.1-flash-image-preview",
{ id: "gemini-2.5-pro", options: { thinkingConfig: { thinkingBudget: 128 } } }, options: { thinkingConfig: { includeThoughts: true, thinkingLevel: "minimal" } },
{ id: "gemini-2.5-flash", options: { thinkingConfig: { thinkingBudget: 0 } } }, },
{ id: "gemini-3-pro-image-preview", options: { thinkingConfig: { includeThoughts: true, thinkingLevel: "high" } } },
{ id: "gemini-2.5-pro", options: { thinkingConfig: { includeThoughts: true, thinkingBudget: 16000 } } },
{ id: "gemini-2.5-flash", options: { thinkingConfig: { includeThoughts: true, thinkingBudget: 16000 } } },
]) { ]) {
test(`${testCase.id} returns supported small thinking options`, () => { test(`${testCase.id} returns supported small thinking options`, () => {
expect(ProviderTransform.smallOptions(createGoogleModel(testCase.id))).toEqual(testCase.options) expect(ProviderTransform.smallOptions(createGoogleModel(testCase.id))).toEqual(testCase.options)
}) })
} }
test("uses the first configured variant when available", () => {
expect(
ProviderTransform.smallOptions({
...createGoogleModel("gemini-2.5-pro"),
variants: {
high: { thinkingConfig: { includeThoughts: true, thinkingBudget: 16000 } },
max: { thinkingConfig: { includeThoughts: true, thinkingBudget: 32768 } },
},
}),
).toEqual({ thinkingConfig: { includeThoughts: true, thinkingBudget: 16000 } })
})
test("does not synthesize thinking options when variants are empty", () => {
expect(ProviderTransform.smallOptions({ ...createGoogleModel("gemini-2.5-pro"), variants: {} })).toEqual({})
})
}) })
describe("ProviderTransform.providerOptions - ai-gateway-provider", () => { describe("ProviderTransform.providerOptions - ai-gateway-provider", () => {