import { ThreadData } from '../types'; import type { SessionStorage } from '../storage'; const DEFAULT_THREAD_ID = 'DEFAULT_THREAD_ID'; /** * Generates a new session ID */ export function generateSessionId(): string { const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; let sid = ''; for (let i = 0; i < 8; i++) { sid += chars.charAt(Math.floor(Math.random() * chars.length)); } return sid; } /** * Creates the thread list adapter for multi-thread support */ export function createThreadListAdapter( currentThreadId: string, threadList: ThreadData[], setCurrentThreadId: (id: string) => void, setThreadList: React.Dispatch>, storage: SessionStorage, onThreadCreate?: (threadId: string) => void, onThreadSwitch?: (threadId: string) => void, onThreadArchive?: (threadId: string) => void, onThreadUnarchive?: (threadId: string) => void, onThreadDelete?: (threadId: string) => void, onThreadRename?: (threadId: string, name: string) => void, ) { return { threadId: currentThreadId, threads: threadList .filter((t) => t.status === 'regular') .map((t) => ({ id: t.threadId, threadId: t.threadId, title: t.title || `Session ${t.threadId}`, status: t.status as 'regular', })), archivedThreads: threadList .filter((t) => t.status === 'archived') .map((t) => ({ id: t.threadId, threadId: t.threadId, title: t.title || `Archived Chat ${t.threadId}`, status: t.status as 'archived', })), onSwitchToNewThread: () => { const newId = generateSessionId(); const newThread = { threadId: newId, status: 'regular' as const, title: `Session ${newId}`, }; setThreadList((prev) => [newThread, ...prev]); setCurrentThreadId(newId); onThreadCreate?.(newId); }, onSwitchToThread: (threadId: string) => { setCurrentThreadId(threadId); onThreadSwitch?.(threadId); }, onArchive: (threadId: string) => { setThreadList((p) => p.map((t) => (t.threadId === threadId ? { ...t, status: 'archived' as const } : t))); onThreadArchive?.(threadId); if (threadId === DEFAULT_THREAD_ID) { return; } storage.archive(threadId); }, onUnarchive: (threadId: string) => { setThreadList((prev) => prev.map((t) => (t.threadId === threadId ? { ...t, status: 'regular' as const } : t))); onThreadUnarchive?.(threadId); }, onRename: (threadId: string, name: string) => { setThreadList((prev) => prev.map((t) => (t.threadId === threadId ? { ...t, title: name } : t))); onThreadRename?.(threadId, name); if (threadId !== DEFAULT_THREAD_ID) { storage.rename(threadId, name); } }, onDelete: async (threadId: string) => { setThreadList((prev) => prev.filter((t) => t.threadId !== threadId)); if (currentThreadId === threadId) { const remaining = threadList.filter((t) => t.threadId !== threadId && t.status === 'regular'); if (remaining.length > 0) { setCurrentThreadId(remaining[0].threadId); } } onThreadDelete?.(threadId); if (threadId === DEFAULT_THREAD_ID) { return; } await storage.delete(threadId); }, }; } /** * Generates a default thread ID */ export function generateDefaultThreadId(): string { return `thread-${Date.now()}`; }