Muyue aa0a3863b6 Refactor: Complete internationalization and modernization to v2.0.0
Major Changes:
  - Remove all emojis from UI, code, and documentation for professional appearance
  - Translate entire codebase from French to English (code, comments, strings, UI)
  - Simplify template system: 18 templates → single default template
  - Rename "Mode Liberté Total" to "Enhanced Mode" throughout
  - Add comprehensive English README with installation and usage guides
  - Add MIT License (open source, no attribution required)
  - Update package.json with proper metadata and keywords

  Breaking Changes:
  - Template API endpoint changed from /api/templates/:domain/:level to /api/templates/default
  - All French UI text and notifications replaced with English
  - Template directory structure simplified

  Technical Improvements:
  - Cleaner, more maintainable codebase
  - Improved internationalization
  - Better developer experience with English documentation
  - Professional appearance suitable for production use
2025-10-14 15:05:39 +02:00

411 lines
12 KiB
JavaScript

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;