"use client"; import { ChevronDown } from "lucide-react"; import { useTranslation } from "react-i18next"; import { Menu, MenuPopup, MenuRadioGroup, MenuRadioItem, MenuSeparator, MenuSub, MenuSubPopup, MenuSubTrigger, MenuTrigger, } from "@/components/ui/menu"; import { type AiModel, type Effort, EFFORT_LEVELS, getModel, MORE_MODELS, PRIMARY_MODELS, } from "@/lib/ai-models"; import { cn } from "@/lib/utils"; type ModelPickerProps = { model: string; effort: Effort; onModelChange: (model: string) => void; onEffortChange: (effort: Effort) => void; triggerClassName: string; }; function ModelRow({ model }: { model: AiModel }) { const { t } = useTranslation(); return (
{model.label} {t(model.descriptionKey)}
); } /** * The single model + effort control in the chat input, styled like the * reference design: a list of primary models, an Effort submenu, and a * "More models" submenu. Selection is owned by the chat panel so it travels * with each send. */ export function ModelPicker({ model, effort, onModelChange, onEffortChange, triggerClassName, }: ModelPickerProps) { const { t } = useTranslation(); const selected = getModel(model); const showEffort = selected?.supportsEffort ?? false; return ( } > {selected?.label ?? t("chat.input.model")} {showEffort ? ( {t(`chat.input.effortOptions.${effort}`)} ) : null} {PRIMARY_MODELS.map((m) => ( ))} {showEffort ? ( {t("chat.input.effort")} {t(`chat.input.effortOptions.${effort}`)} onEffortChange(value as Effort)} value={effort} > {EFFORT_LEVELS.map((level) => ( {t(`chat.input.effortOptions.${level}`)} ))} ) : null} {t("chat.input.moreModels")} {MORE_MODELS.map((m) => ( ))} ); }