date('c'), 'source'=>'opus5-n8n-generator']; // Fix typo $R['ts'] = date('c'); $N8N_URL = 'http://127.0.0.1:5678'; $GEN_DIR = '/var/lib/wevia/n8n-workflows'; if (!file_exists($GEN_DIR)) @mkdir($GEN_DIR, 0775, true); $raw = file_get_contents('php://input'); $d = json_decode($raw, true) ?: []; $action = $_GET['action'] ?? ($d['action'] ?? 'generate'); if ($action === 'health') { $ch = curl_init("$N8N_URL/healthz"); curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER=>true, CURLOPT_TIMEOUT=>5]); $h = curl_exec($ch); $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $R['n8n_up'] = ($code === 200); $R['n8n_response'] = substr((string)$h, 0, 200); $R['n8n_url'] = $N8N_URL; echo json_encode($R, JSON_PRETTY_PRINT); exit; } if ($action === 'generate') { $description = (string)($d['description'] ?? ''); if (!$description) { http_response_code(400); echo json_encode(['err'=>'no_description']); exit; } // Parse description simple via regex NER $description_lower = strtolower($description); $nodes = []; $node_id = 1; $last_node = null; $connections = []; // Start trigger node (manual or webhook) $trigger = [ 'parameters' => [], 'name' => 'Manual Trigger', 'type' => 'n8n-nodes-base.manualTrigger', 'typeVersion' => 1, 'position' => [240, 300], 'id' => 'node_1' ]; $nodes[] = $trigger; $last_node = 'Manual Trigger'; $node_id++; // Detect action nodes in description $action_patterns = [ '/email|mail|envoi.*mail/iu' => ['name'=>'Send Email', 'type'=>'n8n-nodes-base.emailSend', 'params'=>['toEmail'=>'{{$json.to}}', 'subject'=>'Subject', 'text'=>'Body']], '/sms|text message/iu' => ['name'=>'Send SMS', 'type'=>'n8n-nodes-base.twilio', 'params'=>['to'=>'{{$json.phone}}', 'message'=>'{{$json.message}}']], '/slack|mattermost/iu' => ['name'=>'Mattermost Send', 'type'=>'n8n-nodes-base.mattermost', 'params'=>['channel'=>'general', 'message'=>'{{$json.message}}']], '/twenty|crm|contact/iu' => ['name'=>'Twenty CRM Create', 'type'=>'n8n-nodes-base.httpRequest', 'params'=>['url'=>'http://crm.weval-consulting.com/graphql', 'method'=>'POST']], '/http|api|call/iu' => ['name'=>'HTTP Request', 'type'=>'n8n-nodes-base.httpRequest', 'params'=>['url'=>'https://example.com', 'method'=>'GET']], '/wait|delay|sleep/iu' => ['name'=>'Wait', 'type'=>'n8n-nodes-base.wait', 'params'=>['amount'=>5, 'unit'=>'seconds']], '/database|sql|postgres/iu' => ['name'=>'Postgres Query', 'type'=>'n8n-nodes-base.postgres', 'params'=>['query'=>'SELECT 1']], ]; $x = 460; foreach ($action_patterns as $pat => $template) { if (preg_match($pat, $description_lower)) { $node = [ 'parameters' => $template['params'], 'name' => $template['name'], 'type' => $template['type'], 'typeVersion' => 1, 'position' => [$x, 300], 'id' => 'node_' . $node_id ]; $nodes[] = $node; // Connect from last_node if (!isset($connections[$last_node])) $connections[$last_node] = ['main' => [[]]]; $connections[$last_node]['main'][0][] = [ 'node' => $template['name'], 'type' => 'main', 'index' => 0 ]; $last_node = $template['name']; $node_id++; $x += 220; } } $workflow = [ 'name' => 'WEVIA_generated_' . date('YmdHis'), 'nodes' => $nodes, 'connections' => $connections, 'active' => false, 'settings' => ['executionOrder' => 'v1'], 'meta' => ['generated_by' => 'opus5-n8n-generator', 'description' => $description] ]; // Save locally $fname = $workflow['name'] . '.json'; $fpath = "$GEN_DIR/$fname"; @file_put_contents($fpath, json_encode($workflow, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE)); $R['workflow'] = $workflow; $R['saved_to'] = $fpath; $R['nodes_count'] = count($nodes); $R['description'] = $description; $R['parsed_actions'] = array_values(array_filter(array_map(function($n){ return $n['name']; }, $nodes), function($n){ return $n !== 'Manual Trigger'; })); // Note: Actual POST to n8n /api/v1/workflows requires API key auth // For now we generate & save — install script can import via CLI later $R['import_hint'] = "cat $fpath | docker exec -i n8n-docker-n8n-1 n8n import:workflow --input=-"; $R['doctrine'] = '74 — n8n workflow generator (NER-based from description)'; echo json_encode($R, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); exit; } if ($action === 'list') { $files = glob("$GEN_DIR/*.json") ?: []; $list = []; foreach ($files as $f) { $list[] = [ 'name' => basename($f), 'size' => filesize($f), 'mtime' => date('c', filemtime($f)) ]; } $R['count'] = count($list); $R['workflows'] = array_slice(array_reverse($list), 0, 20); echo json_encode($R, JSON_PRETTY_PRINT); exit; } http_response_code(400); echo json_encode(['err'=>'unknown_action', 'available'=>['health', 'generate', 'list']]);