From 8dc513ee96e26e5a5621b441a8b4d4def37f1582 Mon Sep 17 00:00:00 2001 From: lachtan Date: Mon, 14 Sep 2026 20:58:01 +0200 Subject: [PATCH] nanobot: 2026-09-14 20:57:58 --- .env | 1 + skills/usage/SKILL.md | 37 ++++++++++++++ skills/usage/scripts/ollama_usage.py | 72 ++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 .env create mode 100644 skills/usage/SKILL.md create mode 100644 skills/usage/scripts/ollama_usage.py diff --git a/.env b/.env new file mode 100644 index 0000000..7f7e166 --- /dev/null +++ b/.env @@ -0,0 +1 @@ +OLLAMA_API_KEY=1b09fe66435a43f7938d152748e772f1.ZAsdbueIhHetX9Lh3qcqOWLq diff --git a/skills/usage/SKILL.md b/skills/usage/SKILL.md new file mode 100644 index 0000000..6f372c6 --- /dev/null +++ b/skills/usage/SKILL.md @@ -0,0 +1,37 @@ +--- +name: usage +description: > + Show Ollama Cloud credit/usage spent via the ollama.com usage API. + Triggers on: "/usage", "kolik kreditu", "kolik mam vycerpano", + "ollama usage", "spotreba ollama", "credits". +--- + +# Usage + +Zobrazí spotřebu kreditů na Ollama Cloud pro aktuální API klíč. + +## Spuštění + +```bash +uv run skills/usage/scripts/ollama_usage.py +``` + +Skript čte `OLLAMA_API_KEY` z `workspace/.env` (vytvořeného uživatelem). +Pokud chybí nebo klíč nefunguje (401/403), řekni to uživateli — nescrapuj web. + +## Výstup + +Text v češtině, stručně: + +- **Session**: použité $ + per-model requesty +- **Weekly**: použité $ + per-model requesty +- **Aktivita**: `activity.cost` za poslední 4 týdny + +Čísla vypisuj přesně jak je vrací API — žádné dopočítávání procent +(API nezveřejňuje limit, takže % nelze spočítat ověřeně). + +## Poznámky + +- Endpoint: `GET https://ollama.com/api/usage`, hlavička + `Authorization: Bearer ` (ověřeno 2026-09, issue #15132 je zastaralá). +- Klíč z `~/.ollama/id_ed25519` nefunguje — jen API key z ollama.com. \ No newline at end of file diff --git a/skills/usage/scripts/ollama_usage.py b/skills/usage/scripts/ollama_usage.py new file mode 100644 index 0000000..c78258f --- /dev/null +++ b/skills/usage/scripts/ollama_usage.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +"""Ollama Cloud usage — GET https://ollama.com/api/usage with Bearer key.""" + +from __future__ import annotations + +import json +import os +import sys +import urllib.error +import urllib.request +from pathlib import Path + +API_URL = "https://ollama.com/api/usage" + + +def load_api_key() -> str: + env = os.environ.get("OLLAMA_API_KEY") + if env: + return env.strip() + # workspace root = three levels above this script + env_file = Path(__file__).resolve().parents[3] / ".env" + if env_file.is_file(): + for line in env_file.read_text().splitlines(): + line = line.strip() + if line.startswith("OLLAMA_API_KEY="): + return line.split("=", 1)[1].strip().strip('"').strip("'") + sys.exit("OLLAMA_API_KEY nenalezen (ani env, ani workspace/.env)") + + +def fmt_models(models: list[dict]) -> str: + if not models: + return "" + parts = [f'{m["name"]} ({m["request_count"]} req)' for m in models] + return ", ".join(parts) + + +def main() -> None: + req = urllib.request.Request(API_URL, headers={ + "Authorization": f"Bearer {load_api_key()}", + "Accept": "application/json", + }) + try: + with urllib.request.urlopen(req, timeout=15) as resp: + data = json.load(resp) + except urllib.error.HTTPError as e: + sys.exit(f"ollama.com API chyba: HTTP {e.code}") + except urllib.error.URLError as e: + sys.exit(f"ollama.com nedostupné: {e.reason}") + + limits = data.get("limits", {}) + session = limits.get("session", {}) + weekly = limits.get("weekly", {}) + + print("Ollama Cloud — spotřeba") + s_models = fmt_models(session.get("models", [])) + print(f'Session: ${session.get("usage", 0):.3f}' + (f" — {s_models}" if s_models else "")) + w_models = fmt_models(weekly.get("models", [])) + print(f'Weekly: ${weekly.get("usage", 0):.3f}' + (f" — {w_models}" if w_models else "")) + + activity = data.get("activity", {}) + cost = activity.get("cost") + if cost is not None: + period = activity.get("period", {}) + print( + f'Aktivita: ${float(cost):.5f}' + f' ({period.get("type", "?")} {period.get("starting_at", "")[:10]}' + f' → {period.get("ending_at", "")[:10]})' + ) + + +if __name__ == "__main__": + main() \ No newline at end of file