Skip to content

Commit

Permalink
🛂 feat: OpenID Logout Redirect to end_session_endpoint (#5626)
Browse files Browse the repository at this point in the history
* WIP: end session endpoint

* refactor: move useGetBannerQuery outside of package

* refactor: add queriesEnabled and move useGetEndpointsConfigQuery to data-provider (local)

* refactor: move useGetEndpointsQuery import to data-provider

* refactor: relocate useGetEndpointsQuery import to improve module organization

* refactor: move `useGetStartupConfig` from package to `~/data-provider`

* refactor: move useGetUserBalance to data-provider and update imports

* refactor: update query enabled conditions to include config check

* refactor: remove unused useConfigOverride import from useAppStartup

* refactor: integrate queriesEnabled state into file and search queries and move useGetSearchEnabledQuery to data-provider (local)

* refactor: move useGetUserQuery to data-provider and update imports

* refactor: enhance loginUser mutation with success and error handling as pass in options to hook

* refactor: update enabled condition in queries to handle undefined config

* refactor: enhance authentication mutations with queriesEnabled state management

* refactor: improve conditional rendering for error messages and feature flags in Login component

* refactor: remove unused queriesEnabled state from AuthContextProvider

* refactor: implement queriesEnabled state management in LoginLayout with timeout handling

* refactor: add conditional check for end session endpoint in OpenID strategy

* ci: fix tests after changes

* refactor: remove endSessionEndpoint from user schema and update logoutController to use OpenID issuer's end_session_endpoint

* refactor: update logoutController to use end_session_endpoint from issuer metadata
  • Loading branch information
danny-avila authored Feb 3, 2025
1 parent d93f5c9 commit 45dd2b2
Show file tree
Hide file tree
Showing 73 changed files with 383 additions and 268 deletions.
20 changes: 19 additions & 1 deletion api/server/controllers/auth/LogoutController.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
const cookies = require('cookie');
const { Issuer } = require('openid-client');
const { logoutUser } = require('~/server/services/AuthService');
const { isEnabled } = require('~/server/utils');
const { logger } = require('~/config');

const logoutController = async (req, res) => {
Expand All @@ -8,7 +10,23 @@ const logoutController = async (req, res) => {
const logout = await logoutUser(req, refreshToken);
const { status, message } = logout;
res.clearCookie('refreshToken');
return res.status(status).send({ message });
const response = { message };
if (
req.user.openidId != null &&
isEnabled(process.env.OPENID_USE_END_SESSION_ENDPOINT) &&
process.env.OPENID_ISSUER
) {
const issuer = await Issuer.discover(process.env.OPENID_ISSUER);
const redirect = issuer.metadata.end_session_endpoint;
if (!redirect) {
logger.warn(
'[logoutController] end_session_endpoint not found in OpenID issuer metadata. Please verify that the issuer is correct.',
);
} else {
response.redirect = redirect;
}
}
return res.status(status).send(response);
} catch (err) {
logger.error('[logoutController]', err);
return res.status(500).json({ message: err.message });
Expand Down
3 changes: 2 additions & 1 deletion api/strategies/openidStrategy.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ async function setupOpenId() {
redirect_uris: [process.env.DOMAIN_SERVER + process.env.OPENID_CALLBACK_URL],
};
if (isEnabled(process.env.OPENID_SET_FIRST_SUPPORTED_ALGORITHM)) {
clientMetadata.id_token_signed_response_alg = issuer.id_token_signing_alg_values_supported?.[0] || 'RS256';
clientMetadata.id_token_signed_response_alg =
issuer.id_token_signing_alg_values_supported?.[0] || 'RS256';
}
const client = new issuer.Client(clientMetadata);
const requiredRole = process.env.OPENID_REQUIRED_ROLE;
Expand Down
2 changes: 1 addition & 1 deletion client/src/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ export type TAuthConfig = {
};

export type IconProps = Pick<t.TMessage, 'isCreatedByUser' | 'model'> &
Pick<t.TConversation, 'chatGptLabel' | 'modelLabel' | 'jailbreak'> & {
Pick<t.TConversation, 'chatGptLabel' | 'modelLabel'> & {
size?: number;
button?: boolean;
iconURL?: string;
Expand Down
6 changes: 3 additions & 3 deletions client/src/components/Auth/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ function Login() {

return (
<>
{error && <ErrorMessage>{localize(getLoginError(error))}</ErrorMessage>}
{startupConfig?.emailLoginEnabled && (
{error != null && <ErrorMessage>{localize(getLoginError(error))}</ErrorMessage>}
{startupConfig?.emailLoginEnabled === true && (
<LoginForm
onSubmit={login}
startupConfig={startupConfig}
error={error}
setError={setError}
/>
)}
{startupConfig?.registrationEnabled && (
{startupConfig?.registrationEnabled === true && (
<p className="my-4 text-center text-sm font-light text-gray-700 dark:text-white">
{' '}
{localize('com_auth_no_account')}{' '}
Expand Down
3 changes: 1 addition & 2 deletions client/src/components/Auth/LoginForm.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { useForm } from 'react-hook-form';
import React, { useState, useEffect } from 'react';
import { useGetStartupConfig } from 'librechat-data-provider/react-query';
import type { TLoginUser, TStartupConfig } from 'librechat-data-provider';
import type { TAuthContext } from '~/common';
import { useResendVerificationEmail } from '~/data-provider';
import { useResendVerificationEmail, useGetStartupConfig } from '~/data-provider';
import { useLocalize } from '~/hooks';

type TLoginFormProps = {
Expand Down
16 changes: 9 additions & 7 deletions client/src/components/Auth/__tests__/Login.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import reactRouter from 'react-router-dom';
import userEvent from '@testing-library/user-event';
import { getByTestId, render, waitFor } from 'test/layout-test-utils';
import * as mockDataProvider from 'librechat-data-provider/react-query';
import type { TStartupConfig } from 'librechat-data-provider';
import * as authDataProvider from '~/data-provider/Auth/mutations';
import * as endpointQueries from '~/data-provider/Endpoints/queries';
import * as miscDataProvider from '~/data-provider/Misc/queries';
import * as authMutations from '~/data-provider/Auth/mutations';
import * as authQueries from '~/data-provider/Auth/queries';
import AuthLayout from '~/components/Auth/AuthLayout';
import Login from '~/components/Auth/Login';

Expand Down Expand Up @@ -62,23 +64,23 @@ const setup = ({
},
} = {}) => {
const mockUseLoginUser = jest
.spyOn(authDataProvider, 'useLoginUserMutation')
.spyOn(authMutations, 'useLoginUserMutation')
//@ts-ignore - we don't need all parameters of the QueryObserverSuccessResult
.mockReturnValue(useLoginUserReturnValue);
const mockUseGetUserQuery = jest
.spyOn(mockDataProvider, 'useGetUserQuery')
.spyOn(authQueries, 'useGetUserQuery')
//@ts-ignore - we don't need all parameters of the QueryObserverSuccessResult
.mockReturnValue(useGetUserQueryReturnValue);
const mockUseGetStartupConfig = jest
.spyOn(mockDataProvider, 'useGetStartupConfig')
.spyOn(endpointQueries, 'useGetStartupConfig')
//@ts-ignore - we don't need all parameters of the QueryObserverSuccessResult
.mockReturnValue(useGetStartupConfigReturnValue);
const mockUseRefreshTokenMutation = jest
.spyOn(mockDataProvider, 'useRefreshTokenMutation')
.spyOn(authMutations, 'useRefreshTokenMutation')
//@ts-ignore - we don't need all parameters of the QueryObserverSuccessResult
.mockReturnValue(useRefreshTokenMutationReturnValue);
const mockUseGetBannerQuery = jest
.spyOn(mockDataProvider, 'useGetBannerQuery')
.spyOn(miscDataProvider, 'useGetBannerQuery')
//@ts-ignore - we don't need all parameters of the QueryObserverSuccessResult
.mockReturnValue(useGetBannerQueryReturnValue);
const mockUseOutletContext = jest.spyOn(reactRouter, 'useOutletContext').mockReturnValue({
Expand Down
16 changes: 9 additions & 7 deletions client/src/components/Auth/__tests__/LoginForm.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { render, getByTestId } from 'test/layout-test-utils';
import userEvent from '@testing-library/user-event';
import * as mockDataProvider from 'librechat-data-provider/react-query';
import type { TStartupConfig } from 'librechat-data-provider';
import * as authDataProvider from '~/data-provider/Auth/mutations';
import * as endpointQueries from '~/data-provider/Endpoints/queries';
import * as miscDataProvider from '~/data-provider/Misc/queries';
import * as authMutations from '~/data-provider/Auth/mutations';
import * as authQueries from '~/data-provider/Auth/queries';
import Login from '../LoginForm';

jest.mock('librechat-data-provider/react-query');
Expand Down Expand Up @@ -67,23 +69,23 @@ const setup = ({
},
} = {}) => {
const mockUseLoginUser = jest
.spyOn(authDataProvider, 'useLoginUserMutation')
.spyOn(authMutations, 'useLoginUserMutation')
//@ts-ignore - we don't need all parameters of the QueryObserverSuccessResult
.mockReturnValue(useLoginUserReturnValue);
const mockUseGetUserQuery = jest
.spyOn(mockDataProvider, 'useGetUserQuery')
.spyOn(authQueries, 'useGetUserQuery')
//@ts-ignore - we don't need all parameters of the QueryObserverSuccessResult
.mockReturnValue(useGetUserQueryReturnValue);
const mockUseGetStartupConfig = jest
.spyOn(mockDataProvider, 'useGetStartupConfig')
.spyOn(endpointQueries, 'useGetStartupConfig')
//@ts-ignore - we don't need all parameters of the QueryObserverSuccessResult
.mockReturnValue(useGetStartupConfigReturnValue);
const mockUseRefreshTokenMutation = jest
.spyOn(mockDataProvider, 'useRefreshTokenMutation')
.spyOn(authMutations, 'useRefreshTokenMutation')
//@ts-ignore - we don't need all parameters of the QueryObserverSuccessResult
.mockReturnValue(useRefreshTokenMutationReturnValue);
const mockUseGetBannerQuery = jest
.spyOn(mockDataProvider, 'useGetBannerQuery')
.spyOn(miscDataProvider, 'useGetBannerQuery')
//@ts-ignore - we don't need all parameters of the QueryObserverSuccessResult
.mockReturnValue(useGetBannerQueryReturnValue);
return {
Expand Down
12 changes: 8 additions & 4 deletions client/src/components/Auth/__tests__/Registration.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import userEvent from '@testing-library/user-event';
import { render, waitFor, screen } from 'test/layout-test-utils';
import * as mockDataProvider from 'librechat-data-provider/react-query';
import type { TStartupConfig } from 'librechat-data-provider';
import * as miscDataProvider from '~/data-provider/Misc/queries';
import * as endpointQueries from '~/data-provider/Endpoints/queries';
import * as authMutations from '~/data-provider/Auth/mutations';
import * as authQueries from '~/data-provider/Auth/queries';
import Registration from '~/components/Auth/Registration';
import AuthLayout from '~/components/Auth/AuthLayout';

Expand Down Expand Up @@ -62,22 +66,22 @@ const setup = ({
//@ts-ignore - we don't need all parameters of the QueryObserverSuccessResult
.mockReturnValue(useRegisterUserMutationReturnValue);
const mockUseGetUserQuery = jest
.spyOn(mockDataProvider, 'useGetUserQuery')
.spyOn(authQueries, 'useGetUserQuery')
//@ts-ignore - we don't need all parameters of the QueryObserverSuccessResult
.mockReturnValue(useGetUserQueryReturnValue);
const mockUseGetStartupConfig = jest
.spyOn(mockDataProvider, 'useGetStartupConfig')
.spyOn(endpointQueries, 'useGetStartupConfig')
//@ts-ignore - we don't need all parameters of the QueryObserverSuccessResult
.mockReturnValue(useGetStartupConfigReturnValue);
const mockUseRefreshTokenMutation = jest
.spyOn(mockDataProvider, 'useRefreshTokenMutation')
.spyOn(authMutations, 'useRefreshTokenMutation')
//@ts-ignore - we don't need all parameters of the QueryObserverSuccessResult
.mockReturnValue(useRefreshTokenMutationReturnValue);
const mockUseOutletContext = jest.spyOn(reactRouter, 'useOutletContext').mockReturnValue({
startupConfig: useGetStartupConfigReturnValue.data,
});
const mockUseGetBannerQuery = jest
.spyOn(mockDataProvider, 'useGetBannerQuery')
.spyOn(miscDataProvider, 'useGetBannerQuery')
//@ts-ignore - we don't need all parameters of the QueryObserverSuccessResult
.mockReturnValue(useGetBannerQueryReturnValue);
const renderResult = render(
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/Banners/Banner.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useEffect, useRef } from 'react';
import { XIcon } from 'lucide-react';
import { useRecoilState } from 'recoil';
import { useGetBannerQuery } from 'librechat-data-provider/react-query';
import { useGetBannerQuery } from '~/data-provider';
import store from '~/store';
import { useEffect, useRef } from 'react';

export const Banner = ({ onHeightChange }: { onHeightChange?: (height: number) => void }) => {
const { data: banner } = useGetBannerQuery();
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Chat/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useEffect } from 'react';
import ReactMarkdown from 'react-markdown';
import TagManager from 'react-gtm-module';
import { Constants } from 'librechat-data-provider';
import { useGetStartupConfig } from 'librechat-data-provider/react-query';
import { useGetStartupConfig } from '~/data-provider';
import { useLocalize } from '~/hooks';

export default function Footer({ className }: { className?: string }) {
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Chat/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useMemo } from 'react';
import { useOutletContext } from 'react-router-dom';
import { getConfigDefaults, PermissionTypes, Permissions } from 'librechat-data-provider';
import { useGetStartupConfig } from 'librechat-data-provider/react-query';
import type { ContextType } from '~/common';
import { EndpointsMenu, ModelSpecsMenu, PresetsMenu, HeaderNewChat } from './Menus';
import { useGetStartupConfig } from '~/data-provider';
import ExportAndShareMenu from './ExportAndShareMenu';
import { useMediaQuery, useHasAccess } from '~/hooks';
import HeaderOptions from './Input/HeaderOptions';
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Chat/Input/AddedConvo.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useMemo } from 'react';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import type { TConversation, TEndpointOption, TPreset } from 'librechat-data-provider';
import type { SetterOrUpdater } from 'recoil';
import useGetSender from '~/hooks/Conversations/useGetSender';
import { useGetEndpointsQuery } from '~/data-provider';
import { EndpointIcon } from '~/components/Endpoints';
import { getPresetTitle } from '~/utils';

Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Chat/Input/Files/AttachFileMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import * as Ariakit from '@ariakit/react';
import React, { useRef, useState, useMemo } from 'react';
import { FileSearch, ImageUpIcon, TerminalSquareIcon } from 'lucide-react';
import { EToolResources, EModelEndpoint } from 'librechat-data-provider';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import { FileUpload, TooltipAnchor, DropdownPopup } from '~/components/ui';
import { useGetEndpointsQuery } from '~/data-provider';
import { AttachmentIcon } from '~/components/svg';
import { useLocalize } from '~/hooks';
import { cn } from '~/utils';
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Chat/Input/Files/DragDropModal.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React, { useMemo } from 'react';
import { EModelEndpoint, EToolResources } from 'librechat-data-provider';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import { FileSearch, ImageUpIcon, TerminalSquareIcon } from 'lucide-react';
import OGDialogTemplate from '~/components/ui/OGDialogTemplate';
import { useGetEndpointsQuery } from '~/data-provider';
import useLocalize from '~/hooks/useLocalize';
import { OGDialog } from '~/components/ui';

Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Chat/Input/HeaderOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { useRecoilState } from 'recoil';
import { Settings2 } from 'lucide-react';
import { Root, Anchor } from '@radix-ui/react-popover';
import { useState, useEffect, useMemo } from 'react';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import { tConvoUpdateSchema, EModelEndpoint, isParamEndpoint } from 'librechat-data-provider';
import type { TPreset, TInterfaceConfig } from 'librechat-data-provider';
import { EndpointSettings, SaveAsPresetDialog, AlternativeSettings } from '~/components/Endpoints';
import { PluginStoreDialog, TooltipAnchor } from '~/components';
import { ModelSelect } from '~/components/Input/ModelSelect';
import { useSetIndexOptions, useLocalize } from '~/hooks';
import { useGetEndpointsQuery } from '~/data-provider';
import OptionsPopover from './OptionsPopover';
import PopoverButtons from './PopoverButtons';
import { useChatContext } from '~/Providers';
Expand Down
7 changes: 5 additions & 2 deletions client/src/components/Chat/Landing.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { useMemo } from 'react';
import { EModelEndpoint, Constants } from 'librechat-data-provider';
import { useGetEndpointsQuery, useGetStartupConfig } from 'librechat-data-provider/react-query';
import type * as t from 'librechat-data-provider';
import type { ReactNode } from 'react';
import { useChatContext, useAgentsMapContext, useAssistantsMapContext } from '~/Providers';
import { useGetAssistantDocsQuery } from '~/data-provider';
import {
useGetAssistantDocsQuery,
useGetEndpointsQuery,
useGetStartupConfig,
} from '~/data-provider';
import ConvoIcon from '~/components/Endpoints/ConvoIcon';
import { getIconEndpoint, getEntity, cn } from '~/utils';
import { useLocalize, useSubmitMessage } from '~/hooks';
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Chat/Menus/Endpoints/MenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { useState } from 'react';
import { Settings } from 'lucide-react';
import { useRecoilValue } from 'recoil';
import { EModelEndpoint } from 'librechat-data-provider';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import type { TConversation } from 'librechat-data-provider';
import type { FC } from 'react';
import { cn, getConvoSwitchLogic, getEndpointField, getIconKey } from '~/utils';
import { useLocalize, useUserKey, useDefaultConvo } from '~/hooks';
import { SetKeyDialog } from '~/components/Input/SetKeyDialog';
import { useGetEndpointsQuery } from '~/data-provider';
import { useChatContext } from '~/Providers';
import { icons } from './Icons';
import store from '~/store';
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Chat/Menus/Endpoints/MenuItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
PermissionTypes,
Permissions,
} from 'librechat-data-provider';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import { useGetEndpointsQuery } from '~/data-provider';
import MenuSeparator from '../UI/MenuSeparator';
import { getEndpointField } from '~/utils';
import { useHasAccess } from '~/hooks';
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Chat/Menus/EndpointsMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useCallback, useRef } from 'react';
import { alternateName } from 'librechat-data-provider';
import { Content, Portal, Root } from '@radix-ui/react-popover';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import type { FC, KeyboardEvent } from 'react';
import { useChatContext, useAgentsMapContext, useAssistantsMapContext } from '~/Providers';
import { useGetEndpointsQuery } from '~/data-provider';
import { mapEndpoints, getEntity } from '~/utils';
import EndpointItems from './Endpoints/MenuItems';
import useLocalize from '~/hooks/useLocalize';
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Chat/Menus/Models/ModelSpecsMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { useRecoilValue } from 'recoil';
import { useMemo, useCallback, useRef } from 'react';
import { Content, Portal, Root } from '@radix-ui/react-popover';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import { EModelEndpoint, isAssistantsEndpoint } from 'librechat-data-provider';
import type { TModelSpec, TConversation, TEndpointsConfig } from 'librechat-data-provider';
import type { KeyboardEvent } from 'react';
import { useChatContext, useAssistantsMapContext } from '~/Providers';
import { useDefaultConvo, useNewConvo, useLocalize } from '~/hooks';
import { getConvoSwitchLogic, getModelSpecIconURL } from '~/utils';
import { useGetEndpointsQuery } from '~/data-provider';
import MenuButton from './MenuButton';
import ModelSpecs from './ModelSpecs';
import store from '~/store';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { useRecoilState } from 'recoil';
import { useCallback, useEffect, useMemo } from 'react';
import { useQueryClient } from '@tanstack/react-query';
import { QueryKeys, isAgentsEndpoint } from 'librechat-data-provider';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import type { TModelsConfig, TEndpointsConfig } from 'librechat-data-provider';
import {
cn,
Expand All @@ -16,6 +15,7 @@ import { useSetIndexOptions, useLocalize, useDebouncedInput } from '~/hooks';
import PopoverButtons from '~/components/Chat/Input/PopoverButtons';
import DialogTemplate from '~/components/ui/DialogTemplate';
import { EndpointSettings } from '~/components/Endpoints';
import { useGetEndpointsQuery } from '~/data-provider';
import { useChatContext } from '~/Providers';
import store from '~/store';

Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Chat/Menus/Presets/PresetItems.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { useRecoilValue } from 'recoil';
import { Close } from '@radix-ui/react-popover';
import { Flipper, Flipped } from 'react-flip-toolkit';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import type { FC } from 'react';
import type { TPreset } from 'librechat-data-provider';
import { getPresetTitle, getEndpointField, getIconKey } from '~/utils';
import FileUpload from '~/components/Chat/Input/Files/FileUpload';
import { PinIcon, EditIcon, TrashIcon } from '~/components/svg';
import { Dialog, DialogTrigger, Label } from '~/components/ui';
import DialogTemplate from '~/components/ui/DialogTemplate';
import { useGetEndpointsQuery } from '~/data-provider';
import { MenuSeparator, MenuItem } from '../UI';
import { icons } from '../Endpoints/Icons';
import { useLocalize } from '~/hooks';
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Chat/Messages/MessageIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React, { useMemo, memo } from 'react';
import { useGetEndpointsQuery } from 'librechat-data-provider/react-query';
import type { Assistant, Agent } from 'librechat-data-provider';
import type { TMessageIcon } from '~/common';
import { getEndpointField, getIconEndpoint, logger } from '~/utils';
import ConvoIconURL from '~/components/Endpoints/ConvoIconURL';
import { useGetEndpointsQuery } from '~/data-provider';
import Icon from '~/components/Endpoints/Icon';

const MessageIcon = memo(
Expand Down
Loading

0 comments on commit 45dd2b2

Please sign in to comment.