`;
chatMessages.appendChild(loadingElement);
chatMessages.scrollTop = chatMessages.scrollHeight;
};
const removeLoadingIndicator = () => {
shadowRoot.getElementById('loading-indicator')?.remove();
};
const getAiResponseWithRetry = async (userQuery, retries = 4) => {
let delay = 1000;
for (let i = 0; i <= retries; i++) {
try {
return await getAiResponse(userQuery);
} catch (error) {
if (error.status === 429 && i < retries) {
await new Promise(resolve => setTimeout(resolve, delay));
delay *= 2;
} else {
throw error;
}
}
}
};
const getAiResponse = async (userQuery) => {
const systemPrompt = `Eres un asistente de ventas experto para "Falcon Fitness". Tu única fuente de información es el sitio web www.falconfitness.mx. Tu objetivo es responder las preguntas de los usuarios sobre los productos que se encuentran EXCLUSIVAMENTE en ese sitio web. Reglas estrictas: 1. Basa TODAS tus respuestas únicamente en la información encontrada en www.falconfitness.mx. No uses conocimiento general. 2. Si la respuesta no se encuentra en el sitio web, responde amablemente: "No encontré información sobre eso en www.falconfitness.mx. ¿Puedo ayudarte con algún otro equipo?". 3. Sé amable, profesional y conversacional. Responde siempre en español. 4. No inventes precios, especificaciones o disponibilidad. Si no está en el sitio, no lo sabes.`;
const apiKey = "";
const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash-preview-05-20:generateContent?key=${apiKey}`;
const payload = {
contents: [{ parts: [{ text: userQuery }] }],
tools: [{ "google_search": {} }],
systemInstruction: { parts: [{ text: systemPrompt }] },
};
const response = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) });
if (!response.ok) {
const error = new Error(`API request failed with status ${response.status}`);
error.status = response.status;
throw error;
}
const result = await response.json();
const candidate = result.candidates?.[0];
if (candidate?.content?.parts?.[0]?.text) {
const text = candidate.content.parts[0].text;
let sources = [];
const groundingMetadata = candidate.groundingMetadata;
if (groundingMetadata?.groundingAttributions) {
const uniqueUris = new Set();
sources = groundingMetadata.groundingAttributions
.map(attr => ({ uri: attr.web?.uri, title: attr.web?.title }))
.filter(source => {
if (source.uri && source.uri.includes('falconfitness.mx') && !uniqueUris.has(source.uri)) {
uniqueUris.add(source.uri);
return true;
}
return false;
});
}
return { text, sources };
} else {
throw new Error(`Invalid response structure from API: ${JSON.stringify(result)}`);
}
};
});
})();