LibreChat/client/src/hooks/Chat/useAddedResponse.ts
Danny Avila 467df0f07a
🎭 feat: Override Custom Endpoint Schema with Specified Params Endpoint (#11788)
* 🔧 refactor: Simplify payload parsing and enhance getSaveOptions logic

- Removed unused bedrockInputSchema from payloadParser, streamlining the function.
- Updated payloadParser to handle optional chaining for model parameters.
- Enhanced getSaveOptions to ensure runOptions defaults to an empty object if parsing fails, improving robustness.
- Adjusted the assignment of maxContextTokens to use the instance variable for consistency.

* 🔧 fix: Update maxContextTokens assignment logic in initializeAgent function

- Enhanced the maxContextTokens assignment to allow for user-defined values, ensuring it defaults to a calculated value only when not provided or invalid. This change improves flexibility in agent initialization.

* 🧪 test: Add unit tests for initializeAgent function

- Introduced comprehensive unit tests for the initializeAgent function, focusing on maxContextTokens behavior.
- Tests cover scenarios for user-defined values, fallback calculations, and edge cases such as zero and negative values, enhancing overall test coverage and reliability of agent initialization logic.

* refactor: default params Endpoint Configuration Handling

- Integrated `getEndpointsConfig` to fetch endpoint configurations, allowing for dynamic handling of `defaultParamsEndpoint`.
- Updated `buildEndpointOption` to pass `defaultParamsEndpoint` to `parseCompactConvo`, ensuring correct parameter handling based on endpoint type.
- Added comprehensive unit tests for `buildDefaultConvo` and `cleanupPreset` to validate behavior with `defaultParamsEndpoint`, covering various scenarios and edge cases.
- Refactored related hooks and utility functions to support the new configuration structure, improving overall flexibility and maintainability.

* refactor: Centralize defaultParamsEndpoint retrieval

- Introduced `getDefaultParamsEndpoint` function to streamline the retrieval of `defaultParamsEndpoint` across various hooks and middleware.
- Updated multiple files to utilize the new function, enhancing code consistency and maintainability.
- Removed redundant logic for fetching `defaultParamsEndpoint`, simplifying the codebase.
2026-02-13 23:04:51 -05:00

130 lines
4.3 KiB
TypeScript

import { useCallback } from 'react';
import { useRecoilValue } from 'recoil';
import { useGetModelsQuery } from 'librechat-data-provider/react-query';
import {
getEndpointField,
LocalStorageKeys,
isAssistantsEndpoint,
getDefaultParamsEndpoint,
} from 'librechat-data-provider';
import type { TEndpointsConfig, EModelEndpoint, TConversation } from 'librechat-data-provider';
import type { AssistantListItem, NewConversationParams } from '~/common';
import useAssistantListMap from '~/hooks/Assistants/useAssistantListMap';
import { buildDefaultConvo, getDefaultEndpoint } from '~/utils';
import { useGetEndpointsQuery } from '~/data-provider';
import { mainTextareaId } from '~/common';
import store from '~/store';
const ADDED_INDEX = 1;
/**
* Simplified hook for added conversation state.
* Provides just the conversation state and a function to generate a new conversation,
* mirroring the pattern from useNewConvo.
*/
export default function useAddedResponse() {
const modelsQuery = useGetModelsQuery();
const assistantsListMap = useAssistantListMap();
const rootConvo = useRecoilValue(store.conversationByKeySelector(0));
const { data: endpointsConfig = {} as TEndpointsConfig } = useGetEndpointsQuery();
const { conversation, setConversation } = store.useCreateConversationAtom(ADDED_INDEX);
/**
* Generate a new conversation based on template and preset.
* Mirrors the logic from useNewConvo's switchToConversation.
*/
const generateConversation = useCallback(
({ template = {}, preset, modelsData }: NewConversationParams = {}) => {
let newConversation: TConversation = {
conversationId: rootConvo?.conversationId ?? 'new',
title: '',
endpoint: null,
...template,
createdAt: '',
updatedAt: '',
} as TConversation;
const modelsConfig = modelsData ?? modelsQuery.data;
const activePreset = preset ?? newConversation;
const defaultEndpoint = getDefaultEndpoint({
convoSetup: activePreset,
endpointsConfig,
});
const endpointType = getEndpointField(endpointsConfig, defaultEndpoint, 'type');
if (!newConversation.endpointType && endpointType) {
newConversation.endpointType = endpointType;
} else if (newConversation.endpointType && !endpointType) {
newConversation.endpointType = undefined;
}
const isAssistantEndpoint = isAssistantsEndpoint(defaultEndpoint);
const assistants: AssistantListItem[] = assistantsListMap[defaultEndpoint ?? ''] ?? [];
if (
newConversation.assistant_id &&
!assistantsListMap[defaultEndpoint ?? '']?.[newConversation.assistant_id]
) {
newConversation.assistant_id = undefined;
}
if (!newConversation.assistant_id && isAssistantEndpoint) {
newConversation.assistant_id =
localStorage.getItem(`${LocalStorageKeys.ASST_ID_PREFIX}0${defaultEndpoint}`) ??
assistants[0]?.id;
}
if (
newConversation.assistant_id != null &&
isAssistantEndpoint &&
newConversation.conversationId === 'new'
) {
const assistant = assistants.find((asst) => asst.id === newConversation.assistant_id);
newConversation.model = assistant?.model;
}
if (newConversation.assistant_id != null && !isAssistantEndpoint) {
newConversation.assistant_id = undefined;
}
const models = modelsConfig?.[defaultEndpoint ?? ''] ?? [];
const defaultParamsEndpoint = getDefaultParamsEndpoint(endpointsConfig, defaultEndpoint);
newConversation = buildDefaultConvo({
conversation: newConversation,
lastConversationSetup: preset as TConversation,
endpoint: defaultEndpoint ?? ('' as EModelEndpoint),
models,
defaultParamsEndpoint,
});
if (preset?.title != null && preset.title !== '') {
newConversation.title = preset.title;
}
setConversation(newConversation);
setTimeout(() => {
const textarea = document.getElementById(mainTextareaId);
if (textarea) {
textarea.focus();
}
}, 150);
return newConversation;
},
[
endpointsConfig,
setConversation,
modelsQuery.data,
assistantsListMap,
rootConvo?.conversationId,
],
);
return {
conversation,
setConversation,
generateConversation,
};
}