diff --git a/lib/DigitalOceanWorkflow.js b/lib/DigitalOceanWorkflow.js index 52a922b..b2a430c 100644 --- a/lib/DigitalOceanWorkflow.js +++ b/lib/DigitalOceanWorkflow.js @@ -10,7 +10,7 @@ const { JWT } = require('google-auth-library'); // Import des autres modules du projet (à adapter selon votre structure) const { logSh } = require('./ErrorReporting'); -const { handleFullWorkflow } = require('./Main'); +const { handleModularWorkflow } = require('./Main'); const { getPersonalities, selectPersonalityWithAI } = require('./BrainConfig'); // ============= CONFIGURATION DIGITAL OCEAN ============= @@ -104,7 +104,7 @@ async function runAutonomousWorkflowFromTrigger(rowNumber) { source: 'digital_ocean_autonomous' }; - const result = await handleFullWorkflow(workflowData); + const result = await handleModularWorkflow(workflowData); const duration = Date.now() - startTime; logSh(`🏆 ORCHESTRATION TERMINÉE en ${Math.round(duration/1000)}s`, 'INFO'); diff --git a/lib/Main.js b/lib/Main.js index 4459881..7e2ef5d 100644 --- a/lib/Main.js +++ b/lib/Main.js @@ -11,8 +11,8 @@ const { tracer } = require('./trace'); const { readInstructionsData, selectPersonalityWithAI, getPersonalities } = require('./BrainConfig'); const { extractElements, buildSmartHierarchy } = require('./ElementExtraction'); const { generateMissingKeywords } = require('./MissingKeywords'); -// ContentGeneration.js supprimé - Utiliser generateSimple depuis selective-enhancement -const { generateSimple } = require('./selective-enhancement/SelectiveUtils'); +// Migration vers StepExecutor pour garantir la cohérence avec step-by-step +const { StepExecutor } = require('./StepExecutor'); const { injectGeneratedContent } = require('./ContentAssembly'); const { saveGeneratedArticleOrganic } = require('./ArticleStorage'); @@ -107,7 +107,8 @@ async function handleModularWorkflowWithData(data, config = {}) { // ======================================== // Continuer avec le workflow modulaire normal - const generationResult = await generateSimple(hierarchy, csvData); + const executor = new StepExecutor(); + const generationResult = await executor.executeInitialGeneration(csvData, { hierarchy }); const generatedContent = generationResult.content || generationResult; logSh(` ✅ ${Object.keys(generatedContent).length} éléments générés`, 'DEBUG'); @@ -315,7 +316,9 @@ async function handleModularWorkflow(config = {}) { // ======================================== logSh(`💫 PHASE 5: Génération contenu de base`, 'INFO'); - const generatedContent = await generateSimple(hierarchy, csvData); + const executor = new StepExecutor(); + const generationResult = await executor.executeInitialGeneration(csvData, { hierarchy }); + const generatedContent = generationResult.content; logSh(` ✅ ${Object.keys(generatedContent).length} éléments générés`, 'DEBUG'); diff --git a/lib/ManualTrigger.js b/lib/ManualTrigger.js deleted file mode 100644 index 8017e25..0000000 --- a/lib/ManualTrigger.js +++ /dev/null @@ -1,120 +0,0 @@ -const { logSh } = require('./ErrorReporting'); // Using unified logSh from ErrorReporting - -/** - * 🚀 TRIGGER MANUEL - Lit ligne 2 et lance le workflow - * Exécute cette fonction depuis l'éditeur Apps Script - */ -function runWorkflowLigne(numeroLigne = 2) { - cleanLogSheet(); // Nettoie les logs pour ce test - - try { - logSh('🎬 >>> DÉMARRAGE WORKFLOW MANUEL <<<', 'INFO'); - - // 1. LIRE AUTOMATIQUEMENT LA LIGNE INDIQUÉ - const csvData = readCSVDataFromRow(numeroLigne); - logSh(`✅ Données lues - MC0: ${csvData.mc0}`, 'INFO'); - logSh(`✅ Titre: ${csvData.t0}`, 'INFO'); - logSh(`✅ Personnalité: ${csvData.personality.nom}`, 'INFO'); - - // 2. XML TEMPLATE SIMPLE POUR TEST (ou lit depuis Digital Ocean si configuré) - const xmlTemplate = getXMLTemplateForTest(csvData); - logSh(`✅ XML template: ${xmlTemplate.length} caractères`, 'INFO'); - - // 3. 🎯 LANCER LE WORKFLOW PRINCIPAL - const workflowData = { - csvData: csvData, - xmlTemplate: Utilities.base64Encode(xmlTemplate), - source: 'manuel_ligne2' - }; - - const result = handleFullWorkflow(workflowData); - - logSh('🏆 === WORKFLOW MANUEL TERMINÉ ===', 'INFO'); - - // ← EXTRAIRE LES VRAIES DONNÉES - let actualData; - if (result && result.getContentText) { - // C'est un ContentService, extraire le JSON - actualData = JSON.parse(result.getContentText()); - } else { - actualData = result; - } - - logSh(`Type result: ${typeof result}`, 'DEBUG'); - logSh(`Result keys: ${Object.keys(result || {})}`, 'DEBUG'); - logSh(`ActualData keys: ${Object.keys(actualData || {})}`, 'DEBUG'); - logSh(`ActualData: ${JSON.stringify(actualData)}`, 'DEBUG'); - - if (actualData && actualData.stats) { - logSh(`📊 Éléments générés: ${actualData.stats.contentPieces}`, 'INFO'); - logSh(`📝 Nombre de mots: ${actualData.stats.wordCount}`, 'INFO'); - } else { - logSh('⚠️ Format résultat inattendu', 'WARNING'); - logSh('ActualData: ' + JSON.stringify(actualData, null, 2), 'DEBUG'); // Using logSh instead of console.log - } - - return actualData; - - } catch (error) { - logSh(`❌ ERREUR WORKFLOW MANUEL: ${error.toString()}`, 'ERROR'); - logSh(`Stack: ${error.stack}`, 'ERROR'); - throw error; - } -} - -/** - * HELPER - Lire CSV depuis une ligne spécifique - */ -function readCSVDataFromRow(rowNumber) { - const sheetId = '1iA2GvWeUxX-vpnAMfVm3ZMG9LhaC070SdGssEcXAh2c'; - const spreadsheet = SpreadsheetApp.openById(sheetId); - const articlesSheet = spreadsheet.getSheetByName('instructions'); - - // Lire la ligne complète (colonnes A à H) - const range = articlesSheet.getRange(rowNumber, 1, 1, 9); - const [slug, t0, mc0, tMinus1, lMinus1, mcPlus1, tPlus1, lPlus1, xmlFileName] = range.getValues()[0]; - - logSh(`📖 Lecture ligne ${rowNumber}: ${slug}`, 'DEBUG'); - - // Récupérer personnalités et sélectionner automatiquement - const personalitiesSheet = spreadsheet.getSheetByName('Personnalites'); - const personalities = getPersonalities(personalitiesSheet); - const selectedPersonality = selectPersonalityWithAI(mc0, t0, personalities); - - return { - rowNumber: rowNumber, - slug: slug || 'test-slug', - t0: t0 || 'Titre par défaut', - mc0: mc0 || 'mot-clé test', - tMinus1: tMinus1 || 'parent', - lMinus1: lMinus1 || '/parent', - mcPlus1: mcPlus1 || 'mot1,mot2,mot3,mot4', - tPlus1: tPlus1 || 'Titre1,Titre2,Titre3,Titre4', - lPlus1: lPlus1 || '/lien1,/lien2,/lien3,/lien4', - personality: selectedPersonality, - xmlFileName: xmlFileName ? xmlFileName.toString().trim() : null - }; -} - -/** - * HELPER - XML Template simple pour test (ou depuis Digital Ocean) - */ -function getXMLTemplateForTest(csvData) { - logSh("csvData.xmlFileName: " + csvData.xmlFileName, 'DEBUG'); // Using logSh instead of console.log - - if (csvData.xmlFileName) { - logSh("Tentative Digital Ocean...", 'INFO'); // Using logSh instead of console.log - try { - return fetchXMLFromDigitalOceanSimple(csvData.xmlFileName); - } catch (error) { - // ← ENLÈVE LE CATCH SILENCIEUX - logSh("Erreur DO: " + error.toString(), 'WARNING'); // Using logSh instead of console.log - logSh(`❌ ERREUR DO DÉTAILLÉE: ${error.toString()}`, 'ERROR'); - - // Continue sans Digital Ocean - } - } - - logSh("❌ FATAL: Aucun template XML disponible", 'ERROR'); - throw new Error("FATAL: Template XML indisponible (Digital Ocean inaccessible + pas de fallback) - arrêt du workflow"); -} \ No newline at end of file diff --git a/lib/StepExecutor.js b/lib/StepExecutor.js index f9b3c6f..d0b7230 100644 --- a/lib/StepExecutor.js +++ b/lib/StepExecutor.js @@ -149,7 +149,7 @@ class StepExecutor { async executeSelective(inputData, options = {}) { try { // Import dynamique pour éviter les dépendances circulaires - const { applyAllSelectiveLayers } = require('./selective-enhancement/SelectiveCore'); + const { applyPredefinedStack } = require('./selective-enhancement/SelectiveLayers'); logSh('🎯 Démarrage Selective Enhancement seulement', 'DEBUG'); @@ -178,11 +178,10 @@ class StepExecutor { const beforeContent = JSON.parse(JSON.stringify(contentToEnhance)); // Deep copy - // ÉTAPE ENHANCEMENT - Améliorer le contenu fourni - logSh('🎯 Enhancement sélectif du contenu fourni', 'DEBUG'); - const result = await applyAllSelectiveLayers(contentToEnhance, { - ...inputData, - ...config, + // ÉTAPE ENHANCEMENT - Améliorer le contenu fourni avec la stack spécifiée + logSh(`🎯 Enhancement sélectif du contenu avec stack: ${config.selectiveStack}`, 'DEBUG'); + const result = await applyPredefinedStack(contentToEnhance, config.selectiveStack, { + csvData: inputData, analysisMode: false }); @@ -216,7 +215,7 @@ class StepExecutor { */ async executeAdversarial(inputData, options = {}) { try { - const { applyAdversarialLayer } = require('./adversarial-generation/AdversarialCore'); + const { applyPredefinedStack: applyAdversarialStack } = require('./adversarial-generation/AdversarialLayers'); logSh('🎯 Démarrage Adversarial Generation', 'DEBUG'); @@ -244,12 +243,22 @@ class StepExecutor { const beforeContent = JSON.parse(JSON.stringify(contentToTransform)); // Deep copy - const result = await applyAdversarialLayer(contentToTransform, { - ...config, + // Mapping des modes vers les stacks prédéfinies + const modeToStack = { + 'light': 'lightDefense', + 'standard': 'standardDefense', + 'heavy': 'heavyDefense', + 'none': 'none', + 'adaptive': 'adaptive' + }; + + const stackName = modeToStack[config.adversarialMode] || 'standardDefense'; + logSh(`🎯 Adversarial avec stack: ${stackName} (mode: ${config.adversarialMode})`, 'DEBUG'); + + const result = await applyAdversarialStack(contentToTransform, stackName, { csvData: inputData, detectorTarget: config.detectorTarget || 'general', - intensity: config.intensity || 1.0, - method: config.method || 'regeneration' + intensity: config.intensity || 1.0 }); return { @@ -280,7 +289,7 @@ class StepExecutor { */ async executeHumanSimulation(inputData, options = {}) { try { - const { applyHumanSimulationLayer } = require('./human-simulation/HumanSimulationCore'); + const { applyPredefinedSimulation } = require('./human-simulation/HumanSimulationLayers'); logSh('🎯 Démarrage Human Simulation', 'DEBUG'); @@ -308,7 +317,13 @@ class StepExecutor { const beforeContent = JSON.parse(JSON.stringify(contentToHumanize)); // Deep copy - const result = await applyHumanSimulationLayer(contentToHumanize, inputData, config); + const simulationMode = config.humanSimulationMode || 'standardSimulation'; + logSh(`🎯 Human Simulation avec mode: ${simulationMode}`, 'DEBUG'); + + const result = await applyPredefinedSimulation(contentToHumanize, simulationMode, { + csvData: inputData, + ...config + }); return { content: result.content || result, @@ -338,7 +353,7 @@ class StepExecutor { */ async executePatternBreaking(inputData, options = {}) { try { - const { applyPatternBreakingLayer } = require('./pattern-breaking/PatternBreakingCore'); + const { applyPatternBreakingStack } = require('./pattern-breaking/PatternBreakingLayers'); logSh('🎯 Démarrage Pattern Breaking', 'DEBUG'); @@ -366,7 +381,13 @@ class StepExecutor { const beforeContent = JSON.parse(JSON.stringify(contentToTransform)); // Deep copy - const result = await applyPatternBreakingLayer(contentToTransform, inputData, config); + const patternMode = config.patternBreakingMode || 'standardPatternBreaking'; + logSh(`🎯 Pattern Breaking avec mode: ${patternMode}`, 'DEBUG'); + + const result = await applyPatternBreakingStack(contentToTransform, patternMode, { + csvData: inputData, + ...config + }); return { content: result.content || result, diff --git a/process_real.js b/process_real.js index 665218d..0931809 100644 --- a/process_real.js +++ b/process_real.js @@ -4,7 +4,7 @@ // ======================================== const { readCSVDataWithXMLFileName, fetchXMLFromDigitalOceanSimple } = require('./lib/DigitalOceanWorkflow'); -const { handleFullWorkflow } = require('./lib/Main'); +const { handleModularWorkflow } = require('./lib/Main'); /** * Fonction principale qui fait VRAIMENT tout le processus @@ -53,7 +53,7 @@ async function processRealData(rowNumber) { console.log('4️⃣ Lancement workflow (6 LLMs)...'); const startTime = Date.now(); - const result = await handleFullWorkflow(workflowData); + const result = await handleModularWorkflow(workflowData); const duration = Date.now() - startTime;