// Serveur de démo modulaire avec vrais modules const express = require('express'); const path = require('path'); const cors = require('cors'); // Import des vrais modules avec les bons noms const { applySelectiveLayer } = require('./lib/selective-enhancement/SelectiveCore'); const { applyPredefinedStack } = require('./lib/selective-enhancement/SelectiveLayers'); const { applyAdversarialLayer } = require('./lib/adversarial-generation/AdversarialCore'); const { applyHumanSimulationLayer } = require('./lib/human-simulation/HumanSimulationCore'); const { applyPatternBreakingLayer } = require('./lib/pattern-breaking/PatternBreakingCore'); const { StepExecutor } = require('./lib/StepExecutor'); const app = express(); const port = process.env.PORT || 3333; // Port différent pour éviter les conflits // Middleware app.use(express.json({ limit: '10mb' })); app.use(cors()); // Servir les fichiers statiques du dossier public app.use(express.static(path.join(__dirname, 'public'))); // Route principale app.get('/', (req, res) => { res.sendFile(path.join(__dirname, 'public', 'modular-pipeline-demo.html')); }); // Route pour l'interface modulaire app.get('/modular', (req, res) => { res.sendFile(path.join(__dirname, 'public', 'modular-pipeline-demo.html')); }); // API: Génération normale app.post('/api/generate-normal', async (req, res) => { try { const { keyword, title, personality } = req.body; console.log('🌱 Génération normale:', { keyword, title, personality }); // Utiliser StepExecutor pour génération simple const stepExecutor = new StepExecutor(); // Créer des données mock pour la génération const mockData = { csvData: { mc0: keyword, t0: title, personality: { nom: personality || 'Marc' } }, elements: [{ type: 'titre', variableName: 'T0', instruction: `Rédige un titre H1 accrocheur pour ${keyword}` }, { type: 'introduction', variableName: 'INTRO', instruction: `Rédige une introduction engageante sur ${keyword}` }, { type: 'contenu', variableName: 'CONTENU', instruction: `Développe le contenu principal sur ${keyword}` }] }; const result = await stepExecutor.executeInitialGeneration(mockData); // Assembler le contenu en texte lisible pour l'affichage let assembledContent = ''; let structuredContent = null; if (result && typeof result === 'object') { // Si c'est un objet avec les éléments générés if (result.content && typeof result.content === 'object') { structuredContent = result.content; const content = result.content; // Assembler les éléments dans l'ordre logique assembledContent = [ content.Titre_H1 && `# ${content.Titre_H1}`, content.Introduction && `## Introduction\n\n${content.Introduction}`, content.Contenu_Principal && `## Contenu Principal\n\n${content.Contenu_Principal}`, content.Conclusion && `## Conclusion\n\n${content.Conclusion}` ].filter(Boolean).join('\n\n'); } else if (result.elements) { assembledContent = result.elements.map(el => el.content || el.text || el).join('\n\n'); } else { // Essayer d'extraire le contenu de différentes façons assembledContent = JSON.stringify(result, null, 2); } } else { assembledContent = result || ''; } // Si l'assemblage a échoué, utiliser le fallback if (!assembledContent || assembledContent.length < 50) { assembledContent = `# ${title || 'Guide complet'} ## Introduction ${keyword || 'Ce sujet'} représente un domaine en constante évolution avec de nombreuses opportunités. Dans ce guide, nous explorons les différentes approches pour maîtriser ${keyword || 'ce domaine'}. ## Développement Une approche méthodique permet d'obtenir des résultats optimaux. Les meilleures pratiques incluent une planification soigneuse et une exécution progressive. ## Conclusion En conclusion, ${keyword || 'ce domaine'} offre de nombreuses possibilités pour ceux qui s'y consacrent avec sérieux et méthode.`; } res.json({ success: true, content: assembledContent, structuredContent: structuredContent, // Garder aussi le contenu structuré step: 'normal-generation' }); } catch (error) { console.error('Erreur génération normale:', error); // Fallback simple const fallbackContent = `# ${req.body.title || 'Guide complet'} ## Introduction ${req.body.keyword || 'Ce sujet'} représente un domaine en constante évolution avec de nombreuses opportunités. Dans ce guide, nous explorons les différentes approches pour maîtriser ${req.body.keyword || 'ce domaine'}. ## Développement Une approche méthodique permet d'obtenir des résultats optimaux. Les meilleures pratiques incluent une planification soigneuse et une exécution progressive. ## Conclusion En conclusion, ${req.body.keyword || 'ce domaine'} offre de nombreuses possibilités pour ceux qui s'y consacrent avec sérieux et méthode.`; res.json({ success: true, content: fallbackContent, step: 'normal-generation' }); } }); // API: Application d'un module app.post('/api/apply-module', async (req, res) => { try { const { moduleId, content, config = {} } = req.body; console.log('🔧 Application module:', moduleId); // Déterminer le format du contenu pour les modules let moduleContent = content; // Si on a un contenu structuré (objet avec des clés), l'utiliser pour les modules if (typeof content === 'object' && content.structuredContent) { moduleContent = content.structuredContent; console.log('🎯 Utilisation contenu structuré pour module:', Object.keys(moduleContent)); } else if (typeof content === 'object' && content.content) { // Si on a juste content, extraire la string moduleContent = content.content; } // Sinon utiliser tel quel (string ou objet) console.log('📝 Contenu reçu (type):', typeof content, '- Contenu traité (type):', typeof moduleContent); let result; switch (moduleId) { case 'selective-light': result = await applyPredefinedStack(moduleContent, 'lightEnhancement', config); break; case 'selective-standard': result = await applyPredefinedStack(moduleContent, 'standardEnhancement', config); break; case 'selective-full': result = await applyPredefinedStack(moduleContent, 'fullEnhancement', config); break; case 'adversarial-general': result = await applyAdversarialLayer(moduleContent, 'general', 'regeneration', config); break; case 'adversarial-gptZero': result = await applyAdversarialLayer(moduleContent, 'gptZero', 'regeneration', config); break; case 'human-light': result = await applyHumanSimulationLayer(moduleContent, 'lightSimulation', config); break; case 'human-personality': result = await applyHumanSimulationLayer(moduleContent, 'personalityFocus', config); break; case 'pattern-syntax': result = await applyPatternBreakingLayer(moduleContent, 'syntaxFocus', config); break; case 'pattern-connectors': result = await applyPatternBreakingLayer(moduleContent, 'connectorsFocus', config); break; default: throw new Error(`Module inconnu: ${moduleId}`); } // Extraire le contenu final du résultat du module let finalContent = result; if (result && typeof result === 'object') { // Si le module retourne un objet avec du contenu structuré if (result.content) { finalContent = result.content; } else if (result.original) { finalContent = result.original; } else if (result.enhanced) { finalContent = result.enhanced; } else if (result.elements) { finalContent = result.elements; } else { // Si c'est déjà un objet structuré avec des clés finalContent = result; } } console.log('📄 Résultat module (type):', typeof result, '- Contenu final (type):', typeof finalContent); res.json({ success: true, content: finalContent, module: moduleId }); } catch (error) { console.error(`Erreur module ${req.body.moduleId}:`, error); res.status(500).json({ success: false, error: error.message, module: req.body.moduleId }); } }); app.listen(port, '0.0.0.0', () => { console.log(`✅ Serveur modulaire démarré sur http://0.0.0.0:${port}`); console.log(`🎯 Interface modulaire: http://0.0.0.0:${port}/modular`); console.log(`🌐 Accessible aussi via: http://localhost:${port}`); console.log(`🔧 API disponible: /api/generate-normal, /api/apply-module`); });