fix: 使用 wrappedSendMessage 保存用户消息到独立状态

1. 创建 wrappedSendMessage 包装函数
2. 在发送消息时同时保存用户消息到 appendedMessages
3. 这样即使 useChat 重置消息状态,用户消息也会保留在 mergedMessages 中

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Your Name 2026-02-01 10:35:03 +08:00
parent b3d37f815a
commit b60afb16cb

View File

@ -3,7 +3,7 @@
import { useChat } from "@ai-sdk/react"; import { useChat } from "@ai-sdk/react";
import { DefaultChatTransport } from "ai"; import { DefaultChatTransport } from "ai";
import { useRouter, useSearchParams } from "next/navigation"; import { useRouter, useSearchParams } from "next/navigation";
import { useEffect, useMemo, useRef, useState } from "react"; import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import useSWR, { useSWRConfig } from "swr"; import useSWR, { useSWRConfig } from "swr";
import { unstable_serialize } from "swr/infinite"; import { unstable_serialize } from "swr/infinite";
import { ChatHeader } from "@/components/chat-header"; import { ChatHeader } from "@/components/chat-header";
@ -356,28 +356,8 @@ export function Chat({
// 🆕 生成完成,清除持久化状态 // 🆕 生成完成,清除持久化状态
completeGeneration(); completeGeneration();
console.log("[Chat] onFinish called"); console.log("[Chat] onFinish called");
// 🆕 不再尝试在 onFinish 中合并消息,完全依赖 mergedMessages
// 🆕 在流式传输完成后,将 appendedMessages 合并到 messages // 消息会在下次页面加载时从数据库正确获取
// 延迟执行以确保 useChat 内部状态已稳定
setTimeout(() => {
setAppendedMessages((prevAppended) => {
if (prevAppended.length > 0) {
console.log("[Chat] Merging appendedMessages to messages:", prevAppended.length);
setMessages((prevMessages) => {
// 过滤掉已存在的消息
const newMessages = prevAppended.filter(
(appended) => !prevMessages.some((m) => m.id === appended.id)
);
if (newMessages.length > 0) {
console.log("[Chat] Actually adding new messages:", newMessages.length);
return [...prevMessages, ...newMessages];
}
return prevMessages;
});
}
return []; // 清空 appendedMessages
});
}, 100);
}, },
onError: (error) => { onError: (error) => {
if (error instanceof ChatSDKError) { if (error instanceof ChatSDKError) {
@ -393,6 +373,27 @@ export function Chat({
}, },
}); });
// 🆕 包装 sendMessage,在发送时保存用户消息到 appendedMessages
// 这样即使 useChat 重置消息状态,用户消息也会保留在 mergedMessages 中
const wrappedSendMessage = useCallback((message: Parameters<typeof sendMessage>[0]) => {
// 保存用户消息到 appendedMessages
const textPart = message?.parts?.find((p: any) => p.type === "text") as any;
const userMessage: ChatMessage = {
id: generateUUID(),
role: "user",
content: textPart?.text || "",
createdAt: new Date(),
parts: message?.parts || [],
attachments: (message as any)?.attachments || [],
} as ChatMessage;
console.log("[Chat] Saving user message to appendedMessages:", userMessage.id);
setAppendedMessages((prev) => [...prev, userMessage]);
// 调用原始的 sendMessage
return sendMessage(message);
}, [sendMessage]);
// 调试:监控聊天状态变化 & 持久化生成状态 // 调试:监控聊天状态变化 & 持久化生成状态
// 使用 ref 来访问最新的 modelsData,避免依赖数组问题 // 使用 ref 来访问最新的 modelsData,避免依赖数组问题
const modelsDataRef = useRef(modelsData); const modelsDataRef = useRef(modelsData);
@ -430,7 +431,7 @@ export function Chat({
useEffect(() => { useEffect(() => {
if (query && !hasAppendedQuery) { if (query && !hasAppendedQuery) {
sendMessage({ wrappedSendMessage({
role: "user" as const, role: "user" as const,
parts: [{ type: "text", text: query }], parts: [{ type: "text", text: query }],
}); });
@ -1113,7 +1114,7 @@ export function Chat({
isReadonly={isReadonly} isReadonly={isReadonly}
messages={mergedMessages} messages={mergedMessages}
regenerate={regenerate} regenerate={regenerate}
sendMessage={sendMessage} sendMessage={wrappedSendMessage}
selectedModelId={currentModelId} selectedModelId={currentModelId}
setMessages={setMessages} setMessages={setMessages}
status={status} status={status}
@ -1143,7 +1144,7 @@ export function Chat({
onModelChange={setCurrentModelId} onModelChange={setCurrentModelId}
selectedModelId={currentModelId} selectedModelId={currentModelId}
selectedVisibilityType={visibilityType} selectedVisibilityType={visibilityType}
sendMessage={sendMessage} sendMessage={wrappedSendMessage}
setAttachments={setAttachments} setAttachments={setAttachments}
setInput={setInput} setInput={setInput}
setMessages={setMessages} setMessages={setMessages}
@ -1176,7 +1177,7 @@ export function Chat({
regenerate={regenerate} regenerate={regenerate}
selectedModelId={currentModelId} selectedModelId={currentModelId}
selectedVisibilityType={visibilityType} selectedVisibilityType={visibilityType}
sendMessage={sendMessage} sendMessage={wrappedSendMessage}
setAttachments={setAttachments} setAttachments={setAttachments}
setInput={setInput} setInput={setInput}
setMessages={setMessages} setMessages={setMessages}