/** * LLM Client Factory for Simulator Service * Provides a configured LLMGateway instance from process.env * Completely removes direct OpenAI SDK dependency */ import { LLMGateway, type LLMGatewayConfig } from '@wfo/integrations/llm-providers/index'; let _instance: LLMGateway | null = null; export function getSimulatorLLM(): LLMGateway { if (_instance) return _instance; const env = process.env; const provider = (env['LLM_PROVIDER'] ?? 'openai') as LLMGatewayConfig['primary']['provider']; const baseUrl = env['LLM_GATEWAY_URL'] ?? 'https://api.openai.com/v1'; const apiKey = env['LLM_API_KEY'] ?? env['OPENAI_API_KEY'] ?? ''; const defaultModel = env['LLM_MODEL'] ?? 'gpt-4o'; if (!apiKey) { throw new Error( 'LLM API key not configured. Set LLM_API_KEY (or OPENAI_API_KEY for legacy) in environment.', ); } const config: LLMGatewayConfig = { primary: { provider, baseUrl, apiKey, defaultModel }, defaultRetries: 3, defaultRetryDelayMs: 1000, defaultTimeoutMs: 90000, }; // Optional fallback provider const fallbackUrl = env['LLM_FALLBACK_URL']; const fallbackKey = env['LLM_FALLBACK_KEY']; const fallbackModel = env['LLM_FALLBACK_MODEL'] ?? defaultModel; if (fallbackUrl && fallbackKey) { config.fallback = { provider: 'openai-compatible', baseUrl: fallbackUrl, apiKey: fallbackKey, defaultModel: fallbackModel, }; } _instance = new LLMGateway(config); return _instance; } /** * Create a per-request LLM client from a provided API key * Used when the API key is passed per-request (from CF Worker) */ export function createRequestLLM(apiKey: string, model?: string): LLMGateway { const env = process.env; const provider = (env['LLM_PROVIDER'] ?? 'openai') as LLMGatewayConfig['primary']['provider']; const baseUrl = env['LLM_GATEWAY_URL'] ?? 'https://api.openai.com/v1'; return new LLMGateway({ primary: { provider, baseUrl, apiKey, defaultModel: model ?? env['LLM_MODEL'] ?? 'gpt-4o', }, defaultRetries: 3, defaultRetryDelayMs: 1000, defaultTimeoutMs: 90000, }); }