← vibesdk
src/routes/chat/utils/deduplicate-messages.ts
2.1 KB
Download file
import type { ChatMessage } from './message-helpers';
/**
* Deduplicates consecutive assistant messages with identical content.
*
* This handles cases where the backend sends duplicate responses after tool execution,
* even when tool messages appear between them.
*
* Algorithm:
* - Keeps all non-assistant messages
* - For each assistant message, checks if the last assistant (not necessarily adjacent) has identical content
* - If duplicate found, skips the current message
*
* @param messages - Array of chat messages to deduplicate
* @returns Deduplicated array of messages
*/
export function deduplicateMessages(messages: readonly ChatMessage[]): ChatMessage[] {
if (messages.length === 0) return [];
const result: ChatMessage[] = [];
let lastAssistantContent: string | null = null;
for (const msg of messages) {
if (msg.role !== 'assistant') {
// Keep all non-assistant messages (user, tool, etc.)
result.push(msg);
continue;
}
// For assistant messages, check against last assistant content
if (lastAssistantContent !== null && msg.content === lastAssistantContent) {
// Skip this duplicate
continue;
}
// Not a duplicate - keep it and update last content
result.push(msg);
lastAssistantContent = msg.content;
}
return result;
}
/**
* Check if a new assistant message would be a duplicate of the last assistant message.
* Used for live streaming to prevent adding duplicates.
*
* @param messages - Current messages array
* @param newContent - Content of the new assistant message
* @returns true if this would be a duplicate, false otherwise
*/
export function isAssistantMessageDuplicate(
messages: readonly ChatMessage[],
newContent: string
): boolean {
// Find the last assistant message
for (let i = messages.length - 1; i >= 0; i--) {
if (messages[i].role === 'assistant') {
return messages[i].content === newContent;
}
}
return false; // No previous assistant message found
}