mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-21 21:50:49 +02:00

* refactor: useMCPSelect - Add useGetMCPTools to use in useMCPSelect and elsewhere hooks for fetching MCP tools - remove memoized key - remove use of `useChatContext` and require conversationId as prop * feat: Add MCPPanelContext and integrate conversationId as prop for useMCPSelect across components - Introduced MCPPanelContext to manage conversationId state. - Updated MCPSelect, MCPSubMenu, and MCPConfigDialog to accept conversationId as a prop. - Modified ToolsDropdown and BadgeRow to pass conversationId to relevant components. - Refactored MCPPanel to utilize MCPPanelProvider for context management. * fix: remove nested ternary in ServerInitializationSection - Replaced conditional operator with if-else statements for better readability in determining button text based on server initialization state and reinitialization status. * refactor: wrap setValueWrap in useCallback for performance optimization * refactor: streamline useMCPSelect by consolidating storageKey definition * fix: prevent clearing selections on page refresh by tracking initial load completion * refactor: simplify concern of useMCPSelect hook * refactor: move ConfigFieldDetail interface to common types for better reusability, isolate usage of `useGetMCPTools` * refactor: integrate mcpServerNames into BadgeRowContext and update ToolsDropdown and MCPSelect components
72 lines
2 KiB
TypeScript
72 lines
2 KiB
TypeScript
import { useRef, useCallback, useMemo } from 'react';
|
|
import { useRecoilState } from 'recoil';
|
|
import { Constants, LocalStorageKeys } from 'librechat-data-provider';
|
|
import useLocalStorage from '~/hooks/useLocalStorageAlt';
|
|
import { ephemeralAgentByConvoId } from '~/store';
|
|
|
|
const storageCondition = (value: unknown, rawCurrentValue?: string | null) => {
|
|
if (rawCurrentValue) {
|
|
try {
|
|
const currentValue = rawCurrentValue?.trim() ?? '';
|
|
if (currentValue.length > 2) {
|
|
return true;
|
|
}
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
}
|
|
return Array.isArray(value) && value.length > 0;
|
|
};
|
|
|
|
export function useMCPSelect({ conversationId }: { conversationId?: string | null }) {
|
|
const key = conversationId ?? Constants.NEW_CONVO;
|
|
const [ephemeralAgent, setEphemeralAgent] = useRecoilState(ephemeralAgentByConvoId(key));
|
|
|
|
const storageKey = `${LocalStorageKeys.LAST_MCP_}${key}`;
|
|
const mcpState = useMemo(() => {
|
|
return ephemeralAgent?.mcp ?? [];
|
|
}, [ephemeralAgent?.mcp]);
|
|
|
|
const setSelectedValues = useCallback(
|
|
(values: string[] | null | undefined) => {
|
|
if (!values) {
|
|
return;
|
|
}
|
|
if (!Array.isArray(values)) {
|
|
return;
|
|
}
|
|
setEphemeralAgent((prev) => ({
|
|
...prev,
|
|
mcp: values,
|
|
}));
|
|
},
|
|
[setEphemeralAgent],
|
|
);
|
|
|
|
const [mcpValues, setMCPValuesRaw] = useLocalStorage<string[]>(
|
|
storageKey,
|
|
mcpState,
|
|
setSelectedValues,
|
|
storageCondition,
|
|
);
|
|
|
|
const setMCPValuesRawRef = useRef(setMCPValuesRaw);
|
|
setMCPValuesRawRef.current = setMCPValuesRaw;
|
|
|
|
/** Create a stable memoized setter to avoid re-creating it on every render and causing an infinite render loop */
|
|
const setMCPValues = useCallback((value: string[]) => {
|
|
setMCPValuesRawRef.current(value);
|
|
}, []);
|
|
|
|
const [isPinned, setIsPinned] = useLocalStorage<boolean>(
|
|
`${LocalStorageKeys.PIN_MCP_}${key}`,
|
|
true,
|
|
);
|
|
|
|
return {
|
|
isPinned,
|
|
mcpValues,
|
|
setIsPinned,
|
|
setMCPValues,
|
|
};
|
|
}
|