const { Conversation, Message, Plan, User } = require('../models'); const logger = require('../utils/logger'); const model1Service = require('../services/model1Service'); const chatRouter = require('../services/chatRouter'); const createConversation = async (req, res) => { try { const { title } = req.body; const userId = req.user.userId; const conversation = await Conversation.create({ user_id: userId, title: title || 'New Conversation', status: 'active' }); logger.info(`New conversation created: ${conversation.id}`); res.status(201).json({ success: true, data: { conversation } }); } catch (error) { logger.error('Create conversation error:', error); res.status(500).json({ success: false, error: 'Internal server error' }); } }; const getConversations = async (req, res) => { try { const userId = req.user.userId; const { page = 1, limit = 10, status } = req.query; const whereClause = { user_id: userId }; if (status) whereClause.status = status; const conversations = await Conversation.findAndCountAll({ where: whereClause, include: [ { model: Message, limit: 1, order: [['created_at', 'DESC']] } ], order: [['created_at', 'DESC']], limit: parseInt(limit), offset: (parseInt(page) - 1) * parseInt(limit) }); res.json({ success: true, data: { conversations: conversations.rows, pagination: { page: parseInt(page), limit: parseInt(limit), total: conversations.count, pages: Math.ceil(conversations.count / limit) } } }); } catch (error) { logger.error('Get conversations error:', error); res.status(500).json({ success: false, error: 'Internal server error' }); } }; const getConversation = async (req, res) => { try { const { conversationId } = req.params; const userId = req.user.userId; const conversation = await Conversation.findOne({ where: { id: conversationId, user_id: userId }, include: [ { model: Message, order: [['created_at', 'ASC']] }, { model: Plan, order: [['created_at', 'DESC']] } ] }); if (!conversation) { return res.status(404).json({ success: false, error: 'Conversation not found' }); } res.json({ success: true, data: { conversation } }); } catch (error) { logger.error('Get conversation error:', error); res.status(500).json({ success: false, error: 'Internal server error' }); } }; const sendMessage = async (req, res) => { try { const { conversationId, content, messageType = 'text' } = req.body; const userId = req.user.userId; // Verify conversation belongs to user const conversation = await Conversation.findOne({ where: { id: conversationId, user_id: userId } }); if (!conversation) { return res.status(404).json({ success: false, error: 'Conversation not found' }); } // Create user message const userMessage = await Message.create({ conversation_id: conversationId, role: 'user', content, message_type: messageType }); // Get conversation history for context const conversationHistory = await Message.findAll({ where: { conversation_id: conversationId }, order: [['created_at', 'DESC']], limit: 20 // Last 20 messages for context }); // Create properly ordered conversation history for context const orderedHistory = conversationHistory.reverse().map(msg => ({ role: msg.role, content: msg.content, message_type: msg.message_type, timestamp: msg.created_at })); // Route the message to determine response type const routingDecision = await chatRouter.routeMessage(content, { conversationId, userId, timestamp: new Date().toISOString(), conversationHistory: orderedHistory }); let assistantMessage; if (routingDecision.responseType === 'plan_needed' && routingDecision.isEngineeringQuestion) { // Generate engineering plan using MODEL1 try { const planData = await model1Service.generatePlan(content, { conversationId, userId, timestamp: new Date().toISOString() }); // Save the plan to database const plan = await Plan.create({ conversation_id: conversationId, title: planData.title, description: planData.description, steps: planData.steps, status: 'draft', tools_required: planData.toolsRequired || [], estimated_duration: planData.estimatedDuration, complexity_score: planData.complexityScore, metadata: { safetyConsiderations: planData.safetyConsiderations, qualityChecks: planData.qualityChecks, processingTime: planData.processingTime, tokensUsed: planData.tokensUsed, model: planData.model } }); // Create assistant message with plan assistantMessage = await Message.create({ conversation_id: conversationId, plan_id: plan.id, role: 'assistant', content: planData.rawContent || `# ${planData.title}\n\n${planData.description}\n\n## Steps:\n${planData.steps.map((step, index) => `${index + 1}. ${step}`).join('\n')}`, message_type: 'plan', metadata: { modelType: 'MODEL1', processingTime: planData.processingTime, tokensUsed: planData.tokensUsed, routingDecision: routingDecision.reasoning } }); logger.info(`MODEL1 plan generated: ${plan.id} for conversation: ${conversationId}`); } catch (error) { logger.error('MODEL1 plan generation failed:', error); // Fallback to simple response if plan generation fails const fallbackResponse = await chatRouter.generateSimpleResponse(content, { conversationHistory: orderedHistory }); assistantMessage = await Message.create({ conversation_id: conversationId, role: 'assistant', content: fallbackResponse, message_type: 'text', metadata: { error: error.message, modelType: 'FALLBACK', routingDecision: routingDecision.reasoning } }); } } else { // Generate simple conversational response const responseContent = routingDecision.response || await chatRouter.generateSimpleResponse(content, { conversationHistory: orderedHistory }); assistantMessage = await Message.create({ conversation_id: conversationId, role: 'assistant', content: responseContent, message_type: 'text', metadata: { modelType: 'REASONAI', routingDecision: routingDecision.reasoning, responseType: routingDecision.responseType } }); logger.info(`Simple response generated for conversation: ${conversationId}`, { responseType: routingDecision.responseType, reasoning: routingDecision.reasoning }); } logger.info(`Message sent in conversation: ${conversationId}`); res.json({ success: true, data: { userMessage, assistantMessage } }); } catch (error) { logger.error('Send message error:', error); res.status(500).json({ success: false, error: 'Internal server error' }); } }; const updateConversation = async (req, res) => { try { const { conversationId } = req.params; const { title, status } = req.body; const userId = req.user.userId; const conversation = await Conversation.findOne({ where: { id: conversationId, user_id: userId } }); if (!conversation) { return res.status(404).json({ success: false, error: 'Conversation not found' }); } const updateData = {}; if (title) updateData.title = title; if (status) updateData.status = status; await conversation.update(updateData); logger.info(`Conversation updated: ${conversationId}`); res.json({ success: true, data: { conversation } }); } catch (error) { logger.error('Update conversation error:', error); res.status(500).json({ success: false, error: 'Internal server error' }); } }; const deleteConversation = async (req, res) => { try { const { conversationId } = req.params; const userId = req.user.userId; const conversation = await Conversation.findOne({ where: { id: conversationId, user_id: userId } }); if (!conversation) { return res.status(404).json({ success: false, error: 'Conversation not found' }); } await conversation.destroy(); logger.info(`Conversation deleted: ${conversationId}`); res.json({ success: true, message: 'Conversation deleted successfully' }); } catch (error) { logger.error('Delete conversation error:', error); res.status(500).json({ success: false, error: 'Internal server error' }); } }; module.exports = { createConversation, getConversations, getConversation, sendMessage, updateConversation, deleteConversation };