浏览代码

fix(chat): 恢复 AI 对话流式内容逐字显示

commit fe300b8 升级 AI 会话 Agent 流程时移除了 onText 中的 setStreamingContent 调用,导致 streamingContents 永不更新、StreamingMessage 永不渲染,用户看不到逐字显示。修复:onText 只调用 appendStreamToken 更新 streamingContents(不更新 message.content 避免与 StreamingMessage 重复渲染);onDone 用 streamingContents 填充 message.content;停止和出错路径也用 streamingContents 保留已生成内容。
Mochocyang 2 月之前
父节点
当前提交
8f01eb7c9c
共有 1 个文件被更改,包括 13 次插入 和 5 次删除
  1. 13 5
      src/components/chat/chat-panel.tsx

+ 13 - 5
src/components/chat/chat-panel.tsx

@@ -788,6 +788,7 @@ export function ChatPanel() {
   const runStates = useChatStore((s) => s.runStates)
   const runStates = useChatStore((s) => s.runStates)
   const mode = useChatStore((s) => s.mode)
   const mode = useChatStore((s) => s.mode)
   const startStreaming = useChatStore((s) => s.startStreaming)
   const startStreaming = useChatStore((s) => s.startStreaming)
+  const appendStreamToken = useChatStore((s) => s.appendStreamToken)
   const finalizeStream = useChatStore((s) => s.finalizeStream)
   const finalizeStream = useChatStore((s) => s.finalizeStream)
   const clearStreaming = useChatStore((s) => s.clearStreaming)
   const clearStreaming = useChatStore((s) => s.clearStreaming)
   const createConversation = useChatStore((s) => s.createConversation)
   const createConversation = useChatStore((s) => s.createConversation)
@@ -1771,10 +1772,7 @@ export function ChatPanel() {
           callbacks: {
           callbacks: {
             onText: (chunk: string) => {
             onText: (chunk: string) => {
               if (!streamSessionGuardRef.current.isActive(capturedConvId, sessionId)) return
               if (!streamSessionGuardRef.current.isActive(capturedConvId, sessionId)) return
-              updateAgentAssistantMessage(assistantMessage.id, (message) => ({
-                ...message,
-                content: message.content + chunk,
-              }))
+              appendStreamToken(chunk, capturedConvId)
             },
             },
               onToolEvent: (event) => {
               onToolEvent: (event) => {
                 if (contextTrace) {
                 if (contextTrace) {
@@ -1797,8 +1795,10 @@ export function ChatPanel() {
               },
               },
               onDone: () => {
               onDone: () => {
               if (!streamSessionGuardRef.current.isActive(capturedConvId, sessionId)) return
               if (!streamSessionGuardRef.current.isActive(capturedConvId, sessionId)) return
+              const finalContent = useChatStore.getState().streamingContents[capturedConvId] ?? ""
               updateAgentAssistantMessage(assistantMessage.id, (message) => ({
               updateAgentAssistantMessage(assistantMessage.id, (message) => ({
                 ...message,
                 ...message,
+                content: finalContent,
                 isAgentRunning: false,
                 isAgentRunning: false,
               }))
               }))
             },
             },
@@ -1991,7 +1991,15 @@ export function ChatPanel() {
         if (controller.signal.aborted) return
         if (controller.signal.aborted) return
         if (!streamSessionGuardRef.current.isActive(capturedConvId, sessionId)) return
         if (!streamSessionGuardRef.current.isActive(capturedConvId, sessionId)) return
         const errorMessage = error instanceof Error ? error.message : String(error)
         const errorMessage = error instanceof Error ? error.message : String(error)
+        const partialContent = useChatStore.getState().streamingContents[capturedConvId] ?? ""
         finishAgentSession(() => {
         finishAgentSession(() => {
+          if (partialContent) {
+            updateAgentAssistantMessage(assistantMessage.id, (message) => ({
+              ...message,
+              content: partialContent,
+              isAgentRunning: false,
+            }))
+          }
           if (contextTrace) contextTrace = finishTrace(contextTrace, "error", errorMessage)
           if (contextTrace) contextTrace = finishTrace(contextTrace, "error", errorMessage)
           markError(error instanceof Error ? error : new Error(String(error)))
           markError(error instanceof Error ? error : new Error(String(error)))
         })
         })
@@ -2058,7 +2066,7 @@ export function ChatPanel() {
         if (runningAssistant) {
         if (runningAssistant) {
           updateAgentAssistantMessage(runningAssistant.id, (message) => ({
           updateAgentAssistantMessage(runningAssistant.id, (message) => ({
             ...message,
             ...message,
-            content: message.content ? `${message.content}\n\n已停止生成。` : "已停止生成。",
+            content: currentStreamingContent ? `${currentStreamingContent}\n\n已停止生成。` : "已停止生成。",
             agentToolCalls: settleRunningAgentToolCalls(message.agentToolCalls, "cancelled"),
             agentToolCalls: settleRunningAgentToolCalls(message.agentToolCalls, "cancelled"),
             agentStages: settleRunningAgentStages(message.agentStages, "cancelled"),
             agentStages: settleRunningAgentStages(message.agentStages, "cancelled"),
             isAgentRunning: false,
             isAgentRunning: false,