import { db, userAiKeys, userModelPrefs, eq, and } from "@epicure/db"; import { decrypt } from "@/lib/encrypt"; import { getSiteSetting } from "@/lib/site-settings"; import type { AiConfig, AiProvider } from "./factory"; export type ModelUseCase = "text" | "vision" | "mealPlan"; export async function withUserKey(userId: string, config: AiConfig): Promise { const provider = config.provider; if (!provider) return config; const row = await db.query.userAiKeys.findFirst({ where: and(eq(userAiKeys.userId, userId), eq(userAiKeys.provider, provider)), }); if (!row) return config; try { const apiKey = decrypt(row.encryptedKey); return { ...config, apiKey }; } catch { return config; } } export async function getModelConfigForUseCase(userId: string, useCase: ModelUseCase): Promise { const prefs = await db.query.userModelPrefs.findFirst({ where: eq(userModelPrefs.userId, userId), }); const providerField = `${useCase}Provider` as keyof typeof prefs; const modelField = `${useCase}Model` as keyof typeof prefs; const provider = prefs?.[providerField] as AiProvider | null | undefined; const model = prefs?.[modelField] as string | null | undefined; if (provider) { const config: AiConfig = { provider, model: model ?? undefined }; return withUserKey(userId, config); } return getDefaultProviderWithKey(userId); } export async function getDefaultProviderWithKey(userId: string): Promise { const keys = await db.query.userAiKeys.findMany({ where: eq(userAiKeys.userId, userId), columns: { provider: true, encryptedKey: true }, }); const order: AiProvider[] = ["openrouter", "openai", "anthropic", "ollama"]; // 1. User BYOK key takes highest priority for (const p of order) { const row = keys.find((k) => k.provider === p); if (row) { try { return { provider: p, apiKey: decrypt(row.encryptedKey) }; } catch { continue; } } } // 2. Admin site-setting overrides (DB → env fallback handled inside getSiteSetting) const providerEnvKeys: Record = { openrouter: "OPENROUTER_API_KEY", openai: "OPENAI_API_KEY", anthropic: "ANTHROPIC_API_KEY", ollama: null, }; for (const p of order) { const envKey = providerEnvKeys[p]; if (!envKey) continue; const apiKey = await getSiteSetting(envKey as Parameters[0]); if (apiKey) return { provider: p, apiKey }; } // 3. Let factory use raw env vars return {}; }