From cf72540bc9caa682ff9607ded87f868a3cf03a3c Mon Sep 17 00:00:00 2001 From: wuyang6 Date: Thu, 14 May 2026 20:38:24 +0800 Subject: [PATCH] Guard reasoning deltas after visible output --- frontend/app/app/api/chat/route.ts | 79 ++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 25 deletions(-) diff --git a/frontend/app/app/api/chat/route.ts b/frontend/app/app/api/chat/route.ts index 5b37523..19571d8 100644 --- a/frontend/app/app/api/chat/route.ts +++ b/frontend/app/app/api/chat/route.ts @@ -484,20 +484,28 @@ function writeRuntimeEvent( if (event.type === "run_queued") { if (streamState) streamState.phase = "queued"; if (streamState && event.run_id) streamState.runId = event.run_id; - writer.write({ - type: "reasoning-delta", - id: "reasoning-1", - delta: "\n当前会话已有任务在执行,本轮正在排队。", - }); + writeReasoningDelta( + writer, + { + type: "reasoning-delta", + id: "reasoning-1", + delta: "\n当前会话已有任务在执行,本轮正在排队。", + }, + streamState, + ); } if (event.type === "run_started") { if (streamState) streamState.phase = "running"; if (streamState && event.run_id) streamState.runId = event.run_id; - writer.write({ - type: "reasoning-delta", - id: "reasoning-1", - delta: "\n后端已开始执行本轮任务。", - }); + writeReasoningDelta( + writer, + { + type: "reasoning-delta", + id: "reasoning-1", + delta: "\n后端已开始执行本轮任务。", + }, + streamState, + ); } if (event.type === "server_heartbeat") { const elapsed = @@ -505,11 +513,15 @@ function writeRuntimeEvent( ? `,已等待 ${formatDuration(event.elapsed_ms)}` : ""; const phase = streamState?.phase === "queued" ? "仍在排队" : "后端仍在处理"; - writer.write({ - type: "reasoning-delta", - id: "reasoning-1", - delta: `\n${phase}${elapsed}。`, - }); + writeReasoningDelta( + writer, + { + type: "reasoning-delta", + id: "reasoning-1", + delta: `\n${phase}${elapsed}。`, + }, + streamState, + ); } if (event.type === "content_delta" && event.delta) { if (!streamState?.textStarted) { @@ -531,11 +543,15 @@ function writeRuntimeEvent( : `index:${event.tool_call_index}`); if (key && !streamState?.announcedToolCallKeys.has(key)) { streamState?.announcedToolCallKeys.add(key); - writer.write({ - type: "reasoning-delta", - id: "reasoning-1", - delta: `\n准备调用 ${event.tool_name ?? "工具"}。`, - }); + writeReasoningDelta( + writer, + { + type: "reasoning-delta", + id: "reasoning-1", + delta: `\n准备调用 ${event.tool_name ?? "工具"}。`, + }, + streamState, + ); } } if (event.type === "final_text_start") { @@ -576,11 +592,15 @@ function writeRuntimeEvent( }); } if (event.type === "tool_delta" && event.tool_call_id && event.delta) { - writer.write({ - type: "reasoning-delta", - id: "reasoning-1", - delta: `\n${event.tool_name ?? "tool"} 输出中...`, - }); + writeReasoningDelta( + writer, + { + type: "reasoning-delta", + id: "reasoning-1", + delta: `\n${event.tool_name ?? "tool"} 输出中...`, + }, + streamState, + ); } if (event.type === "tool_result" && event.tool_call_id) { const preview = event.metadata?.output_preview; @@ -597,6 +617,15 @@ function writeRuntimeEvent( } } +function writeReasoningDelta( + writer: UIMessageStreamWriter, + part: Parameters["write"]>[0], + streamState?: StreamState, +) { + if (streamState?.reasoningEnded) return; + writer.write(part); +} + function formatClawResponse(payload: ClawChatResponse) { if (payload.error) return payload.error; return payload.final_output ?? "";