From e3cfb81b9ee06472119334f599ffcf216c64ec28 Mon Sep 17 00:00:00 2001 From: sylvain Date: Mon, 23 Mar 2026 19:11:23 +0000 Subject: [PATCH] fix: script.py guillemets, cron bad minute, system_prompt scripts bash Co-Authored-By: Claude Sonnet 4.6 --- config/system_prompt.txt | 20 +++++++++++++++++++- skills/cron.py | 28 +++++++++++++++++++++------- skills/script.py | 2 +- 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/config/system_prompt.txt b/config/system_prompt.txt index 4fbe046..0af52b2 100644 --- a/config/system_prompt.txt +++ b/config/system_prompt.txt @@ -25,7 +25,25 @@ Tu reçois des instructions via MQTT (depuis Nexus) ou XMPP. - Réponds en français, sois concis - Si un playbook échoue, analyse la sortie et propose une correction -## Communication MQTT +## Écriture de scripts bash — règles strictes + +### ❌ Interdit dans les scripts bash +- `muc_send`, `mqtt_send`, `shell` et tous les noms de skills — ce ne sont PAS des commandes bash +- Les guillemets échappés : écris `"texte"` et non `\"texte\"` + +### ✅ Pour envoyer un message depuis un script +Variables injectées automatiquement : `$MQTT_BROKER`, `$MQTT_REPLY_TOPIC`, `$AGENT_ID` + +```bash +mosquitto_pub -h "$MQTT_BROKER" -t "$MQTT_REPLY_TOPIC" -m "mon résultat" +``` + +### ✅ Bonnes pratiques +- Commence toujours par `#!/bin/bash` et `set -euo pipefail` +- Guillemets doubles autour des variables : `"$VAR"` +- Gère les cas d'erreur avec des messages explicites + +## Communication MQTT (depuis le LLM, pas depuis un script) Tu peux envoyer des messages à d'autres agents : SKILL:mqtt_send ARGS:agents/nexus/inbox | résultat ou information importante diff --git a/skills/cron.py b/skills/cron.py index cf8d52a..9462947 100644 --- a/skills/cron.py +++ b/skills/cron.py @@ -35,6 +35,16 @@ def _run(cmd: str, timeout: int = 10) -> str: return str(e) +def _get_current_crontab() -> str: + """Retourne le crontab actuel, ou chaîne vide si inexistant.""" + result = subprocess.run( + "crontab -l", shell=True, text=True, capture_output=True + ) + if result.returncode != 0: + return "" + return result.stdout.strip() + + def run(args: str, context) -> str: parts = args.strip().split(None, 1) action = parts[0].lower() if parts else "list" @@ -54,26 +64,28 @@ def run(args: str, context) -> str: command = " ".join(words[5:]) entry = f"{cron_expr} {command}" - current = _run("crontab -l 2>/dev/null") + current = _get_current_crontab() if entry in current: return f"Cette entrée existe déjà : {entry}" def _do_add(): with tempfile.NamedTemporaryFile(mode="w", suffix=".cron", delete=False) as f: - if current and "no crontab" not in current.lower(): + if current: f.write(current + "\n") f.write(entry + "\n") tmpfile = f.name - out = _run(f"crontab {tmpfile}") + result = subprocess.run(f"crontab {tmpfile}", shell=True, text=True, capture_output=True) os.unlink(tmpfile) - return f"Entrée ajoutée : {entry}\n{out}" + if result.returncode != 0: + return f"❌ Erreur crontab : {(result.stdout + result.stderr).strip()}" + return f"✅ Entrée ajoutée : {entry}" return _confirm_or_execute(context, f"Ajouter cron : {entry}", _do_add) if action == "remove": if not rest: return "Précise le pattern à supprimer." - current = _run("crontab -l 2>/dev/null") + current = _get_current_crontab() lines = [l for l in current.splitlines() if rest not in l] removed_count = len(current.splitlines()) - len(lines) if removed_count == 0: @@ -84,9 +96,11 @@ def run(args: str, context) -> str: with tempfile.NamedTemporaryFile(mode="w", suffix=".cron", delete=False) as f: f.write(new_cron + "\n") tmpfile = f.name - out = _run(f"crontab {tmpfile}") + result = subprocess.run(f"crontab {tmpfile}", shell=True, text=True, capture_output=True) os.unlink(tmpfile) - return f"{removed_count} entrée(s) supprimée(s) contenant '{rest}'.\n{out}" + if result.returncode != 0: + return f"❌ Erreur crontab : {(result.stdout + result.stderr).strip()}" + return f"✅ {removed_count} entrée(s) supprimée(s) contenant '{rest}'." return _confirm_or_execute(context, f"Supprimer {removed_count} cron contenant '{rest}'", _do_remove) diff --git a/skills/script.py b/skills/script.py index 112307a..ce58ee8 100644 --- a/skills/script.py +++ b/skills/script.py @@ -147,7 +147,7 @@ def run(args: str, context) -> str: return "Format : save | " name_raw, content = rest.split("|", 1) name = _safe_name(name_raw) - content = content.strip().replace("\\n", "\n") + content = content.strip().replace("\\n", "\n").replace('\\"', '"').replace("\\'", "'") if not name: return "Nom de script invalide."