From b2f7238a03357f2d928784a8619edb01cd2f86f9 Mon Sep 17 00:00:00 2001 From: roboomp Date: Sun, 5 Jul 2026 19:21:08 +0000 Subject: [PATCH] fix(coding-agent): allowed mixed fallback chains - Allowed implicit default fallback resolution when other role fallback chains are configured. - Covered the mixed-role first-run fallback case. Fixes #4533 --- packages/coding-agent/src/session/agent-session.ts | 11 ++--------- .../test/agent-session-retry-fallback.test.ts | 6 ++++-- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/packages/coding-agent/src/session/agent-session.ts b/packages/coding-agent/src/session/agent-session.ts index e44bd7d81..b57ccbca0 100644 --- a/packages/coding-agent/src/session/agent-session.ts +++ b/packages/coding-agent/src/session/agent-session.ts @@ -13122,10 +13122,7 @@ export class AgentSession { if ( Array.isArray(defaultChain) && defaultChain.length > 0 && - this.#getRetryFallbackPrimarySelector("default") === undefined && - Object.entries(chains).every( - ([role, chain]) => role === "default" || !Array.isArray(chain) || chain.length === 0, - ) + this.#getRetryFallbackPrimarySelector("default") === undefined ) { return "default"; } @@ -13155,11 +13152,7 @@ export class AgentSession { if ( Array.isArray(defaultChain) && defaultChain.length > 0 && - this.#getRetryFallbackPrimarySelector("default") === undefined && - Object.entries(chains).every( - ([chainRole, roleChain]) => - chainRole === "default" || !Array.isArray(roleChain) || roleChain.length === 0, - ) + this.#getRetryFallbackPrimarySelector("default") === undefined ) { const seen = new Set([parsedCurrent.raw]); chain = [parsedCurrent]; diff --git a/packages/coding-agent/test/agent-session-retry-fallback.test.ts b/packages/coding-agent/test/agent-session-retry-fallback.test.ts index 1adeda0ec..345d42df3 100644 --- a/packages/coding-agent/test/agent-session-retry-fallback.test.ts +++ b/packages/coding-agent/test/agent-session-retry-fallback.test.ts @@ -219,10 +219,11 @@ describe("AgentSession retry fallback", () => { ]); }); - it("uses the active initial model as the default fallback primary when the default role is unset", async () => { + it("uses the active initial model as the default fallback primary when other role fallback chains are configured", async () => { const primaryModel = getBundledModel("anthropic", "claude-sonnet-4-5"); const fallbackModel = getBundledModel("openai", "gpt-4o-mini"); - if (!primaryModel || !fallbackModel) { + const otherRoleFallbackModel = getBundledModel("openai", "gpt-4o"); + if (!primaryModel || !fallbackModel || !otherRoleFallbackModel) { throw new Error("Expected bundled test models to exist"); } @@ -235,6 +236,7 @@ describe("AgentSession retry fallback", () => { "retry.maxRetries": 1, "retry.fallbackChains": { default: [`${fallbackModel.provider}/${fallbackModel.id}`], + smol: [`${otherRoleFallbackModel.provider}/${otherRoleFallbackModel.id}`], }, });