Bugfix: Session 180: Why were streaming assistant responses (SSE) ne...

Documentation for Sessions

🐛 Bugfix: Session 180: Why were streaming assistant responses (SSE) ne...

Date: 2026-03-05
Time: 22:29:19 UTC
Session: gspace1-180.3
Agent: storage
Confidence: 95%
Status: ✅ Documented


📋 Decision Context

Question:

Session 180: Why were streaming assistant responses (SSE) never persisted to MongoDB, only to IndexedDB?

Task: Fix chat message persistence — streaming assistant responses lost


🎯 Decision Made

Chosen:

Added backend sync trigger in VittoChatPersistenceService.updateMessage() when isStreaming transitions to false. The addMessage() call skips sync for streaming messages (isStreaming: true) by design. But when the streaming completes, updateMessage() sets isStreaming: false without ever triggering a backend sync. The finalized message only existed in IndexedDB via autoFlashState debounce.

Options Considered:

  1. Add sync trigger in updateMessage() when isStreaming transitions to false (chosen)
  2. Change addMessage() to always sync regardless of isStreaming
  3. Add a separate finalizeMessage() method that handles both state update and sync
  4. Use an effect() to watch for isStreaming changes and trigger sync

💭 Reasoning

Root cause: Two-phase message lifecycle not wired to sync. Phase 1: addMessage() with isStreaming=true → skipped by line 484 'if (!msg.isStreaming)' check. Phase 2: updateMessage() with {isStreaming: false, content: finalContent} → only updates local autoFlashState signal, no backend call. The user's message (role: user) syncs immediately because it's never streaming. But the assistant's response (role: assistant) is always created as streaming first, finalized later → never synced. Fix: In updateMessage(), when updates.isStreaming === false, find the finalized message in state and call syncService.appendMessages(). This is the only point where we can capture the complete assistant response.


📁 Files Involved


🔗 Related


Auto-generated by MCP Smart Consolidation