- Rust 100%
| src | ||
| tests | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| README.md | ||
ollama-cloud (Rust)
Rust-Port von ~/.hermes/scripts/ollama_cloud_usage.py und
~/.hermes/scripts/ollama_cloud_watchdog.py. Liest die Usage-Seite von ollama.com,
parst Session- und Weekly-Verbrauch, führt eine Snapshot-Historie und prognostiziert,
ob das Limit vor dem Reset erreicht wird.
Zwei Binaries, eine Lib:
| Binary | ersetzt |
|---|---|
ollama-cloud-usage |
ollama_cloud_usage.py |
ollama-cloud-watchdog |
ollama_cloud_watchdog.py |
Warum
Beide Skripte laufen bei jedem Agenten-Lauf und der Watchdog zusätzlich im 10-Minuten-Takt. Sie teilen HTTP-Fetch, HTML-Parser, Historie und Prognose — deshalb ein Crate mit gemeinsamer Lib statt zwei getrennter Projekte.
Bauen und installieren
cargo build --release
install -m 755 target/release/ollama-cloud-usage ~/bin/ollama-cloud-usage
install -m 755 target/release/ollama-cloud-watchdog ~/bin/ollama-cloud-watchdog
Benutzen
ollama-cloud-usage # menschlich lesbar (Default)
ollama-cloud-usage --json # Usage-Payload
ollama-cloud-usage --check # Exit 0 OK / 1 Warnung (>=80%) / 2 kritisch (>=95%)
ollama-cloud-watchdog # watch (Default): Snapshot + Meldung nur bei Problemen
ollama-cloud-watchdog --snapshot
ollama-cloud-watchdog --predict # Prognose-Meldung
ollama-cloud-watchdog --message # wie --predict
ollama-cloud-watchdog --json # vollständige Prognose
ollama-cloud-watchdog --check # Exit 0/1/2
ollama-cloud-watchdog --history # letzte 20 Snapshots
ollama-cloud-watchdog --clear # Historie + Statusdatei löschen
Dateien: ~/.hermes/ollama_cookie.txt, ~/.hermes/ollama_usage_history.json,
~/.hermes/ollama_cloud_status.json. HOME wird respektiert.
Für Tests/Proxies lässt sich die Quelle über OLLAMA_SETTINGS_URL überschreiben
(Default https://ollama.com/settings) — eine additive Ergänzung, die das Original
nicht hat.
Abweichungen zum Python-Original
- Login-Seite ist ein Fehler, nicht 0 %. Antwortet ollama.com nach abgelaufenem
Cookie mit einem Redirect auf die Login-Seite (HTTP 200, aber ohne Usage-Marker),
meldet das Original
Session=None%und--checkgibt OK zurück — der Monitor ist dann blind. Hier enden beide Binaries mit Exit 2 und… cookie likely expired. Bewusst und getestet. - JSON ist UTF-8 statt
\uXXXX. Python nutztensure_ascii=True; Umlaute und Emojis in der Prognose-Meldung stehen hier direkt. Semantisch identisch, besser lesbar incat/jq. --help/--versionexistieren zusätzlich.- Ein Snapshot mit
session_pct: nullwird als 0 behandelt; das Original stürzt an dieser Stelle mitTypeErrorab.
Tests
cargo test
10 Tests. Die Paritätstests importieren das jeweilige Python-Modul mit gepatchter
SETTINGS_URL und setzen HOME auf ein Temp-Verzeichnis, sodass beide
Implementierungen dieselben Mock-Antworten und dieselben Dateien sehen. Die Historie-Fixture
wird einmal aus now() gebaut und an beide Seiten gegeben — seeded man jede Seite mit
ihrem eigenen now(), kreuzt das alle paar Dutzend Läufe eine Minutengrenze und die Ausgaben
unterscheiden sich um eine Sekunde (aufgetreten am 2026-10-30, behoben):
usage_json_matches_python— Byte-Vergleichusage_human_matches_python— Byte-Vergleich (nur die Timestamp-Zeile maskiert)usage_check_matches_python— Ausgabe und Exit-Codewatchdog_check_matches_python— mit zwei Snapshots in der Historie (Burn-Rate)watchdog_predict_matches_python— komplette Meldung Byte für Bytewatchdog_json_matches_python_semantically— Felder gleich, Float-Toleranz 1e-6watchdog_history_and_clear_match— Ausgabe, Exit-Code und Dateiinhaltmissing_cookie_exits_twounknown_watchdog_mode_exits_onelogin_page_is_an_error_not_zero_percent— die bewusste Abweichung
Messung (2026-10-29)
--history, also ohne Netzwerk, 5 Läufe:
Rust < 10 ms
Python 30 ms
Mit Netzwerk dominiert der HTTP-Request (15 s Timeout, real ~200–400 ms), dort ist der Startvorteil nebensächlich — der Port lohnt wegen der Aufruffrequenz, nicht wegen CPU.