Files
mesh-configs/skills/devops/mobile-apk-flutter-build/references/persoent-cost-tracking.md
T

150 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PersoEnt-Kosten-Tracking + Budget-Bremse (OpenRouter) — Verlauf & Referenzwerte
> Session 2026-08-07: Nutzer wollte Kostenübersicht für Statistik + künftige Mesh-Bremse. Es wurde festgestellt, dass **keine Kosten im Ereignis-Log erfasst** waren (zeigt 0€), obwohl OpenRouter Budget verbraucht war. Danach wurde das komplette **Bremse-System gebaut und E2E-getestet**.
## Das gebaute System (Master/VPS)
| Komponente | Pfad | Zweck |
|---|---|---|
| `mesh-cost-track.sh` | `/usr/local/bin/` | Stündlich OpenRouter-Usage aller 4 Agenten (VPS+3 Sub) via API abfragen, in Zeitreihe schreiben |
| Zeitreihe | `/srv/work/costs/costs.jsonl` | wachsende Statistik je Agent (ts, master, unraid, switch, laptop) |
| `mesh-cost-report.sh` | `/usr/local/bin/` | erzeugt HTML-Kosten-Übersicht (Dashboard-USD + pro-Agent + Bremse-Status) |
| `budget.yaml` | `/srv/work/costs/` | Deckel: `limits.agent.*`, `limits.gesamt_pro_tag`, `modelle.erlaubt/blockiert`, `bremse.kill_switch_file` |
| `mesh-cost-break.py` | `/usr/local/bin/` | vergleicht Tages-Usage vs. budgurations → schreibt `kill_switches.json` |
| `kill_switches.json` | `/srv/work/costs/` | zentral, **chmod 0666** — welcher Agent PAUSED |
| Agent-Poller-Guard | in `mesh-agent-poller.sh` | liest kill_switches per SSH; bei PAUSED → keine Task-Bearbeitung |
| Cron (stündlich) | `0 * * * *` | `mesh-cost-track.sh && python3 mesh-cost-break.py` |
| Doku-Integration | master-report.sh | `$(bash /usr/local/bin/mesh-cost-report.sh)` vor Betriebsregeln |
## 🔥 PITFALL 1: OpenRouter-Usage-Einheit ≠ Dollar
- `GET https://openrouter.ai/api/v1/auth/key` mit `Authorization: Bearer <KEY>` → `data.usage` = **OpenRouter-Credits je Key**.
- Für die Agenten (je eigener Key in `~/.hermes/.env`) ergeben sich z.B.: master 39.5, unraid 0.33, switch 0.64, laptop 0.87.
- **Summiert (≈41) DIFFERIERT vom OpenRouter-Dashboard ($20.51)** — die API-Credits sind nicht 1:1 USD, und es können verschiedene Key-Pools/Konten sein.
- **Verbindlicher Maßstab ist der Dashboard-USD-Wert** (Nutzer liest ihn in der OpenRouter-UI ab). Den als `nutzer_dashboard_usd` mit Quelle in die Zeitreihe schreiben.
## 🔥 PITFALL 2: Usage ist KUMULATIV — Tages-Delta berechnen
Ohne Korrektur wäre **jeder Agent dauerhaft PAUSED**, weil die kumulierte Gesamt-Usage (seit Key-Start) jeden Deckel sprengt. Fix im Brems-Skript: **Tages-Delta = letzter Wert minus erster Wert desselben Kalendertags**:
```python
today = last["ts"][:10]
today_rows = [r for r in rows if r["ts"][:10] == today]
first = today_rows[0] if today_rows else last
delta = max(0.0, float(last[agent]) - float(first[agent]))
```
## Bremsen (GEBAUT + E2E-getestet 2026-08-07)
Nutzerwunsch: Master überschaut Kosten pro+gesamt über ein wachsendes Mesh (mehr Agents, mehrere Server) und kann alles bremsen. Umsetzung:
1. `mesh-cost-break.py` liest letzte Usage-Zeile (Tages-Delta), vergleicht mit `budget.yaml`-Deckeln.
2. Bei Deckel-Überschreitung (je Agent ODER Gesamt) schreibt es `kill_switches.json` mit `PAUSED`-Status + Grund.
3. Jeder Sub-Agent hat im `mesh-agent-poller.sh` einen **Guard** am Anfang (vor Task-pull), der per SSH prüft: "bin ich PAUSED?" → wenn ja: `exit 0` (keine Task-Übernahme, keine weiteren Kosten).
```bash
# Guard in mesh-agent-poller.sh (nach SSH_CMD, vor Task-pull)
KILL_CHECK=$($SSH_CMD "python3 -c \"
import json
try: d=json.load(open('/srv/work/costs/kill_switches.json'))
except Exception: d={}
sw=d.get('kill_switches',{}).get('<MEINE_ID>',{})
print('PAUSED' if sw and sw.get('status')=='PAUSED' else 'OK')
\" 2>/dev/null")
if [ "$KILL_CHECK" = "PAUSED" ]; then log "⏸️ Budget-BREMSE aktiv"; exit 0; fi
```
**E2E-Test:** UnraidHermes auf PAUSED gesetzt → sein Task blieb in `offen/` (Bremse griff), Poller-Log zeigt "⏸️ Budget-BREMSE aktiv ... pausiert". Nach Reset (leere kill_switches) wieder normal. Der aktualisierte Poller-Guard muss an alle 3 Sub-Agenten verteilt werden (je passender Key-Pfad: `unraid_mesh`/`switch_mesh`/`laptop_mesh`).
## Kostenfakt (OpenRouter-Analyse 07.08, 1 Monat)
- **DeepSeek V4 Pro = 64% aller Kosten (~$26.80)** — teures Top-Modell, nicht Standard lt. Model-Allocation; der Haupt-Kostentreiber.
- Andere: V4 Flash 0731 22,5%, V3 5,9%, Nemotron 2,4%, GLM 1,5%.
- **→ Bremsen muss auf Modell-Ebene ansetzen** (teure Modelle blockieren/deckeln), nicht nur auf Agent-Tages-Summe. Aktuell `modelle.blockiert` in budget.yaml als Konfig/Log; harter Blocker (Modell gar nicht erst laden) ist offen.
## Abfrage-Snippets
### Master (lokal)
```bash
python3 << 'PYEOF'
import json,re,urllib.request
e=open('/root/.hermes/.env').read()
m=re.search(r'OPENROUTER_API_KEY=([A-Za-z0-9_\-\\.]+)',e)
req=urllib.request.Request("https://openrouter.ai/api/v1/auth/key",
headers={"Authorization":f"Bearer {m.group(1)}"})
print(json.load(urllib.request.urlopen(req,timeout=15))["data"]["usage"])
PYEOF
```
### Sub-Agent per SSH (Key bleibt lokal, nur Zahl kommt zurück)
```bash
u=$(sshpass -p 'Bp3lskt0' ssh -o StrictHostKeyChecking=no -o ConnectTimeout=12 mehlzoerwer@<IP> '
python3 -c "
import json,re,urllib.request
e=open(\"/home/mehlzoerwer/.hermes/.env\").read()
m=re.search(r\"OPENROUTER_API_KEY=([A-Za-z0-9_.\-]+)\", e)
req=urllib.request.Request(\"https://openrouter.ai/api/v1/auth/key\", headers={\"Authorization\":\"Bearer \"+m.group(1)})
print(json.load(urllib.request.urlopen(req, timeout=15))[\"data\"].get(\"usage\",0))
"')
```
## Erweiterungen/POLISH 2026-08-08 (Team-geprüft: Unraid+Switch+Laptop)
Das System wurde im Team geschliffen (Gegenprüfung fand echte Fehler). Ergänzungen:
### 🔥 PITFALL 3: Es gibt DREI OpenRouter-Kostenquellen — verwechsle sie nicht
| Endpoint | Feld | Einheit | Zweck |
|---|---|---|---|
| `GET /api/v1/auth/key` | `usage` | OpenRouter-Credits (je Key) | pro-Key-Verteilung, **grobe Relation nur** |
| `GET /api/v1/credits` | `total_usage` | **USD, konto-weit** | **VERBINDLICH fürs Gesamtbudget** |
| `POST chat/completions` | `usage.cost` | USD (im Body) | Kosten je Antwort (Header `X-OR-Usage-Cost-USD` oft NICHT da — Body bevorzugen) |
**Merke:** `/auth/key usage` ≠ USD und summiert anders als `/credits`. Beispiel: `/auth/key`-Werte (41.3) vs `/credits total_usage` (81.45 USD) vs Dashboard ($20.51) — drei verschiedene Zahlen. Für Gesamt-Deckel IMMER `/api/v1/credits` `total_usage` (USD) nehmen; pro-Key-`usage` nur als Aktivitäts-Relation.
### Tages-Delta KORRIGIERT (tag-übergreifend statt innerhalb des Tages)
Der naiv "letzter minus erster Wert des Kalendertags" hat Lücken: Mitternachts-Lücke zwischen Tag N und N+1, Ein-Eintrag-Tag → 0, Counter-Reset → negatives Delta (falsche "Ersparnis"). **Korrekt:**
```python
# Delta für Tag = letzter Wert heute − letzter Wert VORTAG; max(0,…) gegen Reset
vorher = [d for d in daten if d < heute]
base = tvals[vorher[-1]] if vorher else cur
delta = max(0.0, cur - base)
```
Zusätzlich: **7-Tage-Kumulativ-Summe** (fängt "täglich unter Deckel, aber Monat explodiert") + **80%-Warnschwelle** vor hartem PAUSED.
### Master-exempt (Design-Entscheidung)
Der **Master (VPSHermes) wird NIE hart pausiert** — er muss sein eigenes System + den Nutzer pflegen. Bei Monats-USD-Cap-Überschreitung werden NUR Sub-Agenten PAUSED. So bleibt das Kun-den-System bedienbar, auch wenn gespart wird.
### Modell hart blockieren (nicht nur Konfig/Log)
Umsetzung des "Bremsen auf Modell-Ebene": Hermes selbst sperrt das Modell, damit es gar nicht erst geladen wird.
```bash
hermes config set model.providers.openrouter.blocked_models '["deepseek/deepseek-v4-pro"]'
```
- **Achtung Singular:** Schlüssel ist `model.providers.…` NICHT `models.` (sonst nur notiert, nicht gelesen).
- Verifikation: Modell taucht in `hermes models list` nicht mehr auf; Fallback greift aufs nächste.
- Allowlist (`allowed_models` nur günstige) ist noch strikter — blockt automatisch neue teure Modelle.
### Referenzwerte 2026-08-08
- `/credits total_usage` (konto-weiter USD-Verbrauch): **$81.53**
- Nutzer-Entscheidung: **strikt sparen** — Monats-Cap auf $80 gesetzt → Sub-Agenten aktuell PAUSED (Master aktiv).
- Nach dem Setzen von Deckeln IMMER `mesh-cost-break.py` nochmal laufen lassen + prüfen, dass Master-exempt korrekt greift (kein Alle-Pausiert-Dauerschleife).
## 🔥 FINALES NUTZER-KOSTEN-MODELL (verbindlich ab 2026-08-08/09) — ersetzt obiges Monats-Cap-Gedächtnis
**Achtung: Der Nutzer hat das Budgetmodell zuletzt klar und EINFACH gemacht. Folge NUR diesem, nicht den komplexen $-Caps oben:**
- **Harte Grenze = 1 USD pro Tag und Agent** (`limits.tageslimit_agent_usd: 1.0`).
- **Solange OpenRouter-Credits (Guthaben) vorhanden sind, wird gearbeitet.**
- **KEIN Team-weiter Monats-Stopp** — nur pro-Agent-Tageslimit + technischer Stopp, wenn das Konto-Guthaben 0 erreicht.
- Auflade-Rhythmus des Nutzers: ~20$ am 1. des Monats, evtl. noch ~20$ am 15. (nicht garantiert). Das ist nur die Auflade-Geschichte, NICHT der Brems-Heebel.
- Master (VPSHermes) bleibt immer aktiv; nur Sub-Agenten werden pausiert.
- `budget.yaml` entsprechend: `tageslimit_agent_usd: 1.0`, `tageslimit_gesamt_usd: 4.0` (4 Agents × 1$), keine `gesamt_usd_monat`-Logik.
- Guthaben-Check im break: `guthaben = total_credits - total_usage`; wenn ≤ 0 → Sub-Agenten pausieren (Master nicht).
**PITFALL Vermeidung:** Nicht wieder ein komplexes „Monats-Cap in $" / Team-Stopp-Schema einführen — der Nutzer hat das aktiv zurückgenommen („Du oder wir?"-Korrekur + „1$ pro Tag und Agent … solange Credits da, kein Monats-Stopp"). Der Fehler aus dem Tag: Tages-Delta/`gesamt_pro_tag`-Key-Bruch und Monats-Cap-Überkomplexität.
## Referenzwerte 2026-08-07 (historisch)
- OpenRouter-Dashboard-Gesamt: **$20.51**
- API-Usage je Agent: master 39.48, unraid 0.33, switch 0.64, laptop 0.87