#!/usr/bin/env python3 """Track Firecrawl API credit usage for portal dashboard.""" import json, os, time from datetime import datetime, timezone BASE = os.path.expanduser("~/.hermes/scripts") LOG = os.path.join(BASE, "firecrawl-usage.json") LIMIT = 1000 # Current tier def _defaults(): return {"total_used": 0, "calls": [], "monthly": {}, "last_reset": str(datetime.now(timezone.utc))} def load(): """Load usage data, merging in any missing top-level keys. Older state files were written without the `monthly` / `calls` keys, which caused KeyError crashes in summary(). Merging defaults makes the loader forward/backward compatible with partial state files. """ data = _defaults() if os.path.exists(LOG): try: with open(LOG) as f: loaded = json.load(f) if isinstance(loaded, dict): data.update(loaded) except (json.JSONDecodeError, OSError): pass # Corrupt/unreadable state — fall back to defaults # Guarantee required keys/types even if the file had them as null/wrong type if not isinstance(data.get("monthly"), dict): data["monthly"] = {} if not isinstance(data.get("calls"), list): data["calls"] = [] if not isinstance(data.get("total_used"), (int, float)): data["total_used"] = 0 return data def save(data): with open(LOG, "w") as f: json.dump(data, f, indent=2) def record(credits_used, endpoint, url=""): data = load() now = datetime.now(timezone.utc) month_key = now.strftime("%Y-%m") # Track total data["total_used"] += credits_used # Track monthly if month_key not in data["monthly"]: data["monthly"][month_key] = 0 data["monthly"][month_key] += credits_used # Log individual call data["calls"].append({ "ts": now.isoformat(), "endpoint": endpoint, "url": url[:100], "credits": credits_used }) # Trim call log to last 1000 data["calls"] = data["calls"][-1000:] save(data) def summary(): data = load() month_key = datetime.now(timezone.utc).strftime("%Y-%m") month_used = data["monthly"].get(month_key, 0) return { "total_used": data["total_used"], "month_used": month_used, "month_limit": LIMIT, "month_remaining": max(0, LIMIT - month_used), "month_pct": round(month_used / LIMIT * 100, 1), "recent_calls": data["calls"][-10:] } if __name__ == "__main__": import sys if len(sys.argv) > 1 and sys.argv[1] == "summary": print(json.dumps(summary(), indent=2)) else: print(f"Credits: {summary()['month_used']}/{LIMIT} used this month")