Files
nanobot-runtime/plans/ollama-usage-poller.md

4.0 KiB

Ollama Usage Poller — Continuous Collection

Context

The /usage skill shows Ollama Cloud credit usage on demand. The user wants continuous collection: poll GET https://ollama.com/api/usage every minute, store a sample whenever anything changed since the last one. Goal: later analysis of how much each nanobot session cost, and when.

Constraints found in exploration:

  • The API (ollama.com/api/usage, Bearer key from workspace/.env) returns: limits.session.usage (fraction of plan limit, rolling 1-hour window), limits.weekly.usage (weekly window), per-model request_count for both windows, activity.cost (broken, always $0.00000 on Pro).
  • No reset timestamps, no per-model cost split, no token counts in the API.
  • Existing pattern: per-minute system crontab entries running uv run <script> with output to workspace/log/<name>_cron.log (remind, wiki-compile, wiki-sync). Reuse this pattern.
  • Session attribution later needs memory/history.jsonl (per-request timestamps, token counts, session ids) — out of scope for this plan, this plan only builds the collector + a delta report.

Steps

  1. Collectorscripts/ollama_usage_poll.py (English, stdlib only, reuse load_api_key from skills/usage/scripts/ollama_usage.py):

    • GET the API, on network/HTTP error log to stderr and exit 0 (never noisy, never blocks cron).
    • SQLite db/ollama_usage.sqlite, table samples:
      CREATE TABLE IF NOT EXISTS samples (
        ts       TEXT PRIMARY KEY,   -- UTC ISO 8601
        session  REAL NOT NULL,      -- limits.session.usage fraction
        weekly   REAL NOT NULL,      -- limits.weekly.usage fraction
        models   TEXT NOT NULL       -- JSON: weekly {"model": count}
      );
      
    • Write-on-change: compare against the latest row; insert only when session, weekly, or models JSON differ. Unchanged minutes are noise.
    • Session-window reset detection (usage drops instead of rising) is implicit — we store raw values; deltas are computed at report time.
  2. Crontab — add system crontab entry (user's crontab, alongside the existing ones):

    # ollama-usage: continuous usage sampling into db/ollama_usage.sqlite
    * * * * * uv run /home/nanobot/.nanobot/workspace/scripts/ollama_usage_poll.py >> /home/nanobot/.nanobot/workspace/log/ollama_usage_cron.log 2>&1
    
  3. Reportscripts/ollama_usage_report.py (English, stdlib only):

    • No args: last 24 h delta summary (session/weekly spend per hour, model request deltas).
    • --since ISO / --until ISO: arbitrary window.
    • Output: plain text table — for each consecutive sample pair: ts, Δsession %, Δweekly %, Δrequests per model. Detect hourly reset (session drops) and mark it as a new window boundary.
    • Extend the /usage skill SKILL.md with a "Reports" section pointing at this script (does not change the on-demand output format).
  4. Skill updateskills/usage/SKILL.md: add a short note that continuous sampling runs via crontab into db/ollama_usage.sqlite and reports are available via scripts/ollama_usage_report.py.

  5. Git commit — workspace repo, timestamped message.

Out of scope (later)

  • Session-level attribution (join with memory/history.jsonl token counts per session) — separate plan once we have a few days of samples.
  • Notification thresholds (e.g. Telegram alert at 80 % weekly).
  • Retention/compaction of the samples table (1 row per change, negligible size for months).

Verification

  1. Run uv run scripts/ollama_usage_poll.py twice back to back → second run writes nothing (no change), DB has 1 row.
  2. Wait for a real request (or make one via nanobot) → next poll writes a new row with changed session fraction / model counts.
  3. Run the report script → delta table renders, hourly reset detected as boundary when a session window rolls over.
  4. crontab -l shows the new entry; after ~5 minutes log/ollama_usage_cron.log is empty or minimal, DB grew.