Andreas: "waehrend mmnotify per ws angemeldet ist, kann es dann den status des agenten auf online setzen?" Ja -- und hive hatte das Muster schon fertig (channels/team.py): abwesend beim Verbinden, gruen waehrend der Arbeit, wieder abwesend nach Ruhe, offline beim Beenden. Ein Agent ohne Status sieht aus, als sei niemand da; einer, der rund um die Uhr gruen leuchtet, sagt genauso wenig. Beim Testen fiel ein eigener Fehler auf: Der Boden setzte den Agenten auf gruen. Routinemaessiges Nachsehen ist aber keine Anwesenheit -- bei Boden alle 20 s und Frist 25 s blieb er dauerhaft gruen. Jetzt macht nur ein echtes Ereignis gruen. Und zur Verzoegerung, die Andreas zu Recht nicht hinnehmen wollte: Statt weiter zu raten, gemessen. Der eigene Beitrag loest sehr wohl ein posted aus, ein fremder nie -- die Verbindung hat also die Kanal-Abos, es fehlen nur fremde Ereignisse. Ausgeschlossen: authentication_challenge, Token im Authorization-Header, ein echter Bot-Account statt Nutzer-Token, und das Sitzungs-Cookie wie im Browser. Alle vier gleich. Das Mattermost-Forum beschreibt dasselbe, dort auch mit System-Admin-Token, ohne Loesung. Konsequenz: floor_seconds ist der Weg, nicht der Notnagel, und steht deshalb auf 15 s statt 60. Ein Durchgang kostet einen API-Aufruf -- billig genug, um es oft zu tun.
118 lines
4.6 KiB
Markdown
118 lines
4.6 KiB
Markdown
# mmnotify
|
|
|
|
Hört am Mattermost-Websocket und **weckt einen Agenten**, wenn er gemeint ist.
|
|
|
|
Gegenstück zu [`goimapnotify`](https://gitlab.com/shackra/goimapnotify) für
|
|
Mail: ein kleiner Prozess, der lauscht und bei einem Ereignis einen Befehl
|
|
ausführt. Der Agent liest und antwortet danach mit seinen eigenen Werkzeugen —
|
|
`mmnotify` schreibt nie in einen Kanal, es klopft nur an.
|
|
|
|
```
|
|
mmnotify -conf /etc/mmnotify.json
|
|
```
|
|
|
|
## Konfiguration
|
|
|
|
```json
|
|
{
|
|
"url": "https://team.42i.org",
|
|
"token": "<persönliches Zugriffstoken des Agenten>",
|
|
"on_mention": "/root/run-agent.sh team",
|
|
"on_direct": "",
|
|
"debounce_seconds": 5,
|
|
"floor_seconds": 60,
|
|
"ignore_users": []
|
|
}
|
|
```
|
|
|
|
Die Datei enthält ein Token und gehört mit `0600` dem Dienstbenutzer.
|
|
|
|
| Feld | Bedeutung |
|
|
|---|---|
|
|
| `on_mention` | Befehl bei Erwähnung (`@name`) im Kanal |
|
|
| `on_direct` | Befehl bei Direktnachricht; leer = `on_mention` |
|
|
| `debounce_seconds` | Mindestabstand zwischen zwei Läufen (Standard 5) |
|
|
| `floor_seconds` | Nachsehen auch ohne Ereignis (Standard 15, `0` schaltet ab) |
|
|
| `ignore_users` | Absender, die nie wecken |
|
|
| `away_after_seconds` | Wann der grüne Punkt auf abwesend zurückfällt (Standard 120) |
|
|
|
|
Der Befehl bekommt die Ereignisdaten über die Umgebung: `MM_TRIGGER`
|
|
(`event` oder `floor`), `MM_CHANNEL`, `MM_CHANNEL_NAME`, `MM_CHANNEL_TYPE`,
|
|
`MM_SENDER`, `MM_POST_ID`, `MM_ROOT_ID`, `MM_MESSAGE`.
|
|
|
|
## Zwei Wege, und der Boden ist der tragende
|
|
|
|
Der Websocket ist der Beschleuniger; darunter läuft ein Boden, der ohnehin
|
|
nachsieht. Die Aufteilung stammt aus hive (`hive_runtime/channels/team.py`) und
|
|
ist dort begründet: *„A stream that dies quietly must make us LATE, never
|
|
blind."*
|
|
|
|
**Hier ist der Boden nicht nur Vorsicht.** Gemessen am 2026-09-01 gegen
|
|
Mattermost 11.7.10:
|
|
|
|
| | |
|
|
|---|---|
|
|
| eigener Beitrag | `posted` kommt an |
|
|
| Beitrag eines anderen Kontos | kommt **nie** an |
|
|
|
|
Die Verbindung ist also voll funktionsfähig und hat die Kanal-Abos — es fehlen
|
|
ausschließlich die Ereignisse fremder Konten. Ausgeschlossen wurden:
|
|
`authentication_challenge`, Token im Authorization-Header beim Handshake, ein
|
|
echter Bot-Account statt eines Nutzers mit Token, und das Sitzungs-Cookie
|
|
`MMAUTHTOKEN` wie im Browser. Alle vier verhalten sich gleich.
|
|
|
|
Das Verhalten ist [im Mattermost-Forum
|
|
beschrieben](https://forum.mattermost.com/t/websocket-does-not-provide-posted-events-from-other-accounts/14876)
|
|
und tritt dort auch mit einem System-Admin-Token auf; eine Lösung steht nicht
|
|
dabei.
|
|
|
|
Deshalb ist `floor_seconds` der Weg und nicht der Notnagel, und der Standard
|
|
ist kurz: **15 Sekunden**. Ein Durchgang kostet einen API-Aufruf — billig genug,
|
|
um es oft zu tun. Wer den Stream repariert bekommt, kann ihn hochsetzen.
|
|
|
|
Daraus folgt die zweite Entscheidung: **mmnotify liest den Beitrag nicht aus
|
|
dem Ereignis.** Es klopft an; was zu tun ist, entscheidet der Agent, wenn er
|
|
nachsieht. Zwei Leser wären zwei Antworten.
|
|
|
|
## Anwesenheit
|
|
|
|
Solange mmnotify verbunden ist, zeigt der Punkt neben dem Namen, woran man ist:
|
|
|
|
- **abwesend**, sobald die Verbindung steht — da, aber untätig
|
|
- **grün**, während der Befehl wegen einer Erwähnung läuft
|
|
- **abwesend** wieder, wenn es `away_after_seconds` still war
|
|
- **offline** beim Beenden, statt einen grünen Punkt zurückzulassen, hinter dem
|
|
niemand mehr sitzt
|
|
|
|
Das routinemäßige Nachsehen des Bodens macht ausdrücklich **nicht** grün. Läuft
|
|
der Boden häufiger als die Away-Frist, leuchtete der Agent sonst rund um die
|
|
Uhr — und ein Punkt, der immer grün ist, sagt genauso wenig wie gar keiner.
|
|
(Beim Testen genau so passiert: Boden alle 20 s, Frist 25 s, nie abwesend.)
|
|
|
|
Ein Status ist eine Höflichkeit gegenüber dem, der in die Seitenleiste schaut.
|
|
Weigert sich der Server, wird das protokolliert und weitergearbeitet: Ein Agent,
|
|
der aufhört zu antworten, weil er einen Punkt nicht einfärben konnte, wäre
|
|
absurd.
|
|
|
|
## Robustheit
|
|
|
|
- Wiederaufbau mit wachsendem Abstand (1 s bis 60 s). Ein Server, der neu
|
|
startet, wird nicht von einem Client bestürmt, der im Sekundentakt anklopft.
|
|
- Herzschlag alle 30 s, Lesefrist 90 s. Eine halboffene Verbindung liest sich
|
|
sonst für immer wie Stille.
|
|
- Höchstens ein Lauf gleichzeitig; wer währenddessen schreibt, wird vom
|
|
laufenden Durchgang mitgenommen. Ohne das lösen fünf Beiträge in einer Minute
|
|
fünf Agentenläufe aus, die sich gegenseitig überholen.
|
|
- Eigene Beiträge und `system_*`-Ereignisse wecken nie — sonst antwortet ein
|
|
Agent auf sich selbst.
|
|
- `SIGTERM` beendet sofort und sauber.
|
|
|
|
## Bauen
|
|
|
|
```bash
|
|
go build -o mmnotify .
|
|
```
|
|
|
|
Ein statisches Binary ohne Laufzeitabhängigkeiten — gedacht zum Einbacken in
|
|
das Agenten-Image, neben `goimapnotify`.
|