UNPKG

@essentialai/cogent-bridge

Version:

Cogent Bridge — cross-agent comms for Claude Code, OpenAI Codex and Slack. Codex users: install with `curl -fsSL https://cogent.tools/install.sh | sh`, then start with `cogent-codex` for real-time peer wake.

109 lines • 3.37 kB
/** * In-memory message inbox with deduplication and timestamp ordering. * * Aggregates messages from both WebSocket push and poll fallback channels. * Deduplicates by message ID (bounded to last 1000 IDs) and maintains * messages ordered by server timestamp for consistent display. */ export class MessageInbox { messages = []; seenIds = new Set(); seenOrder = []; listeners = []; lastMessageId = null; /** * Add a single message to the inbox. * Returns true if the message was new (not a duplicate). */ addMessage(msg) { if (this.seenIds.has(msg.id)) { return false; } // Track for dedup with bounded size this.seenIds.add(msg.id); this.seenOrder.push(msg.id); if (this.seenOrder.length > 1000) { const toRemove = this.seenOrder.shift(); this.seenIds.delete(toRemove); } // Insert maintaining timestamp order. // Messages usually arrive in order, so search from the end. let insertIdx = this.messages.length; for (let i = this.messages.length - 1; i >= 0; i--) { if (this.messages[i].timestamp <= msg.timestamp) { insertIdx = i + 1; break; } if (i === 0) { insertIdx = 0; } } this.messages.splice(insertIdx, 0, msg); // Update lastMessageId to the latest message by timestamp const last = this.messages[this.messages.length - 1]; this.lastMessageId = last.id; // Notify listeners for (const listener of this.listeners) { listener(); } return true; } /** * Add multiple messages at once. * Returns the count of new (non-duplicate) messages added. */ addMessages(msgs) { let count = 0; for (const msg of msgs) { if (this.addMessage(msg)) { count++; } } return count; } /** * Get all unread messages (copy of the internal array). */ getUnread() { return this.messages.slice(); } /** * Mark messages as read by removing them from the unread list. * Does NOT remove from seenIds -- they remain for deduplication. */ markRead(messageIds) { const idsToRemove = new Set(messageIds); this.messages = this.messages.filter((m) => !idsToRemove.has(m.id)); } /** * Get the ID of the last message received (by timestamp order). * Used for poll sync -- pass as lastMessageId query parameter. */ getLastMessageId() { return this.lastMessageId; } /** * Subscribe to new message notifications. * Returns an unsubscribe function. */ onNewMessage(listener) { this.listeners.push(listener); return () => { const idx = this.listeners.indexOf(listener); if (idx !== -1) { this.listeners.splice(idx, 1); } }; } /** * Clear all state: messages, seen IDs, last message ID, and listeners. */ clear() { this.messages = []; this.seenIds = new Set(); this.seenOrder = []; this.lastMessageId = null; this.listeners = []; } } //# sourceMappingURL=message-inbox.js.map