Fix duplicate gem icon: defer assistant message creation until first token

Instead of pre-creating an empty placeholder assistant message when
streaming starts (which races with GeminiTypingIndicator rendering),
wait until the first SSE token arrives to create the message. This
guarantees only one row is ever visible: either the typing indicator
(before tokens) or the GeminiMessage (after first token).

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
gongzhiyong
2026-04-08 16:45:46 +08:00
co-authored by Claude Sonnet 4.6
parent 743aadb771
commit 3232739a32
+17 -15
View File
@@ -193,23 +193,9 @@ export function GeminiChat() {
);
}
// Create a placeholder AI message for streaming
const aiMsgId = `msg-${Date.now()}-ai`;
const aiMsg: Message = {
id: aiMsgId,
role: "assistant",
content: "",
timestamp: new Date(),
};
const streamConvId = convId;
setConversations((prev) =>
prev.map((c) =>
c.id === streamConvId ? { ...c, messages: [...c.messages, aiMsg] } : c
)
);
abortRef.current = streamChat(
text,
streamConvId,
@@ -220,6 +206,23 @@ export function GeminiChat() {
setConversations((prev) =>
prev.map((c) => {
if (c.id !== streamConvId) return c;
const exists = c.messages.some((m) => m.id === aiMsgId);
if (!exists) {
// First token: create the assistant message
return {
...c,
messages: [
...c.messages,
{
id: aiMsgId,
role: "assistant" as const,
content: event.content!,
timestamp: new Date(),
},
],
};
}
// Subsequent tokens: append to existing message
return {
...c,
messages: c.messages.map((m) =>
@@ -231,7 +234,6 @@ export function GeminiChat() {
})
);
}
// tool_start / tool_end events could be handled here for UI indicators
},
() => {
// on error