diff --git a/frontend/app/app/api/chat/route.ts b/frontend/app/app/api/chat/route.ts index e61b4d1..5b37523 100644 --- a/frontend/app/app/api/chat/route.ts +++ b/frontend/app/app/api/chat/route.ts @@ -53,6 +53,7 @@ type ClawStreamItem = type StreamState = { textStarted: boolean; textStreamed: boolean; + reasoningEnded: boolean; phase: "waiting" | "queued" | "running" | "done"; runId?: string; announcedToolCallKeys: Set; @@ -111,6 +112,7 @@ export async function POST(req: Request) { const streamState: StreamState = { textStarted: false, textStreamed: false, + reasoningEnded: false, phase: "waiting", announcedToolCallKeys: new Set(), streamedToolCallIds: new Set(), @@ -138,12 +140,15 @@ export async function POST(req: Request) { const elapsedMs = payload.elapsed_ms ?? Date.now() - startedAt; const text = formatClawResponse(payload); - writer.write({ - type: "reasoning-delta", - id: "reasoning-1", - delta: `\n思考并执行完成,用时 ${formatDuration(elapsedMs)}。`, - }); - writer.write({ type: "reasoning-end", id: "reasoning-1" }); + if (!streamState.reasoningEnded) { + writer.write({ + type: "reasoning-delta", + id: "reasoning-1", + delta: `\n思考并执行完成,用时 ${formatDuration(elapsedMs)}。`, + }); + writer.write({ type: "reasoning-end", id: "reasoning-1" }); + streamState.reasoningEnded = true; + } writeToolTrace(writer, payload.transcript, streamState); if (!streamState.textStreamed) { writer.write({ type: "text-start", id: "text-1" }); @@ -508,6 +513,10 @@ function writeRuntimeEvent( } if (event.type === "content_delta" && event.delta) { if (!streamState?.textStarted) { + if (streamState && !streamState.reasoningEnded) { + writer.write({ type: "reasoning-end", id: "reasoning-1" }); + streamState.reasoningEnded = true; + } writer.write({ type: "text-start", id: "text-1" }); if (streamState) streamState.textStarted = true; } @@ -531,12 +540,20 @@ function writeRuntimeEvent( } if (event.type === "final_text_start") { if (!streamState?.textStarted) { + if (streamState && !streamState.reasoningEnded) { + writer.write({ type: "reasoning-end", id: "reasoning-1" }); + streamState.reasoningEnded = true; + } writer.write({ type: "text-start", id: "text-1" }); if (streamState) streamState.textStarted = true; } } if (event.type === "final_text_delta" && event.delta) { if (!streamState?.textStarted) { + if (streamState && !streamState.reasoningEnded) { + writer.write({ type: "reasoning-end", id: "reasoning-1" }); + streamState.reasoningEnded = true; + } writer.write({ type: "text-start", id: "text-1" }); if (streamState) streamState.textStarted = true; }