Merge pull request #2663 from code-yeongyu/fix/runtime-fallback-variant-loss

fix(runtime-fallback): preserve agent variant and reasoningEffort on model fallback (fixes #2621)
This commit is contained in:
YeonGyu-Kim
2026-04-04 20:34:40 +09:00
committed by GitHub
3 changed files with 141 additions and 16 deletions
+7 -1
View File
@@ -102,7 +102,13 @@ export function createAutoRetryHelpers(deps: HookDeps) {
return
}
const retryModelPayload = buildRetryModelPayload(newModel)
const agentSettings = resolvedAgent
? pluginConfig?.agents?.[resolvedAgent as keyof typeof pluginConfig.agents]
: undefined
const retryModelPayload = buildRetryModelPayload(newModel, agentSettings ? {
variant: agentSettings.variant,
reasoningEffort: agentSettings.reasoningEffort,
} : undefined)
if (!retryModelPayload) {
log(`[${HOOK_NAME}] Invalid model format (missing provider prefix): ${newModel}`)
const state = sessionStates.get(sessionID)
@@ -0,0 +1,114 @@
import { describe, test, expect } from "bun:test"
import { buildRetryModelPayload } from "./retry-model-payload"
describe("buildRetryModelPayload", () => {
test("should return undefined for empty model string", () => {
// given
const model = ""
// when
const result = buildRetryModelPayload(model)
// then
expect(result).toBeUndefined()
})
test("should return undefined for model without provider prefix", () => {
// given
const model = "kimi-k2.5"
// when
const result = buildRetryModelPayload(model)
// then
expect(result).toBeUndefined()
})
test("should parse provider and model ID", () => {
// given
const model = "chutes/kimi-k2.5"
// when
const result = buildRetryModelPayload(model)
// then
expect(result).toEqual({
model: { providerID: "chutes", modelID: "kimi-k2.5" },
})
})
test("should include variant from model string", () => {
// given
const model = "anthropic/claude-sonnet-4-5 high"
// when
const result = buildRetryModelPayload(model)
// then
expect(result).toEqual({
model: { providerID: "anthropic", modelID: "claude-sonnet-4-5" },
variant: "high",
})
})
test("should use agent variant when model string has no variant", () => {
// given
const model = "chutes/kimi-k2.5"
const agentSettings = { variant: "max" }
// when
const result = buildRetryModelPayload(model, agentSettings)
// then
expect(result).toEqual({
model: { providerID: "chutes", modelID: "kimi-k2.5" },
variant: "max",
})
})
test("should prefer model string variant over agent variant", () => {
// given
const model = "anthropic/claude-sonnet-4-5 high"
const agentSettings = { variant: "max" }
// when
const result = buildRetryModelPayload(model, agentSettings)
// then
expect(result).toEqual({
model: { providerID: "anthropic", modelID: "claude-sonnet-4-5" },
variant: "high",
})
})
test("should include reasoningEffort from agent settings", () => {
// given
const model = "openai/gpt-5.4"
const agentSettings = { variant: "high", reasoningEffort: "xhigh" }
// when
const result = buildRetryModelPayload(model, agentSettings)
// then
expect(result).toEqual({
model: { providerID: "openai", modelID: "gpt-5.4" },
variant: "high",
reasoningEffort: "xhigh",
})
})
test("should not include reasoningEffort when agent settings has none", () => {
// given
const model = "chutes/kimi-k2.5"
const agentSettings = { variant: "medium" }
// when
const result = buildRetryModelPayload(model, agentSettings)
// then
expect(result).toEqual({
model: { providerID: "chutes", modelID: "kimi-k2.5" },
variant: "medium",
})
})
})
@@ -2,24 +2,29 @@ import { parseModelString } from "../../tools/delegate-task/model-string-parser"
export function buildRetryModelPayload(
model: string,
): { model: { providerID: string; modelID: string }; variant?: string } | undefined {
agentSettings?: { variant?: string; reasoningEffort?: string },
): { model: { providerID: string; modelID: string }; variant?: string; reasoningEffort?: string } | undefined {
const parsedModel = parseModelString(model)
if (!parsedModel) {
return undefined
}
return parsedModel.variant
? {
model: {
providerID: parsedModel.providerID,
modelID: parsedModel.modelID,
},
variant: parsedModel.variant,
}
: {
model: {
providerID: parsedModel.providerID,
modelID: parsedModel.modelID,
},
}
const variant = parsedModel.variant ?? agentSettings?.variant
const reasoningEffort = agentSettings?.reasoningEffort
const payload: { model: { providerID: string; modelID: string }; variant?: string; reasoningEffort?: string } = {
model: {
providerID: parsedModel.providerID,
modelID: parsedModel.modelID,
},
}
if (variant) {
payload.variant = variant
}
if (reasoningEffort) {
payload.reasoningEffort = reasoningEffort
}
return payload
}