ChiragPatankar's picture
Upload 24 files
6980b1d verified
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = __importDefault(require("express"));
const uuid_1 = require("uuid");
const axios_1 = __importDefault(require("axios"));
const database_1 = require("../db/database");
const auth_1 = require("../middleware/auth");
const router = express_1.default.Router();
// Create a new chat session (authenticated - for tenant dashboard)
router.post('/sessions', auth_1.authenticateToken, async (req, res) => {
try {
const { tenantId } = req.user;
const { domain, userAgent } = req.body;
const userIp = req.ip || req.connection.remoteAddress;
// Verify tenant exists
const tenant = await database_1.database.get('SELECT id FROM tenants WHERE id = ?', [tenantId]);
if (!tenant) {
return res.status(404).json({ error: 'Tenant not found' });
}
// Generate session token
const sessionToken = (0, uuid_1.v4)();
// Create chat session
const result = await database_1.database.run('INSERT INTO chat_sessions (tenant_id, domain, user_ip, user_agent, session_token) VALUES (?, ?, ?, ?, ?)', [tenantId, domain, userIp, userAgent, sessionToken]);
// Log analytics event
await database_1.database.run('INSERT INTO analytics_events (tenant_id, event_type, event_data) VALUES (?, ?, ?)', [tenantId, 'chat_session_started', JSON.stringify({ sessionId: result.lastID, domain })]);
res.status(201).json({
sessionId: result.lastID,
sessionToken,
tenantId,
message: 'Chat session created successfully'
});
}
catch (error) {
console.error('Create session error:', error);
res.status(500).json({ error: 'Internal server error' });
}
});
// Create a new chat session (public - for widget)
router.post('/public/sessions', async (req, res) => {
try {
const { tenantId, domain, userAgent } = req.body;
const userIp = req.ip || req.connection.remoteAddress;
if (!tenantId) {
return res.status(400).json({ error: 'Tenant ID is required' });
}
// Verify tenant exists
const tenant = await database_1.database.get('SELECT id FROM tenants WHERE id = ?', [tenantId]);
if (!tenant) {
return res.status(404).json({ error: 'Tenant not found' });
}
// Generate session token
const sessionToken = (0, uuid_1.v4)();
// Create chat session
const result = await database_1.database.run('INSERT INTO chat_sessions (tenant_id, domain, user_ip, user_agent, session_token) VALUES (?, ?, ?, ?, ?)', [tenantId, domain, userIp, userAgent, sessionToken]);
// Log analytics event
await database_1.database.run('INSERT INTO analytics_events (tenant_id, event_type, event_data) VALUES (?, ?, ?)', [tenantId, 'chat_session_started', JSON.stringify({ sessionId: result.lastID, domain })]);
res.status(201).json({
sessionId: result.lastID,
sessionToken,
message: 'Chat session created successfully'
});
}
catch (error) {
console.error('Create session error:', error);
res.status(500).json({ error: 'Internal server error' });
}
});
// Send a message and get AI response
router.post('/messages', async (req, res) => {
try {
const { sessionToken, message, tenantId } = req.body;
if (!sessionToken || !message || !tenantId) {
return res.status(400).json({ error: 'Session token, message, and tenant ID are required' });
}
// Get chat session
const session = await database_1.database.get('SELECT * FROM chat_sessions WHERE session_token = ? AND tenant_id = ?', [sessionToken, tenantId]);
if (!session) {
return res.status(404).json({ error: 'Chat session not found' });
}
// Save user message
await database_1.database.run('INSERT INTO chat_messages (session_id, sender, message) VALUES (?, ?, ?)', [session.id, 'user', message]);
// Get chat history for context
const chatHistory = await database_1.database.query('SELECT sender, message, timestamp FROM chat_messages WHERE session_id = ? ORDER BY timestamp ASC', [session.id]);
// Get tenant's knowledge base
const knowledgeBase = await database_1.database.query('SELECT name, type, source FROM knowledge_base WHERE tenant_id = ? AND status = "active"', [tenantId]);
try {
// Call MCP server for AI response
const mcpResponse = await axios_1.default.post(`${process.env.MCP_SERVER_URL}/chat`, {
message,
history: chatHistory,
knowledge_base: knowledgeBase,
tenant_id: tenantId
}, {
headers: {
'Authorization': `Bearer ${process.env.MCP_AUTH_TOKEN}`,
'Content-Type': 'application/json'
},
timeout: 30000 // 30 second timeout
});
const aiResponse = mcpResponse.data.response || 'I apologize, but I encountered an issue processing your request.';
// Save AI response
await database_1.database.run('INSERT INTO chat_messages (session_id, sender, message, metadata) VALUES (?, ?, ?, ?)', [session.id, 'ai', aiResponse, JSON.stringify({
model: mcpResponse.data.model || 'gemini-1.5-flash',
confidence: mcpResponse.data.confidence || 0.8
})]);
// Log analytics event
await database_1.database.run('INSERT INTO analytics_events (tenant_id, event_type, event_data) VALUES (?, ?, ?)', [tenantId, 'message_sent', JSON.stringify({
sessionId: session.id,
messageLength: message.length,
responseLength: aiResponse.length
})]);
res.json({
response: aiResponse,
messageId: session.id,
timestamp: new Date().toISOString()
});
}
catch (mcpError) {
console.error('MCP Server error:', mcpError);
// Fallback response if MCP server is down
const fallbackResponse = "I'm sorry, but I'm experiencing technical difficulties at the moment. Please try again in a few minutes or contact support if the issue persists.";
await database_1.database.run('INSERT INTO chat_messages (session_id, sender, message, metadata) VALUES (?, ?, ?, ?)', [session.id, 'ai', fallbackResponse, JSON.stringify({ error: 'mcp_server_unavailable' })]);
res.json({
response: fallbackResponse,
messageId: session.id,
timestamp: new Date().toISOString(),
error: 'Service temporarily unavailable'
});
}
}
catch (error) {
console.error('Send message error:', error);
res.status(500).json({ error: 'Internal server error' });
}
});
// Get chat history
router.get('/sessions/:sessionToken/history', async (req, res) => {
try {
const { sessionToken } = req.params;
const { tenantId } = req.query;
if (!tenantId) {
return res.status(400).json({ error: 'Tenant ID is required' });
}
// Get session
const session = await database_1.database.get('SELECT * FROM chat_sessions WHERE session_token = ? AND tenant_id = ?', [sessionToken, tenantId]);
if (!session) {
return res.status(404).json({ error: 'Chat session not found' });
}
// Get messages
const messages = await database_1.database.query('SELECT sender, message, metadata, timestamp FROM chat_messages WHERE session_id = ? ORDER BY timestamp ASC', [session.id]);
res.json({
sessionId: session.id,
messages,
session: {
started_at: session.started_at,
resolved: session.resolved,
rating: session.rating
}
});
}
catch (error) {
console.error('Get history error:', error);
res.status(500).json({ error: 'Internal server error' });
}
});
// Rate conversation
router.post('/sessions/:sessionToken/rate', async (req, res) => {
try {
const { sessionToken } = req.params;
const { rating, feedback, tenantId } = req.body;
if (!tenantId || rating === undefined) {
return res.status(400).json({ error: 'Tenant ID and rating are required' });
}
if (rating < 1 || rating > 5) {
return res.status(400).json({ error: 'Rating must be between 1 and 5' });
}
// Update session
await database_1.database.run('UPDATE chat_sessions SET rating = ?, feedback = ?, resolved = TRUE WHERE session_token = ? AND tenant_id = ?', [rating, feedback, sessionToken, tenantId]);
// Log analytics event
await database_1.database.run('INSERT INTO analytics_events (tenant_id, event_type, event_data) VALUES (?, ?, ?)', [tenantId, 'conversation_rated', JSON.stringify({
sessionToken,
rating,
hasFeedback: !!feedback
})]);
res.json({ message: 'Rating submitted successfully' });
}
catch (error) {
console.error('Rate conversation error:', error);
res.status(500).json({ error: 'Internal server error' });
}
});
// End chat session
router.post('/sessions/:sessionToken/end', async (req, res) => {
try {
const { sessionToken } = req.params;
const { tenantId } = req.body;
if (!tenantId) {
return res.status(400).json({ error: 'Tenant ID is required' });
}
// Update session
await database_1.database.run('UPDATE chat_sessions SET ended_at = CURRENT_TIMESTAMP WHERE session_token = ? AND tenant_id = ?', [sessionToken, tenantId]);
// Log analytics event
await database_1.database.run('INSERT INTO analytics_events (tenant_id, event_type, event_data) VALUES (?, ?, ?)', [tenantId, 'chat_session_ended', JSON.stringify({ sessionToken })]);
res.json({ message: 'Chat session ended successfully' });
}
catch (error) {
console.error('End session error:', error);
res.status(500).json({ error: 'Internal server error' });
}
});
exports.default = router;
//# sourceMappingURL=chat.js.map