diff --git a/vps_opencode_bot/opencode_bot.py b/vps_opencode_bot/opencode_bot.py index 3db5baa..7129b5b 100644 --- a/vps_opencode_bot/opencode_bot.py +++ b/vps_opencode_bot/opencode_bot.py @@ -55,6 +55,12 @@ repos_cache = [] # lista de {'slug','dir'} sentidos = {} # chat_id -> [message_id...] enviados por el bot (para /limpiar) entrantes = {} # chat_id -> [message_id...] enviados por el usuario (para /limpiar) menu_msg = {} # chat_id -> message_id del menu abierto +ultima_actividad = time.time() # para liberar memoria por inactividad + + +def _marcar_actividad(): + global ultima_actividad + ultima_actividad = time.time() def log(linea): @@ -840,6 +846,7 @@ def responder_callback(callback): def procesar(texto, chat): + _marcar_actividad() texto = texto.strip() bajo = texto.lower() if not bajo.startswith("/"): @@ -877,12 +884,51 @@ def procesar(texto, chat): enviar(chat, "No reconozco ese comando. Usa /ayuda.") +def _vigilante_inactividad(): + """Libera memoria/CPU: si el serve lleva OC_INACTIVIDAD_MIN minutos sin + uso, lo reinicia y olvida las sesiones (la proxima peticion crea una + sesion nueva). 0 = desactivado.""" + try: + minutos = int(ENV.get("OC_INACTIVIDAD_MIN", "120")) + except Exception: + minutos = 120 + if minutos <= 0: + return + umbral = minutos * 60 + while True: + time.sleep(60) + if time.time() - ultima_actividad < umbral: + continue + log("inactividad: reiniciando opencode-serve para liberar memoria") + try: + subprocess.run(["systemctl", "restart", "opencode-serve"], + timeout=60, capture_output=True) + for _ in range(30): + if health_ok(): + break + time.sleep(1) + except Exception as e: + log(f"vigilante restart error: {e}") + # olvidar sesiones: la proxima peticion arranca sesion nueva + sesiones.clear() + guardar_estado() + _marcar_actividad() + for chat in (ALLOWED.split(",") if ALLOWED else []): + try: + enviar(chat.strip(), "♻️ Reiniciado por inactividad para " + "liberar memoria. La próxima petición " + "arranca en sesión nueva.") + except Exception: + pass + + def main(): if not TOKEN: print("Falta TELEGRAM_BOT_TOKEN en .env") return cargar_estado() listar_repos() + threading.Thread(target=_vigilante_inactividad, daemon=True).start() log("Bot iniciado") offset = cargar_offset() while True: