From 95b1950bb36c6e2dc6ba0ec27e8175ac1244a042 Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Tue, 15 Sep 2026 12:09:58 +0800 Subject: [PATCH] =?UTF-8?q?fix(ohos):=20=E5=8E=86=E5=8F=B2=E5=88=B7?= =?UTF-8?q?=E6=96=B0=E4=B8=8D=E5=86=8D=E6=95=B4=E8=A1=A8=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=EF=BC=8C=E9=81=BF=E5=85=8D=E5=88=9A=E5=8F=91=E5=87=BA=E7=9A=84?= =?UTF-8?q?=E6=B6=88=E6=81=AF=E5=87=AD=E7=A9=BA=E6=B6=88=E5=A4=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sync_required 触发的 reloadHistory 会与刚发出的 POST 竞争:若历史快照 里还没有这条 user 消息,整表替换会让它消失(“客户端侧发出的消息不显示”)。 改为合并:历史为权威,但保留本地两类消息追加在末尾—— - user 且 source 为空(乐观消息)且内容未出现在历史里; - assistant 且 !isFinal(仍在流式输出)。 --- .../entry/src/main/ets/common/ChatStore.ets | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/cmd/ohos/HomeAgent/entry/src/main/ets/common/ChatStore.ets b/cmd/ohos/HomeAgent/entry/src/main/ets/common/ChatStore.ets index 7dfa88a..f5691ed 100644 --- a/cmd/ohos/HomeAgent/entry/src/main/ets/common/ChatStore.ets +++ b/cmd/ohos/HomeAgent/entry/src/main/ets/common/ChatStore.ets @@ -35,6 +35,36 @@ export const K_CHAT_CONNECTED: string = 'chatSseUp'; const SSE_RECONNECT_MS: number = 5000; +/** + * 把服务端历史与本地消息合并:历史是权威,但本地刚发出、尚未被服务端 + * 回显的消息不能丢。 + * + * 保留两类本地消息,追加在历史末尾: + * - user 且 source 为空(本地乐观消息),且内容未出现在历史里; + * - assistant 且 !isFinal(仍在流式输出)。 + */ +function mergeHistoryWithLocal(history: ChatMessage[], local: ChatMessage[]): ChatMessage[] { + const merged: ChatMessage[] = history.slice(); + for (let i = 0; i < local.length; i++) { + const m: ChatMessage = local[i]; + if (m.role === 'user' && (m.source ?? '').length === 0) { + let dup: boolean = false; + for (let j = 0; j < history.length; j++) { + if (history[j].role === 'user' && history[j].content === m.content) { + dup = true; + break; + } + } + if (!dup) { + merged.push(m); + } + } else if (m.role === 'assistant' && m.isFinal !== true) { + merged.push(m); + } + } + return merged; +} + class ChatStore implements ChatStreamSink { private msgs: ChatMessage[] = []; private nextId: number = 1; @@ -287,7 +317,13 @@ class ChatStore implements ChatStreamSink { if (parsed.msgs.length === 0) { return; } - this.msgs = parsed.msgs; + // 与本地未回显的消息合并,而不是整表替换。 + // + // 为什么:sync_required 触发的 reloadHistory 会与刚发出的 POST 竞争; + // 若历史快照里还没有这条 user 消息,整表替换会让它凭空消失 + // (“客户端侧发出的消息不显示”)。同理,仍在流的助消息也不能被 + // 快照截断。 + this.msgs = mergeHistoryWithLocal(parsed.msgs, this.msgs); this.offset = parsed.offset; this.hasEarlier = parsed.hasMore; this.forceRefresh();