Intelligent merge: Align Main.js/StepExecutor with API setup base
Combines two parallel developments:
1. Remote: API setup base (326a6a5) with new /api/generate-simple endpoint
2. Local: Main.js/StepExecutor alignment for production consistency
Key technical improvements:
- Main.js: Migrated from generateSimple() to StepExecutor.executeInitialGeneration()
- StepExecutor: Fixed to respect HTML options (selectiveStack, adversarialMode, etc.)
* executeSelective() now uses applyPredefinedStack() with specific stack
* executeAdversarial() uses proper mode mapping (light→lightDefense, etc.)
* executeHumanSimulation() uses applyPredefinedSimulation() with mode
* executePatternBreaking() uses applyPatternBreakingStack() with mode
- Updated process_real.js and DigitalOceanWorkflow.js to use handleModularWorkflow()
- Removed legacy ManualTrigger.js (Apps Script compatibility)
This ensures 100% consistency between step-by-step debugging interface and
automated Main.js workflow, while preserving the new API functionality.
Both development paths now use identical, tested and validated functions.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
326a6a5284
commit
b60bb48e9e
@ -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');
|
||||
|
||||
11
lib/Main.js
11
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');
|
||||
|
||||
|
||||
@ -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");
|
||||
}
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user