nanobot: 2026-09-14 21:07:55 — usage: resets countdown + per-model list
This commit is contained in:
@@ -21,17 +21,25 @@ Pokud chybí nebo klíč nefunguje (401/403), řekni to uživateli — nescrapuj
|
|||||||
|
|
||||||
## Výstup
|
## Výstup
|
||||||
|
|
||||||
Text v češtině, stručně:
|
Text v češtině, přesně tento formát:
|
||||||
|
|
||||||
- **Session**: použité % + per-model requesty
|
- `Session: <value> %, resets in X hours — <model> (<req count>), …`
|
||||||
- **Weekly**: použité % + per-model requesty
|
- `Weekly: <value> %, resets in Y days — <model> (<req count>), …`
|
||||||
- **Aktivita**: `activity.cost` (skutečné dolary) za poslední 4 týdny
|
- `Modely (počet požadavků, weekly okno):` — seznam modelů s requesty
|
||||||
|
|
||||||
`limits.*.usage` je zlomek limitu plánu (× 100 = % jako na dashboardu).
|
## Reset časy — odvození, ne API
|
||||||
Vypisuj % jako API/dashboard; `$` jen u `activity.cost`.
|
|
||||||
|
`/api/usage` **neobsahuje reset timestamps** (ty existují jen v HTML UI).
|
||||||
|
Skript je počítá: session = do další celé hodiny UTC (dashboard ukazuje
|
||||||
|
„Resets in 1 hour"), weekly = do nejbližšího pondělí 00:00 UTC.
|
||||||
|
Důvod: session usage šel v testu nahoru během pár minut (rolling okno),
|
||||||
|
weekly se mění pomalu, konzistentní s hodinovým/týdenním oknem.
|
||||||
|
Kdyby se ukázalo, že okno není kalendářové, uprav `until_next_*`.
|
||||||
|
|
||||||
## Poznámky
|
## Poznámky
|
||||||
|
|
||||||
- Endpoint: `GET https://ollama.com/api/usage`, hlavička
|
- Endpoint: `GET https://ollama.com/api/usage`, hlavička
|
||||||
`Authorization: Bearer <key>` (ověřeno 2026-09, issue #15132 je zastaralá).
|
`Authorization: Bearer <key>` (ověřeno 2026-09, issue #15132 je zastaralá).
|
||||||
|
- `limits.*.usage` je zlomek limitu plánu (× 100 = % jako na dashboardu).
|
||||||
|
- `activity.cost` u Pro plánu vrací $0.00000 — nefunkční, ve výstupu vynechán.
|
||||||
- Klíč z `~/.ollama/id_ed25519` nefunguje — jen API key z ollama.com.
|
- Klíč z `~/.ollama/id_ed25519` nefunguje — jen API key z ollama.com.
|
||||||
@@ -8,6 +8,7 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import urllib.error
|
import urllib.error
|
||||||
import urllib.request
|
import urllib.request
|
||||||
|
from datetime import datetime, timedelta, timezone
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
API_URL = "https://ollama.com/api/usage"
|
API_URL = "https://ollama.com/api/usage"
|
||||||
@@ -30,8 +31,31 @@ def load_api_key() -> str:
|
|||||||
def fmt_models(models: list[dict]) -> str:
|
def fmt_models(models: list[dict]) -> str:
|
||||||
if not models:
|
if not models:
|
||||||
return ""
|
return ""
|
||||||
parts = [f'{m["name"]} ({m["request_count"]} req)' for m in models]
|
return ", ".join(f'{m["name"]} ({m["request_count"]})' for m in models)
|
||||||
return ", ".join(parts)
|
|
||||||
|
|
||||||
|
def until_next_full_hour(now: datetime) -> timedelta:
|
||||||
|
nxt = (now.replace(minute=0, second=0, microsecond=0)
|
||||||
|
+ timedelta(hours=1))
|
||||||
|
return nxt - now
|
||||||
|
|
||||||
|
|
||||||
|
def until_next_monday(now: datetime) -> timedelta:
|
||||||
|
# days until Monday (weekday(): Mon == 0)
|
||||||
|
days = (7 - now.weekday()) % 7 or 7
|
||||||
|
nxt = (now.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||||
|
+ timedelta(days=days))
|
||||||
|
return nxt - now
|
||||||
|
|
||||||
|
|
||||||
|
def fmt_delta_short(td: timedelta) -> str:
|
||||||
|
"""Human countdown, dashboard style: '1 hour', '55 minutes', '6 days'."""
|
||||||
|
total = td.total_seconds()
|
||||||
|
if total >= 86400:
|
||||||
|
return f"{int(total // 86400)} days"
|
||||||
|
if total >= 3600:
|
||||||
|
return f"{round(total / 3600)} hours"
|
||||||
|
return f"{max(1, round(total / 60))} minutes"
|
||||||
|
|
||||||
|
|
||||||
def main() -> None:
|
def main() -> None:
|
||||||
@@ -50,22 +74,27 @@ def main() -> None:
|
|||||||
limits = data.get("limits", {})
|
limits = data.get("limits", {})
|
||||||
session = limits.get("session", {})
|
session = limits.get("session", {})
|
||||||
weekly = limits.get("weekly", {})
|
weekly = limits.get("weekly", {})
|
||||||
|
now = datetime.now(timezone.utc)
|
||||||
|
|
||||||
print("Ollama Cloud — spotřeba")
|
print("Ollama Cloud — spotřeba")
|
||||||
s_models = fmt_models(session.get("models", []))
|
s_models = fmt_models(session.get("models", []))
|
||||||
print(f'Session: {session.get("usage", 0) * 100:.1f} %' + (f" — {s_models}" if s_models else ""))
|
print(
|
||||||
|
f'Session: {session.get("usage", 0) * 100:.1f} %, '
|
||||||
|
f'resets in {fmt_delta_short(until_next_full_hour(now))}'
|
||||||
|
+ (f" — {s_models}" if s_models else "")
|
||||||
|
)
|
||||||
w_models = fmt_models(weekly.get("models", []))
|
w_models = fmt_models(weekly.get("models", []))
|
||||||
print(f'Weekly: {weekly.get("usage", 0) * 100:.1f} %' + (f" — {w_models}" if w_models else ""))
|
print(
|
||||||
|
f'Weekly: {weekly.get("usage", 0) * 100:.1f} %, '
|
||||||
|
f'resets in {fmt_delta_short(until_next_monday(now))}'
|
||||||
|
+ (f" — {w_models}" if w_models else "")
|
||||||
|
)
|
||||||
|
|
||||||
activity = data.get("activity", {})
|
models = weekly.get("models", [])
|
||||||
cost = activity.get("cost")
|
if models:
|
||||||
if cost is not None:
|
print("Modely (počet požadavků, weekly okno):")
|
||||||
period = activity.get("period", {})
|
for m in models:
|
||||||
print(
|
print(f' {m["name"]}: {m["request_count"]}')
|
||||||
f'Aktivita: ${float(cost):.5f}'
|
|
||||||
f' ({period.get("type", "?")} {period.get("starting_at", "")[:10]}'
|
|
||||||
f' → {period.get("ending_at", "")[:10]})'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in New Issue
Block a user