false, 'error'=>'POST only']); exit; } $input = json_decode(file_get_contents('php://input'), true); $topic = trim($input['topic'] ?? ''); if (strlen($topic) < 3) { echo json_encode(['ok'=>false, 'error'=>'topic too short']); exit; } $topic = substr($topic, 0, 500); $prompt = "Tu es un expert frontend React. Genere UN composant React autonome pour: \"$topic\"\n\n" . "Contraintes techniques:\n" . "- React 18 via CDN (pas d'imports externes npm)\n" . "- TailwindCSS via CDN (class utilities)\n" . "- Pas de Router, pas de state manager\n" . "- TOUT le code dans UN seul fichier HTML renderable directement\n" . "- Design ultra-premium: gradients, animations CSS, hover effects, responsive\n" . "- Palette moderne (indigo/slate/violet/emerald)\n" . "- Composant interactif avec au moins 1 etat useState\n" . "- Pas de alert() ni prompt(), UX seulement\n" . "- Icones via Unicode emojis ou SVG inline\n" . "- Si donnees: tableau/array inline dans le composant (pas fetch externe)\n\n" . "IMPORTANT:\n" . "- Retourne UNIQUEMENT le code HTML complet commencant par \n" . "- Aucun texte d'explication avant ou apres\n" . "- Pas de backticks markdown\n" . "- Le code doit s'ouvrir directement dans un browser et fonctionner"; $prompt = wvia_context_for_prompt() . $prompt; $ch = curl_init('http://127.0.0.1:4000/v1/chat/completions'); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_POSTFIELDS => json_encode([ 'model' => 'auto', 'messages' => [['role'=>'user', 'content'=>$prompt]], 'max_tokens' => 6000, 'temperature' => 0.7 ]), CURLOPT_HTTPHEADER => ['Content-Type: application/json'], CURLOPT_TIMEOUT => 120, ]); $resp = curl_exec($ch); $http = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($http !== 200) { echo json_encode(['ok'=>false, 'error'=>"LLM HTTP $http"]); exit; } $data = json_decode($resp, true); $html = $data['choices'][0]['message']['content'] ?? ''; // Strip markdown code fences if any $html = preg_replace('/^```(?:html)?\s*\n/', '', $html); $html = preg_replace('/\n```\s*$/', '', $html); $html = trim($html); // Validation: must contain DOCTYPE and a react/tailwind reference if (stripos($html, '\n\n
\n\n\n\n\n\n\n\n\n\n\n"; } // Save as standalone HTML $filename = 'react-' . substr(md5($topic . microtime(true)), 0, 10) . '.html'; $outpath = '/var/www/html/files/' . $filename; if (!is_dir('/var/www/html/files')) { mkdir('/var/www/html/files', 0755, true); } file_put_contents($outpath, $html); // SESSION LINK DOC if (isset($outpath) && isset($filename)) { $__wvia_title = isset($doc) && isset($doc['title']) ? $doc['title'] : (isset($spec) && isset($spec['title']) ? $spec['title'] : (isset($deck) && isset($deck['title']) ? $deck['title'] : (isset($topic) ? $topic : 'Document'))); wvia_link_doc('/files/' . $filename, 'react', $__wvia_title); if (isset($topic)) wvia_append_turn('user', $topic); wvia_append_turn('assistant', '[REACT generated: ' . ($__wvia_title ?: 'doc') . ']'); } echo json_encode([ 'ok' => true, 'preview_url' => '/files/' . $filename, 'url' => '/files/' . $filename, 'title' => 'React - ' . substr($topic, 0, 50), 'code_preview' => substr($html, 0, 2000), 'size' => filesize($outpath), 'size_kb' => round(filesize($outpath)/1024, 1), 'lines' => substr_count($html, "\n"), ]);