Files
html/api/opus5-n8n-generator.php

138 lines
5.5 KiB
PHP

<?php
// OPUS5 — n8n Workflow Generator (doctrine 74)
// Génère un JSON n8n workflow depuis description texte, via API n8n si dispo
// Pattern: POST {"description":"envoi email puis sms","nodes":[...]}
header('Content-Type: application/json');
$R = ['ts'=>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']]);