diff --git a/src/renderer/src/pages/home/Messages/Messages.tsx b/src/renderer/src/pages/home/Messages/Messages.tsx index 433d5237..37606f26 100644 --- a/src/renderer/src/pages/home/Messages/Messages.tsx +++ b/src/renderer/src/pages/home/Messages/Messages.tsx @@ -50,6 +50,12 @@ const Messages: React.FC = ({ assistant, topic, setActiveTopic }) const [hasMore, setHasMore] = useState(false) const [isLoadingMore, setIsLoadingMore] = useState(false) + const messagesRef = useRef([]) + + useEffect(() => { + messagesRef.current = messages + }, [messages]) + useEffect(() => { const reversedMessages = [...messages].reverse() const newDisplayMessages = reversedMessages.slice(0, displayCount) @@ -85,15 +91,8 @@ const Messages: React.FC = ({ assistant, topic, setActiveTopic }) setTimeout(() => containerRef.current?.scrollTo({ top: containerRef.current.scrollHeight, behavior: 'auto' }), 50) }, []) - // const onAppendMessageMemo = useCallback( - // async (message: Message) => { - // const newMessages = [...messages, message] - // await dispatch(updateMessages(topic, newMessages)) - // }, - // [topic, dispatch, messages] - // ) - - const autoRenameTopicMemo = useCallback(async () => { + const autoRenameTopic = useCallback(async () => { + const messages = messagesRef.current const _topic = getTopic(assistant, topic.id) if (!enableTopicNaming) { @@ -114,18 +113,16 @@ const Messages: React.FC = ({ assistant, topic, setActiveTopic }) updateTopic(data) } } - }, [assistant, enableTopicNaming, messages, setActiveTopic, topic.id, updateTopic, t]) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [assistant, topic.id, enableTopicNaming, t, setActiveTopic]) useEffect(() => { + const messages = messagesRef.current + const unsubscribes = [ - // EventEmitter.on(EVENT_NAMES.APPEND_MESSAGE, onAppendMessageMemo), - // EventEmitter.on(EVENT_NAMES.RECEIVE_MESSAGE, () => { - // setTimeout(() => EventEmitter.emit(EVENT_NAMES.AI_AUTO_RENAME), 100) - // }), EventEmitter.on(EVENT_NAMES.SEND_MESSAGE, () => { scrollToBottom() }), - EventEmitter.on(EVENT_NAMES.AI_AUTO_RENAME, autoRenameTopicMemo), EventEmitter.on(EVENT_NAMES.CLEAR_MESSAGES, async (data: Topic) => { const defaultTopic = getDefaultTopic(assistant.id) @@ -172,12 +169,13 @@ const Messages: React.FC = ({ assistant, topic, setActiveTopic }) }) ] - return () => { - for (const unsub of unsubscribes) { - unsub() - } - } - }, [assistant, autoRenameTopicMemo, dispatch, messages, handleDeleteMessage, scrollToBottom, topic, updateTopic]) + return () => unsubscribes.forEach((unsub) => unsub()) + }, [assistant, dispatch, handleDeleteMessage, scrollToBottom, topic, updateTopic]) + + useEffect(() => { + const unsubscribes = [EventEmitter.on(EVENT_NAMES.AI_AUTO_RENAME, autoRenameTopic)] + return () => unsubscribes.forEach((unsub) => unsub()) + }, [autoRenameTopic]) useEffect(() => { runAsyncFunction(async () => { diff --git a/src/renderer/src/store/messages.ts b/src/renderer/src/store/messages.ts index 6baf9ec6..bda9e35a 100644 --- a/src/renderer/src/store/messages.ts +++ b/src/renderer/src/store/messages.ts @@ -172,9 +172,13 @@ export const { const handleResponseMessageUpdate = (message, topicId, dispatch, getState) => { dispatch(setStreamMessage({ topicId, message })) + // When message is complete, commit to messages and sync with DB if (message.status !== 'pending') { - EventEmitter.emit(EVENT_NAMES.AI_AUTO_RENAME) + if (message.status === 'success') { + EventEmitter.emit(EVENT_NAMES.AI_AUTO_RENAME) + } + dispatch(commitStreamMessage({ topicId, messageId: message.id })) const state = getState() @@ -225,7 +229,7 @@ export const sendMessage = // 使用用户消息 let userMessage: Message if (isResend) { - userMessage = options.resendUserMessage + userMessage = options.resendUserMessage! } else { // 创建新的用户消息 userMessage = getUserMessage({ assistant, topic, type: 'text', content }) @@ -233,9 +237,11 @@ export const sendMessage = if (options?.files) { userMessage.files = options.files } + if (options?.knowledgeBaseIds) { userMessage.knowledgeBaseIds = options.knowledgeBaseIds } + if (options?.mentionModels) { userMessage.mentions = options.mentionModels } @@ -245,6 +251,7 @@ export const sendMessage = if (!isResend) { dispatch(addMessage({ topicId: topic.id, messages: userMessage })) } + EventEmitter.emit(EVENT_NAMES.SEND_MESSAGE) // 处理助手消息 @@ -284,8 +291,12 @@ export const sendMessage = // Use topic queue to handle request const queue = getTopicQueue(topic.id) + // let assistantMessage: Message | undefined - !isResend && dispatch(addMessage({ topicId: topic.id, messages: assistantMessages })) + if (!isResend) { + dispatch(addMessage({ topicId: topic.id, messages: assistantMessages })) + } + for (const assistantMessage of assistantMessages) { // console.log('assistantMessage', assistantMessage) @@ -295,9 +306,11 @@ export const sendMessage = // Sync user message with database const state = getState() const currentTopicMessages = state.messages.messagesByTopic[topic.id] + if (currentTopicMessages) { await syncMessagesWithDB(topic.id, currentTopicMessages) } + queue.add(async () => { try { const state = getState() @@ -340,7 +353,7 @@ export const sendMessage = throttledDispatch({ ...assistantMessage, ...updatedMsg }, topic.id, dispatch, getState) } }) - } catch (error) { + } catch (error: any) { console.error('Error in chat completion:', error) dispatch( updateMessage({ @@ -354,7 +367,7 @@ export const sendMessage = } }) } - } catch (error) { + } catch (error: any) { console.error('Error in sendMessage:', error) dispatch(setError(error.message)) } finally { @@ -409,7 +422,7 @@ export const resendMessage = resendAssistantMessage: message }) ) - } catch (error) { + } catch (error: any) { console.error('Error in resendMessage:', error) dispatch(setError(error.message)) } finally { @@ -477,7 +490,10 @@ export const selectTopicMessages = createSelector( [(state: RootState) => state.messages, (_, topicId: string) => topicId], (messagesState, topicId) => { const topicMessages = messagesState.messagesByTopic[topicId] - if (!topicMessages) return [] + + if (!topicMessages) { + return [] + } return [...topicMessages].sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()) } @@ -503,7 +519,9 @@ export const selectError = (state: RootState): string | null => { return messagesState?.error || null } -export const selectStreamMessage = (state: RootState, topicId: string, messageId: string): Message | null => - state.messages.streamMessagesByTopic[topicId]?.[messageId] || null +export const selectStreamMessage = (state: RootState, topicId: string, messageId: string): Message | null => { + const messagesState = state.messages as MessagesState + return messagesState.streamMessagesByTopic[topicId]?.[messageId] || null +} export default messagesSlice.reducer