| | import { useCallback } from 'react'; |
| | import { useRecoilValue } from 'recoil'; |
| | import { EModelEndpoint, isAgentsEndpoint, isAssistantsEndpoint } from 'librechat-data-provider'; |
| | import type { |
| | TPreset, |
| | TModelSpec, |
| | TConversation, |
| | TAssistantsMap, |
| | TEndpointsConfig, |
| | } from 'librechat-data-provider'; |
| | import type { MentionOption, ConvoGenerator } from '~/common'; |
| | import { getConvoSwitchLogic, getModelSpecIconURL, removeUnavailableTools, logger } from '~/utils'; |
| | import { useDefaultConvo } from '~/hooks'; |
| | import store from '~/store'; |
| |
|
| | export default function useSelectMention({ |
| | presets, |
| | modelSpecs, |
| | conversation, |
| | assistantsMap, |
| | returnHandlers, |
| | endpointsConfig, |
| | newConversation, |
| | }: { |
| | conversation: TConversation | null; |
| | presets?: TPreset[]; |
| | modelSpecs: TModelSpec[]; |
| | assistantsMap?: TAssistantsMap; |
| | newConversation: ConvoGenerator; |
| | endpointsConfig: TEndpointsConfig; |
| | returnHandlers?: boolean; |
| | }) { |
| | const getDefaultConversation = useDefaultConvo(); |
| | const modularChat = useRecoilValue(store.modularChat); |
| | const availableTools = useRecoilValue(store.availableTools); |
| |
|
| | const onSelectSpec = useCallback( |
| | (spec?: TModelSpec) => { |
| | if (!spec) { |
| | return; |
| | } |
| | const { preset } = spec; |
| | preset.iconURL = getModelSpecIconURL(spec); |
| | preset.spec = spec.name; |
| | const { endpoint } = preset; |
| | const newEndpoint = endpoint ?? ''; |
| | if (!newEndpoint) { |
| | return; |
| | } |
| |
|
| | const { |
| | template, |
| | shouldSwitch, |
| | isNewModular, |
| | newEndpointType, |
| | isCurrentModular, |
| | isExistingConversation, |
| | } = getConvoSwitchLogic({ |
| | newEndpoint, |
| | modularChat, |
| | conversation, |
| | endpointsConfig, |
| | }); |
| |
|
| | if (newEndpointType) { |
| | preset.endpointType = newEndpointType; |
| | } |
| |
|
| | if ( |
| | isAssistantsEndpoint(newEndpoint) && |
| | preset.assistant_id != null && |
| | !(preset.model ?? '') |
| | ) { |
| | preset.model = assistantsMap?.[newEndpoint]?.[preset.assistant_id]?.model; |
| | } |
| |
|
| | const isModular = isCurrentModular && isNewModular && shouldSwitch; |
| | if (isExistingConversation && isModular) { |
| | template.endpointType = newEndpointType as EModelEndpoint | undefined; |
| |
|
| | const currentConvo = getDefaultConversation({ |
| | |
| | conversation: { ...(conversation ?? {}), endpointType: template.endpointType }, |
| | preset: template, |
| | cleanOutput: true, |
| | }); |
| |
|
| | |
| | logger.info('conversation', 'Switching conversation to new spec (modular)', conversation); |
| | newConversation({ |
| | template: currentConvo, |
| | preset, |
| | keepLatestMessage: true, |
| | keepAddedConvos: true, |
| | }); |
| | return; |
| | } |
| |
|
| | logger.info('conversation', 'Switching conversation to new spec', conversation); |
| | newConversation({ |
| | template: { ...(template as Partial<TConversation>) }, |
| | preset, |
| | keepAddedConvos: isModular, |
| | }); |
| | }, |
| | [ |
| | conversation, |
| | getDefaultConversation, |
| | modularChat, |
| | newConversation, |
| | endpointsConfig, |
| | assistantsMap, |
| | ], |
| | ); |
| |
|
| | type Kwargs = { |
| | model?: string; |
| | agent_id?: string; |
| | assistant_id?: string; |
| | spec?: string | null; |
| | }; |
| |
|
| | const onSelectEndpoint = useCallback( |
| | (_newEndpoint?: EModelEndpoint | string | null, kwargs: Kwargs = {}) => { |
| | const newEndpoint = _newEndpoint ?? ''; |
| | if (!newEndpoint) { |
| | return; |
| | } |
| |
|
| | const { |
| | shouldSwitch, |
| | isNewModular, |
| | isCurrentModular, |
| | isExistingConversation, |
| | newEndpointType, |
| | template, |
| | } = getConvoSwitchLogic({ |
| | newEndpoint, |
| | modularChat, |
| | conversation, |
| | endpointsConfig, |
| | }); |
| |
|
| | const model = kwargs.model ?? ''; |
| | if (model) { |
| | template.model = model; |
| | } |
| |
|
| | const assistant_id = kwargs.assistant_id ?? ''; |
| | if (assistant_id) { |
| | template.assistant_id = assistant_id; |
| | } |
| | const agent_id = kwargs.agent_id ?? ''; |
| | if (agent_id) { |
| | template.agent_id = agent_id; |
| | } |
| |
|
| | template.spec = null; |
| | template.iconURL = null; |
| | template.modelLabel = null; |
| | if (isExistingConversation && isCurrentModular && isNewModular && shouldSwitch) { |
| | template.endpointType = newEndpointType; |
| |
|
| | const currentConvo = getDefaultConversation({ |
| | |
| | conversation: { |
| | ...(conversation ?? {}), |
| | spec: null, |
| | iconURL: null, |
| | modelLabel: null, |
| | endpointType: template.endpointType, |
| | }, |
| | preset: template, |
| | }); |
| |
|
| | |
| | logger.info( |
| | 'conversation', |
| | 'Switching conversation to new endpoint/model (modular)', |
| | currentConvo, |
| | ); |
| | newConversation({ |
| | template: currentConvo, |
| | preset: currentConvo, |
| | keepLatestMessage: true, |
| | keepAddedConvos: true, |
| | }); |
| | return; |
| | } |
| |
|
| | logger.info('conversation', 'Switching conversation to new endpoint/model', template); |
| | newConversation({ |
| | template: { ...(template as Partial<TConversation>) }, |
| | preset: { ...kwargs, spec: null, iconURL: null, modelLabel: null, endpoint: newEndpoint }, |
| | keepAddedConvos: isNewModular, |
| | }); |
| | }, |
| | [conversation, getDefaultConversation, modularChat, newConversation, endpointsConfig], |
| | ); |
| |
|
| | const onSelectPreset = useCallback( |
| | (_newPreset?: TPreset) => { |
| | if (!_newPreset) { |
| | return; |
| | } |
| |
|
| | const newPreset = removeUnavailableTools(_newPreset, availableTools); |
| | const newEndpoint = newPreset.endpoint ?? ''; |
| |
|
| | const { |
| | template, |
| | shouldSwitch, |
| | isNewModular, |
| | newEndpointType, |
| | isCurrentModular, |
| | isExistingConversation, |
| | } = getConvoSwitchLogic({ |
| | newEndpoint, |
| | modularChat, |
| | conversation, |
| | endpointsConfig, |
| | }); |
| |
|
| | newPreset.spec = null; |
| | newPreset.iconURL = newPreset.iconURL ?? null; |
| | newPreset.modelLabel = newPreset.modelLabel ?? null; |
| | const isModular = isCurrentModular && isNewModular && shouldSwitch; |
| | const disableParams = newPreset.defaultPreset === true; |
| | if (isExistingConversation && isModular) { |
| | template.endpointType = newEndpointType as EModelEndpoint | undefined; |
| | template.spec = null; |
| | template.iconURL = null; |
| | template.modelLabel = null; |
| | const currentConvo = getDefaultConversation({ |
| | |
| | conversation: { ...(conversation ?? {}), endpointType: template.endpointType }, |
| | preset: template, |
| | cleanInput: true, |
| | }); |
| |
|
| | |
| | logger.info('conversation', 'Switching conversation to new preset (modular)', currentConvo); |
| | newConversation({ |
| | template: currentConvo, |
| | preset: newPreset, |
| | keepLatestMessage: true, |
| | keepAddedConvos: true, |
| | disableParams, |
| | }); |
| | return; |
| | } |
| |
|
| | logger.info('conversation', 'Switching conversation to new preset', template); |
| | newConversation({ |
| | preset: newPreset, |
| | keepAddedConvos: isModular, |
| | disableParams, |
| | }); |
| | }, |
| | [ |
| | modularChat, |
| | conversation, |
| | availableTools, |
| | newConversation, |
| | endpointsConfig, |
| | getDefaultConversation, |
| | ], |
| | ); |
| |
|
| | const onSelectMention = useCallback( |
| | (option: MentionOption) => { |
| | const key = option.value; |
| | if (option.type === 'preset') { |
| | const preset = presets?.find((p) => p.presetId === key); |
| | onSelectPreset(preset); |
| | } else if (option.type === 'modelSpec') { |
| | const modelSpec = modelSpecs.find((spec) => spec.name === key); |
| | onSelectSpec(modelSpec); |
| | } else if (option.type === 'model') { |
| | onSelectEndpoint(key, { model: option.label }); |
| | } else if (option.type === 'endpoint') { |
| | onSelectEndpoint(key); |
| | } else if (isAssistantsEndpoint(option.type)) { |
| | onSelectEndpoint(option.type, { |
| | assistant_id: key, |
| | model: assistantsMap?.[option.type]?.[key]?.model ?? '', |
| | }); |
| | } else if (isAgentsEndpoint(option.type)) { |
| | onSelectEndpoint(option.type, { |
| | agent_id: key, |
| | }); |
| | } |
| | }, |
| | [modelSpecs, onSelectEndpoint, onSelectPreset, onSelectSpec, presets, assistantsMap], |
| | ); |
| |
|
| | if (returnHandlers) { |
| | return { |
| | onSelectSpec, |
| | onSelectEndpoint, |
| | }; |
| | } |
| |
|
| | return { |
| | onSelectMention, |
| | }; |
| | } |
| |
|