🔧 refactor: Consolidate Logging, Model Selection & Actions Optimizations, Minor Fixes (#6553)

* 🔧 feat: Enhance logging configuration for production and debug environments

* 🔒 feat: Implement encryption and decryption functions for sensitive values in ActionService with URL encoding/decoding

* refactor: optimize action service for agent tools

* refactor: optimize action processing for Assistants API

* fix: handle case where agent is not found in loadAgent function

* refactor: improve error handling in API calls by throwing new Error with logAxiosError output

* chore: bump @librechat/agents to 2.3.95, fixes "Invalid tool call structure: No preceding AIMessage with tool_call_ids"

* refactor: enhance error logging in logAxiosError function to include response status

* refactor: remove unused useModelSelection hook from Endpoint

* refactor: add support for assistants in useSelectorEffects hook

* refactor: replace string easing with imported easings in Landing component

* chore: remove duplicate translation

* refactor: update model selection logic and improve localization for UI elements

* refactor: replace endpoint value checks with helper functions for agents and assistants

* refactor: optimize display value logic and utilize useMemo for performance improvements

* refactor: clean up imports and optimize display/icon value logic in endpoint components, fix spec selection

* refactor: enhance error logging in axios utility to include stack traces for better debugging

* refactor: update logging configuration to use DEBUG_LOGGING and streamline log level handling

* refactor: adjust className for export menu button to improve layout consistency and remove unused title prop from ShareButton

* refactor: update import path for logAxiosError utility to improve module organization and clarity

* refactor: implement debounced search value setter in ModelSelectorContext for improved performance
This commit is contained in:
Danny Avila 2025-03-26 14:10:52 -04:00 committed by GitHub
parent 801b602e27
commit 299cabd6ed
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 970 additions and 1135 deletions

View file

@ -1,4 +1,3 @@
export { default as useKeyDialog } from './useKeyDialog';
export { default as useModelSelection } from './useModels';
export { default as useEndpoints } from './useEndpoints';
export { default as useSelectorEffects } from './useSelectorEffects';

View file

@ -1,277 +0,0 @@
import { useCallback, useRef, useContext, useMemo } from 'react';
import { EModelEndpoint, LocalStorageKeys } from 'librechat-data-provider';
import { getConvoSwitchLogic } from '~/utils';
import { mainTextareaId } from '~/common';
import { useRecoilState, useRecoilValue } from 'recoil';
import { useSetIndexOptions, useDefaultConvo } from '~/hooks';
import { useChatContext, useAssistantsMapContext } from '~/Providers';
import { useGetEndpointsQuery } from '~/data-provider';
import store from '~/store';
export const useModelSelection = () => {
const { setOption } = useSetIndexOptions();
const getDefaultConversation = useDefaultConvo();
const { conversation, newConversation, index } = useChatContext();
const { data: endpointsConfig = {} } = useGetEndpointsQuery();
const modularChat = useRecoilValue(store.modularChat);
const assistantsMapResult = useAssistantsMapContext();
const assistantsMap = useMemo(() => assistantsMapResult ?? {}, [assistantsMapResult]);
const timeoutIdRef = useRef<NodeJS.Timeout | undefined>(undefined);
const setAgentId = useCallback(
(agentId: string) => {
setOption('agent_id')(agentId);
localStorage.setItem(`${LocalStorageKeys.AGENT_ID_PREFIX}${index}`, agentId);
clearTimeout(timeoutIdRef.current);
timeoutIdRef.current = setTimeout(() => {
const textarea = document.getElementById(mainTextareaId);
if (textarea) {
textarea.focus();
}
}, 150);
},
[setOption, index, timeoutIdRef],
);
const setAssistantId = useCallback(
(endpoint: string, assistantId: string) => {
const assistant = assistantsMap[endpoint]?.[assistantId];
if (assistant) {
setOption('model')(assistant.model);
setOption('assistant_id')(assistantId);
localStorage.setItem(`${LocalStorageKeys.ASST_ID_PREFIX}${index}${endpoint}`, assistantId);
}
clearTimeout(timeoutIdRef.current);
timeoutIdRef.current = setTimeout(() => {
const textarea = document.getElementById(mainTextareaId);
if (textarea) {
textarea.focus();
}
}, 150);
},
[setOption, index, assistantsMap, timeoutIdRef],
);
const setModel = useCallback(
(model: string) => {
setOption('model')(model);
clearTimeout(timeoutIdRef.current);
timeoutIdRef.current = setTimeout(() => {
const textarea = document.getElementById(mainTextareaId);
if (textarea) {
textarea.focus();
}
}, 150);
},
[setOption, timeoutIdRef],
);
const handleModelSelect = useCallback(
(ep: EModelEndpoint, selectedModel: string) => {
if (ep === EModelEndpoint.assistants) {
if (conversation?.endpoint === ep) {
setAssistantId(ep, selectedModel);
return;
}
const { template } = getConvoSwitchLogic({
newEndpoint: ep,
modularChat: false,
conversation,
endpointsConfig,
});
const assistant = assistantsMap[ep]?.[selectedModel];
const currentConvo = getDefaultConversation({
conversation: {
...conversation,
endpoint: ep,
assistant_id: selectedModel,
model: assistant?.model || '',
},
preset: {
...template,
endpoint: ep,
assistant_id: selectedModel,
model: assistant?.model || '',
},
});
newConversation({
template: currentConvo,
preset: currentConvo,
keepLatestMessage: true,
});
return;
}
if (ep === EModelEndpoint.agents) {
if (conversation?.endpoint === ep) {
setAgentId(selectedModel);
return;
}
const { template } = getConvoSwitchLogic({
newEndpoint: ep,
modularChat: false,
conversation,
endpointsConfig,
});
const currentConvo = getDefaultConversation({
conversation: { ...conversation, endpoint: ep, agent_id: selectedModel },
preset: { ...template, endpoint: ep, agent_id: selectedModel },
});
newConversation({
template: currentConvo,
preset: currentConvo,
keepLatestMessage: true,
});
return;
}
const {
template,
shouldSwitch,
isNewModular,
newEndpointType,
isCurrentModular,
isExistingConversation,
} = getConvoSwitchLogic({
newEndpoint: ep,
modularChat,
conversation,
endpointsConfig,
});
const isModular = isCurrentModular && isNewModular && shouldSwitch;
if (isExistingConversation && isModular) {
template.endpointType = newEndpointType;
const currentConvo = getDefaultConversation({
conversation: { ...(conversation ?? {}), endpointType: template.endpointType },
preset: template,
});
newConversation({
template: currentConvo,
preset: currentConvo,
keepLatestMessage: true,
keepAddedConvos: true,
});
return;
}
newConversation({
template: { ...(template as any) },
keepAddedConvos: isModular,
});
setModel(selectedModel);
},
[
conversation,
endpointsConfig,
modularChat,
newConversation,
getDefaultConversation,
setModel,
setAgentId,
setAssistantId,
assistantsMap,
],
);
const handleEndpointSelect = useCallback(
(ep: string, hasModels: boolean, agents: any[], assistants: any[], modelsData: any) => {
if (hasModels) {
if (conversation?.endpoint !== ep) {
const newEndpoint = ep as EModelEndpoint;
const { template } = getConvoSwitchLogic({
newEndpoint,
modularChat: false,
conversation,
endpointsConfig,
});
let initialModel = '';
let initialAgentId = '';
let initialAssistantId = '';
if (newEndpoint === EModelEndpoint.agents && agents.length > 0) {
initialAgentId = agents[0].id;
} else if (newEndpoint === EModelEndpoint.assistants && assistants.length > 0) {
initialAssistantId = assistants[0].id;
initialModel = assistantsMap[newEndpoint]?.[initialAssistantId]?.model || '';
} else if (modelsData && modelsData[newEndpoint] && modelsData[newEndpoint].length > 0) {
initialModel = modelsData[newEndpoint][0];
}
const currentConvo = getDefaultConversation({
conversation: {
...conversation,
endpoint: newEndpoint,
model: initialModel,
agent_id: initialAgentId,
assistant_id: initialAssistantId,
},
preset: {
...template,
endpoint: newEndpoint,
model: initialModel,
agent_id: initialAgentId,
assistant_id: initialAssistantId,
},
});
newConversation({
template: currentConvo,
preset: currentConvo,
keepLatestMessage: true,
});
}
return;
}
if (!hasModels) {
const newEndpoint = ep as EModelEndpoint;
const { template } = getConvoSwitchLogic({
newEndpoint,
modularChat: false,
conversation,
endpointsConfig,
});
const currentConvo = getDefaultConversation({
conversation: { ...conversation, endpoint: newEndpoint },
preset: { ...template, endpoint: newEndpoint },
});
newConversation({
template: currentConvo,
preset: currentConvo,
keepLatestMessage: true,
});
}
},
[
conversation,
endpointsConfig,
newConversation,
getDefaultConversation,
assistantsMap,
modularChat,
],
);
return {
handleModelSelect,
handleEndpointSelect,
setAgentId,
setAssistantId,
setModel,
};
};
export default useModelSelection;

View file

@ -21,22 +21,51 @@ export default function useSelectorEffects({
const agents: t.Agent[] = useMemo(() => {
return Object.values(agentsMap ?? {}) as t.Agent[];
}, [agentsMap]);
const { agent_id: selectedAgentId = null, endpoint } = conversation ?? {};
const {
agent_id: selectedAgentId = null,
assistant_id: selectedAssistantId = null,
endpoint,
} = conversation ?? {};
const assistants: t.Assistant[] = useMemo(() => {
if (!isAssistantsEndpoint(endpoint)) {
return [];
}
return Object.values(assistantsMap?.[endpoint ?? ''] ?? {}) as t.Assistant[];
}, [assistantsMap, endpoint]);
useEffect(() => {
if (!isAgentsEndpoint(endpoint as string)) {
return;
}
if (selectedAgentId == null && agents.length > 0) {
let agent_id = localStorage.getItem(`${LocalStorageKeys.AGENT_ID_PREFIX}${index}`);
if (agent_id == null) {
agent_id = agents[0].id;
agent_id = agents[0]?.id;
}
const agent = agentsMap?.[agent_id];
if (agent !== undefined && isAgentsEndpoint(endpoint as string) === true) {
if (agent !== undefined) {
setOption('model')('');
setOption('agent_id')(agent_id);
}
}
}, [index, agents, selectedAgentId, agentsMap, endpoint, setOption]);
useEffect(() => {
if (!isAssistantsEndpoint(endpoint as string)) {
return;
}
if (selectedAssistantId == null && assistants.length > 0) {
let assistant_id = localStorage.getItem(`${LocalStorageKeys.ASST_ID_PREFIX}${index}`);
if (assistant_id == null) {
assistant_id = assistants[0]?.id;
}
const assistant = assistantsMap?.[endpoint ?? '']?.[assistant_id];
if (assistant !== undefined) {
setOption('model')('');
setOption('assistant_id')(assistant_id);
}
}
}, [index, assistants, selectedAssistantId, assistantsMap, endpoint, setOption]);
const debounceTimeoutRef = useRef<NodeJS.Timeout | null>(null);
@ -64,7 +93,7 @@ export default function useSelectorEffects({
debouncedSetSelectedValues({
endpoint: conversation.endpoint || '',
model: conversation.agent_id ?? '',
modelSpec: '',
modelSpec: conversation.spec || '',
});
return;
} else if (isAssistantsEndpoint(conversation?.endpoint)) {