false, 'error' => 'No autenticado'], 401); if ($_SERVER['REQUEST_METHOD'] !== 'POST') salir(['ok' => false, 'error' => 'Método no permitido'], 405); $body = json_decode(file_get_contents('php://input'), true) ?? []; $pregunta = trim($body['pregunta'] ?? ''); if ($pregunta === '') salir(['ok' => false, 'error' => 'Pregunta vacía'], 400); if (mb_strlen($pregunta) > 800) salir(['ok' => false, 'error' => 'Pregunta demasiado larga'], 400); $gemini = new GeminiService(Database::getInstance()->getConnection()); if (!$gemini->hayClave()) { salir(['ok' => false, 'error' => 'El asistente no está configurado. Avisa a un administrador.'], 503); } if ($gemini->presupuestoAgotado()) { salir(['ok' => false, 'error' => '⚠️ Se agotaron los tokens de LIA. Solicita tokens a soporte para continuar.'], 402); } // ── Documentación visible para este usuario, acotada a la pregunta ── [$contexto, $titulos] = DocIndex::contextoIA($pregunta); if ($contexto === '') { salir([ 'ok' => true, 'respuesta' => 'Eso no está en el manual de usuario. Pruebe con otras palabras, ' . 'o revise el índice de la izquierda: puede estar en otra sección ' . 'de la documentación.', 'fuentes' => [], ]); } // ── Historial de la conversación ─────────────────────────────── $historial = []; foreach (array_slice(is_array($body['historial'] ?? null) ? $body['historial'] : [], -6) as $h) { $texto = trim((string)($h['texto'] ?? '')); if ($texto === '') continue; $historial[] = [ 'role' => (($h['rol'] ?? '') === 'model') ? 'model' : 'user', 'parts' => [['text' => mb_substr($texto, 0, 1500)]], ]; } $prompt = <<preguntar($prompt, $pregunta, $historial); salir([ 'ok' => true, 'respuesta' => $r['respuesta'], 'truncada' => $r['truncada'], 'fuentes' => $titulos, 'tokens_usados' => $r['tokens_usados'], 'tokens_restantes' => $r['tokens_restantes'], 'tokens_max' => $r['tokens_max'], ]); } catch (\Throwable $e) { salir(['ok' => false, 'error' => $e->getMessage()], 502); }