auto-sync-1715

This commit is contained in:
opus
2026-04-17 17:15:01 +02:00
parent 0d8d7cc44f
commit be368a14ad
10 changed files with 4337 additions and 339 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
{
"generated_at": "2026-04-17T17:05:01.822400",
"generated_at": "2026-04-17T17:15:01.469029",
"stats": {
"total": 31,
"pending": 43,
"pending": 40,
"kaouther_surfaced": 14,
"chrome_surfaced": 8,
"notif_only_done": 0,

View File

@@ -0,0 +1,147 @@
<?php
// OPUS5 — WEVIA AUTONOMOUS META-ORCHESTRATOR v1
// Chaine automatiquement les 44+ top-IA scripts selon complexité + intent classification
// Doctrine 67 : meta-orchestration = chaîne cognitive dynamique
header('Content-Type: application/json');
$R = ['ts'=>date('c'), 'source'=>'opus5-autonomous-orchestrator', 'pipeline'=>[]];
$raw = file_get_contents('php://input');
$d = json_decode($raw, true) ?: [];
$msg = (string)($d['message'] ?? '');
$session = (string)($d['session'] ?? 'auto-' . bin2hex(random_bytes(4)));
if (!$msg) {
http_response_code(400);
echo json_encode(['err'=>'missing_message']);
exit;
}
// === CLASSIFICATION AUTOMATIQUE DE LA COMPLEXITE ===
$complexity = 'simple'; // simple | medium | deep | multi-step
$words = str_word_count($msg);
$has_multi_actions = preg_match('/\b(puis|ensuite|apres|avant|en meme temps|parallele|simultane)\b/iu', $msg);
$has_analysis = preg_match('/\b(analys|compar|evalu|juge|deept|approfondi|raison|pourquoi|explique|detail)\b/iu', $msg);
$has_plan = preg_match('/\b(plan|roadmap|strategie|structure|orchestr|chain|workflow)\b/iu', $msg);
$has_memory = preg_match('/\b(souvien|remember|rappell|dernier|ancienne|avant|histori)\b/iu', $msg);
if ($words > 30 || $has_multi_actions || $has_plan) $complexity = 'multi-step';
elseif ($has_analysis || $words > 15) $complexity = 'deep';
elseif ($has_memory) $complexity = 'medium';
$R['classification'] = [
'words' => $words,
'complexity' => $complexity,
'signals' => compact('has_multi_actions','has_analysis','has_plan','has_memory')
];
// === CHAINE COGNITIVE ADAPTATIVE ===
$chain = [];
// Étape 1 : TOUJOURS — memory_recall (contexte utilisateur)
if ($has_memory || $complexity !== 'simple') {
$chain[] = ['step'=>'memory_recall', 'script'=>'/opt/weval-ops/top-ia/memory_recall.sh', 'args'=>[$session, substr($msg,0,120)]];
}
// Étape 2 : Classification sentiment (adapter ton)
if ($complexity !== 'simple') {
$chain[] = ['step'=>'sentiment_analysis', 'script'=>'/opt/weval-ops/top-ia/sentiment.sh', 'args'=>[substr($msg,0,200)]];
}
// Étape 3 : si complexity deep+ → dispatch fast-path normal OU self-reflect OU speculative
if ($complexity === 'multi-step') {
// Multi-step = dialectical (2 agents opposés) + self_consistency
$chain[] = ['step'=>'dialectical', 'script'=>'/opt/weval-ops/top-ia/dialectical.sh', 'args'=>[substr($msg,0,500)]];
$chain[] = ['step'=>'self_consistency', 'script'=>'/opt/weval-ops/top-ia/self_consistency.sh', 'args'=>[substr($msg,0,500)]];
} elseif ($complexity === 'deep') {
// Deep = CoT tree + reflect_loop
$chain[] = ['step'=>'cot_tree', 'script'=>'/opt/weval-ops/top-ia/cot_tree.sh', 'args'=>[substr($msg,0,500)]];
$chain[] = ['step'=>'reflect_loop', 'script'=>'/opt/weval-ops/top-ia/reflect_loop.sh', 'args'=>[substr($msg,0,500)]];
} else {
// Simple/medium = speculative_parallel (rapide + précis)
$chain[] = ['step'=>'speculative_parallel', 'script'=>'/opt/weval-ops/top-ia/speculative_parallel.sh', 'args'=>[substr($msg,0,500)]];
}
// Étape 4 : TOUJOURS — fast-path dispatch (garde la logique existante)
$chain[] = ['step'=>'dispatch_proxy', 'url'=>'/api/wevia-master-dispatch.php', 'args'=>['message'=>$msg, 'session'=>$session]];
// Étape 5 : Post — méta-cognition + memory_store (async)
$chain[] = ['step'=>'meta_cognition_hook', 'script'=>'/opt/weval-ops/top-ia/meta_cognition_hook.sh', 'args'=>[$session, 'post'], 'async'=>true];
$chain[] = ['step'=>'memory_store', 'script'=>'/opt/weval-ops/top-ia/memory_store.sh', 'args'=>[$session, substr($msg,0,200)], 'async'=>true];
// === EXECUTION AVEC TIMEOUT DUR 20s TOTAL ===
$R['chain_planned'] = count($chain);
$t0 = microtime(true);
$results = [];
$max_total = 20.0; // 20s budget total
foreach ($chain as $step) {
$elapsed = microtime(true) - $t0;
if ($elapsed > $max_total) {
$results[] = ['step'=>$step['step'], 'skipped'=>'timeout_budget_exceeded', 'elapsed'=>$elapsed];
continue;
}
if (!empty($step['async'])) {
// Fire-and-forget async (via & background)
$scr = escapeshellarg($step['script']);
$args = array_map('escapeshellarg', $step['args'] ?? []);
@shell_exec("timeout 15 $scr " . implode(' ', $args) . " > /dev/null 2>&1 &");
$results[] = ['step'=>$step['step'], 'status'=>'launched_async'];
continue;
}
if (!empty($step['url'])) {
// HTTP call
$ch = curl_init('https://127.0.0.1' . $step['url']);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($step['args']),
CURLOPT_HTTPHEADER => ['Content-Type: application/json','Host: weval-consulting.com'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => 0,
CURLOPT_TIMEOUT => 10,
CURLOPT_CONNECTTIMEOUT => 3
]);
$start_step = microtime(true);
$resp = curl_exec($ch);
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$results[] = [
'step'=>$step['step'],
'http'=>$http,
'ms'=>round((microtime(true)-$start_step)*1000),
'response_preview' => substr((string)$resp, 0, 200)
];
// Si dispatch retourne une réponse valide, on la stocke comme réponse finale
$parsed = @json_decode($resp, true);
if ($parsed && isset($parsed['response']) || isset($parsed['content']) || isset($parsed['output'])) {
$R['final_response'] = $parsed['response'] ?? $parsed['content'] ?? $parsed['output'] ?? '';
$R['final_provider'] = $parsed['provider'] ?? 'dispatch-proxy';
}
} else {
// Script CLI avec timeout
$scr = escapeshellarg($step['script']);
$args = array_map('escapeshellarg', $step['args'] ?? []);
$start_step = microtime(true);
$out = @shell_exec("timeout 5 $scr " . implode(' ', $args) . " 2>&1");
$results[] = [
'step'=>$step['step'],
'ms'=>round((microtime(true)-$start_step)*1000),
'output_preview' => substr((string)$out, 0, 200)
];
}
}
$R['pipeline'] = $results;
$R['total_ms'] = round((microtime(true)-$t0)*1000);
$R['doctrine'] = '67 — meta-orchestrator autonomous (chain cognitive selon complexité)';
// Si pas de réponse finale capturée, on propose fallback
if (empty($R['final_response'])) {
$R['final_response'] = '[meta-orchestrator] Pipeline exécuté (' . count($results) . ' étapes en ' . $R['total_ms'] . 'ms). Consulter pipeline pour détails.';
}
echo json_encode($R, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE);

File diff suppressed because it is too large Load Diff

View File

@@ -480,6 +480,7 @@ require_once __DIR__ . '/wevia-ops-intents.php';
require_once __DIR__ . '/wevia-blade-actions-intent.php';
require_once __DIR__ . '/wevia-partners-intent.php';
require_once __DIR__ . '/wevia-test-email-intent.php';
require_once __DIR__ . '/wevia-office-senders-intent.php';
if (function_exists("wevia_write_intents")) {
$_wwmsg = json_decode(file_get_contents("php://input"),true)["message"] ?? $_POST["message"] ?? $_GET["message"] ?? "";

View File

@@ -0,0 +1,106 @@
<?php
// V2 - intent office_senders - diagnostic + activer sender via draft URL (pas auto UPDATE)
if (!function_exists('wevia_office_senders_diag')) {
function wevia_office_senders_diag($msg) {
if (!$msg) return false;
if (!preg_match('/\b(office\s+senders?|graph\s+accounts?|office\s+workflow|senders?\s+office|active[rz]?\s+senders?|can[-_\s]send|oauth\s+office|azure\s+tenants?)\b/i', $msg)) return false;
$out = ['intent' => 'office_senders', 'tool' => 'office_senders_real_diagnostic'];
// Exec RÉEL via sentinel S95
$sr = function($sql) {
$ch = curl_init('http://10.1.0.3:5890/api/sentinel-brain.php?action=exec&cmd=' . urlencode("PGPASSWORD=admin123 psql -U admin -d adx_system -h 127.0.0.1 -t -A -c \"{$sql}\""));
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 6]);
$r = curl_exec($ch);
curl_close($ch);
$j = @json_decode($r, true);
return trim($j['output'] ?? '');
};
$s = [];
$s['office_total'] = (int)$sr("SELECT count(*) FROM admin.office_accounts");
$s['office_active'] = (int)$sr("SELECT count(*) FROM admin.office_accounts WHERE LOWER(status)='active'");
$s['graph_total'] = (int)$sr("SELECT count(*) FROM admin.graph_accounts");
$s['graph_can_send'] = (int)$sr("SELECT count(*) FROM admin.graph_accounts WHERE can_send=true");
$s['graph_has_mailbox'] = (int)$sr("SELECT count(*) FROM admin.graph_accounts WHERE has_mailbox=true");
$s['graph_disabled'] = (int)$sr("SELECT count(*) FROM admin.graph_accounts WHERE status='disabled'");
$s['tenants_active'] = (int)$sr("SELECT count(*) FROM admin.graph_tenants WHERE status='active'");
$s['tenants_sends_today'] = (int)$sr("SELECT COALESCE(SUM(sends_today),0) FROM admin.graph_tenants");
// Tenants actifs + sends_today (preuve OAuth fonctionne)
$top_tenants_raw = $sr("SELECT tenant_domain || '|' || sends_today || '|' || daily_limit || '|' || users_count || '|' || COALESCE(last_send_at::text,'never') FROM admin.graph_tenants WHERE status='active' ORDER BY sends_today DESC LIMIT 5");
$top_tenants = [];
foreach (explode("\n", $top_tenants_raw) as $line) {
$parts = explode('|', trim($line));
if (count($parts) >= 5) {
$top_tenants[] = [
'tenant' => $parts[0],
'sends_today' => (int)$parts[1],
'daily_limit' => (int)$parts[2],
'users_count' => (int)$parts[3],
'last_send' => $parts[4],
'operational' => (int)$parts[1] > 0 ? 'YES - envoyant actuellement' : 'token existe, accounts disabled',
];
}
}
// Diagnostic
$working_tenants = count(array_filter($top_tenants, fn($t) => $t['sends_today'] > 0));
$ready_to_reactivate = $s['graph_has_mailbox'] - $s['graph_can_send'];
$out['stats'] = $s;
$out['top_tenants'] = $top_tenants;
$out['health'] = [
'office_active_rate' => $s['office_total'] > 0 ? round(100 * $s['office_active'] / $s['office_total']) . '%' : '0%',
'graph_tenants_operational' => "{$working_tenants}/9 tenants envoient aujourd'hui",
'accounts_ready_to_reactivate' => "{$ready_to_reactivate} graph_accounts has_mailbox=true mais status=disabled (safety)",
'pmta_alternative' => 'PMTA S95 port 25 - route de secours active',
];
$out['root_cause'] = $s['graph_can_send'] == 0 && $working_tenants > 0
? "Tenants OAuth OK ({$working_tenants} envoyent encore via send queues). graph_accounts status=disabled explicitement (safety/pause precedente). Re-activation = 1 SQL UPDATE pour Yacine."
: "Azure AD tenants client_secret potentiellement expire OU accounts jamais configures.";
$out['actions_drafts'] = [];
// Draft SQL pour Yacine (pas d'exec auto)
if ($ready_to_reactivate > 0 && $working_tenants > 0) {
$out['actions_drafts'][] = [
'label' => 'Option A: Re-activer 10 graph_accounts pour tests (Yacine UPDATE DB)',
'sql_preview' => "UPDATE admin.graph_accounts SET status='active', can_send=true WHERE has_mailbox=true AND status='disabled' AND id IN (SELECT id FROM admin.graph_accounts WHERE has_mailbox=true AND status='disabled' LIMIT 10)",
'who_runs' => 'Yacine (via psql S95 ou interface admin)',
'safety' => 'Limit 10 - micro dose test',
'url' => 'https://weval-consulting.com/office-admins.html',
];
$out['actions_drafts'][] = [
'label' => 'Option B: Test pipeline via PMTA direct (pas besoin Graph)',
'command_preview' => 'curl -X POST http://127.0.0.1/api/wevads-v2-engine.php?action=send_test&token=WEVADS2026 -d "to=yacineutt@gmail.com&method=pmta&..."',
'who_runs' => 'Yacine depuis /send-controller-test.html',
'safety' => 'Rate limit 100/h deja existant',
'url' => 'https://weval-consulting.com/send-controller.php?action=status&token=WEVADS2026',
];
}
$out['dashboard'] = 'https://weval-consulting.com/office-workflow.html';
$out['ui_pages'] = [
'office-hub' => 'https://weval-consulting.com/office-hub.html',
'office-admins' => 'https://weval-consulting.com/office-admins.html',
'office-workflow' => 'https://weval-consulting.com/office-workflow.html',
'azure-reregister' => 'https://weval-consulting.com/azure-reregister.html',
];
$out['doctrine'] = 'JAMAIS UPDATE DB auto sur senders (risque pipeline) - draft SQL pour Yacine';
header("Content-Type: application/json");
echo json_encode($out, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
exit;
}
}
$_os_msg = '';
$_body = @file_get_contents('php://input');
if ($_body) {
$_j = @json_decode($_body, true);
if (is_array($_j) && !empty($_j['message'])) $_os_msg = $_j['message'];
}
if (!$_os_msg) $_os_msg = $_POST['message'] ?? $_GET['message'] ?? '';
if ($_os_msg) wevia_office_senders_diag($_os_msg);

View File

@@ -345,6 +345,40 @@ Next: " . implode(" → ", $j["next_steps"] ?? []),"tool"=>"poc_kickoff"];
return ["provider"=>"opus46","content"=>$out,"tool"=>"universal_connectors_live"];
}
// === V24 WEM ENTERPRISE MANAGEMENT HUB ===
// INTENT: wem_open / enterprise_management
if (preg_match("/\b(wem|weval\s+enterprise|enterprise\s+management|enterprise\s+hub|hub\s+unifi|hub\s+central|acceder?\s+a\s+tout)/iu", $m)) {
$inv_path = "/var/www/html/api/wem-inventory.json";
$stats = "";
if (file_exists($inv_path)) {
$inv = json_decode(file_get_contents($inv_path), true);
$stats = " Pages: " . $inv["total_pages"] . "\n APIs: " . $inv["total_apis"] . "\n Categories: " . $inv["total_categories"] . "\n Services: " . $inv["total_services"] . "\n Intents: " . $inv["total_intents"] . "+\n Quick actions: " . count($inv["quick_actions"]);
}
return ["provider"=>"opus46","content"=>"WEVAL ENTERPRISE MANAGEMENT HUB:\n$stats\n\nURL: https://weval-consulting.com/weval-enterprise-management.html\nAgregateur unifie de toute l architecture — search + tabs + quick actions via chat NL","tool"=>"wem_open"];
}
// INTENT: wem_inventory_stats
if (preg_match("/(inventaire|inventory)\s+(plateforme|architecture|complet)|combien\s+(pages|ecrans|apis|services)\s+total/iu", $m)) {
$inv = @json_decode(@file_get_contents("/var/www/html/api/wem-inventory.json"), true);
if (!$inv) return ["provider"=>"opus46","content"=>"WEM inventory unavailable","tool"=>"wem_inventory_stats"];
$out = "INVENTAIRE PLATEFORME WEVAL:\n";
$out .= " Total pages: " . $inv["total_pages"] . "\n";
$out .= " Total APIs: " . $inv["total_apis"] . "\n";
$out .= " Services externes: " . $inv["total_services"] . "\n";
$out .= " WEVIA intents: " . $inv["total_intents"] . "+\n";
$out .= "\nCategories (top 10):\n";
$cats = $inv["categorized_pages"];
uasort($cats, function($a, $b) { return count($b) - count($a); });
$i = 0;
foreach ($cats as $cat => $pages) {
if ($i++ >= 10) break;
$out .= "" . str_pad($cat, 28) . ": " . count($pages) . " pages\n";
}
$out .= "\nHub: /weval-enterprise-management.html";
return ["provider"=>"opus46","content"=>$out,"tool"=>"wem_inventory_stats"];
}
// === V23 AUTO-EXEC (TOUT AUTO, AUCUN MANUEL) — 17avr session ===
// INTENT: sovereign_health_fix — auto-restart Sovereign si down

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

121
office-senders-diag.html Normal file
View File

@@ -0,0 +1,121 @@
<!DOCTYPE html>
<html lang="fr"><head>
<meta charset="UTF-8"><title>Office Senders — Diagnostic + Réactivation</title>
<style>
body{font-family:-apple-system,BlinkMacSystemFont,sans-serif;background:#0a0e27;color:#e4e8f7;margin:0;padding:0;line-height:1.6}
.container{max-width:1300px;margin:0 auto;padding:24px}
h1{color:#6ba3ff;border-bottom:2px solid #1e3a8a;padding-bottom:8px;margin-top:0}
h2{color:#c084fc;margin-top:28px}
.card{background:#141933;border:1px solid #263161;border-radius:10px;padding:20px;margin:16px 0}
.stats{display:flex;gap:14px;flex-wrap:wrap;margin-bottom:20px}
.stat{background:#141933;padding:16px 20px;border-radius:8px;min-width:140px;border-left:4px solid #10b981}
.stat.warn{border-left-color:#f59e0b}
.stat.danger{border-left-color:#ef4444}
.stat .n{font-size:26px;color:#6ba3ff;font-weight:bold}
.stat .l{font-size:11px;color:#9ca8d3;text-transform:uppercase}
table{width:100%;border-collapse:collapse;margin:16px 0}
th,td{padding:10px;text-align:left;border-bottom:1px solid #263161}
th{color:#c084fc;font-size:12px;text-transform:uppercase}
td{font-size:13px}
.op-yes{color:#10b981;font-weight:bold}.op-no{color:#f59e0b}
.action{background:#0f1529;padding:16px;border-radius:6px;margin-bottom:10px;border-left:4px solid #3b82f6}
.action.a{border-left-color:#10b981}
.action.b{border-left-color:#f59e0b}
.action h3{margin:0 0 8px 0;color:#e4e8f7}
.action code{display:block;background:#0a0e27;padding:10px;border-radius:4px;font-family:Monaco,monospace;font-size:11px;color:#a5b4fc;margin:8px 0;overflow-x:auto;word-break:break-all}
.btn{background:#1e3a8a;color:#fff;padding:10px 20px;border-radius:6px;text-decoration:none;display:inline-block;font-size:13px;margin-right:8px}
.btn:hover{background:#2563eb}
.btn.primary{background:#10b981}.btn.primary:hover{background:#059669}
.doctrine{background:#7c2d12;color:#fff;padding:10px 16px;border-radius:6px;font-size:13px;margin-bottom:16px}
a{color:#6ba3ff}
</style></head>
<body>
<div class="container">
<h1>📧 Office Senders — Diagnostic réel + Options réactivation</h1>
<div class="doctrine">
🛑 <strong>Doctrine 69 + 70 ABSOLUE</strong> : JAMAIS d'envoi auto · JAMAIS d'UPDATE DB auto. WEVIA génère drafts SQL + URLs. <strong>Yacine seul exécute.</strong>
</div>
<div class="stats" id="stats-box">Chargement...</div>
<h2>🏢 Tenants Azure AD actifs (OAuth OK)</h2>
<div class="card">
<table id="tenants-table">
<thead><tr><th>Tenant</th><th>Sends today</th><th>Daily limit</th><th>Users</th><th>Last send</th><th>Status</th></tr></thead>
<tbody id="tenants-body"><tr><td colspan="6">Chargement...</td></tr></tbody>
</table>
</div>
<h2>🎯 Root cause</h2>
<div class="card" id="root-cause">Chargement...</div>
<h2>⚡ Actions disponibles (Yacine seul exécute)</h2>
<div id="actions-box">Chargement...</div>
<h2>🔗 Dashboards liés</h2>
<div class="card">
<a href="/office-hub.html" class="btn">Office Hub</a>
<a href="/office-admins.html" class="btn">Office Admins</a>
<a href="/office-workflow.html" class="btn">Office Workflow</a>
<a href="/azure-reregister.html" class="btn">Azure Re-register</a>
<a href="/automation-hub.html" class="btn primary">Automation Hub</a>
</div>
</div>
<script>
async function load() {
try {
const r = await fetch('/api/wevia-office-senders-intent.php?message=office+senders+status&_=' + Date.now());
const d = await r.json();
// Stats
const s = d.stats || {};
const h = d.health || {};
document.getElementById('stats-box').innerHTML = `
<div class="stat"><div class="n">${s.office_total||0}</div><div class="l">Office accounts</div></div>
<div class="stat"><div class="n">${s.office_active||0}</div><div class="l">Office active</div></div>
<div class="stat"><div class="n">${s.graph_total||0}</div><div class="l">Graph accounts</div></div>
<div class="stat ${s.graph_can_send>0?'':'danger'}"><div class="n">${s.graph_can_send||0}</div><div class="l">Can send</div></div>
<div class="stat warn"><div class="n">${s.graph_disabled||0}</div><div class="l">Graph disabled</div></div>
<div class="stat"><div class="n">${s.tenants_active||0}/9</div><div class="l">Tenants active</div></div>
<div class="stat"><div class="n">${s.tenants_sends_today||0}</div><div class="l">Sends today</div></div>
`;
// Tenants
const ts = d.top_tenants || [];
document.getElementById('tenants-body').innerHTML = ts.map(t => `
<tr>
<td><strong>${t.tenant}</strong></td>
<td>${t.sends_today}</td>
<td>${t.daily_limit}</td>
<td>${t.users_count}</td>
<td style="font-size:11px;color:#9ca8d3">${t.last_send||'never'}</td>
<td class="${t.sends_today>0?'op-yes':'op-no'}">${t.operational}</td>
</tr>
`).join('');
// Root cause
document.getElementById('root-cause').innerHTML = `<p style="font-size:15px">${d.root_cause||''}</p>`;
// Actions
const acts = d.actions_drafts || [];
document.getElementById('actions-box').innerHTML = acts.map((a,i) => `
<div class="action ${i===0?'a':'b'}">
<h3>${a.label}</h3>
${a.sql_preview ? `<code>${a.sql_preview}</code>` : ''}
${a.command_preview ? `<code>${a.command_preview}</code>` : ''}
<p><strong>Qui exécute:</strong> ${a.who_runs} · <strong>Safety:</strong> ${a.safety}</p>
<a href="${a.url}" target="_blank" class="btn primary">🔗 Ouvrir dashboard</a>
</div>
`).join('');
} catch(e) {
document.getElementById('stats-box').innerHTML = 'Erreur: ' + e.message;
}
}
load();
setInterval(load, 60000);
</script>
</body></html>