const express = require('express'); const router = express.Router(); require('dotenv').config({ path: './config/.env' }); // Mistral AI Configuration const MISTRAL_API_KEY = process.env.MISTRAL_API_KEY; const MISTRAL_BASE_URL = process.env.MISTRAL_BASE_URL || 'https://api.mistral.ai/v1'; const MISTRAL_MODEL = process.env.MISTRAL_MODEL || 'mistral-large-latest'; const AI_ENABLED = process.env.AI_ENABLED === 'true'; // Verification middleware function checkAIEnabled(req, res, next) { if (!AI_ENABLED) { return res.status(503).json({ success: false, error: 'AI features are disabled' }); } if (!MISTRAL_API_KEY) { return res.status(500).json({ success: false, error: 'Mistral API key not configured' }); } next(); } // Function to call Mistral API async function callMistralAPI(messages, temperature = null) { try { const response = await fetch(`${MISTRAL_BASE_URL}/chat/completions`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${MISTRAL_API_KEY}` }, body: JSON.stringify({ model: MISTRAL_MODEL, messages: messages, temperature: temperature !== null ? temperature : parseFloat(process.env.AI_TEMPERATURE) || 0.3, max_tokens: parseInt(process.env.AI_MAX_TOKENS) || 35000, top_p: parseFloat(process.env.AI_TOP_P) || 0.85 }) }); if (!response.ok) { const error = await response.text(); throw new Error(`Mistral API Error: ${response.status} - ${error}`); } const data = await response.json(); return data.choices[0].message.content; } catch (error) { console.error('Mistral API Error:', error); throw error; } } // POST /api/ai/rephrase - Rephrase text router.post('/rephrase', checkAIEnabled, async (req, res) => { try { const { text, context = '' } = req.body; if (!text || text.trim().length === 0) { return res.status(400).json({ success: false, error: 'Text to rephrase is required' }); } const messages = [ { role: 'system', content: `You are an assistant specialized in rephrasing technical and design texts. STRICT RULES: 1. Rephrase the text to improve clarity, style, and fluency 2. Preserve the technical level and all important details 3. Respond ONLY with the final rephrased text 4. No introduction, conclusion, explanation, or commentary 5. Do not start with "Here is", "The rephrased text" or other preamble 6. Start directly with the rephrased content ${context ? `Document context: ${context}` : ''}` }, { role: 'user', content: `Rephrase this text: "${text}"` } ]; const result = await callMistralAPI(messages, 0.2); // Precise rephrasing res.json({ success: true, data: { original: text, rephrased: result } }); } catch (error) { console.error('Rephrasing error:', error); res.status(500).json({ success: false, error: 'Error during rephrasing: ' + error.message }); } }); // POST /api/ai/check-inconsistencies - Check for inconsistencies router.post('/check-inconsistencies', checkAIEnabled, async (req, res) => { try { const { content } = req.body; if (!content || content.trim().length === 0) { return res.status(400).json({ success: false, error: 'Content to analyze is required' }); } const messages = [ { role: 'system', content: `You are an expert in technical design document analysis. Analyze the following document and identify all potential inconsistencies: - Contradictions in information - Conflicting decisions - Inconsistencies in terminology - Logical issues in architecture or choices Respond directly with your detailed analysis of the inconsistencies found.` }, { role: 'user', content: `Analyze this document to detect inconsistencies:\n\n${content}` } ]; const result = await callMistralAPI(messages, 0.1); // Precise and factual analysis res.json({ success: true, data: { analysis: result } }); } catch (error) { console.error('Inconsistencies analysis error:', error); res.status(500).json({ success: false, error: 'Error during analysis: ' + error.message }); } }); // POST /api/ai/check-duplications - Check for duplications router.post('/check-duplications', checkAIEnabled, async (req, res) => { try { const { content } = req.body; if (!content || content.trim().length === 0) { return res.status(400).json({ success: false, error: 'Content to analyze is required' }); } const messages = [ { role: 'system', content: `You are a content analysis expert. Analyze the following document to identify: - Repeated or redundant information - Sections that cover the same topic - Duplicated explanations - Concepts presented multiple times Suggest ways to eliminate these duplications while preserving important information. Respond directly with your analysis and suggestions.` }, { role: 'user', content: `Analyze this document to detect duplications:\n\n${content}` } ]; const result = await callMistralAPI(messages, 0.1); // Precise and factual analysis res.json({ success: true, data: { analysis: result } }); } catch (error) { console.error('Duplications analysis error:', error); res.status(500).json({ success: false, error: 'Error during analysis: ' + error.message }); } }); // POST /api/ai/give-advice - Give advice router.post('/give-advice', checkAIEnabled, async (req, res) => { try { const { content, domain = 'general' } = req.body; if (!content || content.trim().length === 0) { return res.status(400).json({ success: false, error: 'Content to analyze is required' }); } const messages = [ { role: 'system', content: `You are an expert consultant in design and technical architecture in the domain: ${domain}. Analyze the provided design document and give constructive advice to improve it. Focus on: - Documentation completeness - Clarity of explanations - Content organization - Domain best practices - Important missing points - Concrete improvement suggestions Be constructive and practical in your recommendations. Respond directly with your advice and improvement suggestions.` }, { role: 'user', content: `Analyze this design document and provide advice to improve it:\n\n${content}` } ]; const result = await callMistralAPI(messages, 0.4); // Balanced advice res.json({ success: true, data: { advice: result } }); } catch (error) { console.error('Advice error:', error); res.status(500).json({ success: false, error: 'Error during analysis: ' + error.message }); } }); // POST /api/ai/liberty-mode - Enhanced mode (iterative generation) router.post('/liberty-mode', checkAIEnabled, async (req, res) => { try { const { content, iterations = 1, precision = 70, focus = 'design' } = req.body; if (!content || content.trim().length === 0) { return res.status(400).json({ success: false, error: 'Base content is required' }); } const maxIterations = Math.min(parseInt(iterations), 10); // Limit to 10 iterations const precisionPercent = Math.min(Math.max(parseInt(precision), 10), 100); // Between 10% and 100% // Configure streaming for real-time responses res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Access-Control-Allow-Origin': '*' }); let currentContent = content; for (let i = 0; i < maxIterations; i++) { try { const messages = [ { role: 'system', content: `You are a technical design expert with "Enhanced Mode". MISSION: Improve and enrich the document respecting EXACTLY this precision level: ${precisionPercent}% PRECISION RULES: - At ${precisionPercent}%: You can deduce and add content up to ${precisionPercent}% based on existing information - At ${100 - precisionPercent}%: You can create logical and relevant content even without explicit info in the text INSTRUCTIONS: 1. Enrich ALL of the document consistently 2. Add sections, details, explanations, conceptual diagrams 3. Develop existing ideas with the allowed creativity 4. Maintain logical structure MANDATORY RESPONSE IN 2 PARTS SEPARATED BY "---SPLIT---": ## Analysis (Iteration ${i + 1}/${maxIterations}) [Explain the improvements made, sections added, reasoning] ---SPLIT--- [THE COMPLETE AND IMPROVED MARKDOWN DOCUMENT - WITHOUT "## Document" TITLE - DIRECTLY THE CONTENT] Focus: ${focus} Precision: ${precisionPercent}%` }, { role: 'user', content: `Document to improve (Iteration ${i + 1}):\n\n${currentContent}` } ]; // Temperature based on precision (more creative = higher temperature) const temperature = (100 - precisionPercent) / 100 * 0.8 + 0.1; // Between 0.1 and 0.9 const result = await callMistralAPI(messages, temperature); // Separate explanation from markdown const parts = result.split('---SPLIT---'); let explanation = ''; let newMarkdown = currentContent; // Default, keep old content if (parts.length >= 2) { explanation = parts[0].trim(); newMarkdown = parts[1].trim(); // Update for next iteration currentContent = newMarkdown; } else { // Fallback if no split found explanation = result; } // Send this iteration's response const iterationData = { iteration: i + 1, explanation: explanation, markdown: newMarkdown, completed: false }; res.write(`data: ${JSON.stringify(iterationData)}\n\n`); // Small delay to allow client-side display await new Promise(resolve => setTimeout(resolve, 500)); } catch (iterationError) { console.error(`Iteration ${i + 1} error:`, iterationError); const errorData = { iteration: i + 1, error: `Iteration ${i + 1} error: ${iterationError.message}`, completed: true }; res.write(`data: ${JSON.stringify(errorData)}\n\n`); break; } } // End signal const finalData = { completed: true, totalIterations: maxIterations, finalMarkdown: currentContent }; res.write(`data: ${JSON.stringify(finalData)}\n\n`); res.end(); } catch (error) { console.error('Enhanced mode error:', error); const errorData = { error: 'Error during generation: ' + error.message, completed: true }; res.write(`data: ${JSON.stringify(errorData)}\n\n`); res.end(); } }); // GET /api/ai/status - AI status router.get('/status', (req, res) => { res.json({ success: true, data: { enabled: AI_ENABLED, model: MISTRAL_MODEL, configured: !!MISTRAL_API_KEY } }); }); module.exports = router;