import { useCallback, useMemo, useState } from "react"; import { clearArchived, findSnapshot, listArchivedConversations, parseArchive, serializeArchive, upsertSnapshot, } from "./conversationArchive"; import { getHistoryActiveSessionKey, getHistoryConversationsKey, normalizeHistoryScope, } from "./storageKeys"; import type { ConversationSnapshot, ConversationSummary } from "./types"; function readStorage(key: string): string | null { try { return window.localStorage.getItem(key); } catch { return null; } } function writeStorage(key: string, value: string): void { try { window.localStorage.setItem(key, value); } catch { // Local history is best-effort. } } function readArchive(key: string | null): ConversationSnapshot[] { return key ? parseArchive(readStorage(key)) : []; } export function useLocalConversationHistory(params: { loadPreviousSession?: boolean; historyStorageScope?: string; }): { enabled: boolean; activeSessionId: string | null; archivedConversations: ConversationSummary[]; loadActiveSnapshot: () => ConversationSnapshot | null; saveActiveSnapshot: (snapshot: ConversationSnapshot) => void; restoreSnapshot: (sessionId: string) => ConversationSnapshot | null; setActiveSessionId: (sessionId: string) => void; clearArchivedConversations: () => void; refresh: () => void; } { const scope = useMemo( () => normalizeHistoryScope(params.historyStorageScope), [params.historyStorageScope], ); const enabled = Boolean(params.loadPreviousSession && scope); const activeKey = scope ? getHistoryActiveSessionKey(scope) : null; const archiveKey = scope ? getHistoryConversationsKey(scope) : null; const [version, setVersion] = useState(0); const refresh = useCallback(() => setVersion((current) => current + 1), []); void version; const activeSessionId = enabled && activeKey ? readStorage(activeKey) : null; const archivedConversations = listArchivedConversations( enabled ? readArchive(archiveKey) : [], activeSessionId, ); const loadActiveSnapshot = useCallback(() => { if (!enabled || !activeKey) { return null; } return findSnapshot(readArchive(archiveKey), readStorage(activeKey)); }, [activeKey, archiveKey, enabled]); const saveActiveSnapshot = useCallback( (snapshot: ConversationSnapshot) => { if (!enabled || !archiveKey) { return; } writeStorage( archiveKey, serializeArchive(upsertSnapshot(readArchive(archiveKey), snapshot)), ); refresh(); }, [archiveKey, enabled, refresh], ); const restoreSnapshot = useCallback( (sessionId: string) => { if (!enabled || !archiveKey) { return null; } return findSnapshot(readArchive(archiveKey), sessionId); }, [archiveKey, enabled], ); const setActiveSessionId = useCallback( (sessionId: string) => { if (!enabled || !activeKey) { return; } writeStorage(activeKey, sessionId); refresh(); }, [activeKey, enabled, refresh], ); const clearArchivedConversations = useCallback(() => { if (!enabled || !archiveKey) { return; } writeStorage( archiveKey, serializeArchive(clearArchived(readArchive(archiveKey), activeSessionId)), ); refresh(); }, [activeSessionId, archiveKey, enabled, refresh]); return useMemo( () => ({ enabled, activeSessionId, archivedConversations, loadActiveSnapshot, saveActiveSnapshot, restoreSnapshot, setActiveSessionId, clearArchivedConversations, refresh, }), [ activeSessionId, archivedConversations, clearArchivedConversations, enabled, loadActiveSnapshot, refresh, restoreSnapshot, saveActiveSnapshot, setActiveSessionId, ], ); }