fix(core): resolve reasoning variants for GitLab Duo models (#51082)

This commit is contained in:
Vladimir Glafirov
2026-10-06 02:12:37 +00:00
committed by GitHub
Unverified
parent 209346a0fe
commit 5ae8a3c1d3
2 changed files with 82 additions and 0 deletions
+38
View File
@@ -526,6 +526,43 @@ const sapAICore: Protocol = (model, support) => {
}
}
// gitlab-ai-provider reads `providerOptions.gitlab.thinking` (Anthropic) and
// `providerOptions.gitlab.reasoningEffort` (OpenAI Chat and Responses). Its adaptive
// thinking config carries the effort inline and always requests summarized display.
const gitlabAnthropic: Protocol = (model, support) => {
const info = claudeInfo(model)
const disabled: Overlay = { settings: { thinking: { type: "disabled" } } }
const adaptive = (effort: string): Overlay => ({ settings: { thinking: { type: "adaptive", effort } } })
switch (support.type) {
case "effort": {
if (info.manual) return gitlabAnthropic(model, { type: "budget_tokens", min: 1024 })
const defaults = info.major === 4 && info.minor === 6 ? [...EFFORTS, "max"] : [...EFFORTS, "xhigh", "max"]
return efforts(support.values ?? defaults, (effort) => (effort === "none" ? disabled : adaptive(effort)))
}
case "toggle": {
if (info.always) return []
const thinking = info.manual ? manualThinking(model) : adaptive("high")
if (!thinking) return []
return toggle(disabled, thinking)
}
case "budget_tokens":
return budgets(
model,
support,
(tokens) => ({ settings: { thinking: { type: "enabled", budgetTokens: tokens } } }),
ANTHROPIC_OUTPUT_TOKEN_MAX,
)
}
}
const gitlab: Protocol = (model, support) => {
const id = modelID(model).toLowerCase()
if (id.startsWith("duo-workflow")) return []
if (claudeInfo(model).family) return gitlabAnthropic(model, support)
if (id.includes("gpt") || id.includes("codex")) return openaiChat(model, support)
return []
}
const PROTOCOLS: Readonly<Record<string, Protocol>> = {
"@opencode/ai/providers/openai": openaiResponses,
"@opencode/ai/providers/azure/responses": openaiResponses,
@@ -580,4 +617,5 @@ const PROTOCOLS: Readonly<Record<string, Protocol>> = {
"@opencode/ai/providers/vercel-ai-gateway": vercelGateway,
[Provider.aisdk("@ai-sdk/gateway")]: vercelGateway,
[Provider.aisdk("@jerome-benoit/sap-ai-provider-v2")]: sapAICore,
[Provider.aisdk("gitlab-ai-provider")]: gitlab,
}
+44
View File
@@ -452,3 +452,47 @@ test("spells Chat Completions variants for hosting providers", () => {
{ id: "xhigh", settings: { reasoningEffort: "xhigh" } },
])
})
test("spells GitLab Duo variants for gitlab-ai-provider routes", () => {
const pkg = Provider.aisdk("gitlab-ai-provider")
const gitlab = (id: string, output?: number) => model(pkg, id, output, "gitlab")
expect(
resolve(gitlab("duo-chat-opus-5-5"), [{ type: "effort", values: ["low", "medium", "high", "xhigh", "max"] }]),
).toEqual(
["low", "medium", "high", "xhigh", "max"].map((effort) => ({
id: effort,
settings: { thinking: { type: "adaptive", effort } },
})),
)
expect(
resolve(gitlab("duo-chat-sonnet-5"), [{ type: "toggle" }, { type: "effort", values: ["low", "max"] }]),
).toEqual([
{ id: "none", settings: { thinking: { type: "disabled" } } },
{ id: "low", settings: { thinking: { type: "adaptive", effort: "low" } } },
{ id: "max", settings: { thinking: { type: "adaptive", effort: "max" } } },
])
expect(resolve(gitlab("duo-chat-fable-5-1"), [{ type: "toggle" }, { type: "effort", values: ["high"] }])).toEqual([
{ id: "high", settings: { thinking: { type: "adaptive", effort: "high" } } },
])
expect(resolve(gitlab("duo-chat-opus-4-5", 64_000), [{ type: "effort" }])).toEqual([
{ id: "high", settings: { thinking: { type: "enabled", budgetTokens: 16_000 } } },
{ id: "max", settings: { thinking: { type: "enabled", budgetTokens: 31_999 } } },
])
expect(resolve(gitlab("duo-chat-gpt-6-sol"), [{ type: "effort", values: ["none", "low", "max"] }])).toEqual([
{ id: "none", settings: { reasoningEffort: "none" } },
{ id: "low", settings: { reasoningEffort: "low" } },
{ id: "max", settings: { reasoningEffort: "max" } },
])
expect(resolve(gitlab("duo-chat-gpt-5-3-codex"), [{ type: "effort", values: ["low"] }])).toEqual([
{ id: "low", settings: { reasoningEffort: "low" } },
])
expect(resolve(gitlab("duo-chat-gpt-5-4"), [])).toEqual([])
expect(resolve(gitlab("duo-workflow-opus-5-5"), [{ type: "effort" }])).toEqual([])
})