From ccbe190d64ae01a0c0fe0cad9e27552e7affbe37 Mon Sep 17 00:00:00 2001 From: can1357 Date: Wed, 22 Jul 2026 20:27:43 +0200 Subject: [PATCH] fix(sdk): inherit role thinking level on startup retry fallback A retry-chain entry without its own :level suffix now inherits the unavailable primary's configured thinking level, matching runtime fallback-chain semantics. Regression test asserts a level that differs from the fallback model's default. --- packages/coding-agent/src/sdk.ts | 7 +++++++ packages/coding-agent/test/sdk-model-selection.test.ts | 8 +++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/coding-agent/src/sdk.ts b/packages/coding-agent/src/sdk.ts index c31b31bb1..d1dd84548 100644 --- a/packages/coding-agent/src/sdk.ts +++ b/packages/coding-agent/src/sdk.ts @@ -2143,6 +2143,13 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {} let selectedModel = primary.model; let selectedThinkingLevel = primary.thinkingLevel; let selectedExplicitThinkingLevel = primary.explicitThinkingLevel; + // A chain entry without its own `:level` suffix inherits the + // unavailable primary's configured thinking level, matching + // runtime fallback-chain semantics. + if (retryFallback && !selectedExplicitThinkingLevel && retryFallback.originalThinkingLevel !== undefined) { + selectedThinkingLevel = retryFallback.originalThinkingLevel; + selectedExplicitThinkingLevel = true; + } let authFallbackUsed = false; if (options.modelPatternAuthFallback) { const primaryKey = await modelRegistry.getApiKey(primary.model); diff --git a/packages/coding-agent/test/sdk-model-selection.test.ts b/packages/coding-agent/test/sdk-model-selection.test.ts index efa2558f6..56af7b8e9 100644 --- a/packages/coding-agent/test/sdk-model-selection.test.ts +++ b/packages/coding-agent/test/sdk-model-selection.test.ts @@ -363,7 +363,7 @@ describe("createAgentSession deferred model pattern resolution", () => { authStorage.setRuntimeApiKey("runtime-provider", "test-key"); authStoragesToClose.push(authStorage); const modelRegistry = new ModelRegistry(authStorage, path.join(tempDir, "missing-role-models.yml")); - const parsed = parseArgs(["--model", "slow:high"]); + const parsed = parseArgs(["--model", "slow:low"]); const exitSpy = vi.spyOn(process, "exit").mockImplementation((code?: number | string | null) => { throw new Error(`buildSessionOptions unexpectedly exited with ${code}`); }); @@ -375,7 +375,7 @@ describe("createAgentSession deferred model pattern resolution", () => { modelRegistry, settings, ); - expect(cliOptions.modelPattern).toBe("slow:high"); + expect(cliOptions.modelPattern).toBe("slow:low"); const { session, modelFallbackMessage } = await createAgentSession({ ...cliOptions, @@ -398,7 +398,9 @@ describe("createAgentSession deferred model pattern resolution", () => { try { expect(session.model?.provider).toBe("runtime-provider"); expect(session.model?.id).toBe("runtime-reasoning-model"); - expect(session.thinkingLevel).toBe(Effort.High); + // `low` differs from the fallback model's default (`high`), so this + // proves the suffix is inherited rather than the model default applied. + expect(session.thinkingLevel).toBe(Effort.Low); expect(modelFallbackMessage).toBeUndefined(); } finally { await session.dispose();