Heaven K
feat: tiered AI pool — free models first, paid fallback on exhaustion
47b1169
import { z } from 'zod';
import dotenv from 'dotenv';
import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
// Load .env from monorepo root (3 levels up from src/config/)
dotenv.config({ path: resolve(__dirname, '../../../../.env') });
const envSchema = z.object({
PORT: z.coerce.number().default(3001),
DATABASE_URL: z.string().default('sqlite.db'),
JWT_SECRET: z.string().default('dev-secret-change-in-production-min32chars'),
VITE_GOOGLE_CLIENT_ID: z.string().optional(),
GOOGLE_CLIENT_SECRET: z.string().optional(),
// AI Provider routing
AI_PRIMARY_PROVIDER: z.string().default('groq'),
AI_FALLBACK_PROVIDER: z.string().default('mistral'),
AI_AUTO_ROTATE: z.coerce.boolean().default(true),
AI_TIER: z.enum(['free', 'paid']).default('free'),
// Groq (free tier)
GROQ_API_KEY: z.string().optional(),
GROQ_MODEL: z.string().default('llama-3.3-70b-versatile'),
// Mistral (free tier)
MISTRAL_API_KEY: z.string().optional(),
MISTRAL_MODEL: z.string().default('mistral-small-latest'),
// Other AI keys (paid / optional)
AI_PROVIDER: z
.enum(['groq', 'mistral', 'anthropic', 'openai', 'google', 'openrouter', 'ollama'])
.default('groq'),
ANTHROPIC_API_KEY: z.string().optional(),
OPENAI_API_KEY: z.string().optional(),
GOOGLE_AI_API_KEY: z.string().optional(),
OPENROUTER_API_KEY: z.string().optional(),
OLLAMA_BASE_URL: z.string().default('http://localhost:11434'),
APP_URL: z.string().default('http://localhost:5173'),
SCAN_INTERVAL_MINUTES: z.coerce.number().default(5),
});
export const config = envSchema.parse(process.env);
export type Config = z.infer<typeof envSchema>;