| import React from 'react'; | |
| import { Bot } from 'lucide-react'; | |
| import { isAgentsEndpoint, isAssistantsEndpoint } from 'librechat-data-provider'; | |
| import type { | |
| TModelSpec, | |
| TAgentsMap, | |
| TAssistantsMap, | |
| TEndpointsConfig, | |
| } from 'librechat-data-provider'; | |
| import type { useLocalize } from '~/hooks'; | |
| import SpecIcon from '~/components/Chat/Menus/Endpoints/components/SpecIcon'; | |
| import { Endpoint, SelectedValues } from '~/common'; | |
| export function filterItems< | |
| T extends { | |
| label: string; | |
| name?: string; | |
| value?: string; | |
| models?: Array<{ name: string; isGlobal?: boolean }>; | |
| }, | |
| >( | |
| items: T[], | |
| searchValue: string, | |
| agentsMap: TAgentsMap | undefined, | |
| assistantsMap: TAssistantsMap | undefined, | |
| ): T[] | null { | |
| const searchTermLower = searchValue.trim().toLowerCase(); | |
| if (!searchTermLower) { | |
| return null; | |
| } | |
| return items.filter((item) => { | |
| const itemMatches = | |
| item.label.toLowerCase().includes(searchTermLower) || | |
| (item.name && item.name.toLowerCase().includes(searchTermLower)) || | |
| (item.value && item.value.toLowerCase().includes(searchTermLower)); | |
| if (itemMatches) { | |
| return true; | |
| } | |
| if (item.models && item.models.length > 0) { | |
| return item.models.some((modelId) => { | |
| if (modelId.name.toLowerCase().includes(searchTermLower)) { | |
| return true; | |
| } | |
| if (isAgentsEndpoint(item.value) && agentsMap && modelId.name in agentsMap) { | |
| const agentName = agentsMap[modelId.name]?.name; | |
| return typeof agentName === 'string' && agentName.toLowerCase().includes(searchTermLower); | |
| } | |
| if (isAssistantsEndpoint(item.value) && assistantsMap) { | |
| const endpoint = item.value ?? ''; | |
| const assistant = assistantsMap[endpoint][modelId.name]; | |
| if (assistant && typeof assistant.name === 'string') { | |
| return assistant.name.toLowerCase().includes(searchTermLower); | |
| } | |
| return false; | |
| } | |
| return false; | |
| }); | |
| } | |
| return false; | |
| }); | |
| } | |
| export function filterModels( | |
| endpoint: Endpoint, | |
| models: string[], | |
| searchValue: string, | |
| agentsMap: TAgentsMap | undefined, | |
| assistantsMap: TAssistantsMap | undefined, | |
| ): string[] { | |
| const searchTermLower = searchValue.trim().toLowerCase(); | |
| if (!searchTermLower) { | |
| return models; | |
| } | |
| return models.filter((modelId) => { | |
| let modelName = modelId; | |
| if (isAgentsEndpoint(endpoint.value) && agentsMap && agentsMap[modelId]) { | |
| modelName = agentsMap[modelId]?.name || modelId; | |
| } else if ( | |
| isAssistantsEndpoint(endpoint.value) && | |
| assistantsMap && | |
| assistantsMap[endpoint.value] | |
| ) { | |
| const assistant = assistantsMap[endpoint.value][modelId]; | |
| modelName = | |
| typeof assistant.name === 'string' && assistant.name ? (assistant.name as string) : modelId; | |
| } | |
| return modelName.toLowerCase().includes(searchTermLower); | |
| }); | |
| } | |
| export function getSelectedIcon({ | |
| mappedEndpoints, | |
| selectedValues, | |
| modelSpecs, | |
| endpointsConfig, | |
| }: { | |
| mappedEndpoints: Endpoint[]; | |
| selectedValues: SelectedValues; | |
| modelSpecs: TModelSpec[]; | |
| endpointsConfig: TEndpointsConfig; | |
| }): React.ReactNode | null { | |
| const { endpoint, model, modelSpec } = selectedValues; | |
| if (modelSpec) { | |
| const spec = modelSpecs.find((s) => s.name === modelSpec); | |
| if (!spec) { | |
| return null; | |
| } | |
| const { showIconInHeader = true } = spec; | |
| if (!showIconInHeader) { | |
| return null; | |
| } | |
| return React.createElement(SpecIcon, { | |
| currentSpec: spec, | |
| endpointsConfig, | |
| }); | |
| } | |
| if (endpoint && model) { | |
| const selectedEndpoint = mappedEndpoints.find((e) => e.value === endpoint); | |
| if (!selectedEndpoint) { | |
| return null; | |
| } | |
| if (selectedEndpoint.modelIcons?.[model]) { | |
| const iconUrl = selectedEndpoint.modelIcons[model]; | |
| return React.createElement( | |
| 'div', | |
| { className: 'h-5 w-5 overflow-hidden rounded-full' }, | |
| React.createElement('img', { | |
| src: iconUrl, | |
| alt: model, | |
| className: 'h-full w-full object-cover', | |
| }), | |
| ); | |
| } | |
| return ( | |
| selectedEndpoint.icon || | |
| React.createElement(Bot, { | |
| size: 20, | |
| className: 'icon-md shrink-0 text-text-primary', | |
| }) | |
| ); | |
| } | |
| if (endpoint) { | |
| const selectedEndpoint = mappedEndpoints.find((e) => e.value === endpoint); | |
| return selectedEndpoint?.icon || null; | |
| } | |
| return null; | |
| } | |
| export const getDisplayValue = ({ | |
| localize, | |
| mappedEndpoints, | |
| selectedValues, | |
| modelSpecs, | |
| agentsMap, | |
| }: { | |
| localize: ReturnType<typeof useLocalize>; | |
| selectedValues: SelectedValues; | |
| mappedEndpoints: Endpoint[]; | |
| modelSpecs: TModelSpec[]; | |
| agentsMap?: TAgentsMap; | |
| }) => { | |
| if (selectedValues.modelSpec) { | |
| const spec = modelSpecs.find((s) => s.name === selectedValues.modelSpec); | |
| return spec?.label || spec?.name || localize('com_ui_select_model'); | |
| } | |
| if (selectedValues.model && selectedValues.endpoint) { | |
| const endpoint = mappedEndpoints.find((e) => e.value === selectedValues.endpoint); | |
| if (!endpoint) { | |
| return localize('com_ui_select_model'); | |
| } | |
| if ( | |
| isAgentsEndpoint(endpoint.value) && | |
| endpoint.agentNames && | |
| endpoint.agentNames[selectedValues.model] | |
| ) { | |
| return endpoint.agentNames[selectedValues.model]; | |
| } else if (isAgentsEndpoint(endpoint.value) && agentsMap) { | |
| const agent = agentsMap[selectedValues.model]; | |
| return agent?.name || selectedValues.model; | |
| } | |
| if ( | |
| isAssistantsEndpoint(endpoint.value) && | |
| endpoint.assistantNames && | |
| endpoint.assistantNames[selectedValues.model] | |
| ) { | |
| return endpoint.assistantNames[selectedValues.model]; | |
| } | |
| return selectedValues.model; | |
| } | |
| if (selectedValues.endpoint) { | |
| const endpoint = mappedEndpoints.find((e) => e.value === selectedValues.endpoint); | |
| return endpoint?.label || localize('com_ui_select_model'); | |
| } | |
| return localize('com_ui_select_model'); | |
| }; | |