diff --git a/services/geminiService.ts b/services/geminiService.ts index f4e9990..8809471 100644 --- a/services/geminiService.ts +++ b/services/geminiService.ts @@ -1,25 +1,34 @@ import { GoogleGenAI } from "@google/genai"; import { KBArticle, Ticket, TicketStatus } from "../types"; +// The API key must be obtained exclusively from the environment variable process.env.API_KEY. const apiKey = process.env.API_KEY || ''; -// Initialize properly with named parameter -const ai = new GoogleGenAI({ apiKey }); + +// Initialize AI only if key exists to prevent immediate instantiation errors +let ai: GoogleGenAI | null = null; +if (apiKey) { + try { + ai = new GoogleGenAI({ apiKey }); + } catch (e) { + console.warn("Failed to initialize GoogleGenAI", e); + } +} /** * Agent 1: Customer Support Chat * Uses the KB to answer questions. - * SUPPORTS MULTI-LANGUAGE via Prompt Engineering. */ export const getSupportResponse = async ( userQuery: string, chatHistory: string[], knowledgeBase: KBArticle[] ): Promise => { - if (!apiKey) return "API Key mancante. Configura l'ambiente."; + if (!ai || !apiKey) { + return "L'assistente AI non è configurato o la chiave API è mancante. Contatta l'amministratore."; + } // Prepare Context from KB const kbContext = knowledgeBase.map(a => { - // Note: We now include 'content' even for URLs because we scrape the text into it. if (a.type === 'url') { return `Fonte Esterna [${a.category}]: ${a.title} - URL: ${a.url}\nContenuto Estratto: ${a.content}`; } @@ -35,7 +44,6 @@ export const getSupportResponse = async ( GESTIONE LINGUA (IMPORTANTE): 1. Rileva automaticamente la lingua utilizzata dall'utente nel suo ultimo messaggio. 2. Anche se la KB è in Italiano, devi tradurre mentalmente la richiesta, cercare la risposta nella KB Italiana, e poi RISPONDERE NELLA LINGUA DELL'UTENTE. - 3. Esempio: Se l'utente scrive in Inglese "How do I reset my password?", tu cerchi "Come reimpostare la password" nella KB e rispondi in Inglese. BASE DI CONOSCENZA (ITALIANO): ${kbContext} @@ -60,22 +68,21 @@ export const getSupportResponse = async ( } }); - return response.text || "I apologize, I cannot process your request at the moment / Mi dispiace, non riesco a rispondere al momento."; + return response.text || "Mi dispiace, non riesco a generare una risposta al momento."; } catch (error) { console.error("Gemini Error:", error); - return "Service Error / Errore del servizio."; + return "Si è verificato un errore nel servizio AI."; } }; /** * Agent 2: Knowledge Extraction - * Scans resolved tickets to find gaps in KB and drafts new articles. */ export const generateNewKBArticle = async ( resolvedTickets: Ticket[], existingArticles: KBArticle[] ): Promise<{ title: string; content: string; category: string } | null> => { - if (!apiKey) return null; + if (!ai || !apiKey) return null; // Filter only resolved tickets const relevantTickets = resolvedTickets.filter(t => t.status === TicketStatus.RESOLVED); @@ -109,15 +116,13 @@ export const generateNewKBArticle = async ( "foundGap": boolean, "title": "Titolo del nuovo articolo", "content": "Contenuto dettagliato in formato Markdown", - "category": "Categoria suggerita (es. Tecnico, Amministrazione, Account)" + "category": "Categoria suggerita" } - - Se non trovi nulla di rilevante o nuovo, imposta "foundGap" a false. `; try { const response = await ai.models.generateContent({ - model: 'gemini-3-pro-preview', // Pro model for better reasoning + model: 'gemini-3-pro-preview', contents: prompt, config: { responseMimeType: "application/json" @@ -140,4 +145,4 @@ export const generateNewKBArticle = async ( console.error("Knowledge Agent Error:", error); return null; } -}; \ No newline at end of file +};