true, CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>json_encode(["token"=>$token]), CURLOPT_HTTPHEADER=>["Content-Type: application/json"], CURLOPT_TIMEOUT=>5]);
$r = curl_exec($ch);
echo json_encode(["status"=>"token_saved","length"=>strlen($token),"ds_web"=>$r?:"ok"]);
exit;
}
if (($raw['action'] ?? '') === 'ds_token_status') {
$has = file_exists("/etc/weval/deepseek-web-token.txt") && strlen(trim(@file_get_contents("/etc/weval/deepseek-web-token.txt"))) > 10;
echo json_encode(["has_token"=>$has]);
exit;
}
$input = json_decode(file_get_contents("php://input"), true);
$message = $input['message'] ?? '';
$mode = $input['mode'] ?? 'instant';
$model = $input['model'] ?? 'auto';
$history = $input['history'] ?? [];
// OPUS 20avr doctrine #2 ZERO simulation: check structured intents BEFORE LLM fallback
// Prevents hallucination on diagnostic/vault/self-reference questions
if (!empty($message) && file_exists(__DIR__ . "/wevia-self-diagnostic-intent.php")) {
require_once __DIR__ . "/wevia-self-diagnostic-intent.php";
if (function_exists("wevia_self_diagnostic")) {
$_sd_result = wevia_self_diagnostic($message);
if ($_sd_result) {
$_sd_content = isset($_sd_result["content"]) ? $_sd_result["content"] : json_encode($_sd_result, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
echo json_encode([
"content" => $_sd_content,
"provider" => "opus46",
"tool" => "self_diagnostic",
"model" => "php-intent-real-exec",
"note" => "Doctrine #2: real shell execution, not LLM simulation"
], JSON_UNESCAPED_UNICODE);
exit;
}
}
}
$temp = floatval($input['temperature'] ?? 0.7);
// === DEEPSEEK WEB DIRECT (port 8901) — FREE UNLIMITED ===
if ($model === 'deepseek-web' || $model === 'deepseek-web-think' || $model === 'deepseek-web-search') {
$ds_mode = 'instant';
if ($model === 'deepseek-web-think' || $mode === 'deepthink') $ds_mode = 'deepthink';
if ($model === 'deepseek-web-search' || $mode === 'search') $ds_mode = 'search';
if ($mode === 'deepthink-search') { $ds_mode = 'deepthink'; } // DeepSeek Web: think takes priority, search via SearXNG
$ds_payload = json_encode(["message" => $message, "mode" => $ds_mode], JSON_UNESCAPED_UNICODE);
$ch = curl_init("http://localhost:8901/chat");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $ds_payload,
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_TIMEOUT => 5
]);
$r = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($code === 200) {
$d = @json_decode($r, true);
if (isset($d['content'])) {
$d['provider'] = 'DeepSeek Web UNLIMITED';
$d['model'] = 'deepseek-web-' . $ds_mode;
$d['cost'] = '0€ illimité';
echo json_encode($d);
exit;
}
}
// If DeepSeek Web fails (no token), fall through to cascade
$model = 'auto'; // FALLTHROUGH: use cascade when DS Web fails
}
// === GEMINI NATIVE DEEPTHINK (with thinking chain) ===
if (($mode === 'deepthink' || $mode === 'deepthink-search') && $model !== 'deepseek-web-think') {
$env2 = @file_get_contents("/etc/weval/secrets.env") ?: "";
$gkey = ""; if (preg_match("/GEMINI_KEY=(.+)/", $env2, $gm)) $gkey = trim($gm[1]);
if ($gkey) {
$prompt = $message;
// If search mode too, enrich with SearXNG
if ($mode === 'deepthink-search') {
$enc = urlencode($message);
$sch = curl_init("http://localhost:8888/search?q=$enc&format=json&categories=general");
curl_setopt_array($sch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 6]);
$sr = curl_exec($sch);
$sd = @json_decode($sr, true);
$web = [];
foreach (array_slice($sd["results"] ?? [], 0, 5) as $wr) {
$web[] = $wr["title"] . ": " . substr($wr["content"] ?? "", 0, 120);
}
if ($web) $prompt .= "\n\nResultats web:\n" . implode("\n", $web);
}
$payload = json_encode([
"contents" => [["parts" => [["text" => $prompt]]]],
"systemInstruction" => ["parts" => [["text" => "Tu es WEVIA DeepSeek en mode DeepThink. COMMENCE TOUJOURS par une section de reflexion entre balises et ou tu raisonnes etape par etape, analyses les hypotheses, explores les pistes. PUIS donne ta reponse finale APRES la balise . Format: \nRaisonnement...\n\nReponse finale."]]],
"generationConfig" => [
"thinkingConfig" => ["thinkingBudget" => 2048],
"maxOutputTokens" => 4000
]
], JSON_UNESCAPED_UNICODE);
$t0 = microtime(true);
$ch = curl_init("https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key=$gkey");
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $payload, CURLOPT_HTTPHEADER => ["Content-Type: application/json"], CURLOPT_TIMEOUT => 45, CURLOPT_SSL_VERIFYPEER => false]);
$r = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($code === 200) {
$d = @json_decode($r, true);
$parts = $d["candidates"][0]["content"]["parts"] ?? [];
$thinking = ""; $answer = "";
$full = "";
foreach ($parts as $p) {
if (isset($p["text"])) $full .= $p["text"];
}
// Parse ... tags
if (preg_match('/(.*?)<\/think>/s', $full, $tm)) {
$thinking = trim($tm[1]);
$answer = trim(preg_replace('/.*?<\/think>/s', '', $full));
} else {
// Fallback: try to split on even without matching regex
if (strpos($full, '') !== false) {
$split = explode('', $full, 2);
$thinking = trim(str_replace('', '', $split[0]));
$answer = trim($split[1] ?? '');
} elseif (strpos($full, '') !== false) {
// exists but no closing tag - treat first 40% as thinking
$thinking = trim(str_replace('', '', substr($full, 0, intval(strlen($full)*0.4))));
$answer = trim(substr($full, intval(strlen($full)*0.4)));
} else {
$answer = $full;
}
}
$elapsed = round((microtime(true) - $t0) * 1000);
$usage = $d["usageMetadata"] ?? [];
echo json_encode([
"content" => $answer ?: ($thinking ?: "No response"),
"thinking" => $thinking,
"provider" => "Gemini 2.5 Flash DeepThink",
"model" => "gemini-2.5-flash-thinking",
"mode" => $mode,
"tokens" => ($usage["totalTokenCount"] ?? 0),
"latency_ms" => $elapsed,
"cost" => "0EUR",
"has_thinking" => strlen($thinking) > 0
]);
exit;
}
}
}
$max_tokens = intval($input['max_tokens'] ?? 2000);
if (!$message) { echo json_encode(["error" => "no message"]); exit; }
$env = @file_get_contents("/etc/weval/secrets.env") ?: "";
// System prompts by mode
// OPUS 20avr doctrine #4 HONNETE: anti-hallucination guard preprended to all system prompts
$__anti_halluc_guard = "REGLES STRICTES DOCTRINE 4 HONNETETE: Tu es un LLM. Tu ne peux PAS executer de commandes shell ni lire de fichiers. Si user demande diagnostic/status/lecture fichier/exec commande: reponds 'Cette requete necessite un intent shell reel. Tape diagnostique toi ou demande a Opus de wire un intent dedie.' N INVENTE JAMAIS outputs commandes PIDs paths MD5 timestamps. Si tu ne connais pas une info factuelle dis-le explicitement. ";
$systems = [
'instant' => "Tu es WEVIA DeepSeek, IA souveraine. Reponds de facon concise et precise.",
'deepthink-search' => "Tu es WEVIA DeepSeek en mode DeepThink+Search. RAISONNE etape par etape ET utilise les resultats de recherche web pour enrichir ton analyse.",
'deepthink' => "Tu es WEVIA DeepSeek en mode DeepThink. RAISONNE etape par etape:\n1. Analyse le probleme\n2. Identifie les hypotheses\n3. Explore chaque piste\n4. Synthetise\n5. Conclus\nSois rigoureux et structure.",
'search' => "Tu es WEVIA DeepSeek avec acces web.",
'expert' => "Tu es WEVIA DeepSeek Expert. PhD-level. Reponds avec rigueur scientifique, citations, formules si necessaire. Profondeur maximale.",
'code' => "Tu es WEVCODE, expert code souverain. Code COMPLET, FONCTIONNEL, documente. Python/PHP/JS/SQL/Bash. Tests inclus.",
'creative' => "Tu es un ecrivain creatif de talent. Style riche, evocateur, immersif. Francais soutenu.",
];
$system = $__anti_halluc_guard . ($systems[$mode] ?? $systems['instant']);
// Search mode: enrich with SearXNG
if ($mode === 'search' || $mode === 'deepthink-search') {
$enc = urlencode($message);
$ch = curl_init("http://localhost:8888/search?q=$enc&format=json&categories=general");
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 8]);
$sr = curl_exec($ch);
$sd = @json_decode($sr, true);
$results = [];
foreach (array_slice($sd['results'] ?? [], 0, 6) as $r) {
$results[] = "- " . ($r['title'] ?? '') . ": " . substr($r['content'] ?? '', 0, 150);
}
if ($results) {
$system .= "\n\nRESULTATS WEB:\n" . implode("\n", $results) . "\n\nSynthetise ces resultats dans ta reponse.";
}
}
// Model routing
$samba_key = ""; $gemini_key = ""; $groq_key = ""; $cerebras_key = "";
if (preg_match("/SAMBANOVA_KEY=(.+)/", $env, $m)) $samba_key = trim($m[1]);
if (preg_match("/GEMINI_KEY=(.+)/", $env, $m)) $gemini_key = trim($m[1]);
if (preg_match("/GROQ_KEY=(.+)/", $env, $m)) $groq_key = trim($m[1]);
if (preg_match("/CEREBRAS_API_KEY=(.+)/", $env, $m)) $cerebras_key = trim($m[1]);
// Auto model selection based on mode
$model_map = [
'auto' => [
'instant' => ['DeepSeek-V3.2', 'samba'],
'deepthink-search' => "Tu es WEVIA DeepSeek en mode DeepThink+Search. RAISONNE etape par etape ET utilise les resultats de recherche web pour enrichir ton analyse.",
'deepthink' => ['DeepSeek-R1-0528', 'samba'],
'search' => ['DeepSeek-V3.2', 'samba'],
'expert' => ['gemini-2.5-pro', 'gemini'],
'code' => ['DeepSeek-V3.2', 'samba'],
'creative' => ['Meta-Llama-3.3-70B-Instruct', 'samba'],
],
];
// Build provider list based on model selection
$providers = [];
if ($model === 'auto') {
$auto = $model_map['auto'][$mode] ?? ['DeepSeek-V3.2', 'samba'];
// Primary based on mode
if ($auto[1] === 'samba' && $samba_key) {
$providers[] = ["url" => "https://api.sambanova.ai/v1/chat/completions", "key" => $samba_key, "model" => $auto[0], "name" => "SambaNova " . $auto[0]];
}
if ($auto[1] === 'gemini' && $gemini_key) {
$providers[] = ["url" => "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions", "key" => $gemini_key, "model" => $auto[0], "name" => "Google " . $auto[0]];
}
// Fallbacks
if ($samba_key) $providers[] = ["url" => "https://api.sambanova.ai/v1/chat/completions", "key" => $samba_key, "model" => "DeepSeek-V3.2", "name" => "SambaNova DeepSeek-V3.2"];
if ($gemini_key) $providers[] = ["url" => "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions", "key" => $gemini_key, "model" => "gemini-2.5-flash", "name" => "Gemini 2.5 Flash"];
if ($groq_key) $providers[] = ["url" => "https://api.groq.com/openai/v1/chat/completions", "key" => $groq_key, "model" => "llama-3.3-70b-versatile", "name" => "Groq Llama-3.3-70B"];
if ($cerebras_key) $providers[] = ["url" => "https://api.cerebras.ai/v1/chat/completions", "key" => $cerebras_key, "model" => "llama3.1-8b", "name" => "Cerebras Llama-8B"];
} else {
// Specific model selected
$specific_models = [
'deepseek-r1' => ["url" => "https://api.sambanova.ai/v1/chat/completions", "key" => $samba_key, "model" => "DeepSeek-R1-0528"],
'deepseek-v3.2' => ["url" => "https://api.sambanova.ai/v1/chat/completions", "key" => $samba_key, "model" => "DeepSeek-V3.2"],
'deepseek-v3.1' => ["url" => "https://api.sambanova.ai/v1/chat/completions", "key" => $samba_key, "model" => "DeepSeek-V3.1"],
'llama-4' => ["url" => "https://api.sambanova.ai/v1/chat/completions", "key" => $samba_key, "model" => "Llama-4-Maverick-17B-128E-Instruct"],
'gpt-oss-120b' => ["url" => "https://api.sambanova.ai/v1/chat/completions", "key" => $samba_key, "model" => "gpt-oss-120b"],
'minimax' => ["url" => "https://api.sambanova.ai/v1/chat/completions", "key" => $samba_key, "model" => "MiniMax-M2.5"],
'gemma-3' => ["url" => "https://api.sambanova.ai/v1/chat/completions", "key" => $samba_key, "model" => "gemma-3-12b-it"],
'gemini-2.5-pro' => ["url" => "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions", "key" => $gemini_key, "model" => "gemini-2.5-pro"],
'gemini-2.5-flash' => ["url" => "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions", "key" => $gemini_key, "model" => "gemini-2.5-flash"],
'groq-llama' => ["url" => "https://api.groq.com/openai/v1/chat/completions", "key" => $groq_key, "model" => "llama-3.3-70b-versatile"],
];
if (isset($specific_models[$model])) {
$p = $specific_models[$model];
$p["name"] = ucfirst(str_replace('-', ' ', $model));
$providers[] = $p;
}
}
// Adjust max_tokens for DeepThink
if ($mode === 'deepthink') $max_tokens = max($max_tokens, 4000);
if ($mode === 'expert') $max_tokens = max($max_tokens, 3000);
$messages = [["role" => "system", "content" => $system]];
foreach (array_slice($history, -12) as $h) {
$messages[] = ["role" => $h['role'], "content" => $h['content']];
}
$messages[] = ["role" => "user", "content" => $message];
$t0 = microtime(true);
// === TIER 0: DeepSeek Web FREE UNLIMITED ===
require_once __DIR__ . chr(47) . "deepseek-web-bridge.php";
foreach ($providers as $p) {
if (!$p['key']) continue;
$data = json_encode(["model" => $p["model"], "messages" => $messages, "max_tokens" => $max_tokens, "temperature" => $temp], JSON_UNESCAPED_UNICODE);
$ch = curl_init($p["url"]);
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => $data, CURLOPT_HTTPHEADER => ["Content-Type: application/json", "Authorization: Bearer " . $p["key"]], CURLOPT_TIMEOUT => 30, CURLOPT_SSL_VERIFYPEER => false]);
$r = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($code === 200) {
$d = @json_decode($r, true);
$content = $d["choices"][0]["message"]["content"] ?? null;
$usage = $d["usage"] ?? [];
if ($content) {
$elapsed = round((microtime(true) - $t0) * 1000);
echo json_encode([
"content" => $content,
"provider" => $p["name"],
"model" => $p["model"],
"mode" => $mode,
"tokens" => ($usage["total_tokens"] ?? 0),
"prompt_tokens" => ($usage["prompt_tokens"] ?? 0),
"completion_tokens" => ($usage["completion_tokens"] ?? 0),
"latency_ms" => $elapsed,
"cost" => "0€"
]);
exit;
}
}
}
echo json_encode(["error" => "All providers failed", "content" => "Providers indisponibles. Reessayez."]);