ia_dev/gitea-issues/agent-loop.sh

91 lines
5.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# Agent loop: poll for unread mails periodically and maintain a witness file.
# Run from repo root. Use a fichier témoin (status) to know if the loop is active.
#
# Usage:
# ./gitea-issues/agent-loop.sh [interval_seconds]
# AGENT_LOOP_INTERVAL_SEC=120 ./gitea-issues/agent-loop.sh
#
# Witness file: projects/<id>/logs/gitea-issues/agent-loop.status (or AGENT_LOOP_STATUS_FILE)
# Updated every iteration. If mtime is older than 2*interval, consider the loop stopped.
# Pending file: projects/<id>/logs/gitea-issues/agent-loop.pending (or AGENT_LOOP_PENDING_FILE)
# Written when unread mails exist; contains timestamp and mail list. Clear after agent run.
#
# Optional: set AGENT_LOOP_RUN_AGENT=1 to run the Cursor Agent CLI when mails are detected.
# Requires Cursor Agent CLI (https://cursor.com/docs/cli/using). If "agent" is not in PATH, the loop only updates status/pending.
#
# Optional: AGENT_LOOP_MODEL=<model> to force the model (e.g. sonnet-4.6, gpt-5.4-low). Default: sonnet-4.6 to avoid Opus usage limits when running unattended.
#
set -euo pipefail
# Source user env so PATH includes ~/.local/bin (Cursor Agent CLI, etc.)
if [ -n "${HOME:-}" ] && [ -r "$HOME/.bashrc" ]; then
set +u
# shellcheck source=/dev/null
source "$HOME/.bashrc" 2>/dev/null || true
set -u
fi
[ -n "${HOME:-}" ] && [ -d "$HOME/.local/bin" ] && export PATH="$HOME/.local/bin:$PATH"
GITEA_ISSUES_DIR="${GITEA_ISSUES_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)}"
ROOT="$(cd "${GITEA_ISSUES_DIR}/../.." && pwd)"
export GITEA_ISSUES_DIR
export REPO_ROOT="${ROOT}"
cd "$ROOT"
# Per-project logs under projects/<id>/logs (lib.sh sets PROJECT_LOGS_DIR)
# shellcheck source=lib.sh
source "${GITEA_ISSUES_DIR}/lib.sh" 2>/dev/null || true
LOGS_GITEA="${PROJECT_LOGS_DIR:-$ROOT/logs}/gitea-issues"
# Load agent-loop parameters from .secrets (optional; .secrets under ia_dev)
AGENT_LOOP_ENV="${GITEA_ISSUES_DIR}/../.secrets/gitea-issues/agent-loop.env"
if [ -r "$AGENT_LOOP_ENV" ]; then
set +u
# shellcheck source=/dev/null
source "$AGENT_LOOP_ENV"
set -u
fi
INTERVAL="${1:-${AGENT_LOOP_INTERVAL_SEC:-60}}"
STATUS_FILE="${AGENT_LOOP_STATUS_FILE:-$LOGS_GITEA/agent-loop.status}"
PENDING_FILE="${AGENT_LOOP_PENDING_FILE:-$LOGS_GITEA/agent-loop.pending}"
mkdir -p "$(dirname "$STATUS_FILE")"
write_status() {
local status="$1"
local detail="${2:-}"
printf "%s\n%s\n%s\n" "$(date -Iseconds)" "$status" "$detail" > "$STATUS_FILE"
}
while true; do
write_status "running" "interval=${INTERVAL}s"
out=""
if out=$("${GITEA_ISSUES_DIR}/mail-list-unread.sh" 2>&1); then
if echo "$out" | grep -q "UID="; then
write_status "mails_pending" "Des mails non lus. Lancer l'agent gitea-issues-process dans Cursor."
printf "%s\n%s\n%s\n%s\n" "$(date -Iseconds)" "mails_pending" "---" "$out" > "$PENDING_FILE"
echo "[agent-loop] $(date -Iseconds) — Mails non lus détectés. Lancer l'agent gitea-issues-process dans Cursor."
if [ "${AGENT_LOOP_RUN_AGENT:-0}" = "1" ] && command -v agent >/dev/null 2>&1; then
write_status "running_agent" "Lancement de l'agent Cursor pour traiter les mails."
echo "[agent-loop] $(date -Iseconds) — Lancement de l'agent Cursor (workflow gitea-issues-process mails)."
AGENT_MODEL="${AGENT_LOOP_MODEL:-sonnet-4.6}"
echo "[agent-loop] $(date -Iseconds) — Modèle: $AGENT_MODEL"
AGENT_OPTS=(-p "Exécute le workflow mails entrants de l'agent gitea-issues-process : les mails non lus viennent d'être détectés. 1) Pour chaque mail listé (voir contenu dans logs/gitea-issues/agent-loop.pending) : exécuter ./gitea-issues/mail-get-thread.sh <uid>, puis ./gitea-issues/mail-thread-log.sh init --uid <uid>, conserver THREAD_ID. 2) Pour chaque mail : rédiger une réponse NOUVELLE (non technique, didactique, contexte LeCoffre.io ; pour bug demander l'environnement, pour évolution considérer test). IMPORTANT : le --body de mail-send-reply.sh doit être du texte COMPOSÉ PAR TOI, jamais une copie ou citation d'un message du fil. Ne jamais renvoyer le contenu d'un message précédent (ex. réponse antérieure de ai.support). Envoyer avec ./gitea-issues/mail-send-reply.sh --to <adresse_From_du_mail_utilisateur> --subject \"Re: ...\" --body \"<ta_réponse>\", puis ./gitea-issues/mail-thread-log.sh append-sent, puis ./gitea-issues/mail-mark-read.sh <uid>. 3) Uniquement branche test, ne pas modifier les agents ni scripts d'agents. Répondre à tous les mails avant de marquer comme lu." -f --model "$AGENT_MODEL")
if agent "${AGENT_OPTS[@]}" 2>&1; then
write_status "agent_done" "Agent terminé."
else
write_status "mails_pending" "Agent terminé avec erreur ou interruption. Relancer l'agent manuellement si besoin."
fi
fi
else
write_status "idle" "Aucun mail non lu."
if [ -f "$PENDING_FILE" ]; then
: > "$PENDING_FILE"
fi
fi
else
write_status "error" "mail-list-unread a échoué"
echo "[agent-loop] $(date -Iseconds) — Erreur mail-list-unread" >&2
fi
sleep "$INTERVAL"
done