import { createStores, SessionStore, MemoryStore, OverviewStore, DiagnosticsStore, SessionInput, MemoryInput, OverviewInput, DiagnosticInput, SessionRow, MemoryRow, OverviewRow, DiagnosticRow, normalizeTimestamp } from '../services/sqlite/index.js'; /** * Storage backend types */ export type StorageBackend = 'sqlite' | 'jsonl'; /** * Unified interface for storage operations */ export interface IStorageProvider { backend: StorageBackend; // Session operations createSession(session: SessionInput): Promise; getSession(sessionId: string): Promise; hasSession(sessionId: string): Promise; getAllSessionIds(): Promise>; getRecentSessions(limit?: number): Promise; getRecentSessionsForProject(project: string, limit?: number): Promise; // Memory operations createMemory(memory: MemoryInput): Promise; createMemories(memories: MemoryInput[]): Promise; getRecentMemories(limit?: number): Promise; getRecentMemoriesForProject(project: string, limit?: number): Promise; hasDocumentId(documentId: string): Promise; // Overview operations createOverview(overview: OverviewInput): Promise; upsertOverview(overview: OverviewInput): Promise; getRecentOverviews(limit?: number): Promise; getRecentOverviewsForProject(project: string, limit?: number): Promise; // Diagnostic operations createDiagnostic(diagnostic: DiagnosticInput): Promise; // Health check isAvailable(): Promise; } /** * SQLite-based storage provider */ export class SQLiteStorageProvider implements IStorageProvider { public readonly backend = 'sqlite'; private stores?: { sessions: SessionStore; memories: MemoryStore; overviews: OverviewStore; diagnostics: DiagnosticsStore; }; private async getStores() { if (!this.stores) { this.stores = await createStores(); } return this.stores; } async isAvailable(): Promise { try { await this.getStores(); return true; } catch (error) { return false; } } async createSession(session: SessionInput): Promise { const stores = await this.getStores(); return stores.sessions.create(session); } async getSession(sessionId: string): Promise { const stores = await this.getStores(); return stores.sessions.getBySessionId(sessionId); } async hasSession(sessionId: string): Promise { const stores = await this.getStores(); return stores.sessions.has(sessionId); } async getAllSessionIds(): Promise> { const stores = await this.getStores(); return stores.sessions.getAllSessionIds(); } async getRecentSessions(limit = 5): Promise { const stores = await this.getStores(); return stores.sessions.getRecent(limit); } async getRecentSessionsForProject(project: string, limit = 5): Promise { const stores = await this.getStores(); return stores.sessions.getRecentForProject(project, limit); } async createMemory(memory: MemoryInput): Promise { const stores = await this.getStores(); return stores.memories.create(memory); } async createMemories(memories: MemoryInput[]): Promise { const stores = await this.getStores(); stores.memories.createMany(memories); } async getRecentMemories(limit = 10): Promise { const stores = await this.getStores(); return stores.memories.getRecent(limit); } async getRecentMemoriesForProject(project: string, limit = 10): Promise { const stores = await this.getStores(); return stores.memories.getRecentForProject(project, limit); } async hasDocumentId(documentId: string): Promise { const stores = await this.getStores(); return stores.memories.hasDocumentId(documentId); } async createOverview(overview: OverviewInput): Promise { const stores = await this.getStores(); return stores.overviews.create(overview); } async upsertOverview(overview: OverviewInput): Promise { const stores = await this.getStores(); return stores.overviews.upsert(overview); } async getRecentOverviews(limit = 5): Promise { const stores = await this.getStores(); return stores.overviews.getRecent(limit); } async getRecentOverviewsForProject(project: string, limit = 5): Promise { const stores = await this.getStores(); return stores.overviews.getRecentForProject(project, limit); } async createDiagnostic(diagnostic: DiagnosticInput): Promise { const stores = await this.getStores(); return stores.diagnostics.create(diagnostic); } } /** * Storage provider singleton */ let storageProvider: IStorageProvider | null = null; /** * Get the configured storage provider (always SQLite) */ export async function getStorageProvider(): Promise { if (storageProvider) { return storageProvider; } const sqliteProvider = new SQLiteStorageProvider(); if (await sqliteProvider.isAvailable()) { storageProvider = sqliteProvider; return storageProvider; } throw new Error('SQLite storage backend unavailable'); }