| import { |
| EModelEndpoint, |
| defaultEndpoints, |
| modularEndpoints, |
| LocalStorageKeys, |
| isAssistantsEndpoint, |
| } from 'librechat-data-provider'; |
| import type { |
| TConfig, |
| TPreset, |
| TModelSpec, |
| TConversation, |
| TEndpointsConfig, |
| } from 'librechat-data-provider'; |
| import type { LocalizeFunction } from '~/common'; |
|
|
| export const getAssistantName = ({ |
| name, |
| localize, |
| }: { |
| name?: string; |
| localize: LocalizeFunction; |
| }) => { |
| if (name && name.length > 0) { |
| return name; |
| } else { |
| return localize('com_ui_assistant'); |
| } |
| }; |
|
|
| export const getEndpointsFilter = (endpointsConfig: TEndpointsConfig) => { |
| const filter: Record<string, boolean> = {}; |
| if (!endpointsConfig) { |
| return filter; |
| } |
| for (const key of Object.keys(endpointsConfig)) { |
| filter[key] = !!endpointsConfig[key]; |
| } |
| return filter; |
| }; |
|
|
| export const getAvailableEndpoints = ( |
| filter: Record<string, boolean>, |
| endpointsConfig: TEndpointsConfig, |
| ) => { |
| const defaultSet = new Set(defaultEndpoints); |
| const availableEndpoints: EModelEndpoint[] = []; |
|
|
| for (const endpoint in endpointsConfig) { |
| |
| if ( |
| filter[endpoint] || |
| (endpointsConfig[endpoint]?.type && |
| defaultSet.has(endpointsConfig[endpoint]?.type as EModelEndpoint)) |
| ) { |
| availableEndpoints.push(endpoint as EModelEndpoint); |
| } |
| } |
|
|
| return availableEndpoints; |
| }; |
|
|
| |
| export function getEndpointField<K extends keyof TConfig>( |
| endpointsConfig: TEndpointsConfig | undefined, |
| endpoint: EModelEndpoint | string | null | undefined, |
| property: K, |
| ): TConfig[K] | undefined { |
| if (!endpointsConfig || endpoint === null || endpoint === undefined) { |
| return undefined; |
| } |
|
|
| const config = endpointsConfig[endpoint]; |
| if (!config) { |
| return undefined; |
| } |
|
|
| return config[property]; |
| } |
|
|
| export function mapEndpoints(endpointsConfig: TEndpointsConfig) { |
| const filter = getEndpointsFilter(endpointsConfig); |
| return getAvailableEndpoints(filter, endpointsConfig).sort( |
| (a, b) => (endpointsConfig?.[a]?.order ?? 0) - (endpointsConfig?.[b]?.order ?? 0), |
| ); |
| } |
|
|
| const firstLocalConvoKey = LocalStorageKeys.LAST_CONVO_SETUP + '_0'; |
|
|
| |
| |
| |
| export function updateLastSelectedModel({ |
| endpoint, |
| model, |
| }: { |
| endpoint: string; |
| model: string | undefined; |
| }) { |
| if (!model) { |
| return; |
| } |
| const lastConversationSetup = JSON.parse(localStorage.getItem(firstLocalConvoKey) || '{}'); |
|
|
| if (lastConversationSetup.endpoint === endpoint) { |
| lastConversationSetup.model = model; |
| localStorage.setItem(firstLocalConvoKey, JSON.stringify(lastConversationSetup)); |
| } |
|
|
| const lastSelectedModels = JSON.parse(localStorage.getItem(LocalStorageKeys.LAST_MODEL) || '{}'); |
| lastSelectedModels[endpoint] = model; |
| localStorage.setItem(LocalStorageKeys.LAST_MODEL, JSON.stringify(lastSelectedModels)); |
| } |
|
|
| interface ConversationInitParams { |
| conversation: TConversation | null; |
| newEndpoint: EModelEndpoint | string; |
| endpointsConfig: TEndpointsConfig; |
| modularChat?: boolean; |
| } |
|
|
| interface InitiatedTemplateResult { |
| template: Partial<TPreset>; |
| shouldSwitch: boolean; |
| isExistingConversation: boolean; |
| isCurrentModular: boolean; |
| isNewModular: boolean; |
| newEndpointType: EModelEndpoint | undefined; |
| } |
|
|
| |
| export function getConvoSwitchLogic(params: ConversationInitParams): InitiatedTemplateResult { |
| const { conversation, newEndpoint, endpointsConfig, modularChat } = params; |
|
|
| const currentEndpoint = conversation?.endpoint; |
| const template: Partial<TPreset> = { |
| ...conversation, |
| endpoint: newEndpoint, |
| conversationId: 'new', |
| }; |
|
|
| const isAssistantSwitch = |
| isAssistantsEndpoint(newEndpoint) && |
| isAssistantsEndpoint(currentEndpoint) && |
| currentEndpoint === newEndpoint; |
|
|
| const conversationId = conversation?.conversationId; |
| const isExistingConversation = !!(conversationId && conversationId !== 'new'); |
|
|
| const currentEndpointType = |
| getEndpointField(endpointsConfig, currentEndpoint, 'type') ?? currentEndpoint; |
| const newEndpointType = |
| getEndpointField(endpointsConfig, newEndpoint, 'type') ?? |
| (newEndpoint as EModelEndpoint | undefined); |
|
|
| const hasEndpoint = modularEndpoints.has(currentEndpoint ?? ''); |
| const hasCurrentEndpointType = modularEndpoints.has(currentEndpointType ?? ''); |
| const isCurrentModular = hasEndpoint || hasCurrentEndpointType || isAssistantSwitch; |
|
|
| const hasNewEndpoint = modularEndpoints.has(newEndpoint ?? ''); |
| const hasNewEndpointType = modularEndpoints.has(newEndpointType ?? ''); |
| const isNewModular = hasNewEndpoint || hasNewEndpointType || isAssistantSwitch; |
|
|
| const endpointsMatch = currentEndpoint === newEndpoint; |
| const shouldSwitch = endpointsMatch || modularChat || isAssistantSwitch; |
|
|
| return { |
| template, |
| shouldSwitch, |
| isExistingConversation, |
| isCurrentModular, |
| newEndpointType, |
| isNewModular, |
| }; |
| } |
|
|
| |
| |
| |
| |
| export function getDefaultModelSpec(modelSpecs?: TModelSpec[]) { |
| const defaultSpec = modelSpecs?.find((spec) => spec.default); |
| const lastSelectedSpecName = localStorage.getItem(LocalStorageKeys.LAST_SPEC); |
| const lastSelectedSpec = modelSpecs?.find((spec) => spec.name === lastSelectedSpecName); |
| return defaultSpec || lastSelectedSpec || modelSpecs?.[0]; |
| } |
|
|
| |
| |
| |
| |
| export function getModelSpecIconURL(modelSpec: TModelSpec) { |
| return modelSpec.iconURL ?? modelSpec.preset.iconURL ?? modelSpec.preset.endpoint ?? ''; |
| } |
|
|
| |
| |
| |
| |
| export function getIconEndpoint({ |
| endpointsConfig, |
| iconURL, |
| endpoint, |
| }: { |
| endpointsConfig: TEndpointsConfig | undefined; |
| iconURL: string | undefined; |
| endpoint: string | null | undefined; |
| }) { |
| return (endpointsConfig?.[iconURL ?? ''] ? iconURL ?? endpoint : endpoint) ?? ''; |
| } |
|
|
| |
| export function getIconKey({ |
| endpoint, |
| endpointType: _eType, |
| endpointsConfig, |
| endpointIconURL: iconURL, |
| }: { |
| endpoint?: string | null; |
| endpointsConfig?: TEndpointsConfig | undefined; |
| endpointType?: string | null; |
| endpointIconURL?: string; |
| }) { |
| const endpointType = _eType ?? getEndpointField(endpointsConfig, endpoint, 'type'); |
| const endpointIconURL = iconURL ?? getEndpointField(endpointsConfig, endpoint, 'iconURL'); |
| if (endpointIconURL && EModelEndpoint[endpointIconURL]) { |
| return endpointIconURL; |
| } |
| return endpointType ? 'unknown' : endpoint ?? 'unknown'; |
| } |
|
|