127 lines
7.6 KiB
Markdown
127 lines
7.6 KiB
Markdown
# Boucle agent (agent-loop) – surveillance des mails et fichier témoin
|
||
|
||
Script qui tourne en boucle dans l’environnement Cursor de ce projet pour surveiller les mails non lus et maintenir un **fichier témoin** indiquant si la boucle est active.
|
||
|
||
## Rôle du script
|
||
|
||
- Exécuter périodiquement `mail-list-unread.sh` (sans modifier l’état des mails).
|
||
- Mettre à jour à chaque tour un **fichier témoin** (statut + horodatage) pour savoir si la boucle est active.
|
||
- Quand des mails non lus sont détectés, écrire un fichier **pending** et afficher un message invitant à lancer l’agent dans Cursor.
|
||
|
||
Le script **ne traite pas** les mails lui‑même : le traitement (réponse, issues, commits) est fait par l’**agent gitea-issues-process**. Vous pouvez soit lancer l’agent à la main dans Cursor, soit faire lancer l’agent par la boucle en activant `AGENT_LOOP_RUN_AGENT=1` (voir ci‑dessous) si la **Cursor Agent CLI** est installée.
|
||
|
||
## Environnement au démarrage
|
||
|
||
Au démarrage, le script **source systématiquement** `~/.bashrc` (si le fichier existe et est lisible), puis ajoute `~/.local/bin` au `PATH` si ce répertoire existe. Ainsi, la commande `agent` (Cursor Agent CLI) est trouvée même si la boucle est lancée depuis un contexte où le shell n’a pas chargé le profil (nohup, cron, etc.).
|
||
|
||
## Lancement
|
||
|
||
Si le fichier `.secrets/gitea-issues/agent-loop.env` existe, il est sourcé au démarrage (voir `agent-loop.env.example`).
|
||
|
||
Depuis la **racine du dépôt** :
|
||
|
||
```bash
|
||
./gitea-issues/agent-loop.sh
|
||
```
|
||
|
||
Avec un intervalle en secondes (défaut 60) :
|
||
|
||
```bash
|
||
./gitea-issues/agent-loop.sh 120
|
||
```
|
||
|
||
Ou via une variable d’environnement :
|
||
|
||
```bash
|
||
AGENT_LOOP_INTERVAL_SEC=120 ./gitea-issues/agent-loop.sh
|
||
```
|
||
|
||
Pour l’exécuter en arrière-plan et garder la boucle active après fermeture du terminal, utiliser `nohup` ou un gestionnaire de processus (systemd, screen, tmux) :
|
||
|
||
```bash
|
||
nohup ./gitea-issues/agent-loop.sh 60 >> logs/gitea-issues/agent-loop.log 2>&1 &
|
||
```
|
||
|
||
## Fichier témoin (actif / inactif)
|
||
|
||
- **Emplacement** : `logs/gitea-issues/agent-loop.status` (ou `AGENT_LOOP_STATUS_FILE` si défini).
|
||
- **Contenu** : trois lignes
|
||
1. Horodatage ISO 8601 du dernier tour.
|
||
2. Statut : `idle` | `mails_pending` | `running` | `error`.
|
||
3. Détail optionnel (ex. message pour l’utilisateur).
|
||
|
||
**Considérer la boucle comme active** si le fichier a été modifié depuis moins de **2 × intervalle** (ex. moins de 120 s si intervalle = 60 s). Au-delà, la boucle est considérée arrêtée.
|
||
|
||
Exemple de vérification (intervalle 60 s) :
|
||
|
||
```bash
|
||
# Fichier modifié il y a moins de 120 s ?
|
||
[ $(($(date +%s) - $(stat -c %Y logs/gitea-issues/agent-loop.status 2>/dev/null || 0))) -lt 120 ] && echo "Actif" || echo "Inactif"
|
||
```
|
||
|
||
Ou simplement consulter la première ligne du fichier (date du dernier tour) et la comparer à l’heure courante.
|
||
|
||
## Fichier pending (mails en attente)
|
||
|
||
- **Emplacement** : `logs/gitea-issues/agent-loop.pending`.
|
||
- **Rôle** : quand des mails non lus sont détectés, le script y écrit un bloc (horodatage, statut `mails_pending`, puis la sortie de `mail-list-unread.sh`). Permet de voir quels mails attendent un traitement par l’agent.
|
||
- Quand il n’y a plus de non lus, le script vide ce fichier au tour suivant.
|
||
|
||
## Variables d’environnement
|
||
|
||
Variables possibles dans `.secrets/gitea-issues/agent-loop.env` ou en export shell :
|
||
|
||
| Variable | Défaut | Description |
|
||
|----------|--------|-------------|
|
||
| `AGENT_LOOP_INTERVAL_SEC` | 60 | Intervalle entre deux vérifications (secondes). Peut aussi être passé en premier argument au script. |
|
||
| `AGENT_LOOP_RUN_AGENT` | 0 | Si mis à `1`, la boucle lance la **Cursor Agent CLI** (`agent`) quand des mails non lus sont détectés, avec un prompt qui exécute le workflow mails de gitea-issues-process. Nécessite que la commande `agent` soit installée (voir [Cursor CLI](https://cursor.com/docs/cli/using)). Si `agent` n’est pas dans le PATH, la boucle se contente de mettre à jour le statut et le fichier pending. |
|
||
| `AGENT_LOOP_MODEL` | `sonnet-4.6` | Modèle utilisé par la CLI (`agent --model ...`). Par défaut `sonnet-4.6` pour limiter les blocages liés aux quotas Opus. Ex. : `AGENT_LOOP_MODEL=gpt-5.4-low` ; liste : `agent models`. |
|
||
| `AGENT_LOOP_STATUS_FILE` | `logs/gitea-issues/agent-loop.status` | Chemin du fichier témoin. |
|
||
| `AGENT_LOOP_PENDING_FILE` | `logs/gitea-issues/agent-loop.pending` | Chemin du fichier pending. |
|
||
| `GITEA_ISSUES_DIR` | répertoire du script | Racine des scripts gitea-issues (pour appeler `mail-list-unread.sh`). |
|
||
|
||
## Traiter les mails
|
||
|
||
Dès que le statut est `mails_pending` ou que des mails apparaissent dans `agent-loop.pending` :
|
||
|
||
1. **Option A (manuel)** : ouvrir le projet dans **Cursor**, lancer l’**agent gitea-issues-process** (commande `/gitea-issues-process` ou via l’interface des agents).
|
||
2. **Option B (automatique)** : lancer la boucle avec `AGENT_LOOP_RUN_AGENT=1` et la **Cursor Agent CLI** installée (`agent` dans le PATH). Lorsque des mails non lus sont détectés, le script invoque `agent -p "..." -f` pour exécuter le workflow mails (fil, log, réponse, marquage lu). Voir [Cursor CLI](https://cursor.com/docs/cli/using) pour l’installation.
|
||
|
||
L’agent lit les non lus, consulte les fils, répond par mail, crée des issues si besoin, et marque les mails comme lus.
|
||
|
||
Après passage de l’agent, au prochain tour de la boucle le statut repassera à `idle` et le fichier pending sera vidé (s’il n’y a plus de non lus).
|
||
|
||
## Logs
|
||
|
||
Le script n’écrit pas de log structuré par défaut. Pour garder une trace des tours et des messages affichés :
|
||
|
||
```bash
|
||
./gitea-issues/agent-loop.sh 60 2>&1 | tee -a logs/gitea-issues/agent-loop.log
|
||
```
|
||
|
||
Ou en arrière-plan :
|
||
|
||
```bash
|
||
nohup ./gitea-issues/agent-loop.sh 60 >> logs/gitea-issues/agent-loop.log 2>&1 &
|
||
```
|
||
|
||
## Arrêter la boucle
|
||
|
||
- Si le script est en premier plan : `Ctrl+C`.
|
||
- Si lancé en arrière-plan : `kill <pid>` (ou `pkill -f agent-loop.sh`).
|
||
|
||
Après arrêt, le fichier témoin ne sera plus mis à jour ; après 2 × intervalle, il doit être considéré comme inactif.
|
||
|
||
## Boucle limitée depuis le chat (sans API payante)
|
||
|
||
Pour lancer depuis **ce** chat (instance Cursor ouverte, abonnement Ultra) une boucle limitée : récupération des mails → attente 1 min → récupération → … sans consommer de crédits API ni lancer la CLI `agent` :
|
||
|
||
1. Demander dans le chat : *« Lance la boucle récupération emails : subagent puis attend 1 min et relance, N itérations »* (ou similaire).
|
||
2. L’agent exécute `cd /home/desk/code/lecoffre_ng_test && ./ia_dev/gitea-issues/agent-loop-chat-iterations.sh [N]` depuis la racine du dépôt projet. Par défaut N=3 ; pour 300 itérations, lancer en terminal (tmux/screen) depuis la même racine.
|
||
3. Au lancement, le script envoie un mail de test à nicolas.cantu@pm.me pour vérifier SMTP ; si l'envoi échoue, le script s'arrête (code 1).
|
||
4. Chaque itération exécute `mail-list-unread.sh` puis attend 60 secondes. Les mails en attente sont écrits dans `logs/gitea-issues/agent-loop.pending` ; traiter ensuite dans le même chat (workflow gitea-issues-process, voir `.cursor/agents/gitea-issues-process.md`).
|
||
|
||
**Pourquoi l'envoi pouvait échouer** : si le script était invoqué depuis la racine projet avec ROOT = toplevel Git (racine projet), le chemin `./gitea-issues/` n'existait pas (gitea-issues est dans ia_dev). Le script utilise maintenant le répertoire contenant gitea-issues (ia_dev) comme racine et appelle les sous-scripts via `GITEA_ISSUES_DIR`.
|
||
|
||
Script : `gitea-issues/agent-loop-chat-iterations.sh [N]`. Boucle illimitée en terminal : `cd <racine_projet> && while true; do ./ia_dev/gitea-issues/mail-list-unread.sh; sleep 60; done`.
|