fix: 修复 AI 消息渲染顺序错乱和搜索结果卡片重复问题
有 tool_calls 的中间 AI 消息不再渲染独立 MessageBubble 正文气泡, thinking 内容移至 ToolCallStatus 上方作为步骤说明, 最终 AI 消息(无 tool_calls)才渲染 MessageBubble,确保工具步骤在前、正文回答在后。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
7d035b21b7
commit
bfcf22d4f8
+22
-13
@@ -913,24 +913,19 @@ function App() {
|
||||
const toolCalls: { name?: string; id?: string }[] = (message as any).tool_calls ?? [];
|
||||
const isLastAi = idx === lastAiIdx;
|
||||
|
||||
const hasToolCalls = toolCalls.length > 0;
|
||||
|
||||
return (
|
||||
<div key={message.id ?? idx} className="flex flex-col gap-3">
|
||||
{/* Text reply — rendered first so user sees conclusion before evidence */}
|
||||
{(plainTextContent || hasThinking) && (
|
||||
<div className="group relative max-w-[85%] rounded-2xl rounded-bl-sm bg-muted text-foreground px-4 py-2.5 text-sm">
|
||||
<MessageBubble content={bubbleContent} role="ai" isStreaming={thread.isLoading && isLastAi} />
|
||||
{thread.isLoading && isLastAi && (
|
||||
<span className="typing-cursor" aria-hidden="true" />
|
||||
)}
|
||||
{/* Copy button */}
|
||||
<div className="flex justify-end mt-1">
|
||||
<CopyButton text={plainTextContent} />
|
||||
</div>
|
||||
{/* Tool call status (with inline expand/collapse for UI cards) */}
|
||||
{/* Thinking block for intermediate messages (with tool_calls): shown above tool status */}
|
||||
{hasThinking && hasToolCalls && (
|
||||
<div className="max-w-[85%]">
|
||||
<MessageBubble content={bubbleContent} role="ai" isStreaming={false} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Tool call status (with inline expand/collapse for UI cards) */}
|
||||
{toolCalls.length > 0 && (
|
||||
{hasToolCalls && (
|
||||
<ToolCallStatus
|
||||
toolCalls={toolCalls}
|
||||
isLoading={thread.isLoading}
|
||||
@@ -943,6 +938,20 @@ function App() {
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Text reply — only for final AI messages without tool_calls */}
|
||||
{(plainTextContent || hasThinking) && !hasToolCalls && (
|
||||
<div className="group relative max-w-[85%] rounded-2xl rounded-bl-sm bg-muted text-foreground px-4 py-2.5 text-sm">
|
||||
<MessageBubble content={bubbleContent} role="ai" isStreaming={thread.isLoading && isLastAi} />
|
||||
{thread.isLoading && isLastAi && (
|
||||
<span className="typing-cursor" aria-hidden="true" />
|
||||
)}
|
||||
{/* Copy button */}
|
||||
<div className="flex justify-end mt-1">
|
||||
<CopyButton text={plainTextContent} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* UI cards not matched to any tool call (standalone) */}
|
||||
{(() => {
|
||||
const standaloneUiItems = uiItems.filter((ui) => !toolCalls.some((tc) => {
|
||||
|
||||
Reference in New Issue
Block a user