@deepseek-ai/dsh-client-ui-token-viewer
English | 中文
Token consumption surface plugin: read-only surfaces over the host-computed token-meter session projections (tokenUsage, contextPressure, contextBreakdown) plus a DeepSeek account-balance read. The browser half owns no domain store, refresh chain, or event listener; the node half owns the one host route the balance row fetches.
TokenDock registers at conversation.input.dock (order 20, after Goal). It shows what the current session has consumed — billed input (uncached + cache read + cache write), output, cache hit rate, and approximate context occupancy (projectedTokens / contextWindow) with a mini progress bar. The hover tooltip carries the full billing breakdown. It renders nothing until a provider reports usage.
SidebarTokenPanel registers at sidebar.workspaces.header, a hole declared by ui-sidebar's shell above the workspaces region. It shows the DeepSeek account balance (currency figure with a refresh control; error-retry when the host proxy fails), aggregates tokenUsage across every session row's projectionValues — billed input, output, cache hit rate, and the number of sessions that reported usage — expands to a per-conversation list (each session's billed input/output, highest total first; clicking a row opens that session), and opens a right-side usage statistics panel (TokenDetailPanel at shell.overlay): a faithful port of CC Switch's usage-dashboard methodology, folded from per-request usage records (the usageLog projection) rather than cumulative session totals. Range presets resolve exactly like CC Switch (today from local midnight, N-day windows from the midnight of N−1 days back, everything); the hero shows real consumption (fresh input + output + cache write + cache read), request count, and total cost, over a five-card breakdown row (fresh input / output / cache write / cache read / cache-hit rate with progress bar); the trend chart buckets by each request's own commit time — hourly for the day, daily otherwise, empty buckets zero-filled — with four token series plus a dashed cost line; and three tabs carry the request log (every billed request newest first; clicking a row opens that session), per-project statistics, and per-model statistics with average cost. Cost is the four-bucket estimate (each bucket priced once, CC Switch's Claude-semantics calculator) under the default DeepSeek CNY prices. Sessions from before the usageLog projection exist fall back to one synthesized record per session from the cumulative tokenUsage, so only that legacy tail stays approximate. It renders nothing until balance or usage is available, and nothing in the collapsed rail (wide === false).
- Host half registers
GET /api/billing/balance: it reads its configuration from the harness settings namespace dsh-token-viewer (which credential reference and provider base URL to use, defaults DEEPSEEK_API_KEY / https://api.deepseek.com, editable in settings.yaml), resolves the API key through the credentials service (the same secret store the LLM adapter uses), and proxies DeepSeek's /user/balance, returning only balance figures — the API key never leaves the server. It also registers the modelUsage session projection (cumulative per-model buckets for the legacy fallback) and the usageLog session projection: a pure fold over assistant/message events that appends one timestamped record per reported step — commit time (event.time), model, and the four token buckets — which the detail panel aggregates with CC Switch's exact statistics method.
The /client exports are the plugin body (apply/inject) and the composed props types.
Model Experience
None. The surfaces are pure presentation over projection values already computed by the host, plus a balance read from the provider's billing endpoint; the plugin adds no prompt content, tools, messages, or provider requests.
KV Cache effect
None. The plugin neither assembles nor sends provider requests.
Known Limitations and Deferred Work
- Heuristic approximations, dock and sidebar only — the dock strip's and sidebar card's cache hit rate and context occupancy inherit the token-meter's fixed 4-chars-per-token density estimate for any content the provider did not bill; CJK text and JSON schemas are systematically underpriced. The detail panel's CC Switch statistics fold provider-reported per-request usage instead, so its figures are exact for any session the
usageLog projection has observed (only sessions predating that projection fall back to a synthesized approximation). Occupancy remains a user-facing reference figure, not a billing or gating input (see the token-meter README).
- Per-model tiered pricing — every request bills under its own model's provider list price (V4-Flash / V4-Pro, CNY per 1M tokens, cache writes at the cache-miss rate) split by the provider's Beijing peak windows (09:00–12:00 and 14:00–18:00, double the off-peak rate); unknown models fall back to the V4-Flash off-peak table. Prices are hardcoded in
MODEL_PRICING and need a sync when the provider reprices.
- Balance is DeepSeek-specific — the host route calls DeepSeek's
/user/balance; other providers are not covered, and multi-currency responses show only the first balance_infos entry.
- The sidebar card depends on ui-sidebar's header hole — it renders only when the shell declares
sidebar.workspaces.header; a composition that replaces ui-sidebar without that hole silently loses the card while the dock strip keeps working.