Commit Graph
7 Commits
Author SHA1 Message Date
wenilandClaude Opus 4.8 b188349262 v2 Phase 4: decouple Session (local usage) from the rate-limit API
The Session screen's tokens/cost are computed locally from transcripts and need
no network, but they were gated behind a successful rate-limit API call — so an
expired OAuth token or API outage froze the whole watch.

Daemon: always compute and send local usage every cycle; rate-limit utilization
is now best-effort and merged on top when available, with ok=true only when it's
fresh (ok=false on expired token / API down). poll_api returns just the
rate-limit fields; connect_and_run owns the payload + ok flag.

Firmware: ui_update always refreshes the Session screen; the rate-limit bars and
the freshness clock update only when data->ok, so the usage view falls back to
its existing idle "Zzz" state instead of showing stale or zeroed percentages.

Verified: with the token expired (HTTP 401) the daemon still sends
tk/tc/tn/to + ok:false and the Session screen keeps updating.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 18:49:34 +03:00
wenilandClaude Opus 4.8 4c1b63e645 daemon: survive BLE adapter removal and auto-restart on crash
Pulling the USB Bluetooth dongle made BleakScanner raise from inside the main
loop; the exception propagated out of daemon_main, the bg thread died, and the
tray froze on its last state with no recovery (reported: "daemon crashed and
doesn't come back").

Two layers of hardening:
1. main() loop now wraps scan+connect in try/except — adapter-gone errors are
   logged, the tray shows Scanning, and it backs off and retries, so replugging
   the adapter recovers automatically. CancelledError is re-raised.
2. The tray supervises the asyncio loop: an unexpected crash is logged and the
   loop is RESTARTED after a backoff, gated by a quit_evt so Quit still stops
   cleanly (and call_soon_threadsafe is guarded against a closed loop).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 18:39:58 +03:00
wenilandClaude Opus 4.8 26bc85ffe6 v2 Phase 4: fix token over-count (dedup) and Opus pricing
Two bugs made the Session numbers wildly inflated (~$300/122M when the real
figures were ~$46/57M):

1. No de-duplication. Claude Code copies prior history into a new transcript
   file on every compaction/resume, so the same API turn appears in several
   .jsonl files. Summing all lines counted each turn multiple times — ~2.7x
   inflation today (a heavily-compacted session). De-dup by (messageId,
   requestId), matching ccusage.

2. Wrong Opus pricing. Used the older $15/$75 in/out rates; claude-opus-4-x is
   actually $5/$25 (cache-write $10, cache-read $0.50) — 3x too high. Rates
   verified against ccusage/LiteLLM, which they now reproduce to 100%.

Verified end to end against a fresh ccusage run: total tokens, output tokens and
cost all match exactly (57,256,809 tok / $45.63). Daemon-only change; no firmware
reflash needed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 15:27:56 +03:00
wenilandClaude Opus 4.8 c2020dcea2 v2 Phase 4: add "generated" (output) tokens under the total on Session
The total is ~97% cache reads, which reads as implausibly large on its own.
Show the cache-inclusive total as the headline token number and the output
tokens ("what Claude actually generated", ~1.1M) as a small line beneath it —
impressive total, believable sub-number. Daemon sends a new `to` field; firmware
parses output_today and renders it. Re-spaced the Session layout for the 5th row.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 15:14:27 +03:00
wenilandClaude Opus 4.8 56b49898a3 v2 Phase 4: Session screen — today's tokens and equivalent cost
Daemon: compute_today_usage() sums today's Claude Code token usage across the
local project transcripts (~/.claude/projects/**/*.jsonl), reading only files
modified today so the scan stays cheap, and prices it with Anthropic list rates
to show the equivalent API cost (the ccusage-style flex for subscription users).
The compact fields tk (total tokens), tc (cost in cents) and tn (message count)
piggyback onto the existing 60s BLE payload.

Firmware: UsageData gains tokens_today (64-bit) / cost_cents_today /
messages_today; parse_json reads tk/tc/tn; a new Session screen shows the cost
as the hero with total tokens and message count below, refreshed from ui_update
so it's current whenever opened. Wire SCREEN_SESSION to the real screen (was a
stub). Verified end to end: daemon sends e.g. tk=105374109 tc=26838 tn=663.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 15:03:23 +03:00
wenilandClaude Opus 4.8 c610e3af48 Add Waveshare ESP32-S3-Touch-AMOLED-2.06 board port + Windows daemon fixes
- New board firmware/src/boards/waveshare_amoled_206/ (CO5300 410x502,
  FT3168 touch, AXP2101 PMU, QMI8658 IMU). PlatformIO env
  waveshare_amoled_206. CO5300_COL_OFFSET=22, fixed orientation,
  PWR button on GPIO10, FocalTech inline touch reader.
- Windows daemon: fix advertised device name (Claude Controller ->
  Clawdmeter) to match firmware ble.cpp, and add CLAWDMETER_ADDRESS env
  fallback so it connects by address when the bonded HID device is not
  advertising (Windows keeps it HID-connected).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 12:46:46 +03:00
kvenanzi eb70456755 Add native Windows host daemon (bleak/WinRT)
Adds a Windows port of the host daemon so the Clawdmeter stays connected
on Windows independent of WSL. Mirrors the macOS daemon and speaks the
existing GATT data service unchanged — no firmware changes.

- claude_usage_daemon_windows.py: Windows-local OAuth token read +
  Anthropic poll + BLE scan/connect/write, with auto-reconnect
  (connect-retry wrapper, zombie-link break, split fast/slow backoff)
- tray_windows.py: pystray login-startup tray app (status icon + Quit)
- autostart_windows.py: winreg HKCU\Run autostart via pythonw.exe
- icon_assets.py: per-state tray icons composited from logo.h
- install-windows.ps1 + daemon/README-windows.md: turnkey setup
- pytest suite: token / poll / reconnect / tray / autostart / no-WSL guard
2026-06-02 16:39:07 -05:00