import { SvelteMap } from 'svelte/reactivity'; import type { ChatMessage } from '$lib/types'; export interface Session { id: string; title: string; messages: ChatMessage[]; createdAt: Date; } const STORAGE_KEY = 'llm-multiverse-sessions'; const ACTIVE_SESSION_KEY = 'llm-multiverse-active-session'; function loadSessions(): SvelteMap { if (typeof localStorage === 'undefined') return new SvelteMap(); try { const raw = localStorage.getItem(STORAGE_KEY); if (!raw) return new SvelteMap(); const arr: [string, Session][] = JSON.parse(raw); return new SvelteMap( arr.map(([id, s]) => [ id, { ...s, createdAt: new Date(s.createdAt), messages: s.messages.map(m => ({ ...m, timestamp: new Date(m.timestamp) })) } ]) ); } catch { return new SvelteMap(); } } function saveSessions(sessions: SvelteMap) { if (typeof localStorage === 'undefined') return; localStorage.setItem(STORAGE_KEY, JSON.stringify([...sessions.entries()])); } function loadActiveSessionId(): string | null { if (typeof localStorage === 'undefined') return null; return localStorage.getItem(ACTIVE_SESSION_KEY); } function saveActiveSessionId(id: string) { if (typeof localStorage === 'undefined') return; localStorage.setItem(ACTIVE_SESSION_KEY, id); } function createSessionStore() { const sessions = $state>(loadSessions()); let activeSessionId = $state(loadActiveSessionId()); function createSession(id?: string): Session { const session: Session = { id: id ?? crypto.randomUUID(), title: 'New Chat', messages: [], createdAt: new Date() }; sessions.set(session.id, session); activeSessionId = session.id; saveSessions(sessions); saveActiveSessionId(session.id); return session; } function getOrCreateSession(id?: string): Session { if (id && sessions.has(id)) { activeSessionId = id; saveActiveSessionId(id); return sessions.get(id)!; } return createSession(id); } function updateMessages(sessionId: string, messages: ChatMessage[]) { const session = sessions.get(sessionId); if (!session) return; session.messages = messages; // Update title from first user message if still default if (session.title === 'New Chat') { const firstUser = messages.find(m => m.role === 'user'); if (firstUser) { session.title = firstUser.content.slice(0, 50) + (firstUser.content.length > 50 ? '...' : ''); } } sessions.set(sessionId, session); saveSessions(sessions); } function switchSession(id: string) { if (sessions.has(id)) { activeSessionId = id; saveActiveSessionId(id); } } function deleteSession(id: string) { sessions.delete(id); if (activeSessionId === id) { const remaining = getAllSessions(); activeSessionId = remaining.length > 0 ? remaining[0].id : null; if (activeSessionId) saveActiveSessionId(activeSessionId); } saveSessions(sessions); } function getAllSessions(): Session[] { return [...sessions.values()].sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime()); } return { get activeSessionId() { return activeSessionId; }, get activeSession() { return activeSessionId ? sessions.get(activeSessionId) ?? null : null; }, createSession, getOrCreateSession, updateMessages, switchSession, deleteSession, getAllSessions }; } export const sessionStore = createSessionStore();