# SEKTION 04 — SCHNITTSTELLE (der Vertrag mit Qwirbel)

> Sobald das steht, kann Qwirbel testweise auf Global UI zeigen.
> Vorlage: Qwirbels `backend/tools/comfyui_api.py` — **NUR LESEN.**

---

## 4.1 Die vier Dinge

Qwirbel macht heute mit ComfyUI genau vier Schritte. Wer die bedient, ist
austauschbar — der Umstieg ist dann ein **Konfigurationswert**, kein Umbau.

| # | Was | Heute bei ComfyUI |
|---|---|---|
| 1 | **Workflow laden** | JSON aus `generation/workflows/` |
| 2 | **Werte einsetzen** | `inject_inputs()` — Prompt, Seed, Größe, Steps, Bilder |
| 3 | **Abschicken + Fortschritt** | `POST /prompt`, WebSocket-Meldungen |
| 4 | **Ergebnis abholen** | Ausgabedatei / Bytes |

**Diese vier sind die Messlatte.** Alles andere ist Zugabe.

## 4.2 Endpunkte

```
GET  /katalog                → KATALOG.fuer_die_ki()   (Grundlage für Sektion 06)
GET  /grafen                 → vorhandene Workflows
POST /graf/pruefen           → {fehler: [...]}         (ändert nichts)
POST /graf/plan              → Speicher-Plan           (ändert nichts)
POST /auftrag                → Graph + Werte → {auftrag_id}
GET  /auftrag/{id}           → Zustand, Ergebnis
POST /auftrag/{id}/abbrechen → sauber abbrechen
WS   /ereignisse             → Fortschritt live
GET  /system                 → GPU, VRAM gesamt/frei, Version
GET  /gesundheit             → läuft?
```

**Prüfen und Planen ändern nichts.** Ein Bericht, der nebenbei etwas
umstellt, ist eine Falle — bei Qwirbel ist genau diese Trennung
(`/berater` liest, `/uebernehmen` schreibt) bewusst gebaut.

## 4.3 Fortschritts-Meldungen

Über `WS /ereignisse`, angelehnt an das, was Qwirbel schon verarbeitet:

| Meldung | Inhalt |
|---|---|
| `auftrag_start` | auftrag_id |
| `knoten` | welcher Knoten läuft gerade (oder null = fertig) |
| `schritt` | Sampler-Fortschritt: wert / gesamt |
| `speicher` | **Räumung passiert** — wer, wie viel, warum |
| `ergebnis` | Dateien / Bytes |
| `fehler` | Knoten, Typ, **Klartext-Meldung** |

Die `speicher`-Meldung gibt es bei ComfyUI nicht. Sie ist der Grund, warum
dort niemand merkt, dass bei jedem Bild 7 GB geschoben werden.

## 4.4 Werte einsetzen — ohne Rätselraten

ComfyUI zwingt zum Raten, welcher Node der positive Text-Encoder ist —
Qwirbel hat dafür eine ganze Mapping-Mechanik gebaut (`erkenne_mapping`,
`workflow_mappings.json`), weil man den Graphen von außen deuten muss.

**Global UI braucht das nicht.** Der Graph benennt seine Knoten sprechend
(`pos`, `neg`, `samp`, `dec`), und ein Graph kann **erklärte Eingänge**
anbieten:

```json
{ "name": "t2i 1024",
  "eingaben": {
     "prompt":   ["pos", "text"],
     "seed":     ["samp", "seed"],
     "breite":   ["leer", "breite"],
     "hoehe":    ["leer", "hoehe"],
     "schritte": ["samp", "schritte"]
  },
  "knoten": { ... } }
```

Dann heißt Werte einsetzen: `{"prompt": "ein Fuchs im Schnee", "seed": 42}`.
Kein Raten, keine Heuristik, keine Mapping-Datei daneben.

## 4.5 Sicherheit

- Standardmäßig nur **127.0.0.1**. Nach außen nur mit Token.
- Dateipfade werden **eingesperrt** (kein `../`), Modelle nur aus
  konfigurierten Ordnern.
- Ein Graph ist **Daten, keine Ausführung**: nie `eval`, nie Code aus dem
  Graphen ausführen. Nodes sind eingetragene Typen, kein freier Import.
- Fehler im Klartext, aber **keine Systempfade nach außen** geben.

## 4.6 Umstieg für Qwirbel

Wenn die vier Dinge stehen:

1. In Qwirbels Config ein Wert `generation.engine: comfyui | globalui`.
2. Ein Adapter, der die vier Aufrufe auf Global UI legt.
3. **Erst nur lesend gegenprüfen** (Katalog, Plan), dann einen echten Lauf.
4. ComfyUI bleibt installiert, bis Global UI dieselben Workflows gleich gut
   fährt. **Kein Umstieg auf Verdacht.**

⚠️ Der Umbau in Qwirbel gehört **nicht in dieses Projekt** — er wird dort
gemacht, wenn Global UI so weit ist, und nur mit des Nutzers Ansage.

## 4.7 Checks für diese Sektion

- [ ] Die vier Dinge laufen gegen einen echten Graphen
- [ ] `/graf/pruefen` und `/graf/plan` ändern nachweislich nichts
- [ ] `speicher`-Meldung erscheint, wenn geräumt wird
- [ ] Pfad-Ausbruch (`../`) wird geblockt
- [ ] Ein Graph mit unbekanntem Node-Typ wird abgelehnt, nicht importiert
- [ ] Abbrechen beendet sauber (kein halber Auftrag, keine Prozess-Leiche)
