import uuid from fastapi import APIRouter, HTTPException from qdrant_client import QdrantClient from app.api.schemas.telemetry import TelemetryPayload from app.core.engine import DECI_Engine router = APIRouter() engine = DECI_Engine() # Intentamos levantar el cliente de Qdrant. # En producción (Hugging Face Spaces), si no lo usas local, puedes usar "deci_vault" o memoria volátil. try: vault = QdrantClient(host="localhost", port=6333, timeout=2.0) except Exception: vault = None @router.post("/analyze") async def analyze_session(payload: TelemetryPayload): """ Analiza la sesión de keystrokes y, si es humana, intenta resguardar la firma en el Cognitive DNA Vault sin bloquear el flujo principal si la DB falla. """ if not payload.events: raise HTTPException(status_code=400, detail="No telemetry events provided") # 1. Procesamos la sesión con el motor continuo calibrado try: result = engine.process_session(payload.events) except Exception as engine_err: print(f"🚨 [ENGINE_ERROR]: Fallo crítico en el motor matemático: {str(engine_err)}") raise HTTPException(status_code=500, detail="Internal processing error in DECI Engine") vault_synced = False # 2. BLINDAJE VERTEX: Aislamiento total de la persistencia vectorial if vault: try: # Solo intentamos el upsert si el veredicto es estrictamente humano if result.get("is_human"): # Inicializamos el vector de 128 dimensiones vector = [0.0] * 128 vector[0] = float(result.get("score", 0.0)) # Extraemos el desglose asegurando fallbacks por si las llaves cambian breakdown = result.get("breakdown", {}) vector[1] = float(breakdown.get("entropy", 0.0)) vector[2] = float(breakdown.get("cv", 0.0)) vector[3] = float(breakdown.get("burst_ratio", breakdown.get("burst", 0.0))) vault.upsert( collection_name="cognitive_dna", points=[{ "id": str(uuid.uuid4()), "vector": vector, "payload": { "user": "Denis", "session_id": payload.session_id, "verdict": result.get("verdict") } }] ) print("🚀 [VAULT] Firma cognitiva sincronizada en Qdrant con éxito.") vault_synced = True except Exception as qdrant_err: # CAPTURAMOS EL ERRNO 111 AQUÍ: El log avisa, pero NO rompe el flujo de la sesión print(f"⚠ [VAULT_FALLBACK] Qdrant no disponible o conexión rechazada ({str(qdrant_err)}). Continuando en modo volátil.") vault_synced = False # 3. Retornamos la respuesta limpia al frontend pase lo que pase con la base de datos return { "session_id": payload.session_id, "analysis": result, "vault_synced": vault_synced }