'use server' import { auth } from '@/auth' import { prisma } from '@/lib/prisma' import { revalidatePath, revalidateTag } from 'next/cache' export type UserAISettingsData = { titleSuggestions?: boolean semanticSearch?: boolean paragraphRefactor?: boolean memoryEcho?: boolean memoryEchoFrequency?: 'daily' | 'weekly' | 'custom' aiProvider?: 'auto' | 'openai' | 'ollama' preferredLanguage?: 'auto' | 'en' | 'fr' | 'es' | 'de' | 'fa' | 'it' | 'pt' | 'ru' | 'zh' | 'ja' | 'ko' | 'ar' | 'hi' | 'nl' | 'pl' demoMode?: boolean showRecentNotes?: boolean emailNotifications?: boolean desktopNotifications?: boolean anonymousAnalytics?: boolean theme?: 'light' | 'dark' | 'auto' fontSize?: 'small' | 'medium' | 'large' } /** * Update AI settings for the current user */ export async function updateAISettings(settings: UserAISettingsData) { const session = await auth() if (!session?.user?.id) { console.error('[updateAISettings] Unauthorized: No session or user ID') throw new Error('Unauthorized') } try { // Upsert settings (create if not exists, update if exists) const result = await prisma.userAISettings.upsert({ where: { userId: session.user.id }, create: { userId: session.user.id, ...settings }, update: settings }) revalidatePath('/settings/ai', 'page') revalidatePath('/', 'layout') revalidateTag('ai-settings') return { success: true } } catch (error) { console.error('Error updating AI settings:', error) throw new Error('Failed to update AI settings') } } /** * Get AI settings for the current user (Cached) */ import { unstable_cache } from 'next/cache' // Internal cached function to fetch settings from DB const getCachedAISettings = unstable_cache( async (userId: string) => { try { const settings = await prisma.userAISettings.findUnique({ where: { userId } }) if (!settings) { return { titleSuggestions: true, semanticSearch: true, paragraphRefactor: true, memoryEcho: true, memoryEchoFrequency: 'daily' as const, aiProvider: 'auto' as const, preferredLanguage: 'auto' as const, demoMode: false, showRecentNotes: false, emailNotifications: false, desktopNotifications: false, anonymousAnalytics: false, theme: 'light' as const, fontSize: 'medium' as const } } return { titleSuggestions: settings.titleSuggestions, semanticSearch: settings.semanticSearch, paragraphRefactor: settings.paragraphRefactor, memoryEcho: settings.memoryEcho, memoryEchoFrequency: (settings.memoryEchoFrequency || 'daily') as 'daily' | 'weekly' | 'custom', aiProvider: (settings.aiProvider || 'auto') as 'auto' | 'openai' | 'ollama', preferredLanguage: (settings.preferredLanguage || 'auto') as 'auto' | 'en' | 'fr' | 'es' | 'de' | 'fa' | 'it' | 'pt' | 'ru' | 'zh' | 'ja' | 'ko' | 'ar' | 'hi' | 'nl' | 'pl', demoMode: settings.demoMode, showRecentNotes: settings.showRecentNotes, emailNotifications: settings.emailNotifications, desktopNotifications: settings.desktopNotifications, anonymousAnalytics: settings.anonymousAnalytics, // theme: 'light' as const, // REMOVED: Should not be handled here or hardcoded fontSize: (settings.fontSize || 'medium') as 'small' | 'medium' | 'large' } } catch (error) { console.error('Error getting AI settings:', error) // Return defaults on error return { titleSuggestions: true, semanticSearch: true, paragraphRefactor: true, memoryEcho: true, memoryEchoFrequency: 'daily' as const, aiProvider: 'auto' as const, preferredLanguage: 'auto' as const, demoMode: false, showRecentNotes: false, emailNotifications: false, desktopNotifications: false, anonymousAnalytics: false, theme: 'light' as const, fontSize: 'medium' as const } } }, ['user-ai-settings'], { tags: ['ai-settings'] } ) export async function getAISettings(userId?: string) { let id = userId if (!id) { const session = await auth() id = session?.user?.id } // Return defaults for non-logged-in users if (!id) { return { titleSuggestions: true, semanticSearch: true, paragraphRefactor: true, memoryEcho: true, memoryEchoFrequency: 'daily' as const, aiProvider: 'auto' as const, preferredLanguage: 'auto' as const, demoMode: false, showRecentNotes: false, emailNotifications: false, desktopNotifications: false, anonymousAnalytics: false, theme: 'light' as const, fontSize: 'medium' as const } } return getCachedAISettings(id) } /** * Get user's preferred AI provider */ export async function getUserAIPreference(): Promise<'auto' | 'openai' | 'ollama'> { const settings = await getAISettings() return settings.aiProvider } /** * Check if a specific AI feature is enabled for the user */ export async function isAIFeatureEnabled(feature: keyof UserAISettingsData): Promise { const settings = await getAISettings() switch (feature) { case 'titleSuggestions': return settings.titleSuggestions case 'semanticSearch': return settings.semanticSearch case 'paragraphRefactor': return settings.paragraphRefactor case 'memoryEcho': return settings.memoryEcho default: return true } }