let LLM handle $m_lower = mb_strtolower(trim($msg)); if (mb_strlen($m_lower) > 60 && preg_match('/\b(redige|ecris|compose|prepare|formule|genere|propose|planifie|organise|convainc|argumente|resume|tradui|ameliore|rapport|email|lettre|message|strategie|plan|brainstorm)\b/iu', $m_lower)) { return null; } $registry = __DIR__ . '/wevia-tool-registry.json'; if (!file_exists($registry)) return null; $data = json_decode(file_get_contents($registry), true); if (!is_array($data)) return null; $tools = $data['tools'] ?? $data; $msg_lower = mb_strtolower(trim($msg)); $best = null; $best_score = 0; foreach ($tools as $tool) { if (empty($tool['kw'])) continue; $score = 0; if (@preg_match('/' . $tool['kw'] . '/i', $msg_lower)) { $score = 10; } else { $keywords = preg_split('/[|.*()]+/', $tool['kw']); foreach ($keywords as $kw) { $kw = trim($kw); if ($kw && mb_strpos($msg_lower, $kw) !== false) $score += 2; } } if ($score > 0 && mb_strlen($msg_lower) > 60 && preg_match("/reconcil|diagnostic|bilan|test_global/", $tool["id"] ?? "")) $score += 1; if ($score > $best_score || ($score == $best_score && !empty($tool["cmd"]) && empty($best["cmd"]))) { $best_score = $score; $best = $tool; } } if (!$best || $best_score < 3) return null; $result = ''; // EXEC with sudo + timeout 15s to avoid CF 520 if (!empty($best['cmd'])) { $result = shell_exec('sudo timeout 15 bash -c ' . escapeshellarg($best['cmd']) . ' 2>&1') ?? ''; if (trim($result) === '') $result = '[timeout 15s] Commande lente. Essayez plus ciblé.'; } elseif (strpos($best['api'] ?? '', 'GET:') === 0) { $ctx = stream_context_create(['http' => ['timeout' => 4]]); $result = @file_get_contents('http://127.0.0.1' . substr($best['api'], 4), false, $ctx) ?? ''; } elseif (strpos($best['api'] ?? '', 'POST:') === 0) { $ctx = stream_context_create(['http' => ['method' => 'POST', 'timeout' => 4]]); $result = @file_get_contents('http://127.0.0.1' . substr($best['api'], 5), false, $ctx) ?? ''; } if (!$result) return ["provider"=>"dynamic-resolver","content"=>"[" . ($best["id"] ?? "tool") . "] pas de reponse (timeout ou service down)","tool"=>$best["id"]??"unknown"]; return ['provider' => 'dynamic-resolver', 'content' => trim($result), 'tool' => $best['id'] ?? 'unknown']; } function wevia_dynamic_resolve($msg) { return wevia_resolve($msg); }