Files
planilla/agent/respuestas/respuestaBrave.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

129 lines
3.9 KiB
JavaScript

// /respuesta/respuestaBrave.js
import fs from 'fs/promises';
import { log } from '../logger.js';
import {
sendText,
fetchChatMessages,
setTypingStatus
} from '../whatsapp.js';
import { processMessage } from '../utils/processMessage.js';
import { saveMedia } from '../utils/saveMedia.js';
import { GoogleGenAI } from '@google/genai';
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
function sanitizeSchema(obj) {
if (Array.isArray(obj)) return obj.map(sanitizeSchema);
if (obj && typeof obj === 'object') {
const out = {};
for (const [k, v] of Object.entries(obj)) {
if (k === 'additionalProperties' || k === '$schema') continue;
out[k] = sanitizeSchema(v);
}
return out;
}
return obj;
}
const cleanForGemini = ({ media, reactions, preview, ...rest }) => rest;
export async function respuestaBrave(msg) {
const text = msg.text || '';
setTypingStatus(msg.chatId, true);
log('info', '🧠 Generando respuesta para @nucleo (Brave)…');
try {
const allraw = await fetchChatMessages(msg.chatId);
const allMsgs = allraw.map(processMessage);
const context = allMsgs.map(cleanForGemini);
let json = JSON.stringify(context);
while (json.length > 100_000 && context.length) {
context.shift();
json = JSON.stringify(context);
}
const chatName = context.length > 0 ? context[0]?.chatName : 'chat';
const prompt = [
`Eres un asistente con acceso a Brave Search mediante herramientas externas.`,
`Pregunta del usuario: ${text}`,
...context
];
const medias = allraw.filter(m => m.type !== 'chat');
const settled = await Promise.allSettled(medias.map(saveMedia));
const MAX = 20 * 1024 * 1024;
let total = 0;
const files = {};
for (const r of settled) {
if (r.status !== 'fulfilled' || !r.value) continue;
const entries = Object.entries(r.value);
if (entries.length === 0) continue;
const [msgId, obj] = entries[0];
let size = Number(obj.sizeBytes || 0);
if (!size && obj.filePath) {
try { size = (await fs.stat(obj.filePath)).size; } catch { size = 0; }
}
if (total + size > MAX && total > 0) break;
if (size > MAX) continue;
total += size;
files[msgId] = { uri: obj.uri || obj.filePath, mimeType: obj.mimeType };
}
// === MCP Brave Search ===
const client = new Client({ name: 'brave-agent', version: '1.0.0' });
const serverParams = new StdioClientTransport({
command: 'uvx',
args: ['mcp-server-fetch']
});
await client.connect(serverParams);
const mcp = await client.listTools();
const tools = mcp.tools.map(t => ({
name: t.name,
description: t.description,
parameters: sanitizeSchema({
type: 'object',
...t.inputSchema
})
}));
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
const response = await ai.models.generateContent({
model: 'gemini-2.5-flash-preview-04-17',
contents: prompt,
config: {
tools: [{ functionDeclarations: tools }],
temperature: 0
}
});
let respuesta;
if (response.functionCalls && response.functionCalls.length > 0) {
const call = response.functionCalls[0];
const result = await client.callTool({ name: call.name, arguments: call.args });
await client.close();
respuesta = result.content?.[0]?.text ?? JSON.stringify(result);
} else {
await client.close();
respuesta = response.text;
}
await sendText(msg.chatId, respuesta);
log('info', '🧠 Respuesta enviada');
} catch (error) {
log('error', 'Error en respuestaBrave:', error);
await sendText(msg.chatId, 'Hubo un error al procesar tu solicitud.');
} finally {
setTypingStatus(msg.chatId, false);
}
}