From 5707a6ee1dc470198ecb01a0b6181c5082c7a81f Mon Sep 17 00:00:00 2001 From: Julius Marminge Date: Fri, 27 Feb 2026 10:07:10 -0800 Subject: [PATCH] Use grouped provider/model select in chat composer Co-authored-by: codex --- apps/web/src/components/ChatView.tsx | 120 ++++++++++++++++----------- 1 file changed, 71 insertions(+), 49 deletions(-) diff --git a/apps/web/src/components/ChatView.tsx b/apps/web/src/components/ChatView.tsx index f583ff69a71562e40ac9a94d9b2a9c59d6b69822..1119967bd6afc49e8c89de095a4fdd04104f914c 100644 --- a/apps/web/src/components/ChatView.tsx +++ b/apps/web/src/components/ChatView.tsx @@ -107,7 +107,15 @@ import { CheckIcon, } from "lucide-react"; import { Button } from "./ui/button"; -import { Select, SelectItem, SelectPopup, SelectTrigger, SelectValue } from "./ui/select"; +import { + Select, + SelectGroup, + SelectGroupLabel, + SelectItem, + SelectPopup, + SelectTrigger, + SelectValue, +} from "./ui/select"; import { Separator } from "./ui/separator"; import { Group, GroupSeparator } from "./ui/group"; import { Menu, MenuItem, MenuPopup, MenuShortcut, MenuTrigger } from "./ui/menu"; @@ -2265,13 +2273,22 @@ export default function ChatView({ threadId }: ChatViewProps) { }, [activeThread, scheduleComposerFocus, selectedProvider], ); - const onProviderSelect = useCallback( - (provider: ProviderKind) => { + const onProviderModelSelect = useCallback( + (provider: ProviderKind, model: ModelSlug) => { + const api = readNativeApi(); if (!activeThread) return; setSelectedProviderByThread((existing) => ({ ...existing, [activeThread.id]: provider, })); + if (api) { + void api.orchestration.dispatchCommand({ + type: "thread.meta.update", + commandId: newCommandId(), + threadId: activeThread.id, + model: resolveModelSlugForProvider(provider, model), + }); + } scheduleComposerFocus(); }, [activeThread, scheduleComposerFocus], @@ -2712,17 +2729,11 @@ export default function ChatView({ threadId }: ChatViewProps) { {/* Bottom toolbar */}
- {/* Model picker */} - - - {/* Divider */} - - - {/* Model picker */} - {/* Divider */} @@ -3866,54 +3877,65 @@ const MessagesTimeline = memo(function MessagesTimeline({ ); }); -const ModelPicker = memo(function ModelPicker(props: { - model: ModelSlug; - options: ReadonlyArray<{ readonly slug: ModelSlug; readonly name: string }>; - onModelChange: (model: ModelSlug) => void; -}) { - return ( - - ); -}); +const PROVIDER_MODEL_GROUPS: ReadonlyArray<{ + readonly provider: ProviderKind; + readonly label: string; + readonly options: ReadonlyArray<{ readonly slug: ModelSlug; readonly name: string }>; +}> = PROVIDER_OPTIONS.filter((option) => option.available).map((option) => ({ + provider: option.value, + label: option.label, + options: getModelOptions(option.value), +})); -const ProviderPicker = memo(function ProviderPicker(props: { +const ProviderModelPicker = memo(function ProviderModelPicker(props: { provider: ProviderKind; - onProviderChange: (provider: ProviderKind) => void; + model: ModelSlug; + onProviderModelChange: (provider: ProviderKind, model: ModelSlug) => void; }) { + const items = PROVIDER_MODEL_GROUPS.flatMap(({ provider, label, options }) => + options.map(({ slug, name }) => ({ + label: `${label} ยท ${name}`, + value: `${provider}:${slug}`, + })), + ); + return ( -- 2.54.0