fix: propagate real message IDs via SSE and fix regenerate model parameter

- Add message_id and user_message_id to SSE done events so frontend
  can replace temp IDs with real DB IDs, fixing "消息不存在" on regenerate
- Replace Body(default=None) with RegenerateRequest Pydantic model for
  proper JSON body parsing, fixing 422 Unprocessable Content
- Frontend always sends model in regenerate request body
- Pass selected model through message-item → regenerateMessage chain
- Various UI refinements to chat sidebar, quick questions, and layout

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-27 09:00:31 +08:00
parent 53a9380d7a
commit 0251a5e3ff
10 changed files with 549 additions and 858 deletions
+31 -27
View File
@@ -28,7 +28,7 @@ interface ChatActions {
addMessage: (message: ChatMessage) => void;
updateMessage: (messageId: number, content: string) => void;
editMessage: (messageId: number, newContent: string) => Promise<void>;
regenerateMessage: (messageId: number) => Promise<void>;
regenerateMessage: (messageId: number, model?: string) => Promise<void>;
feedbackMessage: (messageId: number, feedback: "like" | "dislike") => Promise<void>;
stopGeneration: () => void;
@@ -228,12 +228,6 @@ export const useChatStore = create<ChatStore>((set, get) => ({
// 创建新的 AbortController
const abortController = new AbortController();
console.log("[DEBUG-CHAT] 开始流式发送:", {
message: message,
sessionId: currentSession.id,
knowledgeBaseIds: knowledgeBaseIds
});
set({ isStreaming: true, error: null, abortController });
// 添加用户消息
@@ -299,8 +293,7 @@ export const useChatStore = create<ChatStore>((set, get) => ({
// 处理内容chunk
chunkCount++;
totalChars += data.content.length;
console.log(`[DEBUG-STREAM] 接收并显示chunk ${chunkCount}:`, data.content);
requestAnimationFrame(() => {
set((state) => ({
messages: state.messages.map(msg =>
@@ -315,8 +308,7 @@ export const useChatStore = create<ChatStore>((set, get) => ({
// 向后兼容:纯文本chunk
chunkCount++;
totalChars += chunk.length;
console.log(`[DEBUG-STREAM] 接收并显示chunk ${chunkCount}:`, chunk);
requestAnimationFrame(() => {
set((state) => ({
messages: state.messages.map(msg =>
@@ -328,17 +320,30 @@ export const useChatStore = create<ChatStore>((set, get) => ({
});
}
},
(sessionId: number) => {
// 流式完成,直接处理
console.log(`[DEBUG-STREAM] 流式完成 - 总chunk数: ${chunkCount}, 总字符数: ${totalChars}`);
set({ isStreaming: false, abortController: null });
(sessionId: number, messageId?: number, userMessageId?: number) => {
if (messageId) {
set((state) => ({
messages: state.messages.map(msg => {
if (msg.id === assistantMessage.id) return { ...msg, id: messageId };
if (userMessageId && msg.id === userMessage.id) return { ...msg, id: userMessageId };
return msg;
}),
isStreaming: false,
abortController: null,
}));
} else {
const { currentSession } = get();
if (currentSession) {
get().loadMessages(currentSession.id);
}
set({ isStreaming: false, abortController: null });
}
// 刷新会话列表以确保新会话显示在顶部
get().loadSessions();
},
(error: string) => {
// 流式错误
console.log("[DEBUG-STREAM] 流式错误:", error);
set({ error, isStreaming: false, abortController: null });
},
undefined, // onStatus
@@ -409,20 +414,20 @@ export const useChatStore = create<ChatStore>((set, get) => ({
}
},
// 重新生成消息
regenerateMessage: async (messageId: number) => {
// 重新生成消息(支持 assistant 消息 ID
regenerateMessage: async (messageId: number, model?: string) => {
try {
set({ isLoading: true, error: null });
const response = await chatAPI.regenerateMessage(messageId);
// 删除该消息之后的所有消息
const response = await chatAPI.regenerateMessage(messageId, model);
// 找到该消息,删除它及之后的所有消息
const messageIndex = get().messages.findIndex(msg => msg.id === messageId);
if (messageIndex !== -1) {
set((state) => ({
messages: state.messages.slice(0, messageIndex + 1),
messages: state.messages.slice(0, messageIndex),
}));
}
// 添加新的助手回复
const newMessage: ChatMessage = {
id: response.new_message_id,
@@ -430,7 +435,7 @@ export const useChatStore = create<ChatStore>((set, get) => ({
content: response.content,
created_at: new Date().toISOString(),
};
set((state) => ({
messages: [...state.messages, newMessage],
isLoading: false,
@@ -465,9 +470,8 @@ export const useChatStore = create<ChatStore>((set, get) => ({
// 如果存在 AbortController,调用 abort 中止请求
if (abortController) {
abortController.abort();
console.log("[DEBUG-STOP] 已中止流式请求");
}
// 清理状态
set({ isStreaming: false, abortController: null });
},