import type { ChatMessage } from '@/types'; export function messageFingerprint(msg: ChatMessage): string { const attachmentKey = (msg.attachments ?? []) .map((a) => `${a.file_id ?? ''}:${a.name}:${a.content_type}:${a.size ?? ''}`) .join('|'); return `${msg.role}::${String(msg.content)}::${attachmentKey}`; } export function mergeServerWithPendingUsers(serverMessages: ChatMessage[], localMessages: ChatMessage[]): ChatMessage[] { const counts = new Map(); for (const message of serverMessages) { const key = messageFingerprint(message); counts.set(key, (counts.get(key) ?? 0) + 1); } const pendingUsers: ChatMessage[] = []; for (const message of localMessages) { const key = messageFingerprint(message); const count = counts.get(key) ?? 0; if (count > 0) { counts.set(key, count - 1); continue; } if (message.role === 'user') { pendingUsers.push(message); } } return [...serverMessages, ...pendingUsers]; } export function getTaskCardMessageIndexes(messages: ChatMessage[]): Set { const latestByTask = new Map(); messages.forEach((message, index) => { if (message.role !== 'assistant' || !message.task_id) { return; } latestByTask.set(message.task_id, index); }); return new Set(latestByTask.values()); }