Referenz: gateway/platforms/base.py aus dem Hermes-Checkout; chattolib
0.4.20.post1 (MessageEditedPayload, realtime protocol v1).
Ein message_edited-Event wird je nach Zustand der Original-Nachricht zu
einer Korrektur, einem Nachtrag oder nichts. Drei Pfade:
/stop, cancel_session_processing), mit korrigiertem Text neu
dispatchen. 🚫 entsteht über den CANCELLED-Outcome-Hook (base.py:6345),
👀 wieder über den Neustart._dispatched_ids ist die Sperre gegen
die Retrospektive-Maschine.Konsistenzregel: Gates gelten in beide Richtungen — wer die Mention beim Berichtigen herauseditiert, fällt durchs Gate und wird ignoriert.
CHATTO_EDIT_DISPATCH (bool, default true) — Master-Schalter.
Default an: das Verhalten ist Teil des README-Versprechens.CHATTO_EDIT_WINDOW (int Sekunden, default 300) — max. Alter eines Edits
via Message.updated_at − created_at (types.py:673/678). Neuer "int"-Kind
in der ConfigField-Maschinerie (_get_env_or_extra_int); unparsebare
Werte fallen mit Warnung aufs Default.(default: …)-Angabe._dispatched_ids: Ring-Puffer (SEEN_CAP-Muster) — gefüllt vor jedem
handle_message, both paths. Retro-Sperre._processing: dict[session_key, message_id] — geschrieben in
on_processing_start, geräumt in on_processing_complete (feuert bei
Cancellation mit CANCELLED, base.py:6345-6350). Liefert Pfadwahl UND den
Cancel-Schlüssel._session_key_for(source): ruft gateway.session.build_session_key mit
exakt denselben Extras wie handle_message (base.py:5578) — ohne das
trifft cancel_session_processing die falsche Session._admit_and_build(...): die Admission-Pipeline aus _dispatch_message_posted
ausgezogen (User-Cache → Auth → Room-Kind → DM-Commands → Mention-Gates →
🫥-Ack → Thread-Anker → Source/Event → Media). Beide Pfade teilen sie;
Flag allow_dm_commands=False für Edits — ein editiertes /join läuft
weder doppelt noch zum Agenten durch._dispatch_message_edited(payload): Echo-Filter (actor == me, im Event-Zweig)
→ Respond-Room-Gate → Hydration (deleted_at skip) → Fenster → billige
Retro-Triage vor der Pipeline (schon erledigt ⇒ keine API-Kosten, kein
zweites 🫥) → _admit_and_build → Pfadentscheidung:
cancel_session_processing(discard_pending=False) — geparkte
Folgenachrichten überleben; der neue Turn drainiert sie am Ende selbst._pending_messages[session_key].message_id == id) ⇒ Text in
place umschreiben, kein zweiter Dispatch._handle_realtime_event als eigener Zweig; message_edited
fliegt aus der Known-Kinds-Liste.test_adapter.py::TestEditDispatch (14 Fälle): Default on + Fenster 300 ·
Echo ignoriert · Feature aus · Read-only-Room ohne API-Call · Mention
nachgetragen ⇒ Turn · weiter ohne Mention ⇒ still · schon beantwortet ⇒
ignoriert · gelöscht ⇒ ignoriert · Edit außerhalb des Fensters ⇒ ignoriert ·
frischer Edit in DM ⇒ Turn · Mid-run ⇒ Cancel + Redispatch mit neuem Text ·
Completion-Hook räumt _processing ab (Re-Arming) · queued Follow-up wird
in place korrigiert (kein Cancel, kein zweiter Dispatch) · DM-Command-Edit
läuft weder Command noch Agent.
test_platform_config.py: _get_env_or_extra_int (Env-Präferenz, Extra int
und str, Junk ⇒ Default, YAML-bool ⇒ Default, beides fehlt ⇒ Default).
Lauf: PYTHONPATH=/path/to/hermes-agent uv run --with pyyaml pytest -q
README.md: Verhaltenstabelle (neue Zeile „Editing your messages"), Capability-Matrix („inbound edit processing"), Env-Beispiele, Env-Tabelle, config.yaml-Beispiel, Usage Note „Editing Your Messages" mit Pflichtenheft- Tabelle. AGENTS.md: Behavioural-Contract-Bullet. after-install.md: Satz im Test-Schritt (First-run-Verhalten).
Anhänge im Edit berücksichtigen (queued rewrite toucht nur Text; Media bleibt
vom Original). Mehrere schnelle Edits debouncen — fetch_message liefert
ohnehin den neuesten Stand. Retraction (message_retracted) verarbeiten.
Edits an Nachrichten in anderen Sessions gezielt in deren Queues korrigieren
(der Pending-Match läuft über die Session-Key-Gleichheit).