diff --git a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/model-selector.tsx b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/model-selector.tsx index 871225d7ea5..83a7f75c1f1 100644 --- a/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/model-selector.tsx +++ b/apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/model-selector.tsx @@ -45,7 +45,7 @@ export function ModelSelector() { { effort: effortChoice ?? undefined, modelSelection: selection }, advanced ) - const options = advanced + const options = modelSelection ? mothershipEffortOptions(modelSelection.model) : MOTHERSHIP_SIMPLE_EFFORT_OPTIONS const setEffort = (choice: MothershipEffort) => { @@ -59,13 +59,10 @@ export function ModelSelector() { }, [chatId]) const effortLabel = options.find((option) => option.value === effort)?.label ?? effort - const modelLabel = - MOTHERSHIP_MODEL_OPTIONS.find((option) => option.value === modelSelection.model)?.label ?? - modelSelection.model return (
- {advanced && ( + {modelSelection && ( <> {modelSelection.model !== 'claude-opus-5-5' && ( option.value === modelSelection.model) + ?.label ?? modelSelection.model + } icon={Sparkles} showChevron /> diff --git a/apps/sim/lib/mothership/chat/post.test.ts b/apps/sim/lib/mothership/chat/post.test.ts index 86dcab8c45f..9e804f6fca8 100644 --- a/apps/sim/lib/mothership/chat/post.test.ts +++ b/apps/sim/lib/mothership/chat/post.test.ts @@ -816,7 +816,7 @@ describe('handleUnifiedChatPost', () => { ['low', 'low'], ['none', 'high'], ])( - 'enforces the default model and effort range on submitted %s effort', + 'leaves the model to the worker and enforces the effort range on submitted %s effort', async (effort, expected) => { flags.models.mockResolvedValue(false) const response = await handleUnifiedChatPost( @@ -831,12 +831,9 @@ describe('handleUnifiedChatPost', () => { }) ) expect(response.status).toBe(200) - expect(buildCopilotRequestPayload).toHaveBeenCalledWith( - expect.objectContaining({ - effort: expected, - modelSelection: { model: 'gpt-6-astra', fastMode: false }, - }) - ) + const { requestPayload } = createSSEStream.mock.lastCall?.[0] ?? {} + expect(requestPayload?.effort).toBe(expected) + expect(JSON.stringify(requestPayload)).not.toContain('modelSelection') } ) diff --git a/apps/sim/lib/mothership/model-options.ts b/apps/sim/lib/mothership/model-options.ts index b4d26c75570..aff834b7ab1 100644 --- a/apps/sim/lib/mothership/model-options.ts +++ b/apps/sim/lib/mothership/model-options.ts @@ -38,22 +38,29 @@ export function mothershipEffortOptions(model: ModelSelection['model']) { : MOTHERSHIP_EFFORT_OPTIONS } -/** Shared by the visible controls, send path and server admission so hidden preferences cannot leak. */ +/** + * Shared by the visible controls, send path and server admission so hidden preferences cannot leak. + * Without the model picker no selection is sent, so the worker routes every model role itself. + */ export function resolveMothershipModelSettings( settings: { effort?: MothershipEffort; modelSelection?: ModelSelection }, advanced: boolean -): { effort: MothershipEffort; modelSelection: ModelSelection } { +): { effort: MothershipEffort; modelSelection: ModelSelection | undefined } { let effort = settings.effort ?? DEFAULT_MOTHERSHIP_EFFORT if (!advanced) { if (effort === 'none') effort = DEFAULT_MOTHERSHIP_EFFORT if (effort === 'max') effort = 'xhigh' - return { effort, modelSelection: { model: 'gpt-6-astra', fastMode: false } } + return { effort, modelSelection: undefined } } - const stored = settings.modelSelection ?? { model: 'gpt-6-astra', fastMode: false } + const modelSelection = normalizeModelSelection( + settings.modelSelection ?? { model: 'gpt-6-astra', fastMode: false } + ) + if (effort === 'none' && modelSelection.model !== 'gpt-6-sol') effort = DEFAULT_MOTHERSHIP_EFFORT + return { effort, modelSelection } +} + +/** A stored pick on the current catalog: Opus 5 reads as Opus 5.5, which has no Fast mode. */ +export function normalizeModelSelection(stored: ModelSelection): ModelSelection { const model = stored.model === 'claude-opus-5' ? 'claude-opus-5-5' : stored.model - if (effort === 'none' && model !== 'gpt-6-sol') effort = DEFAULT_MOTHERSHIP_EFFORT - return { - effort, - modelSelection: { model, fastMode: model === 'claude-opus-5-5' ? false : stored.fastMode }, - } + return { model, fastMode: model === 'claude-opus-5-5' ? false : stored.fastMode } } diff --git a/apps/sim/stores/mothership-effort/store.ts b/apps/sim/stores/mothership-effort/store.ts index a885b641931..0ec4b53977b 100644 --- a/apps/sim/stores/mothership-effort/store.ts +++ b/apps/sim/stores/mothership-effort/store.ts @@ -2,10 +2,7 @@ import { omit, toRecord } from '@sim/utils/object' import { create } from 'zustand' import { devtools, persist } from 'zustand/middleware' import { type ModelSelection, ModelSelectionSchema } from '@/lib/mothership/generated/protocol' -import { - type MothershipEffort, - resolveMothershipModelSettings, -} from '@/lib/mothership/model-options' +import { type MothershipEffort, normalizeModelSelection } from '@/lib/mothership/model-options' /** A chat's effort pick and the token that tells it apart from other picks of the same value. */ interface ChatEffortPick { @@ -52,7 +49,7 @@ let lastChatEffortPick = 0 function withModelSelection( modelSelection: ModelSelection ): Pick { - return { modelSelection: resolveMothershipModelSettings({ modelSelection }, true).modelSelection } + return { modelSelection: normalizeModelSelection(modelSelection) } } export const useMothershipEffortStore = create()(