diff --git a/client/src/components/Chat/Messages/Message.tsx b/client/src/components/Chat/Messages/Message.tsx
index fc52a89584..fb8babdd34 100644
--- a/client/src/components/Chat/Messages/Message.tsx
+++ b/client/src/components/Chat/Messages/Message.tsx
@@ -1,16 +1,9 @@
-import React, { useCallback, useMemo } from 'react';
-import { useMessageProcess, useMessageActions } from '~/hooks';
-import type { TMessage } from 'librechat-data-provider';
+import React from 'react';
+import { useMessageProcess } from '~/hooks';
import type { TMessageProps } from '~/common';
-import Icon from '~/components/Chat/Messages/MessageIcon';
-import { Plugin } from '~/components/Messages/Content';
-import MessageContent from './Content/MessageContent';
-import SiblingSwitch from './SiblingSwitch';
+import MessageRender from './ui/MessageRender';
// eslint-disable-next-line import/no-cycle
import MultiMessage from './MultiMessage';
-import HoverButtons from './HoverButtons';
-import SubRow from './SubRow';
-import { cn } from '~/utils';
const MessageContainer = React.memo(
({ handleScroll, children }: { handleScroll: () => void; children: React.ReactNode }) => {
@@ -26,155 +19,6 @@ const MessageContainer = React.memo(
},
);
-const PlaceholderRow = React.memo(({ isLast, isCard }: { isLast: boolean; isCard?: boolean }) => {
- if (!isCard) {
- return null;
- }
- if (!isLast) {
- return null;
- }
- return
;
-});
-
-type MessageRenderProps = {
- message?: TMessage;
- isCard?: boolean;
- isMultiMessage?: boolean;
- isSubmittingFamily?: boolean;
-} & Pick<
- TMessageProps,
- 'currentEditId' | 'setCurrentEditId' | 'siblingIdx' | 'setSiblingIdx' | 'siblingCount'
->;
-
-const MessageRender = React.memo(
- ({
- isCard,
- siblingIdx,
- siblingCount,
- message: msg,
- setSiblingIdx,
- currentEditId,
- isMultiMessage,
- setCurrentEditId,
- isSubmittingFamily,
- }: MessageRenderProps) => {
- const {
- ask,
- edit,
- index,
- assistant,
- enterEdit,
- conversation,
- messageLabel,
- isSubmitting,
- latestMessage,
- handleContinue,
- copyToClipboard,
- setLatestMessage,
- regenerateMessage,
- } = useMessageActions({
- message: msg,
- currentEditId,
- isMultiMessage,
- setCurrentEditId,
- });
-
- const handleRegenerateMessage = useCallback(() => regenerateMessage(), [regenerateMessage]);
- const { isCreatedByUser, error, unfinished } = msg ?? {};
- const isLast = useMemo(
- () => !msg?.children?.length && (msg?.depth === latestMessage?.depth || msg?.depth === -1),
- [msg?.children, msg?.depth, latestMessage?.depth],
- );
-
- if (!msg) {
- return null;
- }
-
- const isLatest = isCard && !isSubmittingFamily && msg.messageId === latestMessage?.messageId;
- const clickHandler =
- isLast && isCard && !isSubmittingFamily && msg.messageId !== latestMessage?.messageId
- ? () => setLatestMessage(msg)
- : undefined;
-
- return (
-
- {isLatest && (
-
- )}
-
-
-
{messageLabel}
-
-
- {msg?.plugin &&
}
-
({}))}
- />
-
-
- {!msg?.children?.length && (isSubmittingFamily || isSubmitting) ? (
-
- ) : (
-
-
-
-
- )}
-
-
- );
- },
-);
-
export default function Message(props: TMessageProps) {
const {
showSibling,
diff --git a/client/src/components/Chat/Messages/ui/MessageRender.tsx b/client/src/components/Chat/Messages/ui/MessageRender.tsx
new file mode 100644
index 0000000000..c78066c53d
--- /dev/null
+++ b/client/src/components/Chat/Messages/ui/MessageRender.tsx
@@ -0,0 +1,154 @@
+import React, { useCallback, useMemo } from 'react';
+import { useMessageActions } from '~/hooks';
+import type { TMessage } from 'librechat-data-provider';
+import type { TMessageProps } from '~/common';
+import MessageContent from '~/components/Chat/Messages/Content/MessageContent';
+import PlaceholderRow from '~/components/Chat/Messages/ui/PlaceholderRow';
+import SiblingSwitch from '~/components/Chat/Messages/SiblingSwitch';
+import HoverButtons from '~/components/Chat/Messages/HoverButtons';
+import Icon from '~/components/Chat/Messages/MessageIcon';
+import { Plugin } from '~/components/Messages/Content';
+import SubRow from '~/components/Chat/Messages/SubRow';
+import { cn } from '~/utils';
+
+type MessageRenderProps = {
+ message?: TMessage;
+ isCard?: boolean;
+ isMultiMessage?: boolean;
+ isSubmittingFamily?: boolean;
+} & Pick<
+ TMessageProps,
+ 'currentEditId' | 'setCurrentEditId' | 'siblingIdx' | 'setSiblingIdx' | 'siblingCount'
+>;
+
+const MessageRender = React.memo(
+ ({
+ isCard,
+ siblingIdx,
+ siblingCount,
+ message: msg,
+ setSiblingIdx,
+ currentEditId,
+ isMultiMessage,
+ setCurrentEditId,
+ isSubmittingFamily,
+ }: MessageRenderProps) => {
+ const {
+ ask,
+ edit,
+ index,
+ assistant,
+ enterEdit,
+ conversation,
+ messageLabel,
+ isSubmitting,
+ latestMessage,
+ handleContinue,
+ copyToClipboard,
+ setLatestMessage,
+ regenerateMessage,
+ } = useMessageActions({
+ message: msg,
+ currentEditId,
+ isMultiMessage,
+ setCurrentEditId,
+ });
+
+ const handleRegenerateMessage = useCallback(() => regenerateMessage(), [regenerateMessage]);
+ const { isCreatedByUser, error, unfinished } = msg ?? {};
+ const isLast = useMemo(
+ () => !msg?.children?.length && (msg?.depth === latestMessage?.depth || msg?.depth === -1),
+ [msg?.children, msg?.depth, latestMessage?.depth],
+ );
+
+ if (!msg) {
+ return null;
+ }
+
+ const isLatestCard =
+ isCard && !isSubmittingFamily && msg.messageId === latestMessage?.messageId;
+ const clickHandler =
+ isLast && isCard && !isSubmittingFamily && msg.messageId !== latestMessage?.messageId
+ ? () => setLatestMessage(msg)
+ : undefined;
+
+ return (
+
+ {isLatestCard && (
+
+ )}
+
+
+
{messageLabel}
+
+
+ {msg?.plugin &&
}
+
({}))}
+ />
+
+
+ {!msg?.children?.length && (isSubmittingFamily || isSubmitting) ? (
+
+ ) : (
+
+
+
+
+ )}
+
+
+ );
+ },
+);
+
+export default MessageRender;
diff --git a/client/src/components/Chat/Messages/ui/PlaceholderRow.tsx b/client/src/components/Chat/Messages/ui/PlaceholderRow.tsx
new file mode 100644
index 0000000000..1c3d17de81
--- /dev/null
+++ b/client/src/components/Chat/Messages/ui/PlaceholderRow.tsx
@@ -0,0 +1,13 @@
+import { memo } from 'react';
+
+const PlaceholderRow = memo(({ isLast, isCard }: { isLast: boolean; isCard?: boolean }) => {
+ if (!isCard) {
+ return null;
+ }
+ if (!isLast) {
+ return null;
+ }
+ return ;
+});
+
+export default PlaceholderRow;
diff --git a/client/src/routes/ChatRoute.tsx b/client/src/routes/ChatRoute.tsx
index 3f9e0a5024..ad933efd61 100644
--- a/client/src/routes/ChatRoute.tsx
+++ b/client/src/routes/ChatRoute.tsx
@@ -38,14 +38,14 @@ export default function ChatRoute() {
const assistantListMap = useAssistantListMap();
useEffect(() => {
- if (
- startupConfig &&
- conversationId === 'new' &&
- endpointsQuery.data &&
- modelsQuery.data &&
- !modelsQuery.data?.initial &&
- !hasSetConversation.current
- ) {
+ const shouldSetConvo =
+ startupConfig && !hasSetConversation.current && !modelsQuery.data?.initial;
+ /* Early exit if startupConfig is not loaded and conversation is already set and only initial models have loaded */
+ if (!shouldSetConvo) {
+ return;
+ }
+
+ if (conversationId === 'new' && endpointsQuery.data && modelsQuery.data) {
const spec = getDefaultModelSpec(startupConfig.modelSpecs?.list);
newConversation({
@@ -63,14 +63,7 @@ export default function ChatRoute() {
});
hasSetConversation.current = true;
- } else if (
- startupConfig &&
- initialConvoQuery.data &&
- endpointsQuery.data &&
- modelsQuery.data &&
- !modelsQuery.data?.initial &&
- !hasSetConversation.current
- ) {
+ } else if (initialConvoQuery.data && endpointsQuery.data && modelsQuery.data) {
newConversation({
template: initialConvoQuery.data,
/* this is necessary to load all existing settings */
@@ -80,9 +73,6 @@ export default function ChatRoute() {
});
hasSetConversation.current = true;
} else if (
- startupConfig &&
- !hasSetConversation.current &&
- !modelsQuery.data?.initial &&
conversationId === 'new' &&
assistantListMap[EModelEndpoint.assistants] &&
assistantListMap[EModelEndpoint.azureAssistants]
@@ -103,9 +93,6 @@ export default function ChatRoute() {
});
hasSetConversation.current = true;
} else if (
- startupConfig &&
- !hasSetConversation.current &&
- !modelsQuery.data?.initial &&
assistantListMap[EModelEndpoint.assistants] &&
assistantListMap[EModelEndpoint.azureAssistants]
) {