Sidebar billing dashboard: real usage aggregated from session logs (per-model and per-day calls/tokens/cache), cost estimated in CNY from a current multi-provider pricing catalog, subscription-plan (coding/token/agent) routes exempt, and per-provider health dots.
Install
# from npm (prebuilt)
dsh plugin --profile web add @kenz1117/dsh-ui-usage-billing
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:kenz1117/dsh-ui-usage-billing
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
dsh-ui-usage-billing
Demo GIF

✨ Why this plugin
Most billing plugins stop at "token count × unit price". dsh-ui-usage-billing turns billing into a reconcilable ledger pipeline — real usage, live prices, and peak/off-peak awareness that follows the model.
Real usage you can reconcile
Usage is aggregated live from persisted session logs — never fabricated (an empty snapshot shows until real data arrives); daily official-balance deltas are cross-checked against the local ledger, and deviations beyond the threshold prompt a review — a bill that survives scrutiny.
Live prices, history never rewritten
A live models.dev catalog + a built-in catalog of 77 models across 24 vendors + user-defined prices in the settings panel (bindable per relay origin) mean new models never wait for a release; DeepSeek time-of-day prices are segmented by official change boundaries (base price before 08-17, weekend peak hours 08-17~08-23, weekend all-day off-peak from 08-23) and later price changes never rewrite old bills.
Peak/off-peak aware, alerts follow the model
The billing channel is detected from the current session's model: DeepSeek metered uses time-of-day prices (weekday 9-12 / 14-18 peak ×2, weekend all-day off-peak), Zhipu Coding Plan uses credit windows (weekday 14-18 peak at full rate, off-peak at 50% of base credits) — the channel layer is extensible for more providers; a popover / system notification fires automatically before each switch, and only sessions whose current model actually involves peak/off-peak get alerted or show the tier section — no watching the clock.
Subscriptions, balances and quotas on one screen
7 official provider balances (DeepSeek / Kimi / Zhipu GLM / Tencent Cloud TokenHub / …), Coding Plan quotas, relay-station rolling quota windows, self-declared endpoints, plus balance-delta reconciliation — what the plan deducted and what the balance deducted, verifiable side by side.
Details few peers offer
- Not just "how much" but "on what": input split by cache hit/miss (including reasoning), official vs third-party buckets, drill-down by workspace/session/relay site, per-turn cost-spike attribution.
- A performance panel: per-model TTFT mean/P50/P90 and generation speed.
- Uncatalogued models are explicitly marked and never silently billed 0; one alias entry prices an out-of-catalog model.
- An optional
usage_statstool lets the model answer "what did I spend today" or "which site used the most". - A pure UI surface: no tools registered, no system-prompt injection, no model-visible log events.
- Chinese / English and ¥ / ≈$ toggles; no chart library, no external CDN, offline & self-contained.
📊 Dashboard
Sidebar trigger card: persistent above the Settings button — month cost as the headline number with a 7-day sparkline mini-trend, second line "Today / This week"; collapses to an icon button; hover reveals a quick-look card.
Six-tab dashboard: Overview / Trends / Detail / Stats / Rates / Settings — hero figures + comparisons + month projection + KPIs + usage heatmap, 7/30-day trends switching cost / tokens, plus the model rate table, budget and peak/off-peak alerts; restrained tones, dark/light adaptive.

Live cost bar: persistent "this turn / session" cost below the composer; the peak/off-peak tier & countdown section appears only when the current model involves peak/off-peak pricing; subscription low-quota chips appear at ≤20% remaining, red at ≤10%; hideable via the settings-tab toggle (display-only preference persisted locally; stats and alerts unaffected).
Peak/off-peak switch alert: a popover plus an optional system notification before a switch; lead time / position / mode / preview configurable; copy differs by billing channel (DeepSeek price halves, Zhipu credits at 50%).
Plugin info card: a persistent "About" card in the Settings tab — version read server-side from the package's
package.json(single source of truth, correct on publish), author / repo / npm / license one click away.
💰 Billing engine
Provider-first grouping: usage is grouped by the llm entry the calls actually went through (channel) — Tencent Cloud TokenHub / Token Plan / DeepSeek official / direct: / unknown routes; the model brand stays as a row logo + sub-line. Official judgement follows the channel origin (
api.deepseek.com) instead of the route name, so gateway routes nameddeepseek-*no longer count as official.routeAliasesrelocates renamed/deleted historical routes;modelKeyAliasesbinds uncatalogued model ids to catalog keys (date suffixes, org prefixes and the TokenHub short idhy3are recognized out of the box).Live rate table: models.dev fetched pricing + live-model alignment — all configured models included; peak/off-peak split (weekdays 9-12 / 14-18 peak ×2, weekends off-peak all day; history priced per official change boundaries, see "Billing details") + a live USD→CNY rate, auto-refreshed every 6 hours; the rate strip shows the last sync time with a one-click "Sync now" button (no host restart needed).

Custom unit prices: set real paid prices (miss / cache-hit / output, optional USD and off-peak columns) for uncatalogued or repriced models; bindable per relay origin; an out-of-catalog model is priced as soon as you fill it in.
Official vs third-party buckets: the detail cost column splits official direct / third-party relay ("official x / third y" when mixed); the Stats tab has a summary card; web-search assist calls count as official.
Monthly budget + tier alerts: budget bar ≥80% amber, over-budget red pulse; one alert per 50/80/100% crossing; a balance below the CNY threshold alerts once a day.
Cost-spike attribution: last-40-turn cost bars, amount at bar top, peak/off-peak background bands, >2× spikes flagged with attribution.
🔌 Subscriptions & balance
Subscription quota: auto-detects subscription providers (Kimi / Z.ai / OpenCode Go / MiniMax / OpenRouter / Xiaomi / Volcano…); those with a quota API show remaining % and reset time live, exhausted in red, otherwise "not wired"; subscription-channel model cost is 0, and plan tiers are recognized by the built-in knowledge base (e.g. OpenCode Go $10/mo + $30 weekly). MiniMax note: use
minimax-token-plan-cnfor the CN domain (api.minimaxi.com),minimax/minimax-token-planinternational; overridebaseUrlper provider if needed.Multi-provider balance: built-in official balances for DeepSeek / Kimi / StepFun / SiliconFlow / xAI / Zhipu GLM, with an "≈N days" estimate from the 7-day daily burn; Tencent Cloud TokenHub Token Plan goes through the cloud-API control plane (TC3-signed,
src/tc3.ts) — set the credential to a<SecretId>:<SecretKey>key pair (not the inference key) and name the routetencent-tokenhub/tokenhub/tencent/tencentcloud; a percentage window is produced only when both remaining and total quotas parse (never guessed).Custom provider balance: configure any HTTP endpoint (
extractsupports constant / dot-path / arithmetic, header{{ENV}}via the credentials seam).Declared endpoints + balance reconcile:
declaredEndpointsself-declares balance/quota interfaces for vendors absent from the built-in table — dot-paths only ("where the number is"), no expressions; safety bounds (single-slash absolute path, GET only, no cross-origin redirects, response-size/timeout caps, credentials from the matched provider only) are enforced bysrc/declarative.ts; a wrong path is markeddeclaredwith a reason. Balance reconcile (reconcilePath) cross-checks the official balance change against the local ledger, flagging drift above the threshold (0.3 CNY and >15%); top-ups / grants / currency changes reset the baseline instead of alerting, and a flat balance (subscription spend) stays silent.Relay-site attribution & quota: usage is grouped by
baseURLorigin — multiple keys on one relay merge into a row named by its domain; New API (/api/status) and Sub2API (/v1/usage) are auto-detected for balance and rolling quota windows, labeled "no quota" when unreadable, <20% remaining in red; recognition caches for 5 minutes (per-key fuse-breaking), and therelay-quotasendpoint attachesdiagnosticsfor "why is my relay not showing"; project attribution prefers the workspace title.
For the full adapter matrix per channel (detection / endpoints / credentials / troubleshooting), see docs/adapters.md.
📈 Usage visualizations
Session detail + heatmap: sessions sorted by cost (title / project / calls / cost / last active); month / half-year / year calendar heatmap (5-color scale, hover detail; the year view is ~52 weeks, GitHub-style, and the half-year view uses 26 weeks of large cells — half a year of intensity in one screenshot-ready chart) with a cost / tokens metric switch; total, active-day and streak counts on top.
Performance metrics: per-model TTFT mean / P50 / P90, generation speed (tokens/s), total-latency mean; per-hour × per-model comparison curves — metric tabs, clickable model chips (top-5 by samples lit by default), hover snapping to the nearest hour with a crosshair and per-model values, broken lines for missing-sample hours (never fabricated); view preferences persist locally.
Token insights: the daily token chart switches between two views — "Structure" (cache-miss / cache-hit / output, including reasoning) and "By model" (the toggle hides itself when snapshots lack per-day-per-model detail); hover shows the day's exact breakdown (thousand-separated); clicking a legend swatch or a model-table row focuses that model (click again to release); structural KPIs (cache-hit rate / reasoning share / input-output ratio / peak day); per-day CSV and JSON export (JSON includes per-day-per-model detail).

Export + drill-down: daily / per-session / per-site CSV and full JSON from the Stats tab; cost breakdown / workspaces / session detail drillable (click a project row to expand its sessions); no chart library, no external CDN, pure design tokens.

🛡️ Robustness & privacy
- Real usage aggregation: incremental server-side aggregation (only written sessions recompute), per-session corruption tolerance, snapshot fallback; the optional
usage_statstool queries today / month / current session / cumulative spend, plusbySite(relay-attributed) andrelay(relay-only) summaries. - Model health + uncatalogued annotation: provider connection dots (green / red / grey); uncatalogued models are marked and priced at the fallback, with the provider inferred (e.g.
mi-mimo-2.5→ Xiaomi); estimated-price models are labeled "estimated". - Multi-language + three currencies: language (EN / 中) and currency (¥ CNY / $ USD / € EUR) switch independently, both plugin-only — neither leaks into the host UI. The rate table, the sidebar card and the composer capsule all convert to the selected currency, and both choices persist locally. On first upgrade the language is seeded once from the stored currency (“$” → English), so no existing user’s interface language changes silently.
- Security hardening: every HTTP endpoint enforces loopback-only access via a dual check of the peer socket address and an exact Host-header match, rejecting
127.0.0.1.evil.com-style DNS-rebinding names (reverse-proxy deployments can allow specific names withtrustedHosts; the peer-socket check stays mandatory); write paths additionally validate a loopback Origin and Content-Type with a body-size cap against cross-site rewrites; balance / subscription / pricing fetches carry bounded retries with per-upstream circuit breaking (auth failures are config issues and do not trip the breaker). - Export injection guard: CSV cells starting with
=/+/-/@get a leading single quote and full escaping, so they cannot execute as formulas in Excel / WPS. - Privacy baseline: a pure UI surface — registers no tools, injects no system prompt, writes no model-visible events; it only aggregates from existing session logs, whose content is owned by other packages.
🚀 Quick start
Check your host generation first (dsh --version), then pick the matching install command — a mismatched line is rejected by the DSH Store via the engines.dsh declaration (declared since v1.0.41). Note that dsh plugin add requires an explicit --profile (otherwise it fails with required option '--profile <name>' not specified), and prefer pinning an exact version over @latest (pnpm's minimumReleaseAge cooldown skips freshly published versions and may fall back to the other line):
DSH 0.1.2 ~ 0.1.6 era (0.1.2-alpha.1 and later; npm
latestcurrently at 0.1.5-rc.2, with the alpha preview moved to 0.1.6-alpha.2;npm ls -g @deepseek-ai/dshshows 0.1.2-* ~ 0.1.6-*):dsh plugin --profile web add npm:@kenz1117/dsh-ui-usage-billing@latestDSH 0.1.0-rc.8 ~ 0.1.1-rc.2 (legacy hosts; this line is frozen —
stablepoints permanently at the final v1.1.17, so existing installs keep working but receive no further releases; rationale and the formal EOL trigger are in COMPATIBILITY.md):dsh plugin --profile web add npm:@kenz1117/dsh-ui-usage-billing@stable
Alternatively, add it to the host cordis.patch.yml by hand:
- insert:
- id: ui-usage-billing
name: '@kenz1117/dsh-ui-usage-billing'
After the host starts, the billing entry appears above the sidebar Settings. No extra configuration is needed; when sessionPersistence is available it aggregates real usage automatically.
⚙️ How it works
The plugin has a server side and a browser side:
Browser Server (Node)
│ │
├─ GET /api/billing/usage-stats ────────▶ ├─ sessionPersistence walks persisted session logs
│ ├─ attributes a call to its preceding request/header model
│ ├─ buckets tokens by cache hit / miss
│ └─ estimates cost (CNY) from the live rate table
├─ GET /api/billing/pricing ────────────▶ ├─ live USD→CNY rate and model prices
├─ GET /api/billing/balance ────────────▶ ├─ DeepSeek official balance API (credentials seam)
├─ llm.models health probe ─────────────▶ └─ returns aggregated stats JSON
└─ renders the dashboard
- Server (
src/index.ts): injectswebServer,sessionPersistenceandcredentials, and registersGET /api/billing/usage-stats,/api/billing/pricing,/api/billing/balance,/api/billing/subscriptions,/api/billing/relay-quotas. The aggregator caches folded results per session: each LLM call is attributed to the model of its precedingrequest/header, tokens split into cache-hit / cache-miss buckets, dates bucketed by the local timezone; a log file with unchanged mtime+size reuses its cached fold, only written sessions are re-folded, and the whole document has a 5s TTL to coalesce heavy polling. Every successfully folded session is also atomically written to an independent durable usage ledger, so permanently deleting a session no longer removes its historical cost or tokens. Aggregation logic lives insrc/aggregate.ts. - Browser (
src/client/): requests the endpoints above to render the dashboard and probes each provider connection viallm.models. Until real data arrives it shows an all-zero empty snapshot, never fabricated samples.
💡 Billing details
The rate table (src/client/pricing.ts) stores each model in its native currency: domestic providers enter CNY directly, overseas providers enter USD. Cost is computed and displayed in CNY uniformly — USD models convert via the live rate, domestic models never pass through a rate. At startup the server fetches the live rate and model prices (src/pricing-fetch.ts): USD→CNY prefers the Tencent Finance quote (keyless, reachable in China), falling back to open.er-api then the built-in default; it then refreshes every 6 hours, and the rate-table modal shows a "today's rate" marker plus live / built-in badge. The display currency follows the user: switching ¥ / $ converts each per-1M-token unit price via convertUnitPrice at the live rate (falling back to the native currency when the rate is unavailable).
cost (CNY) = (missInput × p_input + cacheHit × p_cacheHit + output × p_output) / 10⁶
—— prices in native currency; USD models convert at the live USD → CNY rate
input in the stats is total input (cacheHit + cacheMiss); estimation splits it into hit / miss to avoid double counting. Models with two-band billing are mixed by DEFAULT_PEAK_SHARE (default 0.5); weekends (Beijing Sat/Sun) are charged at the off-peak rate all day.
Supported models (2026-08-21 lineup, OpenAI-compatible)
| Provider | Models |
|---|---|
| DeepSeek | V4.1 Flash, V4 Pro (priced per official change boundary: base tier → peak/off-peak v1 → weekend off-peak) |
| Zhipu AI | GLM-5.3, GLM-5.2, GLM-5.1, GLM-5, GLM-5-Turbo, GLM-4.7, GLM-4.6, GLM-4.5-Air, GLM-5V-Turbo |
| Aliyun | Qwen3.8 Max, Qwen3.7-Max, Qwen3.7-Plus, Qwen3.7-Flash, Qwen3.5-Plus, Qwen3.5-Flash, Qwen3-Coder 480B |
| Doubao | Seed-2.0 Pro, Seed-2.0 Mini, Seed-1.6 |
| Moonshot | Kimi K3, K2.7 Code, K2.7 Code HighSpeed, K2.6, K2.8 Preview |
| Xiaomi | MiMo V2.6 Pro, MiMo V2.6 Flash, MiMo V2.6 Pro UltraSpeed |
| MiniMax | MiniMax-M3, MiniMax-M2.7, MiniMax-M2.7-highspeed |
| Baidu | ERNIE-5.1 |
| Tencent | Hunyuan T1, Hunyuan Hy3 |
| 01.AI | Yi-Lightning |
| StepFun | Step 3.7 Flash |
| iFlytek | Spark 4.0 Ultra (plan-based)¹ |
| SenseTime | SenseNova 6.5 (beta)¹ |
| Baichuan | Baichuan M3-Plus |
| OpenAI | GPT-6 Astra, GPT-5.6 Sol / Terra / Luna |
| Gemini 3.1 Pro, 3.6 Flash (Standard / Flex two-band, Flex = −50%) | |
| xAI | Grok 4.7, Grok 4.6, Grok 4.3 |
| Meta | Llama 4 Maverick, Scout |
| Other | Unified fallback pricing for uncatalogued models |
¹ iFlytek and SenseTime have not published per-token prices — the table shows estimates; cost is 0 when these models go through a subscription channel (coding / token plan / opencode), and recalibrates automatically when official pricing is published. Subscription channels align with pi-ai built-in providers (kimi-coding, zai-coding-cn, opencode, opencode-go, qwen/xiaomi token-plan regional variants), overridable via
subscriptionProviders.
To add a model: append an entry to BUILTIN_MODEL_CATALOG in src/builtin-catalog.ts (key aliases live in BUILTIN_MODEL_KEY_ALIASES in the same file; the catalog is built only into the node half and served to the client from the host via /api/billing/pricing).
🔌 HTTP API
The public HTTP endpoints and field definitions are documented in source: GET /api/billing/pricing, /api/billing/balance, /api/billing/usage-stats, /api/billing/subscriptions, /api/billing/relay-quotas (see src/index.ts, src/aggregate.ts, src/relay.ts). The usage-stats payload carries bySite (relay-attributed usage distribution: site:<origin> / direct:<provider> / unknown) and unpricedModels (ids of models with no price); relay-quotas returns quotas plus diagnostics (per-route origin / kind classification, for "why is my relay not showing"). All endpoints accept loopback requests only (peer socket address + Host header verified).
⚙️ Configuration
| Field | Default | Description |
|---|---|---|
statsPath |
unset | Absolute path to a fallback .dsh-usage-stats.json (used when sessionPersistence is unavailable) |
ledgerPath |
<harness home>/.dsh-usage-ledger.json |
Independent durable ledger path; stores folded metrics only (no message bodies or session titles), so deletion does not erase recorded usage. The default root follows the host harness home (DSH_HOME env first, falling back to ~/.dsh), so isolated environments never share ledger data (issue #52) |
balanceApiKeyEnv |
DEEPSEEK_API_KEY |
Credential ref for the DeepSeek balance query; only used as a fallback when llm-pi-ai has no apiKeyEnv for deepseek |
subscriptionProviders |
11 built-ins (incl. tencent-token-plan) |
Subscription (coding / token plan) provider id list — tokens counted, cost 0; aligned with the subscription-card recognition |
routeAliases |
not set | Historical route aliases (old provider route name -> current route): renamed/deleted routes relocate into their channel instead of the "unknown" bucket. Example: { "deepseek-official": "tencent" } |
modelKeyAliases |
not set | User model aliases (log model id -> billing catalog key, value must be an existing MODEL_CATALOG key): bind uncatalogued ids without waiting for a release. Example: { "hy4-preview": "hunyuan" } |
monthlyBudget |
unset | Default monthly budget (CNY); sent with usage-stats as the budget bar's initial amount (user UI settings take precedence and persist locally) |
lowBalanceThreshold |
50 |
Low-balance alert threshold (CNY); sent with usage-stats, alerts once a day when any provider's CNY balance is below it |
trustedHosts |
unset | Extra host names allowed through the Host-header check when DSH runs behind a reverse proxy (e.g. ['llm.example.com']); empty by default = behaviour identical to previous releases. Consulted only after the peer-socket loopback check has passed, so it widens only the second, defence-in-depth layer; exact host match, case- and port-insensitive, with no suffix or wildcard semantics |
subscriptionPlans |
auto-detect | Subscription quota adapter whitelist ({ provider, baseUrl?, region? }); when unset, auto-detects all subscription providers from llm-pi-ai (queries those with a quota API, marks the rest) |
declaredEndpoints |
unset | Declared endpoints ({ displayName, origin, path, fields?, windows?, raw? }): self-declare balance/quota interfaces for providers absent from the built-in table, writing only dot-paths ("where the number is") with no expressions; the request URL is built from the matched same-origin provider's origin and safety bounds (single-slash absolute path, GET only, reject cross-origin redirects, response-size/timeout caps, credentials only from the matched provider's own apiKeyEnv) are enforced by src/declarative.ts |
reconcilePath |
<harness home>/.dsh-usage-reconcile.json |
Balance-delta reconcile baseline path (default root also follows DSH_HOME / ~/.dsh); cross-checks the official (DeepSeek-direct only) balance change against the local ledger's official-channel cost for the day, and flags a drift above the threshold (0.3 CNY and >15%); top-ups / grants / currency changes reset the baseline instead of alerting |
🛠 Development
Requirements: Node.js ^22.19 || >=24, pnpm.
pnpm install
pnpm --filter @kenz1117/dsh-ui-usage-billing bundle # builds lib/index.js and lib/client.js
npx vitest run packages/client/ui-usage-billing/tests # unit tests
📦 Release
This package is a standalone npm package that other DeepSeek Harness hosts can install once published.
npm publish --access public
The host discovers the browser side automatically via the dsh.client declaration (platform: web) and the exports["./client"] bundle in package.json — no registry registration needed.
🔐 Permissions & Compatibility (DSH STORE)
- Permission level: high: reads durable session logs (files), calls official multi-vendor / subscription / balance / pricing APIs (network), reads
apiKeyEnvvia the credentials seam (credentials), writes the ledger and stats snapshot under the harness home (DSH_HOME/~/.dsh) (persistent state); no command execution / shell. - Update channel:
user-reviewed: with file / network / credential capabilities, DSH STORE requires local manual confirmation on every install; review the repo, pinned commit, lifecycle scripts, and impact scope before installing. - Compatibility: the preview line (npm
latest/alpha, 1.2.x — kept above the stable line to kill the version inversion) targets DSH0.1.2~0.1.6(hostlatestcurrently at 0.1.5-rc.2, verified on real hardware; 0.1.6-alpha.1/2 declared compatible — zero code changes in the plugin's dependency packages); the stable line (npmstable, 1.1.x, frozen, final v1.1.17) targets legacy hosts0.1.0-rc.8~0.1.1-rc.2. Per-version declarations live inpackage.jsonunderdsh.compatibility; the two-line mapping and monitoring mechanism are documented in COMPATIBILITY.md. Node.js^22.19.0 || >=24.0.0. - Lifecycle: no
preinstall/install/postinstall/prepare(ready on install). - No impersonation: adds only its own entry id
ui-usage-billing;@deepseek-ai/dsh-*packages arepeerDependenciesonly (no reinstall / replace / shadowing of official components); the package uses the third-party namespace@kenz1117/*. - Build artifacts: runtime files
lib/*andcordis.patch.ymlare committed at the pinned commit and declared infiles. - Source anchor: sources are locked to a pinned commit on the GitHub default branch and traceable. DSH STORE automation re-reads the default-branch HEAD roughly every 8 hours as the new pinned commit and decides re-review by SemVer change.
🤖 Model Experience
None. This plugin is a pure UI surface: it registers no tools, injects no system prompt, writes no model-visible events to the session log, and touches no session KV cache; usage statistics are aggregated by the server from existing session logs, whose content is owned by other packages.
⚠️ Known Limitations and Deferred Work
- Balance queries cover DeepSeek / Moonshot (Kimi) / StepFun / SiliconFlow / xAI / Zhipu GLM (Z.ai CN region) / Tencent Cloud TokenHub (token-plan quota): the first six use a standard Bearer API key; Tencent Cloud uses the cloud-API key pair (
<SecretId>:<SecretKey>, TC3-signed management API). Other providers expose no public balance API or need non-Bearer auth (Xiaomi MiMo via console Cookie, SenseTime via AccessKey signing, MiniMax/Doubao via quota or AK/SK), so they currently show "not configured"; the extension point issrc/balance.ts(add a querier per provider balance API). - Relay quota depends on upstream private schemas: New API / Sub2API interface fields are not public, so an unreadable station is labeled "no quota" rather than fabricating an amount; if a station's response fields differ, extend the parsers in
src/relay.ts. An "unknown route" means that route no longer exists in the current provider config (renamed / deleted); historical call data is not lost — re-adding the same-named route restores attribution automatically. - Overspend notifications rely on the browser Notification API: when permission is denied or the platform lacks support, only the in-UI red-pulse fallback remains — no host-level notification channel; notifications are capped at once per day.
- Session rows are not navigable: clicking a session row does not open that session (cross-plugin navigation needs a host session-selection channel); sessions are capped at 100 rows and the panel shows the top 20.
- Cost is a catalog estimate: models without published per-token pricing (iFlytek, SenseTime, Xiaomi) use estimates (feature-list footnote ¹); official billing is authoritative.
- The ledger starts at its first successful aggregation: sessions permanently deleted before the upgrade and absent from the old snapshot cannot be recovered. Manually deleting
.dsh-usage-ledger.jsonand its.bakclears independently retained history. Only calls successfully observed by this plugin are retained.
❤️ Contributors
- @lucagiftzek — rate-table CSS polish (PR #59),
trustedHostsreverse-proxy support (PR #60), currency preference persistence (PR #58), rate-table search (PR #67), peak/off-peak indicator dots with pin-to-composer (PR #68), and the EUR display currency with language decoupling (PR #70) - @hwangjunjie — Tencent Cloud TokenHub / Token Plan subscription quota adaptation (
src/tc3.ts), provider-first channel grouping with gateway badges, and therouteAliases/modelKeyAliasesconfig (PR #35) - @ciphoo — MiniMax CN Token Plan quota support (PR #5),
minimax-cnsubscription key wiring (PR #12), a concurrent-ledger-writeMoveFileExW EPERMfix on Windows (PR #11) - @fabulousyuann-tech — durable ledger that retains usage after session deletion (PR #8)
- @hi-fangj — hover tooltip with the exact per-day token breakdown on the token daily chart (PR #21), the live-cost capsule toggle (PR #22), the per-model view and legend focus for the token daily chart (PR #23), and the per-model comparison curve in the perf panel (PR #24)
📄 License
MIT © 2026 KenZ (kenz1117)
Links
More in this category
bowenliang123/dsh-context★ 1573
DSH context insight panel: Context dashboard + /context command + Context browser — one-stop context lifecycle management with categorized composition, content details, evolution trends, compaction/injection events, and stats.
Han-1413141/dsh-cost-meter★ 349
Per-session and daily API cost, budget with usage %, official balance, history dashboard, and one-click official price sync with peak/off-peak pricing.
wssfk12138/dsh-damage-pulse★ 224
Tracks DeepSeek token usage, per-call and session costs, and account balance with cache-aware charge animations in the DSH Web UI.
zh667/TokenLedger★ 202
Sidebar usage panel that attributes tokens to the relay site that served each request, read from your existing provider config: today/month/all-time totals, per-site and per-model breakdowns, a year activity heatmap, and New API / Sub2API / DeepSeek balances.
Ychris12138/dsh-usage-stats★ 169
Multi-provider usage dashboard with provider/model token breakdowns, calendar drill-downs, account balances, and OpenCode Go / Z.ai subscription quota tracking.
PolinniZhong/dsh-personal-center★ 120
Personal center for DeepSeek Harness: cross-session usage statistics, per-model cost estimation, global custom instructions, a global font-size adjuster, a data-driven desktop pet with bitmap & vector skins, and a conversation status overview, all local and offline.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.