90 lines
3.1 KiB
TypeScript
90 lines
3.1 KiB
TypeScript
import express from 'express';
|
|
import { GoogleGenAI, mcpToTool } from '@google/genai';
|
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
|
import dotenv from 'dotenv';
|
|
|
|
dotenv.config();
|
|
|
|
interface Conversation {
|
|
chatId: string;
|
|
messages: { text: string }[];
|
|
createdAt: number;
|
|
updatedAt: number;
|
|
messageCount: number;
|
|
}
|
|
|
|
const PORT = Number(process.env.PORT) || 8001;
|
|
const API_KEY = process.env.GEMINI_API_KEY || '';
|
|
console.log(`Using Gemini API key: ${API_KEY}`);
|
|
|
|
const genAI = API_KEY ? new GoogleGenAI({ apiKey: API_KEY }) : null;
|
|
|
|
const MCP_URL = process.env.MCP_URL || 'http://planilla.interno.com/mcp';
|
|
let mcpClient: Client | undefined;
|
|
let mcpTransport: StreamableHTTPClientTransport | undefined;
|
|
|
|
async function getMcpClient(): Promise<Client> {
|
|
if (!mcpClient) {
|
|
mcpClient = new Client({ name: 'planilla-client', version: '1.0.0' });
|
|
mcpTransport = new StreamableHTTPClientTransport(new URL(MCP_URL));
|
|
await mcpClient.connect(mcpTransport);
|
|
}
|
|
return mcpClient;
|
|
}
|
|
const repoInfo = `This repository contains a WhatsApp router, a simple chat UI and now a conversation-layer-agent service.
|
|
- whatsapp-router: Forwards WhatsApp messages to configured agents.
|
|
- chat-ui: Minimal web interface that also talks to an agent.
|
|
- conversation-layer-agent: Answers questions about the repository.
|
|
Run all services with docker-compose. Configure handler mappings in whatsapp-router/src/chatHandlers.ts.`;
|
|
|
|
const app = express();
|
|
app.use(express.json());
|
|
|
|
app.post('/', async (req, res) => {
|
|
const conversation = req.body?.conversation as Conversation | undefined;
|
|
if (!conversation) return res.status(400).json({ error: 'Missing conversation' });
|
|
const message = conversation.messages[conversation.messages.length - 1]?.text || '';
|
|
|
|
if (!genAI) {
|
|
return res.json({ reply: repoInfo });
|
|
}
|
|
|
|
try {
|
|
const contents = `Repo information: ${repoInfo}\nUser message: ${message}`;
|
|
const config: any = {};
|
|
if (message.toLowerCase().includes('/planilla')) {
|
|
console.log('Using Model Context Protocol tools ', MCP_URL);
|
|
const client = await getMcpClient();
|
|
config.tools = [mcpToTool(client)];
|
|
}
|
|
const result = await genAI.models.generateContent({
|
|
model: 'gemini-2.0-flash',
|
|
contents,
|
|
config,
|
|
});
|
|
const reply = (result.text || '').trim();
|
|
res.json({ reply });
|
|
} catch (err: any) {
|
|
console.error('Gemini error', err.message);
|
|
res.status(500).json({ error: 'Failed to generate reply' });
|
|
}
|
|
});
|
|
|
|
app.get('/', (req, res) => {
|
|
res.send(`
|
|
<h1>Conversation Layer Agent</h1>
|
|
<p>This service answers questions about the repository.</p>
|
|
<p>Send a POST request to / with a JSON body containing {"conversation": {...}}</p>
|
|
<p>Example: {"conversation": {"chatId": "123@c.us", "messages": [{"text": "hello"}]}}</p>
|
|
<p>It will respond with a JSON object containing {"reply": "the answer"}</p>
|
|
|
|
<p>Repository info: ${repoInfo}</p>
|
|
`);
|
|
}
|
|
);
|
|
|
|
app.listen(PORT, () => {
|
|
console.log(`conversation-layer-agent listening on ${PORT}`);
|
|
});
|