# Écouteur WhatNxt : ton agent réagit tout de suite à une @mention

Quand quelqu'un écrit `@Finance` dans le groupe, ton agent répond en quelques secondes. Pas de cron, pas de serveur à ouvrir, pas de domaine.

Comment ça marche : le script `whatnxt-listener.mjs` garde une requête ouverte vers WhatNxt (sortante, en HTTPS, jusqu'à 50 s, puis il recommence). Dès qu'une mention arrive, WhatNxt répond, et le script lance `claude -p` dans ton dossier pour cette mention. Jusqu'à 2 mentions en même temps (réglable), jamais deux dans la même conversation.

## Ce qu'il te faut

- Node 20.3 ou plus récent (`node --version`).
- Claude Code installé et connecté sur le VPS.
- Le serveur MCP `whatnxt` déjà ajouté dans le dossier de l'agent (`claude mcp add ...`, portée locale). Claude s'en sert pour répondre avec `post_message`. Avec les droits fichiers, il peut aussi lire les fichiers du groupe (`list_docs`, `get_doc`) et envoyer un fichier dans le chat (`post_file`).
- La clé de l'agent (`wnk_live_...`).

## 1. Mets la clé dans un fichier privé

```sh
umask 077
read -rs KEY && printf '%s\n' "$KEY" > ~/.whatnxt_agent_key && unset KEY
chmod 600 ~/.whatnxt_agent_key
```

Colle la clé après la commande `read` puis Entrée (elle ne s'affiche pas et ne finit pas dans l'historique). Le script refuse de démarrer si le fichier est lisible par le groupe ou par les autres.

## 2. Teste à la main

Copie `whatnxt-listener.mjs` sur le VPS (par exemple dans `~/whatnxt-listener.mjs`), puis :

```sh
cd ~/team-finance
node ~/whatnxt-listener.mjs
```

Tu dois voir `start cursor=server`. Dans l'app, écris `@Finance test` dans le groupe. Une ligne `mention id=... outcome=ok` apparaît, et la réponse de l'agent arrive dans le chat. Ctrl+C pour arrêter.

Test de l'API seule (répond au bout de 5 s si rien n'arrive) :

```sh
curl -s -H "Authorization: Bearer $(cat ~/.whatnxt_agent_key)" \
  "https://oijlvvqvwhqyjemmuegz.supabase.co/functions/v1/agent-api/v1/mentions/wait?timeout=5"
```

## 3. Lance-le en service (systemd)

`/etc/systemd/system/whatnxt-finance.service` (adapte l'utilisateur et les chemins) :

```ini
[Unit]
Description=WhatNxt listener (agent Finance)
After=network-online.target
Wants=network-online.target

[Service]
User=jerome
WorkingDirectory=/home/jerome/team-finance
Environment=PATH=/home/jerome/.local/bin:/usr/local/bin:/usr/bin:/bin
ExecStart=/usr/bin/node /home/jerome/whatnxt-listener.mjs
Restart=always
RestartSec=10
RestartPreventExitStatus=2
TimeoutStopSec=30

[Install]
WantedBy=multi-user.target
```

```sh
sudo systemctl daemon-reload
sudo systemctl enable --now whatnxt-finance
journalctl -u whatnxt-finance -f
```

Le code de sortie 2 veut dire clé refusée (révoquée, fausse, ou fichier mal protégé) : systemd ne relance pas en boucle. Corrige la clé puis `sudo systemctl restart whatnxt-finance`.

## Règles de l'agent

Dans l'app, ouvre ton agent puis « Règles ». Quatre onglets :

- **Qui** : qui peut lui écrire (les admins, tout le groupe, ou des personnes choisies). C'est WhatNxt qui bloque : les mentions des autres n'arrivent jamais à l'écouteur, et une ligne le dit dans le chat.
- **Machine** : ce qu'il peut faire sur ce serveur (lire, modifier, supprimer, envoyer vers une base externe, lancer des commandes, aller sur internet), chaque fois Oui, Me demander ou Non. C'est l'écouteur qui l'applique, avec les permissions de Claude Code :
  - Oui : l'outil est autorisé (`--allowedTools`).
  - Non : l'outil est interdit (`--disallowedTools`). Claude répond qu'il n'a pas le droit.
  - Me demander : Claude Code pose la question à WhatNxt (`--permission-prompt-tool mcp__whatnxt__check_permission`). L'agent poste une carte Valider / Refuser dans le groupe et attend. Seul toi, le propriétaire de l'agent, peux répondre : c'est ta machine. Les autres voient la carte « En attente de <ton prénom> », sans les boutons. Un OK vaut pour une seule action, celle demandée. Sans réponse, la carte expire au bout de 10 minutes.
  - Tant que tu n'as rien enregistré dans cet onglet, l'écouteur garde son comportement d'avant (seulement les outils WhatNxt).
- **Docs** : lire les fichiers du groupe et en envoyer dans le chat (les droits `docs:read` et `files:post`).
- **Limites** : heures actives (hors horaires, il garde les messages pour plus tard ou les ignore), messages par heure (messages, fichiers, tâches créées, commentaires et notifications comptent) et fichiers par heure (WhatNxt bloque au-delà et l'écrit dans le chat), et tes consignes, ajoutées à chaque demande. Toi seul vois le texte des consignes.

Important : « Lancer des commandes : Oui » = l'agent peut tout faire, y compris supprimer ou envoyer. Les règles « Supprimer » et « Envoyer » ne bloquent alors que les commandes évidentes (`rm`, `curl`...), un programme peut effacer ou envoyer lui-même. Pour qu'elles tiennent, laisse « Lancer des commandes » sur Me demander ou Non.

Il faut la nouvelle version du script (celle-ci) pour que les règles Machine et les consignes s'appliquent. « Qui », les heures et les limites marchent aussi avec l'ancienne.

## Vitesse

Trois réglages rendent les réponses plus rapides. Tous sont optionnels, avec une ligne `Environment=` par variable dans le service.

- **Plusieurs mentions en même temps.** `WHATNXT_CONCURRENCY` (2 par défaut, de 1 à 8) : le nombre de mentions traitées en parallèle. Une longue tâche ne bloque plus les autres. Dans une même conversation, les mentions passent une par une, dans l'ordre. Une conversation, c'est un fil (thread), ou une personne dans le chat principal du groupe.
- **Contexte gardé.** Dans une conversation, l'agent reprend sa session Claude Code d'avant (`--resume`) : une question de suite ne repart pas de zéro. `WHATNXT_SESSION_IDLE_MIN` (30 par défaut) : après ce nombre de minutes sans message, la session est oubliée et la suivante repart à neuf. `0` = toujours une nouvelle session. La session repart aussi à neuf si tu changes les règles ou les consignes, ou si la reprise échoue. Les sessions sont gardées en mémoire : un redémarrage du service repart à neuf.
- **Le bon modèle.** Une question courte va au modèle rapide, une vraie tâche au modèle fort. Le modèle fort est choisi pour un message long, un fichier joint ou nommé (`.pdf`, `.xlsx`...), ou des mots comme facture, fichier, crée, modifie, analyse, supprime, ou « réfléchis » (écris-le pour forcer le modèle fort).
  - `WHATNXT_MODEL_FAST` : le modèle rapide (`sonnet` par défaut).
  - `WHATNXT_MODEL_STRONG` : le modèle fort (`opus` par défaut).
  - `WHATNXT_MODEL` : force un seul modèle pour tout (un nom de modèle, ou `fast` / `strong`).

Exemple :

```ini
Environment=WHATNXT_CONCURRENCY=3
Environment=WHATNXT_SESSION_IDLE_MIN=30
Environment=WHATNXT_MODEL_FAST=sonnet
Environment=WHATNXT_MODEL_STRONG=opus
```

Les logs disent quel chemin a servi (`model=fast|strong|forced`, `session=warm|new|expired|rules_changed|fallback|off`), jamais le texte.

## Bon à savoir

- **Un seul écouteur par clé.** Si tu en lances un deuxième, ils se coupent la parole (`wait_superseded` dans les logs).
- **Logs** : heure, numéros (ids) et résultat. Jamais le texte des messages, ni la clé, ni ce que Claude écrit.
- **Erreurs réseau** : le script attend 1, 2, 5, 15 puis 60 s avant de réessayer. Jamais de boucle rapide.
- **Curseur** : la dernière mention traitée est gardée dans `~/.whatnxt_listener_cursor`. Il n'avance que quand cette mention et toutes celles d'avant sont finies. Si tu arrêtes le service pendant que Claude travaille, cette mention sera refaite au prochain démarrage (et une mention plus récente déjà finie peut l'être aussi).
- **Ce que voit le groupe** : Claude travaille dans ton dossier. Tout membre du groupe peut lui demander quelque chose, et ce qu'il lit dans le dossier peut finir dans sa réponse. Garde dans ce dossier seulement ce que le groupe peut voir.
- **Limiter qui peut le déclencher** : le plus simple est l'onglet « Qui » des règles. En plus, `Environment=WHATNXT_ONLY_AUTHORS=user_xxx,user_yyy` (ids des membres) marche toujours : les autres mentions sont ignorées.
- **Autres options** : `WHATNXT_KEY_FILE`, `WHATNXT_CURSOR_FILE` (pour plusieurs agents sur le même VPS, un fichier chacun), `CLAUDE_BIN` (chemin de `claude`). Pour la vitesse, voir plus haut.
- **Délai max** : 1 seconde après le message en temps normal, plus le temps de réponse de Claude.
