SKILL.md 6.5 KB


name: chatto-plugin-update description: "Use when an installed Chatto plugin must catch up to its remote and the changes must go live in the running Hermes gateway." version: 1.2.0 author: Paul Klumpp license: MIT metadata: hermes:

tags: [chatto, plugin, update, git, gateway]

Chatto-Plugin updaten und Changes aktivieren

When to Use

Eine installierte Chatto-Plugin-Instanz soll auf den Stand ihrer Quelle gebracht werden, und die Änderungen sollen im laufenden Hermes Gateway aktiv werden.

Der Remote steht hier bewusst nicht: er gehört der Installation, nicht dem Plugin. git remote -v des Checkouts ist die Wahrheit, und für einen selbst geklonten Checkout ist das ein privater Remote, den kein mitgeliefertes Dokument kennen kann.

Schritt 1: Wo liegt die Instanz, und welche Art ist sie?

Nicht raten — die drei Fälle haben verschiedene Türen, und zwei davon lassen sich nicht mit git bedienen:

ls -d ~/.hermes/plugins/chatto-platform \
      ~/.hermes/plugins/platforms/hermes-chatto-plugin 2>/dev/null
REPO=<der existierende Pfad>
[ -d "$REPO/.git" ] && echo "hat git" || echo "kein git"
Befund Art Tür
~/.hermes/plugins/chatto-platform/ mit .git und Provenance-Zeile per hermes plugins install hermes plugins update chatto-platform
~/.hermes/plugins/chatto-platform/ mit .git, ohne Zeile selbst geklont einmalig hermes plugins adopt chatto-platform, danach hermes plugins update chatto-platform
~/.hermes/plugins/platforms/hermes-chatto-plugin/ ohne .git Dateien kopiert (README Option B) kein Pull möglich — der User muss neu kopieren oder klonen

Im dritten Fall gibt es keinen Remote und kein git log: hermes plugins update verweigert hier ("no .git directory"). Das ist keine Störung, sondern der Zustand des Verzeichnisses — es zu umgehen hieße, den Zustand zu erfinden. Dem User sagen, dass er die Dateien neu holen muss, und dann bei Schritt 4 weitergehen.

Ablauf

  1. Hermes-Tür benutzen, nicht git. hermes plugins update ist der Weg, weil es mehr tut als git pull:

    hermes plugins update chatto-platform
    

    Es zieht den Stand, verwirft veralteten Bytecode aus __pycache__, schreibt die neue Revision in die Install-Metadaten und fragt nach, wenn der neue Stand Capabilities mitbringt, die noch nicht freigegeben sind (fail closed: ohne Antwort bleiben sie nicht freigegeben). Zwei Fälle lehnt es ab und sagt es: ein gepinnter Checkout (dann hermes plugins install <quelle> --force --ref <40-stelliger SHA>) und ein Verzeichnis ohne .git. Ein Katalog- Install wird auf die geprüfte SHA zurückgesetzt, nicht gepullt — deshalb hier ausdrücklich kein git pull.

    1. Statusbericht: erst fetchen, nie behaupten. Für die Zusammenfassung in Schritt 4 wird der alte Stand gebraucht, also vor dem Update abgreifen: bash git -C "$REPO" fetch --all git -C "$REPO" status -sb git -C "$REPO" branch -avv Aussagen wie „synchron" nur NACH einem fetch — status -sb ohne fetch zeigt ahead/behind nur gegen den zuletzt bekannten Remote-Stand. Den alten Commit aus branch -avv ablesen und festhalten, nicht raten.
  2. Commits zusammenfassen (Nutzersicht):

    git -C "$REPO" log <alter_stand>..<neuer_stand>          # oneline
    git -C "$REPO" log <alter_stand>..<neuer_stand> --stat   # Datei-Umfang
    

    <alter_stand> aus Schritt 3, <neuer_stand> aus Schritt 2 (der Revision, die Hermes gemeldet hat, oder HEAD des Checkouts). Commits haben ausführliche Messages — daraus eine nutzerverständliche Zusammenfassung machen: WAS ändert sich für den Bot-Nutzer, nicht Implementierungsdetails. Für jede Änderung eine Quelle angeben (Commit-Hash).

    1. Gateway-Neustart ANBIETEN (nie selbst ausführen): Plugin-Code-Änderungen werden erst nach einem Neustart des Hermes-Gateways aktiv — die laufende Session hält das alte Modul im Speicher.
    2. Einfachster Weg: /restart als Chat-Nachricht (Gateway-Slash-Command, „Restart gateway after draining active runs"). Der User tippt es direkt im Channel/DM. IMMER zuerst diesen Weg nennen.
    3. Aus der laufenden Agent-Session heraus ist ein Restart UNMÖGLICH: der Lifecycle-Guard blockiert jeden Versuch aus dieser Session, weil der Restart die eigene Session killt. Nicht umgehen versuchen; keine Restart-Skripte/Aliase bauen, wenn /restart genügt.
    4. Ein hermes gateway restart oder systemctl restart … aus einer Bediener-Shell außerhalb des Gateway-Prozesses funktioniert — aber nur dort. Aus einem Tool-Aufruf dieser Session heraus ist es derselbe blockierte Fall. Bei benannten Profilen heißt der Unit hermes-gateway-<profil>, nicht hermes-gateway.service.
    5. User fragen, ob jetzt neu gestartet werden soll (der laufende Bot ist dann kurz offline).
    6. Nach dem Neustart verifizieren: Plugin-Tools live testen (chatto_list_rooms via tool_call), im Log prüfen, dass der Adapter sauber lädt.

    Fallstricke

    • git -C in JEDEM git-Kommando. git pull oder git log ohne -C trifft den Checkout der Session, nicht den Plugin-Checkout.
    • Aussagen über Sync-Status („synchron", „aktuell") NUR NACH git fetch treffen — ohne fetch ist der lokale Status wertlos.
    • hermes plugins adopt nur einmal und nur bei einem selbst geklonten Verzeichnis. Hat Hermes bereits eine Provenance-Zeile, lehnt der Befehl ab ("already has a provenance row") — das ist kein Fehler, sondern heißt: der Fall greift nicht.
    • Vendored Updates (chattolib) kommen als dist-info-Rename + RECORD-Änderungen mit — normal, und über den ganz normalen Neustart aus Schritt 5 hinaus ohne Handlungsbedarf.
    • Der Lifecycle-Guard prüft den Inhalt eines Skripts, sobald ein Shell-Interpreter es referenziert: bash -n skript.sh mit hermes gateway restart darin wird abgelehnt — auch unter einem anderen Dateinamen und auch als sh -n. chmod, mv und cp sind nicht betroffen. Ein Skript also nicht an den Interpreter geben, um es zu prüfen: Inhalt mit den Datei-Tools lesen. Es lohnt auch nicht, es umzubenennen — der Guard liest Bytes, nicht Namen.
    • Das Ausführen von /dev/null (oder /dev/zero, /dev/fd/N) lässt der Guard bewusst fehlschlagen. Das ist keine Störung, sondern das gewollte Verhalten. Eine Umleitung nach > /dev/null in einer Shell-Datei ist davon nicht betroffen — die wird maskiert.