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 @@