diff --git a/agents_core/base_agent.py b/agents_core/base_agent.py index 4485c80..7d0f357 100644 --- a/agents_core/base_agent.py +++ b/agents_core/base_agent.py @@ -511,9 +511,81 @@ class BaseAgent(ABC): all_agents = [a.agent_id for a in self.registry.all_agents()] return f"Agents en ligne : {online}\nAgents connus : {all_agents}" + if cmd == "update": + return self._do_self_update(source_msg) + # Commandes custom de l'agent return self.handle_custom_command(cmd, args, source_msg) + # ────────────────────────────────────────────── + # Mise à jour self + # ────────────────────────────────────────────── + + def _get_install_dir(self) -> str: + """Répertoire d'installation : parent du dossier config.""" + return os.path.dirname(os.path.dirname(os.path.abspath(self._config_path))) + + def _get_service_name(self) -> str: + """Nom du service systemd : depuis config ou nom du répertoire d'install.""" + return self.config.get("service_name") or os.path.basename(self._get_install_dir()) + + def _do_self_update(self, source_msg: Optional[Message] = None) -> str: + """git pull → systemctl restart si des changements sont détectés.""" + import subprocess + + install_dir = self._get_install_dir() + service_name = self._get_service_name() + logger.info(f"[Update] git pull dans {install_dir} (service : {service_name})") + + try: + result = subprocess.run( + ["git", "pull"], + cwd=install_dir, + capture_output=True, text=True, timeout=60, + ) + except Exception as e: + msg = f"[{self.agent_id}] ❌ git pull impossible : {e}" + self._send_update_reply(source_msg, msg) + return msg + + if result.returncode != 0: + msg = f"[{self.agent_id}] ❌ git pull échoué :\n{result.stderr.strip()}" + self._send_update_reply(source_msg, msg) + return msg + + stdout = result.stdout.strip() + + if "Already up to date" in stdout: + msg = f"[{self.agent_id}] ✓ Déjà à jour — pas de redémarrage." + self._send_update_reply(source_msg, msg) + return msg + + msg = ( + f"[{self.agent_id}] ✓ Mis à jour :\n{stdout}\n" + f"Redémarrage du service {service_name}..." + ) + self._send_update_reply(source_msg, msg) + + # Restart différé pour laisser le temps au message MQTT d'être envoyé + def _restart(): + import time + time.sleep(2) + try: + subprocess.run(["systemctl", "restart", service_name], timeout=30, check=True) + except Exception as e: + logger.error(f"[Update] Erreur restart {service_name} : {e}") + + threading.Thread(target=_restart, daemon=True, name="update-restart").start() + return msg + + def _send_update_reply(self, source_msg: Optional[Message], body: str): + """Renvoie la réponse d'update à Nexus via MQTT si possible.""" + if source_msg and source_msg.reply_to: + try: + self.mqtt.reply(source_msg, body) + except Exception as e: + logger.debug(f"[Update] Impossible d'envoyer la réponse : {e}") + # ────────────────────────────────────────────── # Capacités # ──────────────────────────────────────────────