Skip to content

feat: add Usage dashboard panel to desktop app - #77572

Closed
eaglezzz0522-cloud wants to merge 1 commit into
NousResearch:mainfrom
eaglezzz0522-cloud:feat/77221-usage-panel
Closed

feat: add Usage dashboard panel to desktop app#77572
eaglezzz0522-cloud wants to merge 1 commit into
NousResearch:mainfrom
eaglezzz0522-cloud:feat/77221-usage-panel

Conversation

@eaglezzz0522-cloud

Copy link
Copy Markdown

Summary

Adds a new /usage route to the desktop app that shows token and cost metrics. The panel reads from the existing /api/analytics/usage endpoint — no backend changes needed.

Changes

New files:

  • apps/desktop/src/app/usage/index.tsx — UsageView component with summary cards, bar sparklines, and model breakdown table
  • apps/desktop/src/app/usage/sparkline.tsx — BarSparkline component with hover tooltip
  • apps/desktop/src/app/usage/store.ts — nanostores atom for days selector

Modified files:

  • apps/desktop/src/app/routes.ts — add USAGE_ROUTE, AppView, AppRouteId
  • apps/desktop/src/app/chat/sidebar/index.tsx — sidebar nav entry
  • apps/desktop/src/app/contrib/surfaces.tsx — lazy-loaded route
  • apps/desktop/src/lib/keybinds/actions.ts — nav.usage keybind

Features:

  • Sessions, tokens, cost, cache reads summary cards
  • Tokens/day and cost/day bar sparklines
  • Model breakdown with percentage bars
  • 7d/14d/30d/90d/365d preset selector
  • Estimated vs actual cost toggle
  • Sidebar navigation + keybind
  • Lazy-loaded via React.lazy

Verification

  • Uses the existing /api/analytics/usage endpoint — no new backend API
  • Follows the same patterns as ArtifactsView/MessagingView/SkillsView
  • All components use existing UI primitives (Badge, Button, Select, Skeleton, Tooltip, EmptyState, Loader)

Closes #77221

New /usage route with a UsageView component that shows token and cost
metrics via the existing /api/analytics/usage endpoint:

- Summary cards: sessions, tokens, cost, cache reads
- Bar sparklines for tokens/day and cost/day
- Model breakdown table with percentage bar, token count, and cost
- 7d/14d/30d/90d/365d preset selector
- Estimated vs actual cost toggle
- Sidebar nav entry + keybind (nav.usage)
- Lazy-loaded via React.lazy

Closes NousResearch#77221
@alt-glitch alt-glitch added type/feature New feature or request P3 Low — cosmetic, nice to have comp/desktop Electron desktop app (apps/desktop/*) area/usage-cost Token accounting, usage reporting, billing, cost tracking needs-decision Awaiting maintainer decision before any implementation duplicate This issue or pull request already exists labels Aug 3, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Duplicate of #77537 — the current live diff is byte-identical; #77537 is the earlier open usage-panel PR.

@tneemo

tneemo commented Aug 3, 2026

Copy link
Copy Markdown

Independent review notes — from a competing Phase-1 draft (now withdrawn)

I had a Phase-1 draft (#77251) implementing a usage.summary RPC over sessions + session_model_usage plus summary cards. Your PRs cover the same surface and the requested charts via the existing /api/analytics/usage endpoint — reusing the endpoint instead of creating a parallel RPC is the better architecture, so I'm withdrawing my draft in favor of yours.

While building mine, the #77221 triage surfaced three correctness findings (from the automated review on my draft) that apply to any usage surface reading these tables. Sharing them so they don't get re-discovered the hard way:

  1. Token categories must agree. token_sessions (count of sessions with any token activity) includes cache_write_tokens > 0 in my first version, but the displayed totals (input/output/cache-read) omitted cache-write — so a cache-write-only session counted as "token-bearing" while no displayed total matched. Pick one story: either include cache_write_tokens in the totals (and show it), or exclude it from the token-session count. The /api/analytics/usage rows have cache_read + reasoning; verify cache_write is handled consistently if you add a sessions-count card.

  2. Micro-costs collapse to $0.00. The issue's own example is "cheapest session $0.000056". With minimumFractionDigits: 2 that renders as $0.00. For small positive values, use more decimals (I used 6 when 0 < v < 0.01), otherwise tiny costs look like zero.

  3. Cost extrema must come from one source. Deriving cheapest from the sessions table and most_expensive from session_model_usage (grouped) produces numbers that don't tell the same story — the two tables aggregate differently (aux calls in one, not the other). Derive both from the same per-session aggregate; I filtered WHERE estimated_cost_usd > 0 before grouping so zero-cost sessions don't skew the min.

Good work on the lazy-loading and the breakdown table — those are exactly the Phase-2 pieces the issue asks for. Happy to review if you want a second pair of eyes after the triage runs.

@tneemo

tneemo commented Aug 3, 2026

Copy link
Copy Markdown

Correction to my earlier review notes — verified against your diff

After reading your actual diff (and the /api/analytics/usage backend it consumes), I need to correct two of the three findings I posted — they were specific to my draft's RPC design (which grouped per-session and counted cache-write), not to your implementation:

  • Token-category consistency (finding 1): does NOT apply to your code. Your surface has no token_sessions count card and the endpoint aggregates by day/model with cache_read + reasoning only — no cache-write counter to disagree with. Retracted.
  • Single-source cost extrema (finding 3): does NOT apply. Your endpoint has no per-session cheapest/most-expensive at all — it's daily/model aggregates. That finding was about my RPC grouping by session. Retracted.

The one finding that genuinely applies:

  • Micro-cost precision (finding 2): your formatUsd uses toFixed(4) for values < $1. The issue's own example is "cheapest session $0.000056" — with 4 decimals that renders as $0.0001, losing the real value. Consider 6 decimals for values in (0, 0.01) (or a dynamic precision that doesn't lose the least significant digit), so micro-costs don't get rounded away. This is minor and cosmetic; the surface itself is solid.

Sorry for the noise — the two retracted points were about my competing draft, not your diff. Your approach (reusing the existing analytics endpoint, no parallel RPC) is the right call, and the per-model breakdown + sparkline are exactly the Phase-2 pieces the issue asks for.

@eaglezzz0522-cloud

Copy link
Copy Markdown
Author

Closing as duplicate of the earlier first-round PR (#77534 / #77129 / #77536 / #77537 respectively). The original individual PRs remain open for review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/usage-cost Token accounting, usage reporting, billing, cost tracking comp/desktop Electron desktop app (apps/desktop/*) duplicate This issue or pull request already exists needs-decision Awaiting maintainer decision before any implementation P3 Low — cosmetic, nice to have type/feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(usage): desktop app has no local token/cost analytics surface despite full metering in core

3 participants