🎚️ feat: Custom Parameters (#7342)

* #

* - refactor: simplified getCustomConfig func

* #

* - feature: persist values for parameters with optionType of custom

* #

* - refactor: moved `Parameters/settings.ts` into `data-provider` so that both frontend and backend code can use it.

* - feature: loadCustomConfig can now parse and validate customParams property for `endpoints.custom` in `librechat.yaml`

* # fixed linter

* # removed .strict() in config.ts

* change: added packages/data-provider/src to SOURCE_DIRS for i18n check

* # removed unnecessary lodash imports

* # addressed PR comments
# fixed lint for updated files

* # better import for lodash (w/o relying on tree-shaking)
This commit is contained in:
Theo N. Truong 2025-05-19 17:33:25 -06:00 committed by GitHub
parent c79ee32006
commit 7ce782fec6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 340 additions and 132 deletions

View file

@ -1,6 +1,12 @@
import { RotateCcw } from 'lucide-react';
import React, { useMemo, useState, useEffect, useCallback } from 'react';
import { excludedKeys, getSettingsKeys, tConvoUpdateSchema } from 'librechat-data-provider';
import {
excludedKeys,
getSettingsKeys,
tConvoUpdateSchema,
paramSettings,
SettingDefinition,
} from 'librechat-data-provider';
import type { TPreset } from 'librechat-data-provider';
import { SaveAsPresetDialog } from '~/components/Endpoints';
import { useSetIndexOptions, useLocalize } from '~/hooks';
@ -8,7 +14,7 @@ import { useGetEndpointsQuery } from '~/data-provider';
import { getEndpointField, logger } from '~/utils';
import { componentMapping } from './components';
import { useChatContext } from '~/Providers';
import { settings } from './settings';
import keyBy from 'lodash/keyBy';
export default function Parameters() {
const localize = useLocalize();
@ -18,7 +24,9 @@ export default function Parameters() {
const [isDialogOpen, setIsDialogOpen] = useState(false);
const [preset, setPreset] = useState<TPreset | null>(null);
const { data: endpointsConfig } = useGetEndpointsQuery();
const { data: endpointsConfig = {} } = useGetEndpointsQuery();
const provider = conversation?.endpoint ?? '';
const model = conversation?.model ?? '';
const bedrockRegions = useMemo(() => {
return endpointsConfig?.[conversation?.endpoint ?? '']?.availableRegions ?? [];
@ -29,13 +37,17 @@ export default function Parameters() {
[conversation?.endpoint, endpointsConfig],
);
const parameters = useMemo(() => {
const [combinedKey, endpointKey] = getSettingsKeys(
endpointType ?? conversation?.endpoint ?? '',
conversation?.model ?? '',
const parameters = useMemo((): SettingDefinition[] => {
const customParams = endpointsConfig[provider]?.customParams ?? {};
const [combinedKey, endpointKey] = getSettingsKeys(endpointType ?? provider, model);
const overriddenEndpointKey = customParams.defaultParamsEndpoint ?? endpointKey;
const defaultParams = paramSettings[combinedKey] ?? paramSettings[overriddenEndpointKey] ?? [];
const overriddenParams = endpointsConfig[provider]?.customParams?.paramDefinitions ?? [];
const overriddenParamsMap = keyBy(overriddenParams, 'key');
return defaultParams.map(
(param) => (overriddenParamsMap[param.key] as SettingDefinition) ?? param,
);
return settings[combinedKey] ?? settings[endpointKey];
}, [conversation, endpointType]);
}, [endpointType, endpointsConfig, model, provider]);
useEffect(() => {
if (!parameters) {