import React, { useMemo, useState, useEffect, useCallback } from 'react'; import { useGetEndpointsQuery } from 'librechat-data-provider/react-query'; import { getSettingsKeys, tPresetUpdateSchema } from 'librechat-data-provider'; import type { TPreset } from 'librechat-data-provider'; import { SaveAsPresetDialog } from '~/components/Endpoints'; import { useSetIndexOptions, useLocalize } from '~/hooks'; import { getEndpointField, logger } from '~/utils'; import { componentMapping } from './components'; import { useChatContext } from '~/Providers'; import { settings } from './settings'; const excludedKeys = new Set([ 'conversationId', 'title', 'endpoint', 'endpointType', 'createdAt', 'updatedAt', 'messages', 'isArchived', 'tags', 'user', '__v', '_id', 'tools', 'model', ]); export default function Parameters() { const localize = useLocalize(); const { conversation, setConversation } = useChatContext(); const { setOption } = useSetIndexOptions(); const [isDialogOpen, setIsDialogOpen] = useState(false); const [preset, setPreset] = useState(null); const { data: endpointsConfig } = useGetEndpointsQuery(); const bedrockRegions = useMemo(() => { return endpointsConfig?.[conversation?.endpoint ?? '']?.availableRegions ?? []; }, [endpointsConfig, conversation?.endpoint]); const endpointType = useMemo( () => getEndpointField(endpointsConfig, conversation?.endpoint, 'type'), [conversation?.endpoint, endpointsConfig], ); const parameters = useMemo(() => { const [combinedKey, endpointKey] = getSettingsKeys( endpointType ?? conversation?.endpoint ?? '', conversation?.model ?? '', ); return settings[combinedKey] ?? settings[endpointKey]; }, [conversation, endpointType]); useEffect(() => { if (!parameters) { return; } // const defaultValueMap = new Map(); // const paramKeys = new Set( // parameters.map((setting) => { // if (setting.default != null) { // defaultValueMap.set(setting.key, setting.default); // } // return setting.key; // }), // ); const paramKeys = new Set(parameters.map((setting) => setting.key)); setConversation((prev) => { if (!prev) { return prev; } const updatedConversation = { ...prev }; const conversationKeys = Object.keys(updatedConversation); const updatedKeys: string[] = []; conversationKeys.forEach((key) => { // const defaultValue = defaultValueMap.get(key); // if (paramKeys.has(key) && defaultValue != null && prev[key] != null) { // updatedKeys.push(key); // updatedConversation[key] = defaultValue; // return; // } if (paramKeys.has(key)) { return; } if (excludedKeys.has(key)) { return; } if (prev[key] != null) { updatedKeys.push(key); delete updatedConversation[key]; } }); logger.log('parameters', 'parameters effect, updated keys:', updatedKeys); return updatedConversation; }); }, [parameters, setConversation]); const openDialog = useCallback(() => { const newPreset = tPresetUpdateSchema.parse({ ...conversation, }) as TPreset; setPreset(newPreset); setIsDialogOpen(true); }, [conversation]); if (!parameters) { return null; } return (
{' '} {/* This is the parent element containing all settings */} {/* Below is an example of an applied dynamic setting, each be contained by a div with the column span specified */} {parameters.map((setting) => { const Component = componentMapping[setting.component]; if (!Component) { return null; } const { key, default: defaultValue, ...rest } = setting; if (key === 'region' && bedrockRegions.length) { rest.options = bedrockRegions; } return ( ); })}
{preset && ( )}
); }