diff --git a/packages/app/src/hooks/use-agent-form-state.ts b/packages/app/src/hooks/use-agent-form-state.ts index 46b729369..f04a0cbbc 100644 --- a/packages/app/src/hooks/use-agent-form-state.ts +++ b/packages/app/src/hooks/use-agent-form-state.ts @@ -372,6 +372,7 @@ export function useAgentFormState(options: UseAgentFormStateOptions = {}): UseAg } const providerDef = selectableProviderDefinitionMap.get(provider); const providerModels = allProviderModels.get(provider) ?? null; + const providerPrefs = preferences?.providerPreferences?.[provider]; const normalizedModelId = normalizeSelectedModelId(modelId); const nextModelId = normalizedModelId || resolveDefaultModelId(providerModels); @@ -381,6 +382,7 @@ export function useAgentFormState(options: UseAgentFormStateOptions = {}): UseAg modelId, providerDef, providerModels, + providerPrefs, }); void updatePreferences((current) => mergeSelectedComposerPreferences({ @@ -392,7 +394,12 @@ export function useAgentFormState(options: UseAgentFormStateOptions = {}): UseAg }), ); }, - [allProviderModels, selectableProviderDefinitionMap, updatePreferences], + [ + allProviderModels, + preferences?.providerPreferences, + selectableProviderDefinitionMap, + updatePreferences, + ], ); const setModeFromUser = useCallback( diff --git a/packages/app/src/provider-selection/resolve-agent-form.test.ts b/packages/app/src/provider-selection/resolve-agent-form.test.ts index 96e75b3a4..f04fd5fe3 100644 --- a/packages/app/src/provider-selection/resolve-agent-form.test.ts +++ b/packages/app/src/provider-selection/resolve-agent-form.test.ts @@ -768,6 +768,21 @@ describe("resolveAgentForm", () => { expect(next.userModified.model).toBe(true); }); + it("preserves the current preferred mode when selecting a provider and model", () => { + const state = makeState({ provider: "codex", modeId: "full-access" }); + const next = resolveAgentForm(state, { + type: "SET_PROVIDER_AND_MODEL_FROM_USER", + provider: "codex", + modelId: "gpt-5.3-codex", + providerDef: TEST_CODEX_DEFINITION, + providerModels: CODEX_MODELS, + }); + + expect(next.form.provider).toBe("codex"); + expect(next.form.model).toBe("gpt-5.3-codex"); + expect(next.form.modeId).toBe("full-access"); + }); + it("falls back to provider default model when modelId is empty", () => { const state = makeState(); const next = resolveAgentForm(state, { diff --git a/packages/app/src/provider-selection/resolve-agent-form.ts b/packages/app/src/provider-selection/resolve-agent-form.ts index 3763370e2..6cc351188 100644 --- a/packages/app/src/provider-selection/resolve-agent-form.ts +++ b/packages/app/src/provider-selection/resolve-agent-form.ts @@ -82,6 +82,7 @@ export type AgentFormAction = modelId: string; providerDef: AgentProviderDefinition | undefined; providerModels: AgentModelDefinition[] | null; + providerPrefs?: ProviderPrefs | undefined; } | { type: "SET_MODE_FROM_USER"; modeId: string } | { @@ -417,6 +418,27 @@ function pickNextModeForProvider(input: { return providerDef?.defaultModeId ?? ""; } +function pickNextModeForProviderAndModel(input: { + currentProvider: AgentProvider | null; + currentModeId: string; + provider: AgentProvider; + providerDef: AgentProviderDefinition | undefined; + providerPrefs: ProviderPrefs | undefined; +}): string { + const validModeIds = input.providerDef?.modes.map((m) => m.id) ?? []; + if ( + input.currentProvider === input.provider && + input.currentModeId && + validModeIds.includes(input.currentModeId) + ) { + return input.currentModeId; + } + return pickNextModeForProvider({ + providerDef: input.providerDef, + providerPrefs: input.providerPrefs, + }); +} + function pickNextThinkingOptionForProvider(input: { providerModels: AgentModelDefinition[] | null; providerPrefs: ProviderPrefs | undefined; @@ -494,12 +516,19 @@ export function resolveAgentForm( modelId: nextModelId, requestedThinkingOptionId: "", }); + const nextModeId = pickNextModeForProviderAndModel({ + currentProvider: state.form.provider, + currentModeId: state.form.modeId, + provider: action.provider, + providerDef: action.providerDef, + providerPrefs: action.providerPrefs, + }); return { form: { ...state.form, provider: action.provider, model: nextModelId, - modeId: action.providerDef?.defaultModeId ?? "", + modeId: nextModeId, thinkingOptionId: nextThinkingOptionId, }, userModified: { ...state.userModified, provider: true, model: true },