A React Native app for the ultimate thinking partner.

fix: reload sufficient message history after streaming completes

Fixed issue where only middle portion of message history was visible
after streaming, missing both newest and oldest messages.

Root cause:
- Previous fix only fetched 10 most recent messages after streaming
- If user had loaded more messages via scroll, we'd lose them
- Temp user message (id: temp-*) wasn't being removed
- Insufficient messages fetched from server after completion

Solution:
- Count current loaded messages (excluding temp messages)
- Fetch at least currentCount + 5, minimum 50 messages
- Replace messages entirely (removes temp duplicates)
- Increased server finalization delay from 300ms to 500ms

Now preserves full message history while properly updating with
finalized versions from server that include reasoning and metadata.

Example: If user had scrolled to load 80 messages, we now fetch
85 messages after streaming instead of just 10.

+13 -19
+13 -19
App.tsx
··· 696 696 // Wait for server to finalize messages 697 697 setTimeout(async () => { 698 698 try { 699 - // Fetch recent messages to get finalized versions 699 + // Count how many messages we currently have (excluding temp messages) 700 + const currentCount = messages.filter(msg => !msg.id.startsWith('temp-')).length; 701 + const fetchLimit = Math.max(currentCount + 5, 50); // Fetch at least current count + some buffer 702 + 703 + console.log('[STREAM COMPLETE] Current message count:', currentCount, 'Fetching:', fetchLimit); 704 + 705 + // Fetch recent messages with enough limit to cover what we had plus new ones 700 706 const recentMessages = await lettaApi.listMessages(coAgent.id, { 701 - limit: 10, 707 + limit: fetchLimit, 702 708 use_assistant_message: true, 703 709 }); 704 710 705 - if (recentMessages.length > 0) { 706 - setMessages(prev => { 707 - // Create a map of existing messages by ID 708 - const messageMap = new Map(prev.map(msg => [msg.id, msg])); 709 - 710 - // Add/update with recent messages 711 - recentMessages.forEach(msg => { 712 - messageMap.set(msg.id, msg); 713 - }); 714 - 715 - // Convert back to array and sort by timestamp 716 - const merged = Array.from(messageMap.values()).sort((a, b) => { 717 - return new Date(a.created_at || 0).getTime() - new Date(b.created_at || 0).getTime(); 718 - }); 711 + console.log('[STREAM COMPLETE] Received', recentMessages.length, 'messages from server'); 719 712 720 - return filterFirstMessage(merged); 721 - }); 713 + if (recentMessages.length > 0) { 714 + // Replace messages entirely with server response (this removes temp messages) 715 + setMessages(filterFirstMessage(recentMessages)); 722 716 } 723 717 } catch (error) { 724 718 console.error('Failed to fetch finalized messages:', error); ··· 727 721 setIsStreaming(false); 728 722 setCurrentStream({ reasoning: '', toolCalls: [], assistantMessage: '' }); 729 723 } 730 - }, 300); 724 + }, 500); 731 725 }, 732 726 (error) => { 733 727 console.error('=== APP STREAMING ERROR CALLBACK ===');