fix: Wait for Initial Message Save & Correct Latest Message (#3399)

* chore: assistants, unsupported assistant, better logging

* chore: remove unnecessary logger in validateAssistant middleware

* fix: resolve initial conversation save/promise before saving response

* chore: Import and organize dependencies in Speech component

* fix: conversation statefulness
- Latest Message (at index 0) should not be reset if existing convo
- add debugging context for clearAllLatestMessages
- Added logging concerning latest Message updates (dev mode only)
- update latest message Set logic, also checks for change in conversation Id
- consolidated latest message helpers to client/src/utils/messages.ts
This commit is contained in:
Danny Avila 2024-07-20 01:51:59 -04:00 committed by GitHub
parent 9e7615f832
commit 2ad097647c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 275 additions and 113 deletions

View file

@ -107,6 +107,16 @@ export default function useChatFunctions({
const intermediateId = overrideUserMessageId ?? v4();
parentMessageId = parentMessageId || latestMessage?.messageId || Constants.NO_PARENT;
logger.dir('Ask function called with:', {
index,
latestMessage,
conversationId,
intermediateId,
parentMessageId,
currentMessages,
});
logger.log('=====================================');
if (conversationId == Constants.NEW_CONVO) {
parentMessageId = Constants.NO_PARENT;
currentMessages = [];

View file

@ -12,7 +12,7 @@ import type {
TModelsConfig,
TEndpointsConfig,
} from 'librechat-data-provider';
import { buildDefaultConvo, getDefaultEndpoint, getEndpointField } from '~/utils';
import { buildDefaultConvo, getDefaultEndpoint, getEndpointField, logger } from '~/utils';
import store from '~/store';
const useConversation = () => {
@ -60,6 +60,10 @@ const useConversation = () => {
setMessages(messages);
setSubmission({} as TSubmission);
resetLatestMessage();
logger.log(
'[useConversation] Switched to conversation and reset Latest Message',
conversation,
);
if (conversation.conversationId === 'new' && !modelsData) {
queryClient.invalidateQueries([QueryKeys.messages, 'new']);

View file

@ -1,7 +1,7 @@
import { useSetRecoilState } from 'recoil';
import { useNavigate } from 'react-router-dom';
import { useQueryClient } from '@tanstack/react-query';
import { QueryKeys, EModelEndpoint, LocalStorageKeys } from 'librechat-data-provider';
import { QueryKeys, EModelEndpoint, LocalStorageKeys, Constants } from 'librechat-data-provider';
import type { TConversation, TEndpointsConfig, TModelsConfig } from 'librechat-data-provider';
import { buildDefaultConvo, getDefaultEndpoint, getEndpointField } from '~/utils';
import store from '~/store';
@ -10,7 +10,7 @@ const useNavigateToConvo = (index = 0) => {
const navigate = useNavigate();
const queryClient = useQueryClient();
const clearAllConversations = store.useClearConvoState();
const clearAllLatestMessages = store.useClearLatestMessages();
const clearAllLatestMessages = store.useClearLatestMessages(`useNavigateToConvo ${index}`);
const setSubmission = useSetRecoilState(store.submissionByIndex(index));
const { setConversation } = store.useCreateConversationAtom(index);
@ -50,10 +50,10 @@ const useNavigateToConvo = (index = 0) => {
}
clearAllConversations(true);
setConversation(convo);
navigate(`/c/${convo.conversationId ?? 'new'}`);
navigate(`/c/${convo.conversationId ?? Constants.NEW_CONVO}`);
};
const navigateWithLastTools = (conversation: TConversation) => {
const navigateWithLastTools = (conversation: TConversation, _resetLatestMessage?: boolean) => {
// set conversation to the new conversation
if (conversation?.endpoint === EModelEndpoint.gptPlugins) {
let lastSelectedTools = [];
@ -63,12 +63,15 @@ const useNavigateToConvo = (index = 0) => {
} catch (e) {
// console.error(e);
}
navigateToConvo({
...conversation,
tools: conversation?.tools?.length ? conversation?.tools : lastSelectedTools,
});
navigateToConvo(
{
...conversation,
tools: conversation?.tools?.length ? conversation?.tools : lastSelectedTools,
},
_resetLatestMessage,
);
} else {
navigateToConvo(conversation);
navigateToConvo(conversation, _resetLatestMessage);
}
};

View file

@ -1,9 +1,9 @@
import { useEffect, useRef, useCallback } from 'react';
import { isAssistantsEndpoint } from 'librechat-data-provider';
import { Constants, isAssistantsEndpoint } from 'librechat-data-provider';
import type { TMessageProps } from '~/common';
import { useChatContext, useAssistantsMapContext } from '~/Providers';
import { getLatestText, getLengthAndFirstFiveChars } from '~/utils';
import useCopyToClipboard from './useCopyToClipboard';
import { getTextKey, logger } from '~/utils';
export default function useMessageHelpers(props: TMessageProps) {
const latestText = useRef<string | number>('');
@ -27,7 +27,8 @@ export default function useMessageHelpers(props: TMessageProps) {
const isLast = !children?.length;
useEffect(() => {
if (conversation?.conversationId === 'new') {
const convoId = conversation?.conversationId;
if (convoId === Constants.NEW_CONVO) {
return;
}
if (!message) {
@ -37,15 +38,25 @@ export default function useMessageHelpers(props: TMessageProps) {
return;
}
const text = getLatestText(message);
const textKey = `${message?.messageId ?? ''}${getLengthAndFirstFiveChars(text)}`;
const textKey = getTextKey(message, convoId);
if (textKey === latestText.current) {
return;
// Check for text/conversation change
const logInfo = {
textKey,
'latestText.current': latestText.current,
messageId: message?.messageId,
convoId,
};
if (
textKey !== latestText.current ||
(latestText.current && convoId !== latestText.current.split(Constants.COMMON_DIVIDER)[2])
) {
logger.log('[useMessageHelpers] Setting latest message: ', logInfo);
latestText.current = textKey;
setLatestMessage({ ...message });
} else {
logger.log('No change in latest message', logInfo);
}
latestText.current = textKey;
setLatestMessage({ ...message });
}, [isLast, message, setLatestMessage, conversation?.conversationId]);
const enterEdit = useCallback(

View file

@ -1,8 +1,9 @@
import { useRecoilValue } from 'recoil';
import { Constants } from 'librechat-data-provider';
import { useEffect, useRef, useCallback, useMemo, useState } from 'react';
import type { TMessage } from 'librechat-data-provider';
import { useChatContext, useAddedChatContext } from '~/Providers';
import { getLatestText, getLengthAndFirstFiveChars } from '~/utils';
import { getTextKey, logger } from '~/utils';
import store from '~/store';
export default function useMessageProcess({ message }: { message?: TMessage | null }) {
@ -26,7 +27,8 @@ export default function useMessageProcess({ message }: { message?: TMessage | nu
);
useEffect(() => {
if (conversation?.conversationId === 'new') {
const convoId = conversation?.conversationId;
if (convoId === Constants.NEW_CONVO) {
return;
}
if (!message) {
@ -36,15 +38,27 @@ export default function useMessageProcess({ message }: { message?: TMessage | nu
return;
}
const text = getLatestText(message);
const textKey = `${message?.messageId ?? ''}${getLengthAndFirstFiveChars(text)}`;
const textKey = getTextKey(message, convoId);
if (textKey === latestText.current) {
return;
// Check for text/conversation change
const logInfo = {
textKey,
'latestText.current': latestText.current,
messageId: message?.messageId,
convoId,
};
if (
textKey !== latestText.current ||
(convoId &&
latestText.current &&
convoId !== latestText.current.split(Constants.COMMON_DIVIDER)[2])
) {
logger.log('[useMessageProcess] Setting latest message: ', logInfo);
latestText.current = textKey;
setLatestMessage({ ...message });
} else {
logger.log('No change in latest message', logInfo);
}
latestText.current = textKey;
setLatestMessage({ ...message });
}, [hasNoChildren, message, setLatestMessage, conversation?.conversationId]);
const handleScroll = useCallback(() => {

View file

@ -34,9 +34,9 @@ const useNewConvo = (index = 0) => {
const { data: startupConfig } = useGetStartupConfig();
const clearAllConversations = store.useClearConvoState();
const defaultPreset = useRecoilValue(store.defaultPreset);
const clearAllLatestMessages = store.useClearLatestMessages();
const { setConversation } = store.useCreateConversationAtom(index);
const [files, setFiles] = useRecoilState(store.filesByIndex(index));
const clearAllLatestMessages = store.useClearLatestMessages(`useNewConvo ${index}`);
const setSubmission = useSetRecoilState<TSubmission | null>(store.submissionByIndex(index));
const { data: endpointsConfig = {} as TEndpointsConfig } = useGetEndpointsQuery();