diff --git a/src/routes/api/llm.ts b/src/routes/api/llm.ts index 567055b10..4f4a226e5 100644 --- a/src/routes/api/llm.ts +++ b/src/routes/api/llm.ts @@ -837,10 +837,22 @@ async function streamMessage(req: Request, res: Response) { throw new Error('Content cannot be empty'); } - // Check if session exists - const session = restChatService.getSessions().get(sessionId); + // Check if session exists in memory + let session = restChatService.getSessions().get(sessionId); + + // If session doesn't exist in memory, try to recreate it from the Chat Note if (!session) { - throw new Error('Session not found'); + log.info(`Session ${sessionId} not found in memory, attempting to restore from Chat Note`); + + const restoredSession = await restChatService.restoreSessionFromChatNote(sessionId); + + if (!restoredSession) { + // If we can't find the Chat Note either, then it's truly not found + log.error(`Chat Note ${sessionId} not found, cannot restore session`); + throw new Error('Session not found and no corresponding Chat Note exists'); + } + + session = restoredSession; } // Update last active timestamp diff --git a/src/services/llm/chat/rest_chat_service.ts b/src/services/llm/chat/rest_chat_service.ts index 36b824892..3890f31c7 100644 --- a/src/services/llm/chat/rest_chat_service.ts +++ b/src/services/llm/chat/rest_chat_service.ts @@ -18,6 +18,8 @@ import SessionsStore from "./sessions_store.js"; import * as MessageFormatter from "./utils/message_formatter.js"; import type { NoteSource } from "./interfaces/session.js"; import type { LLMStreamMessage } from "./interfaces/ws_messages.js"; +import type { ChatMessage } from '../chat/interfaces/session.js'; +import type { ChatSession } from '../chat/interfaces/session.js'; /** * Service to handle chat API interactions @@ -124,16 +126,34 @@ class RestChatService { if (!session) { if (req.method === 'GET') { - // For GET requests, we must have an existing session - throw new Error('Session not found'); - } + // For GET requests, we should try to restore from Chat Note + log.info(`Session ${sessionId} not found in memory for GET request, attempting to restore from Chat Note`); - // For POST requests, we can create a new session automatically - log.info(`Session ${sessionId} not found, creating a new one automatically`); - session = SessionsStore.createSession({ - title: 'Auto-created Session' - }); - log.info(`Created new session with ID: ${session.id}`); + const restoredSession = await this.restoreSessionFromChatNote(sessionId); + + if (!restoredSession) { + // If we still can't find the Chat Note, throw error + throw new Error('Session not found and no corresponding Chat Note exists'); + } + + session = restoredSession; + } else { + // For POST requests, we can create a new session, or try to restore from Chat Note + log.info(`Session ${sessionId} not found for POST request, checking if Chat Note exists`); + + const restoredSession = await this.restoreSessionFromChatNote(sessionId); + + if (!restoredSession) { + // If we can't find a Chat Note, create a new session + log.info(`No Chat Note found for ${sessionId}, creating a new session`); + session = SessionsStore.createSession({ + title: 'Auto-created Session' + }); + log.info(`Created new session with ID: ${session.id}`); + } else { + session = restoredSession; + } + } } // Update session last active timestamp @@ -555,6 +575,55 @@ class RestChatService { getSessions() { return SessionsStore.getAllSessions(); } + + /** + * Restore a session from a Chat Note + * This is used when a session doesn't exist in memory but there's a corresponding Chat Note + */ + async restoreSessionFromChatNote(sessionId: string): Promise { + try { + log.info(`Attempting to restore session ${sessionId} from Chat Note`); + + // Import chat storage service + const chatStorageService = (await import('../../llm/chat_storage_service.js')).default; + + // Try to get the Chat Note data + const chatNote = await chatStorageService.getChat(sessionId); + + if (!chatNote) { + log.error(`Chat Note ${sessionId} not found, cannot restore session`); + return null; + } + + log.info(`Found Chat Note ${sessionId}, recreating session from it`); + + // Convert Message[] to ChatMessage[] by ensuring the role is compatible + const chatMessages: ChatMessage[] = chatNote.messages.map(msg => ({ + role: msg.role === 'tool' ? 'assistant' : msg.role, // Map 'tool' role to 'assistant' + content: msg.content, + timestamp: new Date() + })); + + // Create a new session with the same ID as the Chat Note + const session: ChatSession = { + id: chatNote.id, + title: chatNote.title, + messages: chatMessages, + createdAt: chatNote.createdAt || new Date(), + lastActive: new Date(), + metadata: chatNote.metadata || {} + }; + + // Add the session to the in-memory store + SessionsStore.getAllSessions().set(sessionId, session); + + log.info(`Successfully restored session ${sessionId} from Chat Note`); + return session; + } catch (error) { + log.error(`Failed to restore session from Chat Note: ${error}`); + return null; + } + } } // Create singleton instance