MCP Vector Sync
by qtoexdj
Verified
- mcp_vector_sync
- src
- config
import { z } from 'zod';
import dotenv from 'dotenv';
// @ts-ignore - pino tiene problemas con los tipos en ESM
import pino from 'pino';
// Cargar variables de entorno
dotenv.config();
// Schema de validación para la configuración
const configSchema = z.object({
// Supabase
supabase: z.object({
url: z.string().url('Supabase URL inválida'),
serviceRoleKey: z.string().min(1, 'Service role key es requerida'),
}),
// OpenAI
openai: z.object({
apiKey: z.string().min(1, 'OpenAI API key es requerida'),
maxRetries: z.number().int().positive().default(3),
}),
// Monitor
monitor: z.object({
// Intervalo alto por defecto ya que ahora el sistema usa principalmente webhooks
interval: z.number().int().positive().default(21600000), // 6 horas por defecto
batchSize: z.number().int().positive().default(50),
maxConcurrent: z.number().int().positive().default(3),
}),
// Rate Limiting
rateLimit: z.object({
requestsPerMinute: z.number().int().positive().default(100),
concurrent: z.number().int().positive().default(5),
}),
// Logging
logging: z.object({
level: z.enum(['debug', 'info', 'warn', 'error']).default('info'),
pretty: z.boolean().default(false),
}),
});
// Tipo inferido del schema
type Config = z.infer<typeof configSchema>;
// Función para crear la configuración validada
// Función auxiliar para convertir string a número con valor predeterminado
function parseNumber(value: string | undefined, defaultValue: number): number {
if (!value) return defaultValue;
const parsed = Number(value);
return isNaN(parsed) ? defaultValue : parsed;
}
// Verificar si estamos en modo demo
const isDemoMode = process.env.DEMO_MODE === 'true';
function createConfig(): Config {
try {
// Verificar que las variables requeridas estén presentes y no vacías
if (!isDemoMode && (!process.env.SUPABASE_URL?.trim() || !process.env.SUPABASE_SERVICE_ROLE_KEY?.trim() || !process.env.OPENAI_API_KEY?.trim())) {
throw new Error('Variables de entorno requeridas no están configuradas. Configure SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY y OPENAI_API_KEY, o active el modo DEMO con DEMO_MODE=true');
}
// Configuración con valores predeterminados para modo demo o producción
const config = {
supabase: {
url: isDemoMode ? 'https://demo-project.supabase.co' : process.env.SUPABASE_URL,
serviceRoleKey: isDemoMode ? 'demo-service-role-key' : process.env.SUPABASE_SERVICE_ROLE_KEY,
},
openai: {
apiKey: isDemoMode ? 'demo-openai-api-key' : process.env.OPENAI_API_KEY,
maxRetries: parseNumber(process.env.MAX_RETRIES, 3),
},
monitor: {
// Intervalo largo por defecto (6 horas) para el modo de respaldo
// Se puede anular con la variable de entorno MONITOR_INTERVAL
interval: parseNumber(process.env.MONITOR_INTERVAL, 21600000), // 6 horas (21600000 ms)
batchSize: parseNumber(process.env.BATCH_SIZE, 50),
maxConcurrent: parseNumber(process.env.MAX_CONCURRENT, 3),
},
rateLimit: {
requestsPerMinute: parseNumber(process.env.RATE_LIMIT_PER_TENANT, 100),
concurrent: parseNumber(process.env.CONCURRENT_REQUESTS, 5),
},
logging: {
level: (process.env.LOG_LEVEL as any) || 'info',
pretty: process.env.NODE_ENV === 'development',
},
};
if (isDemoMode) {
console.warn('⚠️ Ejecutando en MODO DEMO - No se realizarán conexiones reales a Supabase u OpenAI');
}
return configSchema.parse(config);
} catch (error) {
if (error instanceof z.ZodError) {
console.error('Error de validación en la configuración:', error.errors);
if (isDemoMode) {
console.error('Asegúrate de que DEMO_MODE=true esté configurado correctamente en las variables de entorno');
} else {
console.error('Variables de entorno requeridas: SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, OPENAI_API_KEY');
}
}
throw error;
}
}
// Crear instancia de configuración
export const config = createConfig();
// Crear logger con tipos ignorados para evitar problemas con ESM
export const logger = pino({
level: config.logging.level,
transport: config.logging.pretty
? {
target: 'pino-pretty',
options: {
colorize: true,
},
}
: undefined,
}) as any;
// Exportar tipos útiles
export type { Config };
// Constants
export const VECTOR_DIMENSIONS = 1536; // Dimensiones del modelo text-embedding-ada-002
export const MAX_CONTENT_LENGTH = 8192; // Máximo número de tokens para embedding
export const BATCH_TIMEOUT = 30000; // 30 segundos timeout para procesamiento de batch
export const HEALTH_CHECK_INTERVAL = 60000; // 1 minuto entre health checks
export const MAX_RETRY_DELAY = 300000; // 5 minutos máximo delay entre reintentos