diff --git a/docs/v3-roadmap.md b/docs/v3-roadmap.md new file mode 100644 index 0000000..3c6a66d --- /dev/null +++ b/docs/v3-roadmap.md @@ -0,0 +1,89 @@ +# Clawdmeter v3 — multi-provider (alpha) + +Extend the watch beyond Claude Code to show usage for several AI coding +providers, let you pick which one the display tracks, and recolor the whole UI +to the active provider's brand. + +Branch: **`v3-dev`** (off v2 `d55dc4a`). v2 stays on `v2-dev`. + +## Providers (initial set) + +| id | provider | used via | brand accent | +| ----------- | --------------------- | -------------------------------- | ------------ | +| `anthropic` | Claude Code | Anthropic OAuth (today's daemon) | `#d97757` clay | +| `openai` | OpenAI Codex | Codex CLI subscription (`~/.codex`) | `#10a37f` green | +| `zai` | z.ai GLM Coding Plan | Anthropic-compatible endpoint | blue (TBD) | + +## Locked decisions (2026-07-10) + +- **Metric = rate-limit %** — the same two-bar 5h / weekly model as Claude, read + from each provider's CLI subscription. Fall back to spend / token counts for a + provider only if it genuinely doesn't expose limits. +- **Switch on both PC and watch** — pick the active provider in the desktop + panel *and* on the watch (cycle / selector); the theme recolors live. +- **Brand palette** (starting point, tuned on-device): Anthropic clay `#d97757`, + OpenAI `#10a37f`, z.ai blue (exact hex TBD). + +## Architecture + +### Daemon — provider abstraction +- New `daemon/providers/` package: + - `base.py` — `Provider` ABC: `id`, `label`, `accent`, `async poll() -> ProviderStatus`. + - `anthropic.py` — today's logic moved here (`poll_api`, `compute_today_usage`, + OAuth refresh), behaviour-identical. + - `openai_codex.py`, `zai.py` — added in M2 / M3. +- `ProviderStatus` = normalized `{s, sr, w, wr, st, ok, tokens_today?, cost_cents_today?}`. +- **Config v2** (`config.py`): add `providers` (per-provider enable + creds), + `active_provider`, `display_order`. Migrate v1→v2 by wrapping the existing + setup as `anthropic`. +- Poll loop drives the **active** provider; for on-watch cycling it may poll all + enabled providers and cache, so switching is instant. + +### Payload +- Add **`pv`** (provider id) so the watch knows which theme to wear; usage fields + stay normalized (`s/sr/w/wr/st/tk/tc/...`). +- On-watch switch: watch → PC command **`{"cmd":"prov","id":"..."}`** sets + `active_provider` (same channel as the dimmer / button commands, no new GATT). + +### Firmware — runtime theming (the meaty part) +- Convert `theme.h` compile-time `#define`s into a runtime **`Palette`** + (`lv_color_t accent/green/amber/panel/bar_bg/...`) plus shared `lv_style_t` + objects for the accent / panel / text roles. +- `ui_set_theme(pv)` swaps the palette + updates the shared styles + invalidates + — **no widget recreation** (LVGL styles propagate to attached widgets). +- Per-provider **logo** on the usage screen (swap the image source). +- On-watch provider switch: a small selector (button on the usage screen, or a + Providers entry in the launcher) → sends `{"cmd":"prov",...}`. + +### Panel (desktop) +- Provider selector (which one displays) + per-provider credential / enable + fields. Reuses the existing FastAPI + WebView2 settings panel. + +## Milestones + +- **M1 — framework + Anthropic refactor + runtime theming.** Provider ABC + + `AnthropicProvider` (identical behaviour) + config v2 + `pv` in the payload. + Firmware runtime palette + shared styles + `ui_set_theme` + per-provider logo + slot + on-watch switch plumbing. Panel provider selector (only Anthropic active + yet). *Deliverable: behaviour unchanged, but themeable and switch-ready.* This + is the big refactor and de-risks M2/M3. +- **M2 — OpenAI (Codex) provider.** Read Codex rate-limit / usage. Source TBD — + Codex is installed at `~/.codex` (`auth.json`, `config.toml`, `state_*.sqlite`, + `logs_*.sqlite`, `sessions/`); investigate whether limits come from the state + DB or ChatGPT backend headers. Green theme + OpenAI logo. Fall back to + spend/tokens if the % model isn't available. +- **M3 — z.ai (GLM Coding Plan) provider.** `ANTHROPIC_BASE_URL` is already set on + the dev machine → z.ai is likely used through its Anthropic-compatible endpoint, + so reuse the Anthropic poll pointed at z.ai's base URL + z.ai key, reading the + same `anthropic-ratelimit-*` headers. Blue theme + z.ai logo. +- **M4 — polish.** On-watch switch UX, per-provider splash decision, panel niceties. + +## Open items / assets + +- Exact brand hexes (OpenAI `#10a37f` proposed; z.ai blue TBD — finalize on device). +- **Logos** — need official OpenAI + z.ai marks as RGB565 (user provides / points + to source, per the "don't hand-author brand art" preference). Claude logo already + in `logo.h`. +- Splash — currently Claude pixel-art (claudepix); per-provider splash is an open + choice (keep Claude, go neutral, or per-provider). +- Naming — keep **Clawdmeter**; multi-provider under the same identity.