mirror of
https://github.com/memohai/Memoh.git
synced 2026-04-25 07:00:48 +09:00
fix(web): prevent duplicate assistant message after refresh with tool-call sequences
When messages like [assistant(tool_calls), tool, assistant(text)] are merged into a single ChatMessage by convertMessagesToChats, the merged message uses the first assistant's ID. The SSE /messages/events backlog (which uses >= for the since filter) could re-deliver the final assistant message, and hasMessageWithId failed to recognize it because the merged ID was different. This caused the last assistant message to appear twice after a page refresh. Track all original server message IDs in a Set (knownServerMessageIds) so that hasMessageWithId can catch messages whose IDs were absorbed during merging.
This commit is contained in:
@@ -112,6 +112,7 @@ export const useChatStore = defineStore('chat', () => {
|
|||||||
let abortFn: (() => void) | null = null
|
let abortFn: (() => void) | null = null
|
||||||
let messageEventsSince = ''
|
let messageEventsSince = ''
|
||||||
let pendingAssistantStream: PendingAssistantStream | null = null
|
let pendingAssistantStream: PendingAssistantStream | null = null
|
||||||
|
const knownServerMessageIds = new Set<string>()
|
||||||
const messageEventsStream = useRetryingStream()
|
const messageEventsStream = useRetryingStream()
|
||||||
const localStream = useRetryingStream()
|
const localStream = useRetryingStream()
|
||||||
let activeWs: ChatWebSocket | null = null
|
let activeWs: ChatWebSocket | null = null
|
||||||
@@ -342,8 +343,19 @@ export const useChatStore = defineStore('chat', () => {
|
|||||||
|
|
||||||
// ---- Message list management ----
|
// ---- Message list management ----
|
||||||
|
|
||||||
function replaceMessages(items: ChatMessage[]) {
|
function replaceMessages(items: ChatMessage[], serverRowIds?: string[]) {
|
||||||
messages.splice(0, messages.length, ...items)
|
messages.splice(0, messages.length, ...items)
|
||||||
|
knownServerMessageIds.clear()
|
||||||
|
for (const item of items) {
|
||||||
|
const tid = String(item.id ?? '').trim()
|
||||||
|
if (tid) knownServerMessageIds.add(tid)
|
||||||
|
}
|
||||||
|
if (serverRowIds) {
|
||||||
|
for (const id of serverRowIds) {
|
||||||
|
const tid = id.trim()
|
||||||
|
if (tid) knownServerMessageIds.add(tid)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- SSE real-time events ----
|
// ---- SSE real-time events ----
|
||||||
@@ -580,7 +592,9 @@ export const useChatStore = defineStore('chat', () => {
|
|||||||
|
|
||||||
function hasMessageWithId(id: string) {
|
function hasMessageWithId(id: string) {
|
||||||
const tid = id.trim()
|
const tid = id.trim()
|
||||||
return tid ? messages.some((m) => String(m.id).trim() === tid) : false
|
if (!tid) return false
|
||||||
|
if (knownServerMessageIds.has(tid)) return true
|
||||||
|
return messages.some((m) => String(m.id).trim() === tid)
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveMessagePlatform(raw: Message): string {
|
function resolveMessagePlatform(raw: Message): string {
|
||||||
@@ -667,7 +681,8 @@ export const useChatStore = defineStore('chat', () => {
|
|||||||
async function loadMessages(botId: string, sid: string) {
|
async function loadMessages(botId: string, sid: string) {
|
||||||
const rows = await fetchMessages(botId, sid, { limit: PAGE_SIZE })
|
const rows = await fetchMessages(botId, sid, { limit: PAGE_SIZE })
|
||||||
const items = convertMessagesToChats(rows)
|
const items = convertMessagesToChats(rows)
|
||||||
replaceMessages(items)
|
const serverRowIds = rows.map((r) => r.id).filter(Boolean)
|
||||||
|
replaceMessages(items, serverRowIds)
|
||||||
hasMoreOlder.value = true
|
hasMoreOlder.value = true
|
||||||
updateSinceFromRows(rows)
|
updateSinceFromRows(rows)
|
||||||
}
|
}
|
||||||
@@ -685,6 +700,14 @@ export const useChatStore = defineStore('chat', () => {
|
|||||||
const rows = await fetchMessages(bid, sid, { limit: PAGE_SIZE, before })
|
const rows = await fetchMessages(bid, sid, { limit: PAGE_SIZE, before })
|
||||||
const items = convertMessagesToChats(rows)
|
const items = convertMessagesToChats(rows)
|
||||||
if (rows.length < PAGE_SIZE) hasMoreOlder.value = false
|
if (rows.length < PAGE_SIZE) hasMoreOlder.value = false
|
||||||
|
for (const r of rows) {
|
||||||
|
const tid = (r.id ?? '').trim()
|
||||||
|
if (tid) knownServerMessageIds.add(tid)
|
||||||
|
}
|
||||||
|
for (const item of items) {
|
||||||
|
const tid = String(item.id ?? '').trim()
|
||||||
|
if (tid) knownServerMessageIds.add(tid)
|
||||||
|
}
|
||||||
messages.unshift(...items)
|
messages.unshift(...items)
|
||||||
return items.length
|
return items.length
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
Reference in New Issue
Block a user