import { ANTIGRAVITY_DEFAULT_MODEL, type ProviderInstanceId, type EnvironmentId, type ProviderDriverKind, type ResolvedKeybindingsConfig, MODEL_PICKER_JUMP_KEYBINDING_COMMANDS, } from "@t3tools/contracts"; import { resolveSelectableModel } from "@t3tools/shared/model"; import { useAtomValue } from "@effect/atom-react"; import { formatProviderUpdateRequiredNotice } from "@t3tools/client-runtime/providerUpdateRequiredModels"; import { useNavigate } from "@tanstack/react-router"; import { LegendList, type LegendListRef } from "@legendapp/list/react"; import { memo, useState, useEffect, useEffectEvent, useLayoutEffect, useRef, type ReactNode, type RefObject, } from "react"; import { ModelListRow } from "./ModelListRow"; import { ModelPickerSidebar } from "./ModelPickerSidebar"; import { getProviderStatusMessage, hasProviderSetup } from "./ProviderStatusBanner"; import { modelPickerLegacySectionKey, modelPickerModelKey, parseModelPickerLegacySectionKey, parseModelPickerModelKey, } from "./modelPickerKeys"; import { rankModelPickerSearch } from "./modelPickerSearch"; import { Combobox, ComboboxEmpty, ComboboxSearchInput, ComboboxItem, ComboboxListVirtualized, } from "../ui/combobox"; import { ModelEsque } from "./providerIconUtils"; import { isCommandPaletteOpen } from "../../commandPaletteBus"; import { registerModelPickerContent } from "../../modelPickerVisibility"; import { primaryServerKeybindingsAtom } from "../../state/server"; import { modelPickerJumpCommandForIndex, modelPickerJumpIndexFromCommand, resolveShortcutCommand, shortcutLabelForCommand, } from "../../keybindings"; import { useEnvironmentModelPreferences, useToggleEnvironmentModelFavorite, } from "~/hooks/useSettings"; import { announce } from "~/lib/announce"; import { cn } from "~/lib/utils"; import { getVirtualizedScrollFadeClassName } from "../ui/scroll-area"; import { TooltipProvider } from "../ui/tooltip"; import { InlineButton } from "../ui/button"; import { isProviderInstancePickerReady, isProviderInstancePickerVisible, shouldShowInstanceBadge, type ProviderInstanceEntry, } from "../../providerInstances"; import { providerModelKey, sortProviderModelItems } from "../../modelOrdering"; type ModelPickerItem = { slug: string; name: string; shortName?: string; subProvider?: string; badge?: "new"; instanceId: ProviderInstanceId; driverKind: ProviderDriverKind; instanceDisplayName: string; instanceAccentColor?: string | undefined; acpRegistryAgentId?: string | undefined; acpRegistryIconUrl?: string | undefined; continuationGroupKey?: string | undefined; isLegacy?: boolean | undefined; isUnavailable?: boolean | undefined; }; export function resolveModelPickerSelectedModel(input: { driverKind: ProviderDriverKind | undefined; model: string; options: ReadonlyArray; }) { if (input.driverKind === "antigravity" && input.model === ANTIGRAVITY_DEFAULT_MODEL) { const availableModels = input.options.filter( (option) => option.slug !== ANTIGRAVITY_DEFAULT_MODEL && !option.isUnavailable, ); return ( availableModels.find((option) => option.aliases?.includes(ANTIGRAVITY_DEFAULT_MODEL)) ?? availableModels.find((option) => option.isDefault) ); } return input.options.find((option) => option.slug === input.model); } function shouldIncludeModelPickerOption(input: { readonly entry: ProviderInstanceEntry; readonly option: ModelEsque; readonly activeInstanceId: ProviderInstanceId; readonly activeModel: string; }): boolean { if (input.entry.driverKind === "antigravity" && input.option.slug === ANTIGRAVITY_DEFAULT_MODEL) { return false; } if (isProviderInstancePickerReady(input.entry)) return true; return ( input.entry.enabled && (input.entry.driverKind === "opencode" || input.entry.driverKind === "antigravity") && input.entry.instanceId === input.activeInstanceId && input.option.slug === input.activeModel && input.option.isUnavailable === true ); } function shouldOfferModelPickerSetup( entry: ProviderInstanceEntry, options: ReadonlyArray, ): boolean { return ( entry.enabled && entry.status !== "disabled" && hasProviderSetup(entry.snapshot) && (!isProviderInstancePickerReady(entry) || !entry.installed || entry.snapshot.auth.status === "unauthenticated" || !options.some((option) => !option.isUnavailable)) ); } function adjacentModelPickerProvider(input: { entries: ReadonlyArray; selectedInstanceId: ProviderInstanceId | "favorites"; direction: 1 | -1; disabledInstanceIds: ReadonlySet | undefined; selectableUnavailableInstanceIds: ReadonlySet | undefined; }) { const providers: Array = [ "favorites", ...input.entries .filter( (entry) => !input.disabledInstanceIds?.has(entry.instanceId) && (isProviderInstancePickerReady(entry) || input.selectableUnavailableInstanceIds?.has(entry.instanceId)), ) .map((entry) => entry.instanceId), ]; const index = providers.indexOf(input.selectedInstanceId); return providers[ index < 0 ? input.direction === 1 ? 0 : providers.length - 1 : (index + input.direction + providers.length) % providers.length ]!; } const EMPTY_MODEL_JUMP_LABELS = new Map(); const MODEL_LIST_ESTIMATED_ITEM_SIZE = 32; // Rendered heights in `--spacing` units. Chrome is the search box and list padding, plus a 1px border. const ROW_UNITS = 8; const ROW_SEPARATOR_UNITS = 0.5; const LIST_CHROME_UNITS = 15.5; function ModelListSeparator() { return
; } function modelJumpLabelsByKey( modelKeys: ReadonlyArray, keybindings: ResolvedKeybindingsConfig, terminalOpen: boolean, ): ReadonlyMap { const shortcutLabelOptions = { platform: navigator.platform, context: { terminalFocus: false, terminalOpen, modelPickerOpen: true }, }; const mapping = new Map(); for (const [index, modelKey] of modelKeys.entries()) { const command = modelPickerJumpCommandForIndex(index); const label = command && shortcutLabelForCommand(keybindings, command, shortcutLabelOptions); if (label) { mapping.set(modelKey, label); } } return mapping.size > 0 ? mapping : EMPTY_MODEL_JUMP_LABELS; } function ModelPickerProviderNotices({ setupEntries, updateRequiredNotices, emptyLabel, onRequestClose, onOpenProviderSetup, }: { setupEntries: ReadonlyArray; emptyLabel: string; updateRequiredNotices: ReadonlyArray<{ instanceId: ProviderInstanceId; notice: string }>; onRequestClose: (() => void) | undefined; onOpenProviderSetup: ((instanceId: ProviderInstanceId) => void) | undefined; }) { const navigate = useNavigate(); return ( <> {setupEntries.length > 0 ? (
{setupEntries.map((entry) => (

{getProviderStatusMessage(entry.snapshot)}

{ onRequestClose?.(); onOpenProviderSetup?.(entry.instanceId); }} > {setupEntries.length > 1 ? `Set up ${entry.displayName}` : "Open provider setup"}
))}
) : ( {emptyLabel} )} {updateRequiredNotices.map(({ instanceId, notice }) => (

{notice}{" "} { onRequestClose?.(); void navigate({ to: "/settings/providers" }); }} > Provider settings

))} ); } function ModelPickerList({ listRef, itemKeys, extraData, renderItem, }: { listRef: RefObject; itemKeys: ReadonlyArray; extraData: unknown; renderItem: (props: { item: string; index: number }) => ReactNode; }) { const [showTopScrollFade, setShowTopScrollFade] = useState(false); const [showBottomScrollFade, setShowBottomScrollFade] = useState(false); const updateScrollFades = () => { const scrollElement = listRef.current?.getScrollableNode(); if (!(scrollElement instanceof HTMLElement)) { return; } const maxScrollOffset = Math.max(0, scrollElement.scrollHeight - scrollElement.clientHeight); setShowTopScrollFade(scrollElement.scrollTop > 1); setShowBottomScrollFade(maxScrollOffset - scrollElement.scrollTop > 1); }; // Disabled-reason closures rebuild identical key arrays; compare contents. const itemListKey = JSON.stringify(itemKeys); const [fadesResetFor, setFadesResetFor] = useState(itemListKey); if (fadesResetFor !== itemListKey) { setFadesResetFor(itemListKey); setShowTopScrollFade(false); setShowBottomScrollFade(itemKeys.length > 5); } const measureScrollFades = useEffectEvent(updateScrollFades); // oxlint-disable-next-line t3code/no-unreasoned-state-sync -- measures the list scroller in animation frames after a new list lays out to set scroll fades useLayoutEffect(() => { let nestedFrame = 0; const frame = window.requestAnimationFrame(() => { measureScrollFades(); nestedFrame = window.requestAnimationFrame(() => measureScrollFades()); }); return () => { window.cancelAnimationFrame(frame); window.cancelAnimationFrame(nestedFrame); }; // oxlint-disable-next-line react/exhaustive-effect-dependencies -- A new list re-measures its scroll fades once it has laid out. }, [itemListKey]); return (
0 ? "flex-1" : "h-0", )} > ref={listRef} data={itemKeys} extraData={extraData} keyExtractor={(modelKey) => modelKey} renderItem={renderItem} estimatedItemSize={MODEL_LIST_ESTIMATED_ITEM_SIZE} drawDistance={480} recycleItems contentContainerClassName="pl-2 pr-px" ItemSeparatorComponent={ModelListSeparator} onLayout={updateScrollFades} onScroll={updateScrollFades} className={cn( "scrollbar-gutter-stable h-full overflow-x-hidden overscroll-y-contain py-1.5 [&::-webkit-scrollbar-track]:my-2", getVirtualizedScrollFadeClassName({ top: showTopScrollFade, bottom: showBottomScrollFade, }), )} />
); } // Capture gives picker shortcuts priority over the composer. function WindowKeyDownListener({ onKeyDown }: { onKeyDown: (event: KeyboardEvent) => void }) { const handleKeyDown = useEffectEvent(onKeyDown); // oxlint-disable-next-line t3code/no-unreasoned-state-sync -- subscribes a capture-phase window keydown listener for the picker's lifetime useEffect(() => { const listener = (event: KeyboardEvent) => handleKeyDown(event); window.addEventListener("keydown", listener, true); return () => { window.removeEventListener("keydown", listener, true); }; }, []); return null; } export const ModelPickerContent = memo(function ModelPickerContent(props: { environmentId: EnvironmentId | null; activeInstanceId: ProviderInstanceId; model: string; selectedModels?: ReadonlyArray<{ instanceId: ProviderInstanceId; model: string }>; onToggleModel?: (instanceId: ProviderInstanceId, model: string) => void; lockedProvider: ProviderDriverKind | null; lockedContinuationGroupKey?: string | null; instanceEntries: ReadonlyArray; keybindings?: ResolvedKeybindingsConfig; modelOptionsByInstance: ReadonlyMap>; terminalOpen: boolean; onRequestClose?: () => void; onOpenProviderSetup?: (instanceId: ProviderInstanceId) => void; getModelDisabledReason?: (instanceId: ProviderInstanceId, model: string) => string | null; onInstanceModelChange: (instanceId: ProviderInstanceId, model: string) => void; /** The owning popup moves focus here when it opens (its `initialFocus`). */ searchInputRef: RefObject; /** Sits beside an effort column: fills the shared row, and stacks above it on narrow screens. */ docked?: boolean; /** Right at the end of the search text moves into the popup's effort column. */ onFocusEffort?: () => void; /** Closes the list column, inside the popup's fixed height. */ listFooter?: ReactNode; }) { const { searchInputRef, keybindings: providedKeybindings, modelOptionsByInstance, instanceEntries, getModelDisabledReason, onInstanceModelChange, onToggleModel, onRequestClose, onOpenProviderSetup, } = props; const [searchQuery, setSearchQuery] = useState(""); const modelListRef = useRef(null); const pickerContentRef = useRef(null); // oxlint-disable-next-line t3code/no-unreasoned-state-sync -- publishes this picker's mount to global keydown handlers useLayoutEffect(() => registerModelPickerContent(), []); const highlightedModelKeyRef = useRef(null); const { favorites } = useEnvironmentModelPreferences(props.environmentId); const activeEntry = props.instanceEntries.find( (entry) => entry.instanceId === props.activeInstanceId, ); const activeModel = resolveModelPickerSelectedModel({ driverKind: activeEntry?.driverKind, model: props.model, options: modelOptionsByInstance.get(props.activeInstanceId) ?? [], }); const activeModelSlug = activeModel?.slug ?? (props.model === ANTIGRAVITY_DEFAULT_MODEL ? "" : props.model); const activeModelKey = activeModelSlug ? modelPickerModelKey(props.activeInstanceId, activeModelSlug) : null; const selectedModelKeys = props.selectedModels?.map((selection) => { const entry = instanceEntries.find((entry) => entry.instanceId === selection.instanceId); const model = resolveModelPickerSelectedModel({ driverKind: entry?.driverKind, model: selection.model, options: modelOptionsByInstance.get(selection.instanceId) ?? [], }); return modelPickerModelKey(selection.instanceId, model?.slug ?? selection.model); }); const selectedModelKeySet = new Set( selectedModelKeys ?? (activeModelKey ? [activeModelKey] : []), ); const activeInstanceHasSelectableUnavailableModel = activeEntry !== undefined && (modelOptionsByInstance.get(props.activeInstanceId) ?? []).some((option) => shouldIncludeModelPickerOption({ entry: activeEntry, option, activeInstanceId: props.activeInstanceId, activeModel: activeModelSlug, }), ) && !isProviderInstancePickerReady(activeEntry); const activeInstanceNeedsSetup = onOpenProviderSetup !== undefined && activeEntry !== undefined && shouldOfferModelPickerSetup( activeEntry, modelOptionsByInstance.get(props.activeInstanceId) ?? [], ); const [selectedInstanceId, setSelectedInstanceId] = useState( () => { if ( props.lockedProvider !== null || activeInstanceHasSelectableUnavailableModel || activeInstanceNeedsSetup ) { return props.activeInstanceId; } return favorites.length > 0 ? "favorites" : props.activeInstanceId; }, ); const favoritesSet = new Set(favorites.map((fav) => providerModelKey(fav.provider, fav.model))); const [expandedLegacyInstances, setExpandedLegacyInstances] = useState( () => new Set( activeModel?.isLegacy && !favoritesSet.has(providerModelKey(props.activeInstanceId, activeModelSlug)) ? [props.activeInstanceId] : [], ), ); const serverKeybindings = useAtomValue(primaryServerKeybindingsAtom); const keybindings = providedKeybindings ?? serverKeybindings; const [searchHeight, setSearchHeight] = useState(0); const toggleFavorite = useToggleEnvironmentModelFavorite(props.environmentId); const focusSearchInput = () => { searchInputRef.current?.focus({ preventScroll: true }); }; const handleSelectInstance = (instanceId: ProviderInstanceId | "favorites") => { setSelectedInstanceId(instanceId); window.requestAnimationFrame(() => { focusSearchInput(); }); }; const toggleLegacySection = (instanceId: ProviderInstanceId) => { setExpandedLegacyInstances((expanded) => { const next = new Set(expanded); if (next.has(instanceId)) { next.delete(instanceId); } else { next.add(instanceId); } return next; }); }; const handleModelSelect = ( modelSlug: string, instanceId: ProviderInstanceId, additive = false, ): string | null => { if (getModelDisabledReason?.(instanceId, modelSlug)) { return null; } const options = modelOptionsByInstance.get(instanceId); if (!options) { return null; } const entry = instanceEntries.find((candidate) => candidate.instanceId === instanceId); if (!entry) { return null; } const resolvedModel = resolveSelectableModel(entry.driverKind, modelSlug, options); if (!resolvedModel) return null; if (additive && onToggleModel) { onToggleModel(instanceId, resolvedModel); } else { onInstanceModelChange(instanceId, resolvedModel); } return resolvedModel; }; const modelJumpShortcutContext = { terminalFocus: false, terminalOpen: props.terminalOpen, modelPickerOpen: true, } as const; const lockedProvider = props.lockedProvider; const lockedContinuationGroupKey = props.lockedContinuationGroupKey; const canOpenProviderSetup = onOpenProviderSetup !== undefined; const entryByInstanceId = new Map(instanceEntries.map((entry) => [entry.instanceId, entry])); const matchesLockedProvider = ( entry: Pick, ): boolean => { if (lockedProvider === null) return true; if (entry.driverKind !== lockedProvider) return false; if (!lockedContinuationGroupKey) return true; return entry.continuationGroupKey === lockedContinuationGroupKey; }; const selectableUnavailableInstanceIds = (() => { const instanceIds = new Set(); if (activeInstanceHasSelectableUnavailableModel) { instanceIds.add(props.activeInstanceId); } if (canOpenProviderSetup) { for (const entry of instanceEntries) { if ( shouldOfferModelPickerSetup(entry, modelOptionsByInstance.get(entry.instanceId) ?? []) ) { instanceIds.add(entry.instanceId); } } } return instanceIds.size > 0 ? instanceIds : undefined; })(); const flatModels = (() => { const out: ModelPickerItem[] = []; for (const [instanceId, models] of modelOptionsByInstance) { const entry = entryByInstanceId.get(instanceId); if (!entry) { continue; } for (const model of models) { if ( !shouldIncludeModelPickerOption({ entry, option: model, activeInstanceId: props.activeInstanceId, activeModel: activeModelSlug, }) ) { continue; } out.push({ slug: model.slug, name: model.name, ...(model.shortName ? { shortName: model.shortName } : {}), ...(model.subProvider ? { subProvider: model.subProvider } : {}), ...(model.badge ? { badge: model.badge } : {}), ...(model.isLegacy ? { isLegacy: true } : {}), ...(model.isUnavailable ? { isUnavailable: true } : {}), instanceId, driverKind: entry.driverKind, instanceDisplayName: entry.displayName, ...(entry.accentColor ? { instanceAccentColor: entry.accentColor } : {}), ...(entry.acpRegistryAgentId ? { acpRegistryAgentId: entry.acpRegistryAgentId } : {}), ...(entry.acpRegistryIconUrl ? { acpRegistryIconUrl: entry.acpRegistryIconUrl } : {}), ...(entry.continuationGroupKey ? { continuationGroupKey: entry.continuationGroupKey } : {}), }); } } return out; })(); const isLocked = lockedProvider !== null; const isSearching = searchQuery.trim().length > 0; // Fit the tallest tab so switching tabs never resizes the popup and moves the rail under the cursor. const tallestTabUnits = (() => { const unitsByTab = new Map(); const addRow = (tab: ProviderInstanceId | "favorites") => { const previous = unitsByTab.get(tab); unitsByTab.set( tab, previous === undefined ? ROW_UNITS : previous + ROW_SEPARATOR_UNITS + ROW_UNITS, ); }; const tabsWithLegacyRow = new Set(); for (const model of flatModels) { if (!matchesLockedProvider(model)) continue; const isFavorite = favoritesSet.has(providerModelKey(model.instanceId, model.slug)); if (isFavorite) addRow("favorites"); if (model.isLegacy && !isFavorite) { tabsWithLegacyRow.add(model.instanceId); } else { addRow(model.instanceId); } } for (const instanceId of tabsWithLegacyRow) addRow(instanceId); return Math.max(0, ...unitsByTab.values()); })(); const lockedDisabledInstanceIds = (() => { if (!isLocked) { return undefined; } const disabled = new Set(); for (const entry of instanceEntries) { if (!matchesLockedProvider(entry)) { disabled.add(entry.instanceId); } } return disabled; })(); const sidebarInstanceEntries = (() => { const enabledEntries = instanceEntries.filter(isProviderInstancePickerVisible); if (!isLocked) { return enabledEntries; } const available: ProviderInstanceEntry[] = []; const disabled: ProviderInstanceEntry[] = []; for (const entry of enabledEntries) { if (matchesLockedProvider(entry)) { available.push(entry); } else { disabled.push(entry); } } return [...available, ...disabled]; })(); const showSidebar = !isSearching && sidebarInstanceEntries.length > 0; const instanceOrder = instanceEntries.map((entry) => entry.instanceId); const filteredModels = (() => { let result = flatModels; if (searchQuery.trim()) { const candidates = lockedProvider !== null ? result.filter((m) => matchesLockedProvider(m)) : result; return rankModelPickerSearch(candidates, searchQuery, (model) => ({ name: model.name, ...(model.shortName ? { shortName: model.shortName } : {}), ...(model.subProvider ? { subProvider: model.subProvider } : {}), driverKind: model.driverKind, providerDisplayName: model.instanceDisplayName, isFavorite: favoritesSet.has(providerModelKey(model.instanceId, model.slug)), })); } if (lockedProvider !== null) { result = result.filter((m) => matchesLockedProvider(m)); if (selectedInstanceId === "favorites") { result = result.filter((m) => favoritesSet.has(providerModelKey(m.instanceId, m.slug))); } else { result = result.filter((m) => m.instanceId === selectedInstanceId); } } else if (selectedInstanceId === "favorites") { result = result.filter((m) => favoritesSet.has(providerModelKey(m.instanceId, m.slug))); } else { result = result.filter((m) => m.instanceId === selectedInstanceId); } return sortProviderModelItems(result, { favoriteModelKeys: favoritesSet, groupFavorites: selectedInstanceId !== "favorites", instanceOrder: selectedInstanceId === "favorites" ? instanceOrder : [], }); })(); const legacySection = (() => { if (isSearching || selectedInstanceId === "favorites") { return null; } const currentModels: ModelPickerItem[] = []; const legacyModels: ModelPickerItem[] = []; for (const model of filteredModels) { const isLegacy = model.isLegacy && !favoritesSet.has(providerModelKey(model.instanceId, model.slug)); (isLegacy ? legacyModels : currentModels).push(model); } if (legacyModels.length === 0) { return null; } return { key: modelPickerLegacySectionKey(selectedInstanceId), currentModels, legacyModels, isExpanded: expandedLegacyInstances.has(selectedInstanceId), }; })(); const visibleModels = (() => { if (!legacySection) { return filteredModels; } return [ ...legacySection.currentModels, ...(legacySection.isExpanded ? legacySection.legacyModels : []), ]; })(); const selectedEntry = selectedInstanceId === "favorites" ? undefined : entryByInstanceId.get(selectedInstanceId); const providerSetupEntries = !isSearching && canOpenProviderSetup ? instanceEntries.filter( (entry) => matchesLockedProvider(entry) && shouldOfferModelPickerSetup( entry, modelOptionsByInstance.get(entry.instanceId) ?? [], ) && (selectedEntry ? entry.instanceId === selectedEntry.instanceId : filteredModels.length === 0), ) : []; const updateRequiredNotices = instanceEntries.flatMap((entry) => { const shown = isSearching ? matchesLockedProvider(entry) : entry.instanceId === selectedEntry?.instanceId; const notice = shown ? formatProviderUpdateRequiredNotice(entry.snapshot, searchQuery) : null; return notice ? [{ instanceId: entry.instanceId, notice }] : []; }); const modelJumpModelKeys = visibleModels .filter((model) => !getModelDisabledReason?.(model.instanceId, model.slug)) .slice(0, MODEL_PICKER_JUMP_KEYBINDING_COMMANDS.length) .map((model) => modelPickerModelKey(model.instanceId, model.slug)); const allItemKeys = ((): string[] => [ ...flatModels.map((model) => modelPickerModelKey(model.instanceId, model.slug)), ...new Set( flatModels .filter((model) => model.isLegacy) .map((model) => modelPickerLegacySectionKey(model.instanceId)), ), ])(); const filteredItemKeys = ((): string[] => { const modelKeys = visibleModels.map((model) => modelPickerModelKey(model.instanceId, model.slug), ); // The toggle trails the list, so expanding it reveals older models above it. return legacySection ? [...modelKeys, legacySection.key] : modelKeys; })(); const filteredModelByKey = ((): ReadonlyMap => new Map( visibleModels.map( (model) => [modelPickerModelKey(model.instanceId, model.slug), model] as const, ), ))(); const modelJumpLabelByKey = modelJumpLabelsByKey( modelJumpModelKeys, keybindings, props.terminalOpen, ); const badgedInstanceIds = new Set( instanceEntries .filter((entry) => shouldShowInstanceBadge(entry, instanceEntries)) .map((entry) => entry.instanceId), ); const modelListExtraData = { badgedInstanceIds, favoritesSet, modelJumpLabelByKey, activeModelKey, selectedModelKeySet, }; const onWindowKeyDown = (event: globalThis.KeyboardEvent) => { if ( event.defaultPrevented || event.repeat || event.isComposing || event.keyCode === 229 || isCommandPaletteOpen() ) { return; } const command = resolveShortcutCommand(event, keybindings, { platform: navigator.platform, context: modelJumpShortcutContext, }); if (command === "modelPicker.previousProvider" || command === "modelPicker.nextProvider") { event.preventDefault(); event.stopPropagation(); const next = adjacentModelPickerProvider({ entries: sidebarInstanceEntries, selectedInstanceId, direction: command === "modelPicker.nextProvider" ? 1 : -1, disabledInstanceIds: lockedDisabledInstanceIds, selectableUnavailableInstanceIds, }); setSearchQuery(""); handleSelectInstance(next); announce( next === "favorites" ? "Favorites" : (entryByInstanceId.get(next)?.displayName ?? next), "model-picker", ); return; } const jumpIndex = modelPickerJumpIndexFromCommand(command ?? ""); if (jumpIndex === null) { return; } event.preventDefault(); event.stopPropagation(); const targetModelKey = modelJumpModelKeys[jumpIndex]; if (!targetModelKey) { return; } const model = parseModelPickerModelKey(targetModelKey); if (!model) { return; } const selectedSlug = handleModelSelect(model.slug, model.instanceId); if (selectedSlug === null) return; const name = flatModels.find( (item) => item.slug === selectedSlug && item.instanceId === model.instanceId, )?.name; announce(`Model: ${name ?? selectedSlug}`, "model-picker"); }; return (
{showSidebar && ( `${entry.displayName} is unavailable in this thread. Start a new thread to switch providers.`, } : {})} /> )} inline items={allItemKeys} filteredItems={filteredItemKeys} filter={null} autoHighlight open virtualized multiple={onToggleModel !== undefined} value={onToggleModel ? [...selectedModelKeySet] : activeModelKey} onItemHighlighted={(modelKey, eventDetails) => { highlightedModelKeyRef.current = typeof modelKey === "string" ? modelKey : null; if (eventDetails.reason === "keyboard" && eventDetails.index >= 0) { void modelListRef.current?.scrollIndexIntoView?.({ index: eventDetails.index, animated: false, }); } }} onValueChange={(value, details) => { const modelKey = Array.isArray(value) ? (value.find((key) => !selectedModelKeySet.has(key)) ?? [...selectedModelKeySet].find((key) => !value.includes(key))) : value; if (typeof modelKey !== "string") { return; } const legacyInstanceId = parseModelPickerLegacySectionKey(modelKey); if (legacyInstanceId) { toggleLegacySection(legacyInstanceId); return; } const model = parseModelPickerModelKey(modelKey); if (model) { handleModelSelect( model.slug, model.instanceId, "shiftKey" in details.event && details.event.shiftKey === true, ); } }} >
{ if (!isSearching) setSearchHeight(pickerContentRef.current?.offsetHeight ?? 0); setSearchQuery(e.target.value); }} onKeyDown={(e) => { if (e.nativeEvent.isComposing || e.keyCode === 229) { (e as typeof e & { preventBaseUIHandler?: () => void }).preventBaseUIHandler?.(); e.stopPropagation(); return; } if ( showSidebar && !e.altKey && !e.ctrlKey && !e.metaKey && ((e.key === "ArrowLeft" && !e.shiftKey && searchQuery.length === 0) || (e.key === "Tab" && e.shiftKey)) ) { const sidebar = e.currentTarget .closest("[data-model-picker-content]") ?.querySelector("[data-model-picker-sidebar]"); const button = sidebar?.querySelector( 'button[aria-pressed="true"]:not(:disabled)', ) ?? sidebar?.querySelector("button:not(:disabled)"); if (button) { e.preventDefault(); e.stopPropagation(); button.focus(); return; } } if (e.key === "Escape") { e.preventDefault(); e.stopPropagation(); onRequestClose?.(); return; } if ( props.onFocusEffort && e.key === "ArrowRight" && !e.altKey && !e.ctrlKey && !e.metaKey && !e.shiftKey && e.currentTarget.selectionStart === searchQuery.length ) { e.preventDefault(); e.stopPropagation(); // The column shows the selected model's effort, so a highlighted model is picked // first; the owning popup then moves focus to that model's levels. const highlighted = highlightedModelKeyRef.current ? parseModelPickerModelKey(highlightedModelKeyRef.current) : null; const pickedNew = highlighted !== null && highlightedModelKeyRef.current !== activeModelKey && handleModelSelect(highlighted.slug, highlighted.instanceId) !== null; if (!pickedNew) props.onFocusEffort(); return; } if (e.key === "Enter" && highlightedModelKeyRef.current) { (e as typeof e & { preventBaseUIHandler?: () => void }).preventBaseUIHandler?.(); e.preventDefault(); e.stopPropagation(); const legacyInstanceId = parseModelPickerLegacySectionKey( highlightedModelKeyRef.current, ); if (legacyInstanceId) { toggleLegacySection(legacyInstanceId); return; } const model = parseModelPickerModelKey(highlightedModelKeyRef.current); if (model) { handleModelSelect(model.slug, model.instanceId, e.shiftKey); } return; } e.stopPropagation(); }} onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} /> { if (legacySection?.key === modelKey) { return ( {legacySection.isExpanded ? "Show less" : "Show more"} ); } const model = filteredModelByKey.get(modelKey); if (!model) { return null; } const disabledReason = getModelDisabledReason?.(model.instanceId, model.slug) ?? null; return ( ); }} /> {props.listFooter}
); });