feat: confirmations cron/systemd, renforcement script skill, éditeur de script
- base_agent: _pending_confirmations + intercepteur oui/non dans _on_xmpp_message - cron: add/remove/clear demandent confirmation (requêtes XMPP directes) - systemd: start/stop/restart/enable/disable/mask/unmask/daemon-reload demandent confirmation - script: _safe_name strip toutes les extensions, extensions système interdites, contenu vide rejeté, nouvelle commande edit <nom> <ligne> | <contenu> - README mis à jour Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -127,9 +127,15 @@ Toutes les commandes suivantes sont disponibles sur chaque agent :
|
|||||||
/report — Rapport de l'agent
|
/report — Rapport de l'agent
|
||||||
/update — Git pull + redémarrage du service
|
/update — Git pull + redémarrage du service
|
||||||
/script — Gestion de la bibliothèque de scripts bash
|
/script — Gestion de la bibliothèque de scripts bash
|
||||||
list, show <nom>, save <nom> | <contenu>, exec <nom> [args], run | <inline>, delete <nom>
|
list, show <nom>, save <nom> | <contenu>, edit <nom> <ligne> | <contenu>, exec <nom> [args], run | <inline>, delete <nom>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Mécanisme de confirmation
|
||||||
|
|
||||||
|
Les actions destructives demandent confirmation avant d'être exécutées lorsqu'elles proviennent d'un message XMPP direct (pas d'une délégation MQTT).
|
||||||
|
|
||||||
|
`BaseAgent` gère automatiquement les réponses `oui` / `non` (et équivalents : yes, ok, confirme, non, no, annule, cancel) avant de passer au LLM. Les skills utilisent `context.agent._pending_confirmations[sender]` pour enregistrer l'action en attente.
|
||||||
|
|
||||||
## Topics MQTT
|
## Topics MQTT
|
||||||
|
|
||||||
| Topic | Usage |
|
| Topic | Usage |
|
||||||
|
|||||||
@@ -102,6 +102,10 @@ class BaseAgent(ABC):
|
|||||||
self._online_lock = threading.Lock()
|
self._online_lock = threading.Lock()
|
||||||
self._llm_lock = threading.Lock() # Empêche les appels LLM concurrents
|
self._llm_lock = threading.Lock() # Empêche les appels LLM concurrents
|
||||||
|
|
||||||
|
# Confirmations en attente : {jid: {"description": str, "fn": callable}}
|
||||||
|
self._pending_confirmations: dict = {}
|
||||||
|
self._last_xmpp_sender: str = ""
|
||||||
|
|
||||||
self._running = False
|
self._running = False
|
||||||
|
|
||||||
# ──────────────────────────────────────────────
|
# ──────────────────────────────────────────────
|
||||||
@@ -462,12 +466,39 @@ class BaseAgent(ABC):
|
|||||||
# XMPP
|
# XMPP
|
||||||
# ──────────────────────────────────────────────
|
# ──────────────────────────────────────────────
|
||||||
|
|
||||||
|
_CONFIRM_YES = {"oui", "yes", "ok", "confirme", "confirm", "y"}
|
||||||
|
_CONFIRM_NO = {"non", "no", "annule", "cancel", "abort", "n"}
|
||||||
|
|
||||||
def _on_xmpp_message(self, sender: str, body: str, is_muc: bool = False):
|
def _on_xmpp_message(self, sender: str, body: str, is_muc: bool = False):
|
||||||
"""Traitement des messages XMPP entrants."""
|
"""Traitement des messages XMPP entrants."""
|
||||||
# Les sub-agents ne traitent pas les messages MUC pour éviter les boucles.
|
# Les sub-agents ne traitent pas les messages MUC pour éviter les boucles.
|
||||||
# Seul Nexus override cette méthode pour gérer le MUC.
|
# Seul Nexus override cette méthode pour gérer le MUC.
|
||||||
if is_muc:
|
if is_muc:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# ── Gestion des confirmations en attente ──────────────────────────
|
||||||
|
self._last_xmpp_sender = sender
|
||||||
|
body_clean = body.strip().lower()
|
||||||
|
if sender in self._pending_confirmations:
|
||||||
|
pending = self._pending_confirmations[sender]
|
||||||
|
if body_clean in self._CONFIRM_YES:
|
||||||
|
del self._pending_confirmations[sender]
|
||||||
|
result = pending["fn"]()
|
||||||
|
if self.xmpp:
|
||||||
|
self.xmpp.send_message(sender, f"✅ Exécuté.\n{result}")
|
||||||
|
elif body_clean in self._CONFIRM_NO:
|
||||||
|
del self._pending_confirmations[sender]
|
||||||
|
if self.xmpp:
|
||||||
|
self.xmpp.send_message(sender, f"❌ Annulé : {pending['description']}")
|
||||||
|
else:
|
||||||
|
# Message hors-sujet : rappel de la confirmation en attente
|
||||||
|
if self.xmpp:
|
||||||
|
self.xmpp.send_message(
|
||||||
|
sender,
|
||||||
|
f"⚠️ Action en attente de confirmation :\n{pending['description']}\n\nRéponds **oui** pour confirmer ou **non** pour annuler."
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
cmd = parse_command(body)
|
cmd = parse_command(body)
|
||||||
context = AgentContext(self)
|
context = AgentContext(self)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user