From e57b4b7d9acb2a120416531ef00bdfb0bc062d5c Mon Sep 17 00:00:00 2001 From: ViperEkura <3081035982@qq.com> Date: Thu, 26 Mar 2026 21:32:29 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=20message=20thin?= =?UTF-8?q?king=20=E5=AD=97=E6=AE=B5=E5=B9=B6=E4=BF=AE=E5=A4=8D=E6=B5=81?= =?UTF-8?q?=E5=BC=8F=E6=B8=B2=E6=9F=93=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/services/chat.py | 5 +- docs/Design.md | 2 - frontend/src/App.vue | 6 +- frontend/src/api/index.js | 10 +-- frontend/src/components/ChatView.vue | 2 - frontend/src/components/MessageBubble.vue | 1 - frontend/src/components/ProcessBlock.vue | 80 ++++++----------------- 7 files changed, 31 insertions(+), 75 deletions(-) diff --git a/backend/services/chat.py b/backend/services/chat.py index 6061469..4c0af58 100644 --- a/backend/services/chat.py +++ b/backend/services/chat.py @@ -64,8 +64,8 @@ class ChatService: msg_id = str(uuid.uuid4()) tool_calls_list = [] - # Send thinking_start event to clear previous thinking in frontend - yield f"event: thinking_start\ndata: {{}}\n\n" + # Clear state for new iteration + # (frontend resets via onProcessStep when first step arrives) try: with app.app_context(): @@ -102,7 +102,6 @@ class ChatService: reasoning = delta.get("reasoning_content", "") if reasoning: full_thinking += reasoning - yield f"event: thinking\ndata: {json.dumps({'content': reasoning}, ensure_ascii=False)}\n\n" # Accumulate text content for this iteration text = delta.get("content", "") diff --git a/docs/Design.md b/docs/Design.md index 6518862..bf9b419 100644 --- a/docs/Design.md +++ b/docs/Design.md @@ -465,8 +465,6 @@ def process_tool_calls(self, tool_calls, context=None): | 事件 | 说明 | |------|------| -| `thinking_start` | 新一轮思考开始,前端应清空之前的思考缓冲 | -| `thinking` | 思维链增量内容(启用时) | | `message` | 回复内容的增量片段 | | `tool_calls` | 工具调用信息 | | `tool_result` | 工具执行结果 | diff --git a/frontend/src/App.vue b/frontend/src/App.vue index e3ce5ed..f316a9d 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -44,7 +44,6 @@ :messages="messages" :streaming="streaming" :streaming-content="streamContent" - :streaming-tool-calls="streamToolCalls" :streaming-process-steps="streamProcessSteps" :has-more-messages="hasMoreMessages" :loading-more="loadingMessages" @@ -342,6 +341,11 @@ function createStreamCallbacks(convId, { updateConvList = true } = {}) { steps[step.index] = step return steps }) + // When text is finalized as a process_step, reset streaming content + // to prevent duplication (the text is now rendered via processSteps). + if (step.type === 'text') { + updateStreamField(convId, 'streamContent', streamContent, () => '') + } }, async onDone(data) { streamStates.delete(convId) diff --git a/frontend/src/api/index.js b/frontend/src/api/index.js index 8c960b0..dae4a07 100644 --- a/frontend/src/api/index.js +++ b/frontend/src/api/index.js @@ -29,10 +29,10 @@ async function request(url, options = {}) { * Shared SSE stream processor - parses SSE events and dispatches to callbacks * @param {string} url - API URL (without BASE prefix) * @param {object} body - Request body - * @param {object} callbacks - Event handlers: { onThinkingStart, onThinking, onMessage, onToolCalls, onToolResult, onProcessStep, onDone, onError } + * @param {object} callbacks - Event handlers: { onMessage, onToolCalls, onToolResult, onProcessStep, onDone, onError } * @returns {{ abort: () => void }} */ -function createSSEStream(url, body, { onThinkingStart, onThinking, onMessage, onToolCalls, onToolResult, onProcessStep, onDone, onError }) { +function createSSEStream(url, body, { onMessage, onToolCalls, onToolResult, onProcessStep, onDone, onError }) { const controller = new AbortController() const promise = (async () => { @@ -67,11 +67,7 @@ function createSSEStream(url, body, { onThinkingStart, onThinking, onMessage, on currentEvent = line.slice(7).trim() } else if (line.startsWith('data: ')) { const data = JSON.parse(line.slice(6)) - if (currentEvent === 'thinking_start' && onThinkingStart) { - onThinkingStart() - } else if (currentEvent === 'thinking' && onThinking) { - onThinking(data.content) - } else if (currentEvent === 'message' && onMessage) { + if (currentEvent === 'message' && onMessage) { onMessage(data.content) } else if (currentEvent === 'tool_calls' && onToolCalls) { onToolCalls(data.calls) diff --git a/frontend/src/components/ChatView.vue b/frontend/src/components/ChatView.vue index 624dc18..f3703af 100644 --- a/frontend/src/components/ChatView.vue +++ b/frontend/src/components/ChatView.vue @@ -47,7 +47,6 @@