import React from 'react'; import { RiAddLine, RiCloseLine, RiSearchLine, RiStarFill, RiTimeLine } from '@remixicon/react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { ScrollableOverlay } from '@/components/ui/ScrollableOverlay'; import { ProviderLogo } from '@/components/ui/ProviderLogo'; import { cn } from '@/lib/utils'; import { useConfigStore } from '@/stores/useConfigStore'; import { useModelLists } from '@/hooks/useModelLists'; import type { ModelMetadata } from '@/types'; /** Chip height class - shared between chips and add button */ const CHIP_HEIGHT_CLASS = 'h-7'; /** UI-only type with instanceId for React keys and duplicate tracking */ export interface ModelSelectionWithId { providerID: string; modelID: string; displayName?: string; instanceId: string; } /** Model selection without instanceId (for external use) */ export interface ModelSelection { providerID: string; modelID: string; displayName?: string; } // eslint-disable-next-line react-refresh/only-export-components -- Utility is tightly coupled with ModelMultiSelect export const generateInstanceId = (): string => { return `${Date.now()}-${Math.random().toString(36).substring(2, 9)}`; }; const COMPACT_NUMBER_FORMATTER = new Intl.NumberFormat('en-US', { notation: 'compact', compactDisplay: 'short', maximumFractionDigits: 1, minimumFractionDigits: 0, }); const formatTokens = (value?: number | null) => { if (typeof value !== 'number' || Number.isNaN(value)) { return ''; } if (value === 0) { return '0'; } const formatted = COMPACT_NUMBER_FORMATTER.format(value); return formatted.endsWith('.0') ? formatted.slice(0, -2) : formatted; }; /** * Model selection chip with remove button. * Shows instance index (e.g., "(2)") when same model is selected multiple times. */ export const ModelChip: React.FC<{ model: ModelSelectionWithId; instanceIndex: number; totalSameModel: number; onRemove: () => void; }> = ({ model, instanceIndex, totalSameModel, onRemove }) => { const displayName = model.displayName || `${model.providerID}/${model.modelID}`; const label = totalSameModel > 1 ? `${displayName} (${instanceIndex})` : displayName; return (
Select at least {minModels} model{minModels > 1 ? 's' : ''} {maxModels !== undefined ? `and at most ${maxModels} models` : ''}.
)}