From 7565b8676fdcf1e737038bd5ea060c55fd54873d Mon Sep 17 00:00:00 2001 From: Rick Ye Date: Mon, 7 Sep 2026 19:15:17 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=8E=86=E5=8F=B2=E5=9B=9E=E5=90=88?= =?UTF-8?q?=E8=AF=AF=E6=98=BE=E7=A4=BA=E6=B4=BB=E8=B7=83=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E4=B8=8E=E6=B5=81=E5=BC=8F=E6=AE=B5=E9=97=B4=E9=9A=90=E5=BD=A2?= =?UTF-8?q?=E7=A9=BA=E7=99=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/renderer/src/components/ChatView.tsx | 12 +++-- .../renderer/src/components/MessageItem.tsx | 7 ++- .../renderer/src/components/StreamingText.tsx | 46 +++++++++---------- 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/apps/desktop/src/renderer/src/components/ChatView.tsx b/apps/desktop/src/renderer/src/components/ChatView.tsx index d7c9da6..8b03e28 100644 --- a/apps/desktop/src/renderer/src/components/ChatView.tsx +++ b/apps/desktop/src/renderer/src/components/ChatView.tsx @@ -48,13 +48,17 @@ function renderTurns( if (message.role === 'assistant') { let j = i + 1 while (j < messages.length && messages[j].role === 'assistant') j += 1 + // turnActive/streaming 是会话级信号:只有延伸到消息列表末尾的最后一个 + // assistant 组是「活跃回合」。透传给历史回合会让它们误显示 + // 「已工作/处理中」并保持过程区展开。 + const isLive = j === messages.length items.push( ) @@ -65,8 +69,8 @@ function renderTurns( key={message.key} message={message} tools={tools} - streaming={streaming} - turnActive={turnActive} + streaming={streaming && i === messages.length - 1} + turnActive={turnActive && i === messages.length - 1} pendingApprovals={pendingApprovals} /> ) diff --git a/apps/desktop/src/renderer/src/components/MessageItem.tsx b/apps/desktop/src/renderer/src/components/MessageItem.tsx index daccade..170be65 100644 --- a/apps/desktop/src/renderer/src/components/MessageItem.tsx +++ b/apps/desktop/src/renderer/src/components/MessageItem.tsx @@ -177,15 +177,18 @@ export function AssistantTurn({ const streamNodes: ReactNode[] = [] let visibleThinkingRows = 0 if (stream) { - stream.segments.forEach((seg, i) => { + const segments = stream.segments + segments.forEach((seg, i) => { if (seg.kind === 'thinking') { if (!showStreamThinking) return const rows = thinkingRows(seg.text) if (rows.length === 0) return visibleThinkingRows += rows.length + // 该思考段之后已有正文段在流:思考已完成,表头从「思考中…」切回「思考过程」 + const followedByText = segments.some((s, k) => k > i && s.kind === 'text' && s.text.length > 0) streamNodes.push(
- +
) return diff --git a/apps/desktop/src/renderer/src/components/StreamingText.tsx b/apps/desktop/src/renderer/src/components/StreamingText.tsx index 6e8452e..2131a97 100644 --- a/apps/desktop/src/renderer/src/components/StreamingText.tsx +++ b/apps/desktop/src/renderer/src/components/StreamingText.tsx @@ -48,29 +48,29 @@ export function StreamingText({ /> - {/* 操作行:流式结束后淡入 */} -
- -
+ {/* 操作行:流式结束后淡入。流式期间不渲染(opacity:0 也会占位, + * 每个正文段后会挂一块约 32px 的隐形空白,且完成后卸载造成布局跳动) */} + {done && ( +
+ +
+ )} {/* Follow-ups:完成后的跟进问题列表 */} {done && followUps && followUps.length > 0 && (