/** * In-memory session store for diagram chat sessions. * Stores conversation history and entity snapshots. */ import { v4 as uuidv4 } from 'uuid'; // Session structure: // { // id: string, // diagramId: string, // conversationHistory: Array<{role, content, toolResults?, timestamp}>, // entities: Array<{id, template, text, color, position}>, // cameraPosition: { position: {x,y,z}, forward: {x,y,z}, groundForward: {x,y,z}, groundRight: {x,y,z} }, // preferences: { useDefaultConnectionLabels?: boolean }, // createdAt: Date, // lastAccess: Date // } const sessions = new Map(); // Session timeout (1 hour of inactivity) const SESSION_TIMEOUT_MS = 60 * 60 * 1000; /** * Create a new session for a diagram */ export function createSession(diagramId) { const id = uuidv4(); const session = { id, diagramId, conversationHistory: [], entities: [], cameraPosition: null, preferences: {}, createdAt: new Date(), lastAccess: new Date() }; sessions.set(id, session); return session; } /** * Get a session by ID */ export function getSession(sessionId) { const session = sessions.get(sessionId); if (session) { session.lastAccess = new Date(); } return session || null; } /** * Find existing session for a diagram */ export function findSessionByDiagram(diagramId) { for (const [, session] of sessions) { if (session.diagramId === diagramId) { session.lastAccess = new Date(); return session; } } return null; } /** * Update entities snapshot for a session */ export function syncEntities(sessionId, entities) { const session = sessions.get(sessionId); if (!session) return null; session.entities = entities; session.lastAccess = new Date(); return session; } /** * Update camera position for a session */ export function syncCameraPosition(sessionId, cameraPosition) { const session = sessions.get(sessionId); if (!session) return null; session.cameraPosition = cameraPosition; session.lastAccess = new Date(); return session; } /** * Add a message to conversation history */ export function addMessage(sessionId, message) { const session = sessions.get(sessionId); if (!session) return null; session.conversationHistory.push({ ...message, timestamp: new Date() }); session.lastAccess = new Date(); return session; } /** * Get conversation history for API calls (formatted for Claude) */ export function getConversationForAPI(sessionId) { const session = sessions.get(sessionId); if (!session) return []; // Convert to Claude message format return session.conversationHistory.map(msg => ({ role: msg.role, content: msg.content })); } /** * Clear conversation history but keep session */ export function clearHistory(sessionId) { const session = sessions.get(sessionId); if (!session) return null; session.conversationHistory = []; session.lastAccess = new Date(); return session; } /** * Delete a session */ export function deleteSession(sessionId) { return sessions.delete(sessionId); } /** * Clean up expired sessions */ export function cleanupExpiredSessions() { const now = Date.now(); for (const [id, session] of sessions) { if (now - session.lastAccess.getTime() > SESSION_TIMEOUT_MS) { sessions.delete(id); } } } // Run cleanup every 15 minutes setInterval(cleanupExpiredSessions, 15 * 60 * 1000); /** * Get session stats (for debugging) */ export function getStats(includeDetails = false) { return { activeSessions: sessions.size, sessions: Array.from(sessions.values()).map(s => ({ id: s.id, diagramId: s.diagramId, messageCount: s.conversationHistory.length, entityCount: s.entities.length, lastAccess: s.lastAccess, // Include full details if requested ...(includeDetails && { entities: s.entities, conversationHistory: s.conversationHistory }) })) }; } /** * Get session preferences */ export function getPreferences(sessionId) { const session = sessions.get(sessionId); if (!session) return null; session.lastAccess = new Date(); return session.preferences || {}; } /** * Set a session preference */ export function setPreference(sessionId, key, value) { const session = sessions.get(sessionId); if (!session) return null; if (!session.preferences) { session.preferences = {}; } session.preferences[key] = value; session.lastAccess = new Date(); return session.preferences; }