203 lines
9.5 KiB
JavaScript
203 lines
9.5 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.buildChatbotRoutes = buildChatbotRoutes;
|
|
/**
|
|
* chatbot.routes.ts — CRUD de credenciais e bots IA por instância.
|
|
*
|
|
* Montado em /api/chatbot (ver server.ts)
|
|
* Todos os endpoints requerem authMiddleware.
|
|
*/
|
|
const express_1 = require("express");
|
|
const zod_1 = require("zod");
|
|
const prisma_1 = require("../../infra/database/prisma");
|
|
const chatbot_repository_1 = require("./chatbot.repository");
|
|
const logger_1 = require("../../config/logger");
|
|
function buildChatbotRoutes() {
|
|
const router = (0, express_1.Router)();
|
|
// ── Helpers ──────────────────────────────────────────────────────────────
|
|
const validateInstance = async (instanceId, tenantId) => {
|
|
return prisma_1.prisma.instance.findFirst({ where: { id: instanceId, tenantId } });
|
|
};
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
// CREDENTIALS
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
// GET /api/chatbot/credentials/:instanceId
|
|
router.get('/credentials/:instanceId', async (req, res) => {
|
|
try {
|
|
const tenantId = req.tenantId;
|
|
const instanceId = req.params['instanceId'];
|
|
if (!await validateInstance(instanceId, tenantId)) {
|
|
res.status(404).json({ error: 'Instância não encontrada' });
|
|
return;
|
|
}
|
|
const creds = await chatbot_repository_1.credentialRepo.findAll(tenantId, instanceId);
|
|
res.json(creds);
|
|
}
|
|
catch (err) {
|
|
logger_1.logger.error({ err }, 'Erro ao listar credenciais');
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
// POST /api/chatbot/credentials/:instanceId
|
|
router.post('/credentials/:instanceId', async (req, res) => {
|
|
const schema = zod_1.z.object({
|
|
name: zod_1.z.string().min(1).max(80),
|
|
apiKey: zod_1.z.string().min(10),
|
|
provider: zod_1.z.enum(['GEMINI', 'OPENAI']).default('GEMINI'),
|
|
});
|
|
try {
|
|
const tenantId = req.tenantId;
|
|
const instanceId = req.params['instanceId'];
|
|
if (!await validateInstance(instanceId, tenantId)) {
|
|
res.status(404).json({ error: 'Instância não encontrada' });
|
|
return;
|
|
}
|
|
const body = schema.parse(req.body);
|
|
const cred = await chatbot_repository_1.credentialRepo.create({ tenantId, instanceId, ...body });
|
|
res.status(201).json(cred);
|
|
}
|
|
catch (err) {
|
|
if (err instanceof zod_1.z.ZodError) {
|
|
res.status(400).json({ error: err.errors });
|
|
return;
|
|
}
|
|
logger_1.logger.error({ err }, 'Erro ao criar credencial');
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
// DELETE /api/chatbot/credentials/:instanceId/:credId
|
|
router.delete('/credentials/:instanceId/:credId', async (req, res) => {
|
|
try {
|
|
const tenantId = req.tenantId;
|
|
const credId = req.params['credId'];
|
|
await chatbot_repository_1.credentialRepo.delete(credId, tenantId);
|
|
res.status(204).send();
|
|
}
|
|
catch (err) {
|
|
logger_1.logger.error({ err }, 'Erro ao deletar credencial');
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
// BOTS
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
// GET /api/chatbot/bots/:instanceId
|
|
router.get('/bots/:instanceId', async (req, res) => {
|
|
try {
|
|
const tenantId = req.tenantId;
|
|
const instanceId = req.params['instanceId'];
|
|
if (!await validateInstance(instanceId, tenantId)) {
|
|
res.status(404).json({ error: 'Instância não encontrada' });
|
|
return;
|
|
}
|
|
const bots = await chatbot_repository_1.botRepo.findAll(tenantId, instanceId);
|
|
res.json(bots);
|
|
}
|
|
catch (err) {
|
|
logger_1.logger.error({ err }, 'Erro ao listar bots');
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
// POST /api/chatbot/bots/:instanceId
|
|
router.post('/bots/:instanceId', async (req, res) => {
|
|
const schema = zod_1.z.object({
|
|
credentialId: zod_1.z.string().uuid(),
|
|
name: zod_1.z.string().min(1).max(80),
|
|
systemPrompt: zod_1.z.string().min(10),
|
|
model: zod_1.z.string().default('gemini-1.5-flash'),
|
|
enabled: zod_1.z.boolean().default(false),
|
|
triggerMode: zod_1.z.enum(['ALL', 'KEYWORD']).default('ALL'),
|
|
keywords: zod_1.z.array(zod_1.z.string()).default([]),
|
|
});
|
|
try {
|
|
const tenantId = req.tenantId;
|
|
const instanceId = req.params['instanceId'];
|
|
if (!await validateInstance(instanceId, tenantId)) {
|
|
res.status(404).json({ error: 'Instância não encontrada' });
|
|
return;
|
|
}
|
|
const body = schema.parse(req.body);
|
|
const existing = await chatbot_repository_1.botRepo.findAll(tenantId, instanceId);
|
|
if (existing.length > 0) {
|
|
res.status(409).json({ error: 'Já existe um bot nesta instância. Use PUT para atualizar.' });
|
|
return;
|
|
}
|
|
const bot = await chatbot_repository_1.botRepo.create({ tenantId, instanceId, ...body });
|
|
res.status(201).json(bot);
|
|
}
|
|
catch (err) {
|
|
if (err instanceof zod_1.z.ZodError) {
|
|
res.status(400).json({ error: err.errors });
|
|
return;
|
|
}
|
|
logger_1.logger.error({ err }, 'Erro ao criar bot');
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
// PUT /api/chatbot/bots/:instanceId/:botId
|
|
router.put('/bots/:instanceId/:botId', async (req, res) => {
|
|
const schema = zod_1.z.object({
|
|
credentialId: zod_1.z.string().uuid().optional(),
|
|
name: zod_1.z.string().min(1).max(80).optional(),
|
|
systemPrompt: zod_1.z.string().min(10).optional(),
|
|
model: zod_1.z.string().optional(),
|
|
enabled: zod_1.z.boolean().optional(),
|
|
triggerMode: zod_1.z.enum(['ALL', 'KEYWORD']).optional(),
|
|
keywords: zod_1.z.array(zod_1.z.string()).optional(),
|
|
});
|
|
try {
|
|
const tenantId = req.tenantId;
|
|
const botId = req.params['botId'];
|
|
const body = schema.parse(req.body);
|
|
await chatbot_repository_1.botRepo.update(botId, tenantId, body);
|
|
const updated = await chatbot_repository_1.botRepo.findById(botId, tenantId);
|
|
res.json(updated);
|
|
}
|
|
catch (err) {
|
|
if (err instanceof zod_1.z.ZodError) {
|
|
res.status(400).json({ error: err.errors });
|
|
return;
|
|
}
|
|
logger_1.logger.error({ err }, 'Erro ao atualizar bot');
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
// DELETE /api/chatbot/bots/:instanceId/:botId
|
|
router.delete('/bots/:instanceId/:botId', async (req, res) => {
|
|
try {
|
|
const tenantId = req.tenantId;
|
|
const botId = req.params['botId'];
|
|
await chatbot_repository_1.botRepo.delete(botId, tenantId);
|
|
res.status(204).send();
|
|
}
|
|
catch (err) {
|
|
logger_1.logger.error({ err }, 'Erro ao deletar bot');
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
// BOT STATE — Human Takeover por chat
|
|
// ─────────────────────────────────────────────────────────────────────────
|
|
// POST /api/chatbot/chats/:chatId/pause — pausa o bot (human takeover)
|
|
router.post('/chats/:chatId/pause', async (req, res) => {
|
|
try {
|
|
await chatbot_repository_1.chatBotState.pauseBot(req.params['chatId']);
|
|
res.json({ paused: true });
|
|
}
|
|
catch (err) {
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
// POST /api/chatbot/chats/:chatId/resume — retoma o bot
|
|
router.post('/chats/:chatId/resume', async (req, res) => {
|
|
try {
|
|
await chatbot_repository_1.chatBotState.resumeBot(req.params['chatId']);
|
|
res.json({ paused: false });
|
|
}
|
|
catch (err) {
|
|
res.status(500).json({ error: err.message });
|
|
}
|
|
});
|
|
return router;
|
|
}
|