From 4776b33c2c09f4520cea3fa70fbd1565cece7e2c Mon Sep 17 00:00:00 2001 From: Adam Higgins Date: Wed, 21 Oct 2026 14:22:26 +0100 Subject: [PATCH] fix(web): restore the composer account picker lost in the upstream sync The upstream merge in #415 took upstream's refactored ChatComposer, which moved the model picker into ComposerModelPicker. The fork's account picker block, its overflow-menu entry, and the onForkModel/modelRequiresFork props were dropped along the way. ChatView kept passing those props, but the spread hid the mismatch from the type checker. Co-Authored-By: Claude Opus 5.5 --- apps/web/src/components/chat/ChatComposer.tsx | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/apps/web/src/components/chat/ChatComposer.tsx b/apps/web/src/components/chat/ChatComposer.tsx index 6a5dddfb67cf1..2965cc8daf5f9 100644 --- a/apps/web/src/components/chat/ChatComposer.tsx +++ b/apps/web/src/components/chat/ChatComposer.tsx @@ -285,6 +285,12 @@ import { } from "./ComposerCommandMenu"; import { ComposerPendingApprovalActions } from "./ComposerPendingApprovalActions"; import { CompactComposerControlsMenu } from "./CompactComposerControlsMenu"; +import { ProviderAccountPicker } from "./ProviderAccountPicker"; +import { + accountsForProvider, + resolveModelForAccountSwitch, + shouldShowProviderAccountPicker, +} from "./providerAccountSelection"; import { ComposerAttachmentFileList, ComposerAttachmentMediaRow, @@ -1391,6 +1397,9 @@ export interface ChatComposerProps { ) => void; onOpenProviderSetup: (instanceId: ProviderInstanceId) => void; getModelDisabledReason: (instanceId: ProviderInstanceId, model: string) => string | null; + /** Set once the thread has started: the pickers can then fork into a new tab. */ + onForkModel?: (instanceId: ProviderInstanceId, model: string) => void; + modelRequiresFork?: (instanceId: ProviderInstanceId, model: string) => boolean; toggleInteractionMode: () => void; handleRuntimeModeChange: (mode: RuntimeMode) => void; handleInteractionModeChange: (mode: ProviderInteractionMode) => void; @@ -1764,6 +1773,8 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) onProviderModelSelect, onOpenProviderSetup, getModelDisabledReason, + onForkModel, + modelRequiresFork, toggleInteractionMode, handleRuntimeModeChange, handleInteractionModeChange, @@ -4944,6 +4955,52 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps) size: composerControlsCollapsed ? "xs" : "sm", hidden: composerControlsHidden || restingHiddenBlockCount > 1, }); + const allProviderAccounts = accountsForProvider({ + entries: providerInstanceEntries, + driverKind: selectedProvider, + }); + const lockedProviderAccounts = + lockedContinuationGroupKey != null + ? accountsForProvider({ + entries: providerInstanceEntries, + driverKind: selectedProvider, + lockedContinuationGroupKey, + }) + : allProviderAccounts; + const showProviderAccountPicker = shouldShowProviderAccountPicker(allProviderAccounts); + // A started thread that can fork lists every account; the ones it cannot switch to in place + // open in a new tab instead. + const providerAccounts = onForkModel ? allProviderAccounts : lockedProviderAccounts; + const resolveAccountSwitchModel = (instanceId: ProviderInstanceId) => + resolveModelForAccountSwitch({ + currentModel: selectedModelForPickerWithCustomFallback, + destinationModels: modelOptionsByInstance.get(instanceId) ?? [], + }); + const accountRequiresFork = (instanceId: ProviderInstanceId) => + onForkModel !== undefined && + (!lockedProviderAccounts.some((account) => account.instanceId === instanceId) || + modelRequiresFork?.(instanceId, resolveAccountSwitchModel(instanceId)) === true); + const onAccountChange = (instanceId: ProviderInstanceId) => { + const nextModel = resolveAccountSwitchModel(instanceId); + if (onForkModel && accountRequiresFork(instanceId)) { + onForkModel(instanceId, nextModel); + return; + } + setMultipleModelSelections(null); + onProviderModelSelect(instanceId, nextModel); + }; + const restingProviderAccountPicker = showProviderAccountPicker ? ( +