/** * XFlow AI Utility — OpenRouter & Google Gemini Integration (Updated for May 2026 Models) */ const OPENROUTER_BASE_URL = 'https://openrouter.ai/api/v1/chat/completions' /** Доступные модели с описанием для выбора в UI */ export const AI_MODELS = { /** Сложные инженерные и архитектурные задачи, высокая стабильность */ laguna: 'poolside/laguna-m.1:free', /** MoE 120B тяжёлая аналитика, архитектурный анализ, сложные рассуждения */ nemotron: 'nvidia/nemotron-3-super-120b-a12b:free', /** Прямой вызов Gemini 3.5 Flash */ geminiFlash: 'gemini-3.5-flash', /** Прямой вызов Gemini 3.1 Pro Preview */ geminiPro: 'gemini-3.1-pro-preview', /** Прямой вызов Gemini 3.1 Flash Lite */ geminiLite: 'gemini-3.1-flash-lite' } as const export type AiModelKey = keyof typeof AI_MODELS /** Дефолтная модель, если не указана */ const DEFAULT_MODEL: AiModelKey = 'geminiFlash' export const generateAIResponse = async ( prompt: string, systemPrompt = 'You are a helpful assistant.', modelKey?: AiModelKey | string, ): Promise => { // Получаем ключи из окружения const openRouterKey = process.env.NUXT_OPEN_ROUTER_API_KEY || process.env.OPEN_ROUTER_API_KEY const geminiKey = process.env.GEMINI_API_KEY || process.env.NUXT_GEMINI_API_KEY || process.env.GOOGLE_API_KEY // Резолвим модель: принимаем как ключ ('laguna') так и полное имя const resolvedModel: string = modelKey && modelKey in AI_MODELS ? AI_MODELS[modelKey as AiModelKey] : modelKey && (modelKey.includes('/') || modelKey.startsWith('gemini')) ? modelKey : AI_MODELS[DEFAULT_MODEL] // Определяем, использовать ли Gemini напрямую const useGeminiDirect = resolvedModel.startsWith('gemini') || (!openRouterKey && geminiKey) if (useGeminiDirect) { if (!geminiKey) { throw new Error('Gemini API key (GEMINI_API_KEY or GOOGLE_API_KEY) is not configured') } const geminiModel = resolvedModel.startsWith('gemini') ? resolvedModel : 'gemini-3.5-flash' console.log(`[AI] Direct Google Gemini call: ${geminiModel}`) try { const url = `https://generativelanguage.googleapis.com/v1beta/models/${geminiModel}:generateContent?key=${geminiKey}` const response = await $fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: { contents: [ { role: 'user', parts: [{ text: prompt }] } ], systemInstruction: { parts: [{ text: systemPrompt }] }, generationConfig: { temperature: 0.3 } } }) const content = response?.candidates?.[0]?.content?.parts?.[0]?.text if (!content) { throw new Error('Empty response from Gemini API') } return content } catch (error: any) { console.error(`[AI] Gemini direct error:`, error?.data || error?.message) throw new Error(`Gemini direct generation failed: ${error?.message || error?.toString()}`) } } // Иначе используем OpenRouter if (!openRouterKey) { throw new Error('Neither OPEN_ROUTER_API_KEY nor GEMINI_API_KEY is configured') } console.log(`[AI] OpenRouter call: ${resolvedModel}`) try { const response = await $fetch(OPENROUTER_BASE_URL, { method: 'POST', headers: { 'Authorization': `Bearer ${openRouterKey}`, 'Content-Type': 'application/json', 'HTTP-Referer': 'https://a-crm.controlsystem.kz', 'X-Title': 'XFlow AI Node', }, body: { model: resolvedModel, messages: [ { role: 'system', content: systemPrompt }, { role: 'user', content: prompt }, ], stream: false, }, }) const content = response?.choices?.[0]?.message?.content if (!content) { throw new Error('Empty response from OpenRouter model') } return content } catch (error: any) { console.error(`[AI] OpenRouter error with model ${resolvedModel}:`, error?.data || error?.message) throw new Error(`OpenRouter generation failed (${resolvedModel}): ${error?.message}`) } } /** Хелпер: список моделей для фронтенда */ export const getAvailableModels = () => Object.entries(AI_MODELS).map(([key, modelId]) => ({ key, modelId, label: modelLabels[key as AiModelKey], })) const modelLabels: Record = { laguna: '🏊 Laguna M.1 — стабильная инженерная (Claude via OpenRouter)', nemotron: '🔬 Nemotron Super 120B — тяжёлая аналитика (NVIDIA via OpenRouter)', geminiFlash: '⚡ Gemini 3.5 Flash — быстрая и стабильная (Google Direct)', geminiPro: '🧠 Gemini 3.1 Pro — продвинутая аналитика (Google Direct)', geminiLite: '🍃 Gemini 3.1 Flash Lite — экономичная (Google Direct)' }