Skip to content

Commit 3a68169

Browse files
committed
Fix: Branching Message Duplicate Storage
1 parent e108d4d commit 3a68169

File tree

8 files changed

+62
-77
lines changed

8 files changed

+62
-77
lines changed

src/components/chat/ChatMessageArea.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,10 @@ export const ChatMessageArea: React.FC<ChatMessageAreaProps> = ({
3939
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
4040
}, 50);
4141

42-
console.log(activeConversation);
43-
4442
if(activeConversation) {
4543
setMessagesList(MessageHelper.mapMessagesTreeToList(activeConversation));
4644
}
47-
}, [activeConversation?.messages]);
45+
}, [activeConversation, activeConversation?.messages]);
4846

4947
const handleSubmit = (e: FormEvent) => {
5048
e.preventDefault();
@@ -124,7 +122,7 @@ export const ChatMessageArea: React.FC<ChatMessageAreaProps> = ({
124122
}
125123

126124
// Check if there's a streaming message
127-
const hasStreamingMessage = activeConversation.messages.some(m => m.messageId.startsWith('streaming-'));
125+
const hasStreamingMessage = Array.from(activeConversation.messages.values()).some(m => m.messageId.startsWith('streaming-'));
128126

129127
return (
130128
<div className="flex flex-col h-full">

src/pages/ChatPage.tsx

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export const ChatPage: React.FC<ChatPageProps> = ({
2626
const initServices = async () => {
2727
try {
2828
// Initialize chat service
29+
2930
const chatService = ChatService.getInstance();
3031
await chatService.initialize();
3132
chatServiceRef.current = chatService;
@@ -68,14 +69,18 @@ export const ChatPage: React.FC<ChatPageProps> = ({
6869
console.error('Failed to initialize services:', error);
6970
}
7071
};
72+
73+
if(!isServiceInitialized) {
74+
initServices();
75+
}
7176

72-
initServices();
73-
}, [initialSelectedModel]);
77+
}, [initialSelectedModel, isServiceInitialized]);
7478

7579
// Load active conversation details when selected
7680
useEffect(() => {
7781
if (activeConversationId && isServiceInitialized && chatServiceRef.current) {
7882
const loadConversation = async () => {
83+
7984
try {
8085
const chatService = chatServiceRef.current;
8186
if (!chatService) return;
@@ -99,30 +104,6 @@ export const ChatPage: React.FC<ChatPageProps> = ({
99104
}
100105
}, [activeConversationId, isServiceInitialized]);
101106

102-
// Update selected model when initialSelectedModel changes
103-
useEffect(() => {
104-
const selectedModel = SettingsService.getInstance().getSelectedModel();
105-
if (initialSelectedModel && initialSelectedModel !== selectedModel) {
106-
SettingsService.getInstance().setSelectedModel(initialSelectedModel);
107-
}
108-
}, [initialSelectedModel, SettingsService.getInstance().getSelectedModel()]);
109-
110-
// Save selected model to settings when it changes
111-
useEffect(() => {
112-
const selectedModel = SettingsService.getInstance().getSelectedModel();
113-
if (selectedModel && isServiceInitialized) {
114-
const settingsService = SettingsService.getInstance();
115-
const settings = settingsService.getSettings();
116-
117-
if (settings.selectedModel !== selectedModel) {
118-
settingsService.updateSettings({
119-
...settings,
120-
selectedModel: selectedModel
121-
});
122-
}
123-
}
124-
}, [SettingsService.getInstance().getSelectedModel(), isServiceInitialized]);
125-
126107
// Get the active conversation
127108
const activeConversation = activeConversationId
128109
? conversations.find(c => c.id === activeConversationId) || null
@@ -311,7 +292,7 @@ export const ChatPage: React.FC<ChatPageProps> = ({
311292
<div className="flex flex-col flex-1 min-w-0 overflow-hidden">
312293
{isApiKeyMissing && (
313294
<div className="p-2 text-sm text-center text-yellow-800 bg-yellow-100">
314-
Please set your OpenAI API key in the settings to use this model.
295+
Please set your API key for the selected provider in the settings.
315296
</div>
316297
)}
317298

src/services/chat-service.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ export class ChatService {
167167
// Create a placeholder for the streaming message
168168
const placeholderMessage: Message = MessageHelper.getPlaceholderMessage(model, provider, conversationId);
169169

170-
const latestMessage = updatedConversation.messages.length > 0 ? updatedConversation.messages[updatedConversation.messages.length - 1] : null;
170+
const latestMessage = Array.from(updatedConversation.messages.values()).length > 0 ? Array.from(updatedConversation.messages.values())[Array.from(updatedConversation.messages.values()).length - 1] : null;
171171

172172
if(latestMessage) {
173173
latestMessage.childrenMessageIds.push(placeholderMessage.messageId);
@@ -177,7 +177,10 @@ export class ChatService {
177177
// Add placeholder to conversation and update UI
178178
updatedConversation = {
179179
...updatedConversation,
180-
messages: [...updatedConversation.messages, placeholderMessage],
180+
messages: new Map([
181+
...Array.from(updatedConversation.messages.entries()),
182+
[placeholderMessage.messageId, placeholderMessage]
183+
]),
181184
updatedAt: new Date()
182185
};
183186

@@ -273,22 +276,22 @@ export class ChatService {
273276
}
274277

275278
// Find the message
276-
const messageIndex = currentConversation.messages.findIndex(m => m.messageId === messageId);
279+
const messageIndex = Array.from(currentConversation.messages.values()).findIndex(m => m.messageId === messageId);
277280

278281
if (messageIndex === -1) {
279282
throw new Error('Message not found');
280283
}
281284

282285
// Get the original message
283-
const originalMessage = currentConversation.messages[messageIndex];
286+
const originalMessage = Array.from(currentConversation.messages.values())[messageIndex];
284287

285288
// Check if the message is a user message (only user messages can be edited)
286289
if (originalMessage.role !== 'user') {
287290
throw new Error('Only user messages can be edited');
288291
}
289292

290293
const fatherMessageId = originalMessage.fatherMessageId;
291-
const fatherMessage = currentConversation.messages.find(m => m.messageId === fatherMessageId);
294+
const fatherMessage = Array.from(currentConversation.messages.values()).find(m => m.messageId === fatherMessageId);
292295

293296
if(!fatherMessage) {
294297
throw new Error('Father message not found');
@@ -319,7 +322,7 @@ export class ChatService {
319322
// Create a placeholder for the streaming message
320323
const placeholderMessage: Message = MessageHelper.getPlaceholderMessage(model, provider, conversationId);
321324

322-
const latestMessage = updatedConversation.messages.length > 0 ? updatedConversation.messages[updatedConversation.messages.length - 1] : null;
325+
const latestMessage = Array.from(updatedConversation.messages.values()).length > 0 ? Array.from(updatedConversation.messages.values())[Array.from(updatedConversation.messages.values()).length - 1] : null;
323326

324327
if(latestMessage) {
325328
latestMessage.childrenMessageIds.push(placeholderMessage.messageId);
@@ -329,7 +332,10 @@ export class ChatService {
329332
// Add placeholder to conversation and update UI
330333
updatedConversation = {
331334
...updatedConversation,
332-
messages: [...updatedConversation.messages, placeholderMessage],
335+
messages: new Map([
336+
...Array.from(updatedConversation.messages.entries()),
337+
[placeholderMessage.messageId, placeholderMessage]
338+
]),
333339
updatedAt: new Date()
334340
};
335341

@@ -527,7 +533,7 @@ export class ChatService {
527533
}
528534

529535
// Find the last user message
530-
const messages = [...activeConversation.messages];
536+
const messages = Array.from(activeConversation.messages.values());
531537

532538
// Remove the last assistant message
533539
let lastAssistantIndex = -1;
@@ -544,12 +550,12 @@ export class ChatService {
544550
}
545551

546552
// Keep only messages up to the last user message before the assistant response
547-
const updatedMessages = messages.slice(0, lastAssistantIndex);
553+
const updatedMessages = Array.from(activeConversation.messages.values()).slice(0, lastAssistantIndex);
548554

549555
// Create a new conversation state without the last assistant message
550556
const updatedConversation: Conversation = {
551557
...activeConversation,
552-
messages: updatedMessages,
558+
messages: new Map(updatedMessages.map(message => [message.messageId, message])),
553559
updatedAt: new Date()
554560
};
555561

src/services/database-integration.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,6 @@ export class DatabaseIntegrationService {
6666
* Load a specific conversation including all messages
6767
*/
6868
public async loadConversation(conversationId: string): Promise<Conversation | null> {
69-
console.log(`loadConversation: ${conversationId}`);
70-
7169
try {
7270
// Get conversation details
7371
const dbConversations = await this.dbService.getConversations();
@@ -76,12 +74,12 @@ export class DatabaseIntegrationService {
7674

7775
// Get chat messages
7876
const messages = await this.dbService.getChatHistory(conversationId);
79-
77+
8078
// Map to app conversation format
8179
const appConversation = this.mapDbConversationToAppConversation(conversation);
8280

8381
// Add messages
84-
appConversation.messages = messages.map((msg) => this.mapDbMessageToAppMessage(msg));
82+
appConversation.messages = new Map(messages.map((msg) => [msg.messageId, this.mapDbMessageToAppMessage(msg)]));
8583

8684
return appConversation;
8785
} catch (error) {
@@ -117,7 +115,9 @@ export class DatabaseIntegrationService {
117115
await this.dbService.saveChatMessage(systemMessage);
118116

119117
// Add system message to the conversation
120-
dbConversation.messages = [systemMessage];
118+
dbConversation.messages = new Map([
119+
[systemMessage.messageId, systemMessage]
120+
]);
121121

122122
return dbConversation;
123123
} catch (error) {
@@ -141,7 +141,6 @@ export class DatabaseIntegrationService {
141141
childrenMessageIds: string[],
142142
preferIndex: number
143143
): Promise<Message> {
144-
console.log(`saveChatMessage: ${messageId} | conversationId: ${conversationId} | role: ${role} | content: ${content} | provider: ${provider} | model: ${model} | tokens: ${tokens} | fatherMessageId: ${fatherMessageId} | childrenMessageIds: ${childrenMessageIds} | preferIndex: ${preferIndex}`);
145144

146145
try {
147146
// Create message object
@@ -355,8 +354,6 @@ export class DatabaseIntegrationService {
355354
}
356355

357356
private mapDbMessageToAppMessage(dbMessage: Message): Message {
358-
console.log(`mapDbMessageToAppMessage`);
359-
console.log(dbMessage);
360357
return {
361358
...dbMessage,
362359
};

src/services/database.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export class DatabaseService {
4040
autoIncrement: true
4141
});
4242
chatStore.createIndex('conversationId', 'conversationId');
43-
chatStore.createIndex('timestamp', 'timestamp');
43+
chatStore.createIndex('messageId', 'messageId');
4444
}
4545

4646
// Create API settings store
@@ -63,7 +63,7 @@ export class DatabaseService {
6363
title,
6464
createdAt: new Date(),
6565
updatedAt: new Date(),
66-
messages: [],
66+
messages: new Map(),
6767
firstMessageId: null
6868
};
6969

@@ -96,6 +96,7 @@ export class DatabaseService {
9696

9797
const transaction = this.db.transaction('conversations', 'readwrite');
9898
const store = transaction.objectStore('conversations');
99+
console.log(conversation);
99100
const request = store.put(conversation);
100101

101102
request.onsuccess = () => resolve();
@@ -134,14 +135,16 @@ export class DatabaseService {
134135
return new Promise((resolve, reject) => {
135136
if (!this.db) throw new Error('Database not initialized');
136137

138+
console.log(`saveChatMessage: ${message.messageId}`);
139+
137140
const transaction = this.db.transaction(['chatHistory', 'conversations'], 'readwrite');
138141
const chatStore = transaction.objectStore('chatHistory');
139142
const conversationStore = transaction.objectStore('conversations');
140143

141144
// Save the message
142145
const chatRequest = chatStore.add({
143146
...message,
144-
timestamp: new Date()
147+
messageId: message.messageId
145148
});
146149

147150
// Update conversation's last message and timestamp

0 commit comments

Comments
 (0)