Files
planilla/agent/respuestas/respuestaNormal.js
josedario87 745168cf51
Some checks failed
build-and-push / deploy (push) Has been skipped
build-and-push / build (push) Failing after 6s
sistema creado v0.5.0
2025-05-14 16:10:41 -06:00

100 lines
3.5 KiB
JavaScript

// /respuesta/respuestaNormal.js
import fs from 'fs/promises';
import { log } from '../logger.js'; // <- Nota el '../'
import {
sendText,
fetchChatMessages,
setTypingStatus
} from '../whatsapp.js'; // <- Nota el '../'
import { askGemini } from '../gemini.js'; // <- Nota el '../'
import { processMessage } from '../utils/processMessage.js'; // <- Nota el '../'
import { saveMedia } from '../utils/saveMedia.js'; // <- Nota el '../'
/* Quita campos pesados antes de mandar a Gemini */
const cleanForGemini = ({ media, reactions, preview, ...rest }) => rest;
/**
* Procesa la lógica específica para el comando @nucleo.
* Obtiene el historial, prepara el contexto, procesa media,
* llama a Gemini y envía la respuesta.
* @param {object} msg - El objeto de mensaje procesado.
*/
export async function respuestaNormal(msg) {
const text = msg.text || ''; // Necesitamos el texto original aquí también
setTypingStatus(msg.chatId, true);
log('info', '🧠 Generando respuesta para @nucleo…');
try {
/* 1) historial completo del chat */
const allraw = await fetchChatMessages(msg.chatId);
const allMsgs = allraw.map(processMessage);
/* 2) recorta contexto a ≤100 kB */
const context = allMsgs.map(cleanForGemini);
let json = JSON.stringify(context);
while (json.length > 100_000 && context.length) {
context.shift();
json = JSON.stringify(context);
}
// Asegurarse de que el contexto no esté vacío antes de acceder a context[0]
const chatName = context.length > 0 ? context[0]?.chatName : 'chat';
/* 3) prompt */
const prompt = [
`Eres el asistente del grupo "${chatName}".`,
`Pregunta del usuario: ${text}` // Usamos el 'text' del mensaje original que activó el comando
, ...context];
/* 4) procesa medias y respeta el límite de 20 MB */
// Filtrar solo los mensajes que no son de tipo 'chat' del historial obtenido
const medias = allraw.filter(m => m.type !== 'chat');
const settled = await Promise.allSettled(medias.map(saveMedia));
const MAX = 20 * 1024 * 1024; // 20 MB
let total = 0;
const files = {};
for (const r of settled) {
if (r.status !== 'fulfilled' || !r.value) continue;
if (typeof r.value !== 'object' || r.value === null) continue;
const entries = Object.entries(r.value);
if (entries.length === 0) continue;
const [msgId, obj] = entries[0];
if (typeof obj !== 'object' || obj === null) continue;
let size = Number(obj.sizeBytes || 0);
if (!size && obj.filePath) {
try { size = (await fs.stat(obj.filePath)).size; }
catch { size = 0; }
}
// Comprobar si añadir este archivo excede el límite MÁXIMO TOTAL
// y si ya tenemos *algo* (total > 0) para evitar empezar con un archivo demasiado grande
if (total + size > MAX && total > 0) break;
// Si este archivo *por sí solo* excede el límite, saltarlo
if (size > MAX) continue;
total += size;
files[msgId] = { uri: obj.uri || obj.filePath, mimeType: obj.mimeType };
}
// log('info', '🧠 Enviando a Gemini...', { files });
/* 5) llama a Gemini y responde */
const respuesta = await askGemini(prompt, files);
await sendText(msg.chatId, respuesta);
log('info', '🧠 Respuesta enviada');
} catch (error) {
log('error', 'Error en respuestaNormal:', error);
await sendText(msg.chatId, 'Hubo un error al procesar tu solicitud.');
} finally {
setTypingStatus(msg.chatId, false);
}
}