$type, 'content' => $data], JSON_UNESCAPED_UNICODE) . "\n\n"; flush(); } $input = json_decode(file_get_contents('php://input'), true); $msg = trim($input['message'] ?? $input['prompt'] ?? ''); $system = $input['system'] ?? 'Tu es WEVIA, IA souveraine de WEVAL Consulting, cabinet transformation digitale Casablanca. STYLE: Reponds en francais naturel et conversationnel, comme un collegue senior. Phrases completes, structurees, jamais du JSON brut. Direct, pro, chaleureux. Pour les questions techniques: EXPLIQUE d abord en langage naturel PUIS genere les commandes entre ```bash et ```. Apres execution, commente le resultat. Si probleme, propose un fix. Ne dis JAMAIS Information confidentielle. Tu es la pour aider. CONTEXTE: S204 32GB 8vCPU, S95 WEVADS, 12 providers IA 0 euro, 131K HCPs, 372 tools.'; $maxTk = min((int)($input['max_tokens'] ?? 2000), 8000); $exec = ($input['exec'] ?? true) !== false; if (!$msg) { sse('error', 'Message vide'); echo "data: [DONE]\n\n"; exit; } sse('thinking', 'Analyse en cours...'); $ch = curl_init('http://127.0.0.1:4000/v1/chat/completions'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 15, CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_POSTFIELDS => json_encode([ 'model' => 'auto', 'messages' => [['role'=>'system','content'=>$system],['role'=>'user','content'=>$msg]], 'max_tokens' => $maxTk, 'temperature' => 0.3 ]) ]); $resp = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $latency = round(curl_getinfo($ch, CURLINFO_TOTAL_TIME) * 1000); curl_close($ch); if ($httpCode !== 200 || !$resp) { sse('error', 'Sovereign indisponible (HTTP ' . $httpCode . ')'); echo "data: [DONE]\n\n"; exit; } $data = json_decode($resp, true); $fullText = $data['choices'][0]['message']['content'] ?? ''; $provider = $data['provider'] ?? 'sovereign'; if (!$fullText) { sse('error', 'Reponse vide'); echo "data: [DONE]\n\n"; exit; } sse('provider', ['name' => $provider, 'latency_ms' => $latency]); // Stream word by word + detect and execute bash blocks $words = preg_split('/(\s+)/', $fullText, -1, PREG_SPLIT_DELIM_CAPTURE); $buf = ''; $inCode = false; $codeLang = ''; foreach ($words as $w) { $buf .= $w; if (preg_match('/```(\w*)/', $w, $m) && !$inCode) { $inCode = true; $codeLang = $m[1] ?: 'bash'; } if ($inCode && substr_count($buf, '```') >= 2) { $inCode = false; if (preg_match('/```\w*\s*(.*?)```/s', $buf, $cm)) { $code = trim($cm[1]); sse('token', $buf); $buf = ''; if ($exec && in_array($codeLang, ['bash','sh','']) && $code) { $bad = ['rm -rf /','mkfs','dd if=',':(){','chmod -R 777 /','reboot','shutdown']; $blocked = false; foreach ($bad as $b) { if (stripos($code, $b) !== false) { $blocked = true; break; } } if ($blocked) { sse('exec_blocked', 'Commande dangereuse bloquee'); } else { sse('exec_start', $code); $out = trim(shell_exec($code . ' 2>&1')); sse('exec_result', ['cmd'=>$code, 'output'=>substr($out,0,5000), 'ok'=>true]); } } continue; } } if (!$inCode && strlen($buf) > 15) { sse('token', $buf); $buf = ''; usleep(12000); } } if ($buf) sse('token', $buf); sse('done', ['provider'=>$provider, 'latency_ms'=>$latency, 'words'=>str_word_count($fullText)]); echo "data: [DONE]\n\n";