ia_dev/.cursor/agents/README.md

15 KiB
Raw Blame History

Gitea issues scripts et agents

Dossier dédié au traitement des tickets (issues) Gitea du dépôt 4nk/lecoffre_ng (https://git.4nkweb.com/4nk/lecoffre_ng/issues). Toute la logique d'appel API et Git est dans les scripts ; les agents orchestrent et appellent /fix ou /evol.

Agents (.cursor/agents/)

Agent Fichier Rôle
agent-loop agent-loop.md Orchestre la boucle de récupération des mails et le traitement : lance les 2 boucles en arrière-plan (récupération + traitement, pas de timeout) ou exécute x fois (récupération 1 fois puis traitement 1 fois via gitea-issues-process).
gitea-issues-process gitea-issues-process.md Traite les issues Gitea et les mails en attente : liste les issues/mails, crée des branches, lance /fix ou /evol, /push-by-script ; workflow mails (fil, réponse réelle, marquage lu).

Spooler tickets (nouveau) : mails dans projects//data/issues/ (filtre par tickets.authorized_emails dans conf.json), pas de « non lu », aucun enregistrement supprimé. Format : gitea-issues/TICKETS_SPOOL_FORMAT.md. Récupération : ./ia_dev/gitea-issues/tickets-fetch-inbox.sh. Référence boucle mails (legacy) : gitea-issues/AGENT_LOOP.md. Hook Cursor : sessionStart.cursor/hooks/remonter-mails.sh (lit projects/<id>/data/issues/*.pending).

Contexte d'exécution

  • Emplacement : gitea-issues/ est dans le sous-module ia_dev du dépôt projet. Chemin typique : <racine_projet>/ia_dev/gitea-issues/. Fonctionne pour tout projet utilisant ia_dev de la même manière.
  • Projet cible : le projet est identifié dynamiquement par le fichier ../ai_project_id (à la racine du dépôt projet, parent de ia_dev). Son contenu (slug) sert à charger la config dans ia_dev/projects/<id>/. Changer de projet = changer le dépôt (ou le contenu de ai_project_id) ; aucun chemin à hardcoder.
  • Lancement : le chat Cursor et les scripts sont lancés depuis ia_dev (<racine_projet>/ia_dev/), mais les opérations (issues, mails, déploiement) concernent le dépôt parent (../ = racine projet). Invoquer les scripts depuis la racine du dépôt projet : cd <racine_projet> && ./ia_dev/gitea-issues/<script>.sh. Depuis le workspace ia_dev, racine projet = ...
  • Secrets et logs : .secrets est sous ia_dev (ia_dev/.secrets, soit ./.secrets depuis ia_dev), et ne dépend pas du projet parent. Les scripts résolvent la racine pour .secrets et logs via le répertoire contenant gitea-issues (ia_dev), afin que la config IMAP/SMTP et les logs soient les mêmes quel que soit le projet ; un même clone ia_dev peut servir plusieurs projets configurés par ../ai_project_id.

Prérequis

  • jq : apt install jq ou brew install jq
  • Token Gitea : variable denvironnement GITEA_TOKEN ou fichier .secrets/gitea-issues/token (contenu = le token, non versionné). Créer le token dans Gitea : Settings → Applications → Generate New Token (scopes read:issue, write:issue si commentaires).

Scripts (depuis la racine du dépôt)

Script Usage Description
list-open-issues.sh ./gitea-issues/list-open-issues.sh [--lines] [--limit N] Liste les issues ouvertes (JSON ou lignes number|title|state).
get-issue.sh ./gitea-issues/get-issue.sh <num> [--summary] Détail dune issue (JSON ou résumé texte).
print-issue-prompt.sh ./gitea-issues/print-issue-prompt.sh <num> Affiche titre + corps pour fournir la consigne à lagent.
create-branch-for-issue.sh ./gitea-issues/create-branch-for-issue.sh <num> [base] Crée et checkout la branche issue/<num> depuis base (défaut test).
comment-issue.sh ./gitea-issues/comment-issue.sh <num> <message> ou echo "msg" | ./gitea-issues/comment-issue.sh <num> - Ajoute un commentaire à lissue.
mail-list-unread.sh ./gitea-issues/mail-list-unread.sh Liste les mails non lus envoyés à l'alias (MAIL_FILTER_TO, défaut ai.support.lecoffreio@4nkweb.com) ; lecture seule ; sortie : UID, Message-ID, From, To, Subject, Date, Body. Aucun autre mail n'est listé.
mail-get-thread.sh ./gitea-issues/mail-get-thread.sh <uid> Récupère tout le fil (conversation) du mail donné : tous les messages liés par References/In-Reply-To, tri chronologique (ancien → récent). Même format de sortie que mail-list-unread. À utiliser avant de décider ou répondre sur un mail.
mail-send-reply.sh ./gitea-issues/mail-send-reply.sh --to <addr> --subject "..." [--body "..." | stdin] [--in-reply-to "<msg-id>" [--references "..."]] Envoie une réponse par mail via le Bridge (SMTP) ; signature « Support IA du projet Lecoffre.io » / ai.support.lecoffreio@4nkweb.com ajoutée automatiquement.
mail-create-issue-from-email.sh ./gitea-issues/mail-create-issue-from-email.sh --uid <uid> [--title "..." ] [--body "..."] Crée une issue à partir dun mail (UID), optionnel titre/corps formalisés ; marque le mail lu.
mail-mark-read.sh ./gitea-issues/mail-mark-read.sh <uid> Marque un mail comme lu.
mail-thread-log.sh ./gitea-issues/mail-thread-log.sh get-id | init | append-sent | append-issue | append-commit ... Log par fil : un fichier par conversation dans projects/<id>/logs/gitea-issues/threads/ (échanges reçus/envoyés, tickets, commits). get-id --uid <uid> affiche THREAD_ID=... ; init --uid <uid> crée/met à jour le fichier ; append-sent/issue/commit enregistrent une réponse, une issue ou un commit.
mail-to-issue.sh ./gitea-issues/mail-to-issue.sh Batch : crée une issue par mail non lu (titre = sujet, corps = texte + From), marque lus. À éviter si on suit le workflow agent (voir cidessous).
agent-loop.sh ./ia_dev/gitea-issues/agent-loop.sh [interval_sec] Boucle de surveillance : exécute périodiquement mail-list-unread.sh, met à jour un fichier témoin (projects/<id>/logs/gitea-issues/agent-loop.status) et écrit les mails en attente dans agent-loop.pending. Voir gitea-issues/AGENT_LOOP.md.
agent-loop-treatment.sh ./ia_dev/gitea-issues/agent-loop-treatment.sh Boucle traitement : vérifie périodiquement agent-loop.pending ; si non vide, lance l'agent Cursor (workflow gitea-issues-process) pour traiter les mails. À lancer en arrière-plan (pas de timeout).
agent-loop-retrieval-once.sh ./ia_dev/gitea-issues/agent-loop-retrieval-once.sh Récupération une fois (legacy, basé non lu) : exécute mail-list-unread.sh et écrit dans agent-loop.pending. Utilisé par l'agent agent-loop pour les cycles « x fois ».
tickets-fetch-inbox.sh ./ia_dev/gitea-issues/tickets-fetch-inbox.sh Récupération par expéditeurs autorisés : filtre tickets.authorized_emails (conf.json), pas de marquage lu/non lu. Écrit les nouveaux mails dans projects/<id>/data/issues/<date>_<from>_<uid>.pending (JSON). Voir TICKETS_SPOOL_FORMAT.md.

Variables optionnelles : GITEA_API_URL, GITEA_REPO_OWNER, GITEA_REPO_NAME, GITEA_ISSUES_DIR.

Création dissues depuis les mails (IMAP) workflow agent

Ne pas enchaîner directement : lagent doit dabord lire les non lus, formaliser lissue ou répondre par mail, et ne créer/traiter quau moment où la demande est prête.

  1. Lire les non lus : ./gitea-issues/mail-list-unread.sh (ne marque pas les mails comme lus).
  2. Pour chaque mail : consulter tout l'historique du fil avec ./gitea-issues/mail-get-thread.sh <uid>, créer/mettre à jour le log du fil avec ./gitea-issues/mail-thread-log.sh init --uid <uid> (sortie THREAD_ID=... à conserver), puis décider soit denvoyer une réponse directe (demande dinfos) via mail-send-reply.sh, soit de formaliser et créer lissue avec mail-create-issue-from-email.sh (optionnel --title / --body formalisés). Si la demande est une correction/évolution prête : créer lissue, traiter (fix/evol), commenter lissue, répondre au mail via mail-send-reply.sh (avec --in-reply-to pour le fil). Le corps de la réponse doit contenir la réponse réelle à la question (ex. si le mail demande « Décrit les rôles », le body = une description des rôles), jamais le sujet du mail ni la question reçue.
  3. Réponses aux mails : toujours via le Bridge avec mail-send-reply.sh. Le --body doit être la réponse réelle rédigée par l'agent (contenu de la réponse à la demande), pas le sujet du mail, pas la question reçue, pas un message précédent du fil. Chaque envoi est enregistré dans le log du fil avec mail-thread-log.sh append-sent --thread-id <id> --to <addr> --subject "..." --body "..." pour tracer l'expéditeur, le titre et le corps de la réponse envoyée.

Prérequis :

  • Python 3 (stdlib : imaplib, email, smtplib, json, urllib).
  • Token Gitea : comme les autres scripts (GITEA_TOKEN ou .secrets/gitea-issues/token).
  • Config IMAP/SMTP : copier gitea-issues/imap-bridge.env.example vers .secrets/gitea-issues/imap-bridge.env. Pour la boucle agent (optionnel) : agent-loop.env.example vers .secrets/gitea-issues/agent-loop.env (voir AGENT_LOOP.md). Renseigner IMAP_USER, IMAP_PASSWORD (et optionnellement SMTP_* pour lenvoi ; par défaut SMTP reprend les mêmes host/port Bridge 1025). Optionnel : MAIL_FILTER_TO=ai.support.lecoffreio@4nkweb.com (seuls les mails envoyés à cette adresse sont listés).
  • Proton Mail Bridge (ou serveur IMAP/SMTP) en cours dexécution.

Scripts : mail-list-unread.sh, mail-get-thread.sh, mail-thread-log.sh, mail-send-reply.sh, mail-create-issue-from-email.sh, mail-mark-read.sh. Le script batch mail-to-issue.sh reste disponible mais ne doit pas être utilisé dans le cadre du workflow agent (liste → lecture du fil → log du fil → décision → création/ réponse). Le script agent-loop.sh permet de lancer une boucle de surveillance des mails avec fichier témoin ; voir gitea-issues/AGENT_LOOP.md.

API Wiki (tests préalables)

Script de test de lAPI Wiki Gitea pour le même dépôt (prérequis à une éventuelle migration de docs/ vers le wiki) :

Script Usage Description
wiki-api-test.sh ./gitea-issues/wiki-api-test.sh [--create] Teste GET list pages, GET page Home ; avec --create : POST une page test puis DELETE.

Prérequis : même token que les issues (GITEA_TOKEN ou .secrets/gitea-issues/token). Pour lécriture (création / suppression de pages), le token doit avoir les droits décriture sur le dépôt.

Endpoints utilisés (référence Gitea API 1.25) :

  • GET /repos/{owner}/{repo}/wiki/pages — liste des pages
  • GET /repos/{owner}/{repo}/wiki/page/{pageName} — contenu dune page (ex. Home)
  • POST /repos/{owner}/{repo}/wiki/new — créer une page (body : title, content_base64, message)
  • PATCH /repos/{owner}/{repo}/wiki/page/{pageName} — modifier une page
  • DELETE /repos/{owner}/{repo}/wiki/page/{pageName} — supprimer une page

Si le wiki na jamais été initialisé (aucune page créée via linterface), les GET peuvent renvoyer 404 ou une liste vide. Initialiser le wiki : aller sur https://git.4nkweb.com/4nk/lecoffre_ng/wiki et créer au moins une page (ex. « Home ») via linterface, puis relancer le script avec un token valide.

Branche par défaut du wiki : si lAPI renvoie object does not exist [id: refs/heads/master] alors que la branche par défaut du dépôt wiki est autre (ex. prod), cest un bug connu de certaines versions de Gitea (lAPI suppose master). Contournements possibles : (1) mettre à jour Gitea (correctif dans les versions récentes, ex. PR #34244) ; (2) changer la branche par défaut du wiki en master dans les réglages du dépôt (Settings → Branches). Variable optionnelle GITEA_WIKI_REF=master (défaut si wiki configuré sur master).

Migration docs/ → wiki

Décision : tout le contenu de docs/ (racine du dépôt) est migré vers le wiki ; pas de CI sur le wiki.

Script de migration :

Script Usage Description
wiki-migrate-docs.sh ./gitea-issues/wiki-migrate-docs.sh [--dry-run] [fichier.md ...] Migre docs/*.md vers le wiki. --dry-run affiche le mapping sans appel API. Si des fichiers sont passés en argument, migre uniquement ceux-là.
wiki-put-page.sh ./gitea-issues/wiki-put-page.sh <page_name> <file_path> Met à jour ou crée une page wiki à partir dun fichier local (ex. Home docs/README.md).
wiki-get-page.sh ./gitea-issues/wiki-get-page.sh <page_name> Affiche le markdown brut dune page wiki (pour scripts ou agents).

Correspondance fichier → page wiki : nom de fichier sans .md, _ remplacé par -, title-case par segment. Ex. OPERATIONS.md → Operations, README.md → Readme.

Les 17 fichiers de docs/ ont été migrés ; les pages sont visibles sur https://git.4nkweb.com/4nk/lecoffre_ng/wiki. La page Home contient le contenu de docs/README.md (index et correspondance). docs/ est exclu du versionnement (.gitignore) : maintenir docs/ localement (ne pas le supprimer), pousser les modifications vers le wiki avec wiki-migrate-docs.sh ou wiki-put-page.sh ; ne pas committer docs/.

Après un clone

Le répertoire docs/ n'est pas versionné. Pour disposer d'une copie locale (édition puis synchro wiki), recréer le contenu à partir du wiki : ex. ./gitea-issues/wiki-get-page.sh Home > docs/README.md, ou créer les fichiers manuellement à partir des pages wiki listées dans la section Migration ci-dessus.

Usage « wiki uniquement » pour les agents

La connaissance du projet peut reposer uniquement sur le wiki (sans lire docs/) : les agents peuvent exécuter ./gitea-issues/wiki-get-page.sh <PageName> pour récupérer le contenu markdown dune page et lutiliser comme référence. Exemples : ./gitea-issues/wiki-get-page.sh Home, ./gitea-issues/wiki-get-page.sh Operations, ./gitea-issues/wiki-get-page.sh Code-Standards. Prérequis : token Gitea (comme pour les autres scripts wiki). Les agents peuvent ainsi consulter la doc projet à la demande depuis le wiki, sans dépendre des fichiers locaux docs/.

Agents (commandes)

  • /agent-loop (agent-loop.md) : lance les 2 boucles (récupération + traitement) en arrière-plan ou exécute x cycles (récupération 1 fois puis traitement 1 fois). À la fin d'une boucle de récupération, la boucle traitement lance gitea-issues-process sur les mails reçus.
  • /gitea-issues-process (gitea-issues-process.md) : traite les issues Gitea et les mails en attente (workflow script au maximum, /fix ou /evol, /push-by-script). Voir le fichier de l'agent pour le workflow exact.

Référence