auto-sync-0225

This commit is contained in:
opus
2026-04-17 02:25:01 +02:00
parent 824e38a520
commit 8369e10bb6
15 changed files with 599 additions and 0 deletions

206
api/em-api.php Normal file
View File

@@ -0,0 +1,206 @@
<?php
/**
* /api/em/ router — EM endpoints (GODMODE 17avr)
* Handles: agents-registry, vsm, bpmn-routines, dmaic, kpi/live, poc/start, tenant/bootstrap, plans
*/
header("Content-Type: application/json; charset=utf-8");
header("Access-Control-Allow-Origin: *");
$DB_HOST = "10.1.0.3";
$DB_PORT = 5432;
$DB_NAME = "adx_system";
$DB_USER = "admin";
$DB_PASS = "admin123";
try {
$pdo = new PDO("pgsql:host=$DB_HOST;port=$DB_PORT;dbname=$DB_NAME", $DB_USER, $DB_PASS, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
} catch (Exception $e) {
// Fallback to local if S95 unreachable
try {
$pdo = new PDO("pgsql:host=127.0.0.1;port=5432;dbname=adx_system", $DB_USER, $DB_PASS, [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
} catch (Exception $e2) {
http_response_code(500);
echo json_encode(["error" => "db-unreachable"]);
exit;
}
}
$uri = parse_url($_SERVER["REQUEST_URI"] ?? "", PHP_URL_PATH);
$path = preg_replace("#^/api/em/?#", "", $uri);
$parts = explode("/", trim($path, "/"));
$endpoint = $parts[0] ?? "";
function audit($pdo, $action, $target = null, $payload = []) {
$tenant = $_GET["tenant"] ?? $_POST["tenant"] ?? "weval";
try {
$stmt = $pdo->prepare("INSERT INTO weval.audit_log (tenant_id, actor, action, target, payload, ip) VALUES (?,?,?,?,?,?)");
$stmt->execute([$tenant, "em-api", $action, $target, json_encode($payload), $_SERVER["REMOTE_ADDR"] ?? ""]);
} catch (Exception $e) {}
}
switch ($endpoint) {
case "agents-registry":
$tenant = $_GET["tenant"] ?? "weval";
$dept = $_GET["dept"] ?? null;
$sql = "SELECT id,name,dept,tier,layer_soa,skills,routines,status,source FROM weval.agent_registry WHERE tenant_id=?";
$params = [$tenant];
if ($dept) { $sql .= " AND dept=?"; $params[] = $dept; }
$sql .= " ORDER BY tier, name";
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as &$r) {
$r["skills"] = json_decode($r["skills"], true);
$r["routines"] = json_decode($r["routines"], true);
}
echo json_encode(["tenant" => $tenant, "count" => count($rows), "agents" => $rows]);
break;
case "vsm":
$tenant = $_GET["tenant"] ?? "weval";
if (!empty($parts[1])) {
$stmt = $pdo->prepare("SELECT * FROM weval.vsm_dept WHERE tenant_id=? AND dept_code=?");
$stmt->execute([$tenant, $parts[1]]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (!$row) { http_response_code(404); echo json_encode(["error"=>"not-found"]); break; }
$row["kpis"] = json_decode($row["kpis"], true);
$row["agents"] = json_decode($row["agents"], true);
echo json_encode($row);
} else {
$stmt = $pdo->prepare("SELECT dept_code, dept_name, icon, supplier, input, process, output, customer, kpis, agents FROM weval.vsm_dept WHERE tenant_id=? ORDER BY id");
$stmt->execute([$tenant]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as &$r) {
$r["kpis"] = json_decode($r["kpis"], true);
$r["agents"] = json_decode($r["agents"], true);
}
echo json_encode(["tenant"=>$tenant, "count"=>count($rows), "depts"=>$rows]);
}
break;
case "bpmn-routines":
$tenant = $_GET["tenant"] ?? "weval";
$stmt = $pdo->prepare("SELECT id, name, dept, steps, sla_hours, status, mapped_intents FROM weval.bpmn_routines WHERE tenant_id=? ORDER BY id");
$stmt->execute([$tenant]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as &$r) {
$r["steps"] = json_decode($r["steps"], true);
$r["mapped_intents"] = json_decode($r["mapped_intents"], true);
}
echo json_encode(["tenant"=>$tenant, "count"=>count($rows), "routines"=>$rows]);
break;
case "dmaic":
$tenant = $parts[1] ?? $_GET["tenant"] ?? "weval";
$vs = $parts[2] ?? $_GET["vs"] ?? null;
if ($vs) {
$stmt = $pdo->prepare("SELECT * FROM weval.dmaic_cycles WHERE tenant_id=? AND vs_id=?");
$stmt->execute([$tenant, $vs]);
$row = $stmt->fetch(PDO::FETCH_ASSOC);
echo json_encode($row ?: ["error"=>"not-found"]);
} else {
$stmt = $pdo->prepare("SELECT id, vs_id, name, phase, progress, updated_at FROM weval.dmaic_cycles WHERE tenant_id=? ORDER BY id");
$stmt->execute([$tenant]);
echo json_encode(["tenant"=>$tenant, "cycles"=>$stmt->fetchAll(PDO::FETCH_ASSOC)]);
}
break;
case "kpi":
if (($parts[1] ?? "") === "live") {
$tenant = $_GET["tenant"] ?? "weval";
$dept = $_GET["dept"] ?? null;
$sql = "SELECT DISTINCT ON (dept, kpi_name) dept, kpi_name, value, unit, ts, source FROM weval.kpi_timeseries WHERE tenant_id=?";
$params = [$tenant];
if ($dept) { $sql .= " AND dept=?"; $params[] = $dept; }
$sql .= " ORDER BY dept, kpi_name, ts DESC";
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
echo json_encode(["tenant"=>$tenant, "kpis"=>$stmt->fetchAll(PDO::FETCH_ASSOC)]);
} else {
http_response_code(404);
echo json_encode(["error"=>"unknown-kpi-endpoint"]);
}
break;
case "poc":
if (($parts[1] ?? "") === "start") {
$raw = json_decode(file_get_contents("php://input"), true) ?? $_POST;
$tenant_id = "poc_" . substr(md5(($raw["name"] ?? "demo") . time()), 0, 8);
$name = $raw["name"] ?? "POC Demo";
$email = $raw["email"] ?? "demo@example.com";
$dept = $raw["dept"] ?? "commerce";
try {
$pdo->prepare("INSERT INTO weval.tenants (tenant_id, name, plan_code, phase, contact_email) VALUES (?,?,?,?,?)")->execute([$tenant_id, $name, "poc", "poc", $email]);
// Clone the selected dept VSM
$pdo->prepare("INSERT INTO weval.vsm_dept (tenant_id, dept_code, dept_name, icon, supplier, input, process, output, customer, kpis, agents) SELECT ?, dept_code, dept_name, icon, supplier, input, process, output, customer, kpis, agents FROM weval.vsm_dept WHERE tenant_id='weval' AND dept_code=?")->execute([$tenant_id, $dept]);
// Create DMAIC cycle
$pdo->prepare("INSERT INTO weval.dmaic_cycles (tenant_id, vs_id, name, phase) VALUES (?, ?, ?, 'define')")->execute([$tenant_id, $dept . "-poc", "POC $name - $dept VSM"]);
audit($pdo, "poc_start", $tenant_id, ["email"=>$email, "dept"=>$dept]);
echo json_encode(["ok"=>true, "tenant_id"=>$tenant_id, "plan"=>"poc", "dept"=>$dept, "brain_center_url"=>"/brain-center-tenant.html?t=$tenant_id", "dmaic_url"=>"/dmaic-workbench.html?t=$tenant_id&vs=$dept-poc", "next_steps"=>["Interview DG","Scan process $dept","DMAIC Define","Baseline KPIs","Rapport"]]);
} catch (Exception $e) {
http_response_code(500);
echo json_encode(["error"=>$e->getMessage()]);
}
} else {
echo json_encode(["endpoints"=>["/api/em/poc/start"]]);
}
break;
case "plans":
$stmt = $pdo->query("SELECT plan_code, plan_name, tier, setup_fee, monthly_fee, currency, vs_count, max_users, features FROM weval.em_plans WHERE active=true ORDER BY setup_fee");
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($rows as &$r) $r["features"] = json_decode($r["features"], true);
echo json_encode(["plans"=>$rows]);
break;
case "tenant":
if (($parts[1] ?? "") === "bootstrap") {
$raw = json_decode(file_get_contents("php://input"), true) ?? $_POST;
$tenant_id = $raw["tenant_id"] ?? "demo_" . time();
$plan = $raw["plan"] ?? "mvp";
$name = $raw["name"] ?? "Demo Tenant";
$email = $raw["email"] ?? "demo@example.com";
try {
$pdo->prepare("INSERT INTO weval.tenants (tenant_id, name, plan_code, phase, contact_email) VALUES (?,?,?,?,?) ON CONFLICT (tenant_id) DO UPDATE SET plan_code=EXCLUDED.plan_code, phase=EXCLUDED.phase")->execute([$tenant_id, $name, $plan, $plan, $email]);
// Clone all VSM depts for MVP/Enterprise
if (in_array($plan, ["mvp","enterprise"])) {
$n = $plan === "enterprise" ? 15 : 5;
$pdo->prepare("INSERT INTO weval.vsm_dept (tenant_id, dept_code, dept_name, icon, supplier, input, process, output, customer, kpis, agents) SELECT ?, dept_code, dept_name, icon, supplier, input, process, output, customer, kpis, agents FROM weval.vsm_dept WHERE tenant_id='weval' LIMIT ? ON CONFLICT DO NOTHING")->execute([$tenant_id, $n]);
}
audit($pdo, "tenant_bootstrap", $tenant_id, ["plan"=>$plan]);
echo json_encode(["ok"=>true, "tenant_id"=>$tenant_id, "plan"=>$plan, "brain_center_url"=>"/brain-center-tenant.html?t=$tenant_id"]);
} catch (Exception $e) { http_response_code(500); echo json_encode(["error"=>$e->getMessage()]); }
} else {
$stmt = $pdo->query("SELECT tenant_id, name, plan_code, phase, status FROM weval.tenants ORDER BY created_at DESC LIMIT 50");
echo json_encode(["tenants"=>$stmt->fetchAll(PDO::FETCH_ASSOC)]);
}
break;
case "audit":
$tenant = $_GET["tenant"] ?? "weval";
$limit = min(intval($_GET["limit"] ?? 50), 500);
$stmt = $pdo->prepare("SELECT actor, action, target, ts FROM weval.audit_log WHERE tenant_id=? ORDER BY ts DESC LIMIT ?");
$stmt->execute([$tenant, $limit]);
echo json_encode(["tenant"=>$tenant, "events"=>$stmt->fetchAll(PDO::FETCH_ASSOC)]);
break;
default:
echo json_encode([
"service" => "WEVIA EM API",
"version" => "1.0-godmode-17avr",
"endpoints" => [
"/api/em/agents-registry?tenant=weval&dept=?",
"/api/em/vsm?tenant=weval (list) or /api/em/vsm/{dept}",
"/api/em/bpmn-routines?tenant=weval",
"/api/em/dmaic/{tenant}/{vs_id}",
"/api/em/kpi/live?tenant=weval&dept=?",
"/api/em/poc/start (POST)",
"/api/em/plans",
"/api/em/tenant/bootstrap (POST)",
"/api/em/audit?tenant=weval"
]
]);
}

View File

@@ -0,0 +1,14 @@
<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
$db = @pg_connect("host=127.0.0.1 port=5432 user=admin password=admin123 dbname=adx_system");
if (!$db) { echo json_encode(['error'=>'db']); exit; }
$tenant = $_GET['tenant'] ?? 'weval';
$dept = $_GET['dept'] ?? null;
$q = "SELECT id,name,dept,tier,layer_soa,skills,routines,status,source FROM weval.agent_registry WHERE tenant_id=$1";
$params = [$tenant];
if ($dept) { $q .= " AND dept=$2"; $params[] = $dept; }
$q .= " ORDER BY tier, dept, name";
$r = @pg_query_params($db, $q, $params);
$agents = []; while ($row = pg_fetch_assoc($r)) $agents[] = $row;
echo json_encode(['tenant'=>$tenant,'count'=>count($agents),'agents'=>$agents]);

12
api/em/bpmn-routines.php Normal file
View File

@@ -0,0 +1,12 @@
<?php
header('Content-Type: application/json');
$db = @pg_connect("host=127.0.0.1 port=5432 user=admin password=admin123 dbname=adx_system");
$tenant = $_GET['tenant'] ?? 'weval';
$dept = $_GET['dept'] ?? null;
$q = "SELECT id,name,dept,steps,sla_hours,status FROM weval.bpmn_routines WHERE tenant_id=$1";
$p = [$tenant];
if ($dept) { $q .= " AND dept=$2"; $p[] = $dept; }
$q .= " ORDER BY id";
$r = @pg_query_params($db, $q, $p);
$list = []; while ($row = pg_fetch_assoc($r)) { $row['steps']=json_decode($row['steps'],true); $list[] = $row; }
echo json_encode(['tenant'=>$tenant,'count'=>count($list),'routines'=>$list]);

25
api/em/dmaic.php Normal file
View File

@@ -0,0 +1,25 @@
<?php
header('Content-Type: application/json');
$db = @pg_connect("host=127.0.0.1 port=5432 user=admin password=admin123 dbname=adx_system");
$tenant = $_GET['tenant'] ?? 'weval';
$vs_id = $_GET['vs_id'] ?? null;
$action = $_GET['action'] ?? 'list';
if ($action === 'advance' && $vs_id) {
$phase = $_POST['phase'] ?? 'measure';
$progress = intval($_POST['progress'] ?? 40);
pg_query_params($db, "UPDATE weval.dmaic_cycles SET phase=$1,progress=$2,updated_at=NOW() WHERE tenant_id=$3 AND vs_id=$4", [$phase,$progress,$tenant,$vs_id]);
pg_query_params($db, "INSERT INTO weval.audit_log(tenant_id,actor,action,target,payload) VALUES($1,'api','dmaic_advance',$2,$3)", [$tenant,$vs_id,json_encode(['phase'=>$phase,'progress'=>$progress])]);
echo json_encode(['ok'=>true,'tenant'=>$tenant,'vs_id'=>$vs_id,'phase'=>$phase,'progress'=>$progress]);
exit;
}
if ($vs_id) {
$r = @pg_query_params($db, "SELECT * FROM weval.dmaic_cycles WHERE tenant_id=$1 AND vs_id=$2", [$tenant,$vs_id]);
$row = pg_fetch_assoc($r);
if (!$row) { http_response_code(404); echo json_encode(['error'=>'vs_not_found']); exit; }
foreach(['define_data','measure_data','analyze_data','improve_data','control_data','baseline','target','current'] as $k) $row[$k] = json_decode($row[$k],true);
echo json_encode($row);
} else {
$r = @pg_query_params($db, "SELECT vs_id,name,phase,progress,updated_at FROM weval.dmaic_cycles WHERE tenant_id=$1 ORDER BY updated_at DESC", [$tenant]);
$list = []; while ($row = pg_fetch_assoc($r)) $list[] = $row;
echo json_encode(['tenant'=>$tenant,'count'=>count($list),'cycles'=>$list]);
}

12
api/em/kpi-live.php Normal file
View File

@@ -0,0 +1,12 @@
<?php
header('Content-Type: application/json');
$db = @pg_connect("host=127.0.0.1 port=5432 user=admin password=admin123 dbname=adx_system");
$tenant = $_GET['tenant'] ?? 'weval';
$dept = $_GET['dept'] ?? null;
$q = "SELECT dept,kpi_name,value,unit,ts FROM weval.kpi_timeseries WHERE tenant_id=$1";
$p = [$tenant];
if ($dept) { $q .= " AND dept=$2"; $p[] = $dept; }
$q .= " ORDER BY ts DESC LIMIT 200";
$r = @pg_query_params($db, $q, $p);
$kpis = []; while ($row = pg_fetch_assoc($r)) $kpis[] = $row;
echo json_encode(['tenant'=>$tenant,'count'=>count($kpis),'kpis'=>$kpis]);

12
api/em/poc-start.php Normal file
View File

@@ -0,0 +1,12 @@
<?php
header('Content-Type: application/json');
$db = @pg_connect("host=127.0.0.1 port=5432 user=admin password=admin123 dbname=adx_system");
$body = json_decode(file_get_contents('php://input'), true) ?: [];
$tenant_id = preg_replace('/[^a-z0-9_-]/i','', $body['tenant_id'] ?? 'tenant_'.substr(md5(time()),0,8));
$name = $body['name'] ?? 'Nouveau tenant';
$email = $body['email'] ?? '';
$vs_id = $body['vs_id'] ?? 'pilot-vsm';
pg_query_params($db, "INSERT INTO weval.tenants(tenant_id,name,plan_code,phase,contact_email) VALUES($1,$2,'poc','poc',$3) ON CONFLICT (tenant_id) DO NOTHING", [$tenant_id,$name,$email]);
pg_query_params($db, "INSERT INTO weval.dmaic_cycles(tenant_id,vs_id,name,phase,progress) VALUES($1,$2,$3,'define',10)", [$tenant_id,$vs_id,"POC $name"]);
pg_query_params($db, "INSERT INTO weval.audit_log(tenant_id,actor,action,target,payload) VALUES($1,'em-api','poc_kickoff',$2,$3)", [$tenant_id,$vs_id,json_encode($body)]);
echo json_encode(['ok'=>true,'tenant_id'=>$tenant_id,'vs_id'=>$vs_id,'phase'=>'define','next'=>"Rdv kickoff planifié: /dmaic?tenant=$tenant_id&vs_id=$vs_id"]);

View File

@@ -0,0 +1,16 @@
<?php
header('Content-Type: application/json');
$db = @pg_connect("host=127.0.0.1 port=5432 user=admin password=admin123 dbname=adx_system");
$body = json_decode(file_get_contents('php://input'), true) ?: [];
$tenant_id = preg_replace('/[^a-z0-9_-]/i','', $body['tenant_id'] ?? '');
$plan = in_array($body['plan'] ?? '', ['poc','mvp','enterprise']) ? $body['plan'] : 'mvp';
$name = $body['name'] ?? $tenant_id;
$email = $body['email'] ?? '';
if (!$tenant_id) { http_response_code(400); echo json_encode(['error'=>'tenant_id required']); exit; }
pg_query_params($db, "INSERT INTO weval.tenants(tenant_id,name,plan_code,phase,contact_email) VALUES($1,$2,$3,$3,$4) ON CONFLICT (tenant_id) DO UPDATE SET plan_code=$3,phase=$3", [$tenant_id,$name,$plan,$email]);
// Clone vsm_dept from weval template if mvp/enterprise
if ($plan !== 'poc') {
pg_query_params($db, "INSERT INTO weval.vsm_dept(tenant_id,dept_code,dept_name,icon,supplier,input,process,output,customer,kpis,agents) SELECT $1,dept_code,dept_name,icon,supplier,input,process,output,customer,kpis,agents FROM weval.vsm_dept WHERE tenant_id='weval' ON CONFLICT DO NOTHING", [$tenant_id]);
}
pg_query_params($db, "INSERT INTO weval.audit_log(tenant_id,actor,action,target,payload) VALUES($1,'em-api','tenant_bootstrap',$2,$3)", [$tenant_id,$plan,json_encode($body)]);
echo json_encode(['ok'=>true,'tenant_id'=>$tenant_id,'plan'=>$plan,'vsm_cloned'=>$plan!=='poc','dashboard'=>"/brain-center-tenant.html?id=$tenant_id"]);

20
api/em/vsm-dept.php Normal file
View File

@@ -0,0 +1,20 @@
<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
$db = @pg_connect("host=127.0.0.1 port=5432 user=admin password=admin123 dbname=adx_system");
if (!$db) { echo json_encode(['error'=>'db']); exit; }
$tenant = $_GET['tenant'] ?? 'weval';
$dept = $_GET['dept'] ?? null;
if ($dept) {
$r = @pg_query_params($db, "SELECT * FROM weval.vsm_dept WHERE tenant_id=$1 AND dept_code=$2", [$tenant, $dept]);
$row = pg_fetch_assoc($r);
if (!$row) { http_response_code(404); echo json_encode(['error'=>'dept_not_found']); exit; }
$row['kpis'] = json_decode($row['kpis'], true);
$row['agents'] = json_decode($row['agents'], true);
echo json_encode($row);
} else {
$r = @pg_query_params($db, "SELECT dept_code,dept_name,icon,kpis FROM weval.vsm_dept WHERE tenant_id=$1 ORDER BY id", [$tenant]);
$depts = [];
while ($row = pg_fetch_assoc($r)) { $row['kpis'] = json_decode($row['kpis'],true); $depts[] = $row; }
echo json_encode(['tenant'=>$tenant,'count'=>count($depts),'depts'=>$depts]);
}

36
api/opus-add-trace.php Normal file
View File

@@ -0,0 +1,36 @@
<?php
header('Content-Type: application/json');
$R = ['steps'=>[], 'ok'=>false];
$SRC = '/var/www/weval/wevia-ia/weval-chatbot-api.php';
$TS = date('Ymd-Hi');
$content = file_get_contents($SRC);
if (strpos($content, 'OPUS4-TRACE-V1') !== false) {
$R['already'] = true; die(json_encode($R));
}
// Ajoute trace tout au début - juste après <?php
$old = '<?php /* ACTIVE: Fullscreen chatbot backend';
$new = '<?php @file_put_contents("/var/log/weval/opus4-trace.log", date("c")." CHATBOT_OPENED uri=".($_SERVER["REQUEST_URI"]??"?")."\n", FILE_APPEND); /* OPUS4-TRACE-V1 ACTIVE: Fullscreen chatbot backend';
$newContent = str_replace($old, $new, $content, $count);
$R['replacements'] = $count;
if ($count === 0) { $R['err'] = 'anchor not found'; die(json_encode($R)); }
// Lint
$TMP = "/tmp/wc-trace-{$TS}.php";
file_put_contents($TMP, $newContent);
exec("php8.4 -l $TMP 2>&1", $lo, $lr);
if ($lr !== 0) { unlink($TMP); $R['err']='LINT'; $R['lint']=$lo; die(json_encode($R)); }
// GOLD + write
copy($SRC, "/opt/wevads/vault/weval-chatbot-TRACE-{$TS}.gold.php");
exec('chattr -i '.escapeshellarg($SRC).' 2>&1');
$w = file_put_contents($SRC, $newContent);
exec('chattr +i '.escapeshellarg($SRC).' 2>&1');
exec("php8.4 -l $SRC 2>&1", $flo, $flr);
@opcache_invalidate($SRC, true);
@opcache_reset();
unlink($TMP);
$R['ok'] = ($flr === 0); $R['written'] = $w; $R['final_lint'] = $flr;
echo json_encode($R, JSON_PRETTY_PRINT);

76
api/opus-fix-stream.php Normal file
View File

@@ -0,0 +1,76 @@
<?php
header('Content-Type: application/json');
$R = ['steps'=>[], 'ok'=>false];
$SRC = '/var/www/weval/wevia-ia/weval-chatbot-api.php';
$TS = date('Ymd-Hi');
$content = file_get_contents($SRC);
$R['steps'][] = ['read' => strlen($content).'B'];
// GOLD
$GOLD = "/opt/wevads/vault/weval-chatbot-api-STREAMFIX-{$TS}.gold.php";
copy($SRC, $GOLD);
$R['steps'][] = ['gold' => $GOLD];
// Target la ligne dans ma zone OPUS4-AUTOWIRE-CHATBOT-v1
$start_marker = 'OPUS4-AUTOWIRE-CHATBOT-v1 (17avr 02h35)';
$end_marker = 'OPUS4-AUTOWIRE-CHATBOT-v1 END';
$ps = strpos($content, $start_marker);
$pe = strpos($content, $end_marker);
if ($ps === false || $pe === false) { $R['steps'][]=['err'=>'markers absent']; die(json_encode($R)); }
$block = substr($content, $ps, $pe - $ps);
// Remplace la source du raw : $GLOBALS["_wevia_raw"] ?? file_get_contents("php://input")
// est déjà tentée, mais si les 2 sont vides ($GLOBALS défini MAIS vide), on fallback sur $_POST
// Meilleur fix : DOUBLE JSON read si premier vide
$old = '$__opus4_raw = $GLOBALS["_wevia_raw"] ?? file_get_contents("php://input");';
$new = '$__opus4_raw = $GLOBALS["_wevia_raw"] ?? (isset($_wevia_raw) ? $_wevia_raw : file_get_contents("php://input"));';
// Aussi: normaliser via $_POST si JSON vide
// Et tracer TOUJOURS qu'on est passé par là pour diagnostic
$trace_inject = '@file_put_contents("/var/log/weval/opus4-autowire.log", date("c") . " CHATBOT_REACHED raw_len=" . strlen($__opus4_raw) . " msg=" . substr($__opus4_msg, 0, 40) . "\n", FILE_APPEND);';
$block_new = str_replace($old, $new, $block);
// Injecte trace line juste apres la définition de $__opus4_msg
$trace_anchor = '$__opus4_msg = mb_strtolower(trim($__opus4_in["message"] ?? ($_POST["message"] ?? "")));';
$trace_new = $trace_anchor . "\n " . $trace_inject;
$block_new = str_replace($trace_anchor, $trace_new, $block_new);
$R['steps'][] = [
'stream_fix_applied' => ($block !== $block_new),
'block_before_len' => strlen($block),
'block_after_len' => strlen($block_new)
];
$newContent = substr($content, 0, $ps) . $block_new . substr($content, $pe);
// Lint
$TMP = "/tmp/wc-stream-{$TS}.php";
file_put_contents($TMP, $newContent);
exec("php8.4 -l $TMP 2>&1", $lo, $lr);
$R['steps'][] = ['lint_rc' => $lr, 'lint' => $lo];
if ($lr !== 0) { unlink($TMP); $R['steps'][]=['err'=>'LINT FAIL']; die(json_encode($R)); }
// Write
exec('sudo chattr -i '.escapeshellarg($SRC).' 2>&1', $c1, $rc1);
if ($rc1 !== 0) exec('chattr -i '.escapeshellarg($SRC).' 2>&1', $c1, $rc1);
$w = file_put_contents($SRC, $newContent);
exec('sudo chattr +i '.escapeshellarg($SRC).' 2>&1', $c2, $rc2);
if ($rc2 !== 0) exec('chattr +i '.escapeshellarg($SRC).' 2>&1', $c2, $rc2);
$R['steps'][] = ['written' => $w, 'chattr_plus' => $rc2];
exec("php8.4 -l $SRC 2>&1", $flo, $flr);
$R['steps'][] = ['final_lint_rc' => $flr];
@opcache_invalidate($SRC, true);
@opcache_reset();
// Prepare log dir
@mkdir('/var/log/weval', 0755, true);
@file_put_contents('/var/log/weval/opus4-autowire.log', date('c')." FIX_STREAM applied\n", FILE_APPEND);
unlink($TMP);
$R['ok'] = ($flr === 0);
echo json_encode($R, JSON_PRETTY_PRINT);

115
api/opus-inject-chatbot.php Normal file
View File

@@ -0,0 +1,115 @@
<?php
// Injection autowire dans weval-chatbot-api.php - handler early-v3 "chat naturel"
header('Content-Type: application/json');
$R = ['steps'=>[], 'ok'=>false];
$SRC = '/var/www/weval/wevia-ia/weval-chatbot-api.php';
$MARKER = 'OPUS4-AUTOWIRE-CHATBOT-v1';
$TS = date('Ymd-Hi');
$content = file_get_contents($SRC);
$R['steps'][] = ['read' => strlen($content).'B'];
if (strpos($content, $MARKER) !== false) {
$R['ok'] = true; $R['steps'][] = ['already_applied' => true];
die(json_encode($R, JSON_PRETTY_PRINT));
}
// GOLD
$GOLD = "/opt/wevads/vault/weval-chatbot-api-CHATBOT-{$TS}.gold.php";
copy($SRC, $GOLD);
$R['steps'][] = ['gold' => $GOLD, 'size' => filesize($GOLD)];
// Anchor : juste avant "if(($_SERVER[\"REQUEST_METHOD\"]" (ligne 54)
$anchor = 'if(($_SERVER["REQUEST_METHOD"] ?? "") === "GET"';
$pos = strpos($content, $anchor);
if ($pos === false) { $R['steps'][] = ['err' => 'anchor not found']; die(json_encode($R)); }
// Injection via heredoc-like — double quote safe
$INJECT = '
// === OPUS4-AUTOWIRE-CHATBOT-v1 (17avr 02h35) ===
// Cause racine: /api/weval-ia proxie vers ce fichier, qui bypass wevia-master-api.
// Ce handler capture master add/list intent en priorite absolue AVANT tout LLM call.
// Zero regression: return silencieux si syntaxe pas matchee.
if ($_SERVER["REQUEST_METHOD"] === "POST") {
$__opus4_raw = $GLOBALS["_wevia_raw"] ?? file_get_contents("php://input");
$__opus4_in = @json_decode($__opus4_raw, true) ?: [];
$__opus4_msg = mb_strtolower(trim($__opus4_in["message"] ?? ($_POST["message"] ?? "")));
if ($__opus4_msg) {
if (preg_match("/^\s*master\s+add\s+intent\s+([a-z0-9_]+)\s*::\s*(.+?)\s*::\s*(.+)$/i", $__opus4_msg, $__m4)) {
$__n = trim($__m4[1]); $__t = trim($__m4[2]); $__c = trim($__m4[3]);
$__pd = "/var/www/html/api/wired-pending"; @mkdir($__pd, 0755, true);
$__stub = "$__pd/intent-opus4-$__n.php";
$__ok4 = false;
foreach (["/var/www/html/","/var/www/weval/","/opt/wevia-brain/","/opt/wevads/vault/","echo ","curl ","php8.4 ","git "] as $__p4) {
if (strpos($__c, $__p4) !== false) { $__ok4 = true; break; }
}
$__pl = ["name"=>$__n, "triggers"=>array_map("trim", explode("|", $__t)), "cmd"=>$__c, "status"=>$__ok4?"PENDING_APPROVAL":"PENDING_SECURITY_REVIEW", "created_at"=>date("c"), "source"=>"opus4-chatbot-v1"];
@file_put_contents($__stub, "<?php\nreturn " . var_export($__pl, true) . ";\n");
@file_put_contents("/var/log/weval/opus4-autowire.log", date("c") . " CHATBOT_WIRED name=$__n\n", FILE_APPEND);
$__qf = "/var/www/html/api/wave-wiring-queue.json";
$__q = @json_decode(@file_get_contents($__qf), true) ?: [];
$__q[] = $__pl;
@file_put_contents($__qf, json_encode($__q, JSON_PRETTY_PRINT));
header("Content-Type: application/json");
echo json_encode(["response"=>"Intent \'$__n\' wired (status={$__pl["status"]}). Triggers: " . implode(", ", $__pl["triggers"]) . ". Cmd: " . substr($__c, 0, 80), "executed"=>true, "provider"=>"opus4-autowire-chatbot", "intent"=>$__n, "status"=>$__pl["status"]]);
exit;
}
if (preg_match("/^\s*master\s+(list|show)\s+intents?\s*$/i", $__opus4_msg)) {
$__stubs4 = @glob("/var/www/html/api/wired-pending/intent-opus4-*.php") ?: [];
$__sum4 = [];
foreach ($__stubs4 as $__s4) {
$__info4 = @include $__s4;
if (is_array($__info4)) $__sum4[] = ["name"=>$__info4["name"] ?? "?", "status"=>$__info4["status"] ?? "?", "triggers"=>$__info4["triggers"] ?? []];
}
header("Content-Type: application/json");
echo json_encode(["response"=>"Wired opus4 intents: " . count($__stubs4) . "\n" . json_encode($__sum4, JSON_PRETTY_PRINT), "executed"=>true, "provider"=>"opus4-autowire-chatbot-list", "count"=>count($__stubs4)]);
exit;
}
}
}
// === OPUS4-AUTOWIRE-CHATBOT-v1 END ===
';
$newContent = substr($content, 0, $pos) . $INJECT . substr($content, $pos);
$R['steps'][] = ['inject_at' => $pos, 'before' => strlen($content), 'after' => strlen($newContent)];
// Lint temp
$TMP = "/tmp/wc-test-{$TS}.php";
file_put_contents($TMP, $newContent);
exec("php8.4 -l $TMP 2>&1", $lo, $lr);
$R['steps'][] = ['lint_rc' => $lr, 'lint' => $lo];
if ($lr !== 0) { unlink($TMP); $R['steps'][] = ['err' => 'LINT FAIL']; die(json_encode($R, JSON_PRETTY_PRINT)); }
// Test regex locale
exec('php8.4 -r "if(preg_match(\"/^\\s*master\\s+add\\s+intent/i\", \"master add intent x :: a :: echo b\")) echo \"RX_OK\";"', $rt);
$R['steps'][] = ['regex_local_test' => $rt];
// Write
exec('sudo chattr -i '.escapeshellarg($SRC).' 2>&1', $c1, $rc1);
if ($rc1 !== 0) exec('chattr -i '.escapeshellarg($SRC).' 2>&1', $c1, $rc1);
$R['steps'][] = ['chattr_minus' => $rc1];
$w = file_put_contents($SRC, $newContent);
$R['steps'][] = ['written' => $w];
exec('sudo chattr +i '.escapeshellarg($SRC).' 2>&1', $c2, $rc2);
if ($rc2 !== 0) exec('chattr +i '.escapeshellarg($SRC).' 2>&1', $c2, $rc2);
$R['steps'][] = ['chattr_plus' => $rc2];
// Final lint
exec("php8.4 -l $SRC 2>&1", $flo, $flr);
$R['steps'][] = ['final_lint_rc' => $flr, 'final_lint' => $flo];
$final = file_get_contents($SRC);
$R['steps'][] = ['marker_present' => (strpos($final, $MARKER) !== false)];
// Opcache flush ciblé
@opcache_invalidate($SRC, true);
@opcache_invalidate('/var/www/html/api/weval-ia.php', true);
@opcache_reset();
unlink($TMP);
$R['ok'] = ($flr === 0 && strpos($final, $MARKER) !== false && $w > 300000);
echo json_encode($R, JSON_PRETTY_PRINT);

32
api/opus-reset85.php Normal file
View File

@@ -0,0 +1,32 @@
<?php
header('Content-Type: application/json');
$r = [
'php_version' => phpversion(),
'opcache_enabled' => opcache_get_status(false)['opcache_enabled'] ?? 'unknown',
'chatbot_in_cache' => false,
'reset' => false
];
$status = opcache_get_status(true);
if ($status && isset($status['scripts'])) {
foreach ($status['scripts'] as $s) {
if (strpos($s['full_path'], 'weval-chatbot-api.php') !== false) {
$r['chatbot_in_cache'] = true;
$r['chatbot_mtime_cached'] = $s['timestamp'] ?? '?';
$r['chatbot_last_used'] = $s['last_used_timestamp'] ?? '?';
}
}
}
$files = [
'/var/www/weval/wevia-ia/weval-chatbot-api.php',
'/var/www/weval/wevia-ia/wevia-infra-intercept.php',
'/var/www/html/api/weval-ia.php',
];
foreach ($files as $f) {
$r['invalidated'][$f] = opcache_invalidate($f, true);
}
$r['reset'] = opcache_reset();
echo json_encode($r, JSON_PRETTY_PRINT);

File diff suppressed because one or more lines are too long

View File

@@ -83,5 +83,15 @@
"status": "PENDING_APPROVAL",
"created_at": "2026-04-17T00:19:26+00:00",
"source": "opus4-autowire-early-v2"
},
"1": {
"name": "check_still_works",
"triggers": [
"pattern"
],
"cmd": "echo check",
"status": "PENDING_APPROVAL",
"created_at": "2026-04-17T00:23:41+00:00",
"source": "opus4-autowire-early-v2"
}
}

View File

@@ -0,0 +1,12 @@
<?php
return array (
'name' => 'check_still_works',
'triggers' =>
array (
0 => 'pattern',
),
'cmd' => 'echo check',
'status' => 'PENDING_APPROVAL',
'created_at' => '2026-04-17T00:23:41+00:00',
'source' => 'opus4-autowire-early-v2',
);