@chengwd96/dsh-usage-analytics
v0.1.0
Published
Per-provider/per-model model usage statistics with GUI charts for the DeepSeek Harness (dsh web)
Maintainers
Readme
@chengwd96/dsh-usage-analytics
Per-provider / per-model model usage statistics for the DeepSeek Harness web GUI. Adds a 用量统计 settings page with:
- Grand totals (requests, input / output / cache-read / cache-write / reasoning tokens, RPM / TPM, estimated cost)
- A daily token trend (stacked input / output / cache segments; per-hour view on "今日")
- An activity heatmap with 按日 / 按周 / 累计 modes — every column is a full natural week (Mon–Sun), the rightmost column is the current week, and future days render as gray cells until reached; hovering a cell reveals the date plus tokens and requests
- Per-provider and per-model views with expandable daily trends
- A pricing settings tab: DeepSeek official preset (idle/peak pairs, weighted-average tier), CNY/USD switching with a configurable rate, and estimated cost everywhere
Token values auto-format as K / M / B / T / Q with precise hover tooltips. The whole dashboard is also validated as a runtime (dynamic) plugin inside the harness; this package is its durable, independently published form.
Installation (once published)
pnpm add @chengwd96/dsh-usage-analyticsThen add the plugin row to the harness composition (cordis.yml or a profile patch layer):
- insert:
- id: usage-stat
name: '@chengwd96/dsh-usage-analytics'dsh web discovers the browser half automatically through the dsh.client manifest and exports["./client"], and the Remote methods through exports["./remote"].
Local (pre-publish) mount
The package was end-to-end verified against a running dsh web instance: the
Remote stats/statsProgress/clearSnapshot/pricing/pricingSave methods
answered with real per-provider/per-model aggregates, and the storage-domain
snapshot + pricing state persisted to ~/.dsh/storages/usage_stat.json. To
mount a local checkout before publishing:
# 1. resolve the package from the web profile
ln -s /path/to/dsh-usage-analytics ~/.dsh/profiles/web/node_modules/dsh-usage-analytics
# 2. add the plugin row to the profile patch
# (edit ~/.dsh/profiles/web/cordis.patch.yml, then restart `dsh web`)The host half requires storageDomain and sessionQuery, both provided by the
dsh-web-app bundle; no extra host configuration is needed.
Architecture
- Node half (
src/index.ts):UsageStatService extends TypertRemoteServiceaggregatesassistant/message.usageattributed to the currentrequest/contextroute (provider/model) across every session log. A warm cache builds at plugin mount (startup prewarm), stays hot through thesession/eventappend feed, and persists a cross-restart snapshot in actx.storageDomainKV domain so a later start restores totals and reconciles only the seq delta. Pricing state is persisted as the domain global. - Remote surface (
@Remoteonsrc/index.ts, generated intolib/typert.*):stats,statsProgress,clearSnapshot,pricing,pricingSave. The browser half calls these through the generatedctx.remote.usageStatnamespace. - Browser half (
src/client/): registers thesettings.sectionentryusage-statsand renders the dashboard as React + CSS Modules; the CSS is inlined into the client bundle at build time. - Pure domain (
src/usage.ts): fold, bucketing, snapshot serialization/rebuild, transpose, heatmap series, cost estimation, and formatting — free of cordis imports, unit-tested intests/. - Durable domain (
src/spec.ts):usageStatDomainSpecdeclares the snapshot table and the pricing global with zod validation at the storage boundary.
Development
pnpm install
pnpm run build # tsc types into lib/types + tsdown bundles lib/ + regenerates lib/typert.*
pnpm run gen:typert # regenerate Typert artifacts only (needs DSH_HARNESS_ROOT)
pnpm run typecheck
pnpm testThe client bundle follows the harness web protocol: lib/client.js is a closure factory handed to window.__ModuleLoader__.load, with platform modules (react, @deepseek-ai/cordis, …) kept external and resolved from the shell module table. Build config is derived from the harness's packages/client/tsdown.client.ts (MIT).
The Typert artifacts (lib/typert.host.js, lib/typert.remote-client.js, and their .d.ts) are generated by scripts/gen-typert.mjs, which stages a minimal workspace (.typert-workspace/, gitignored) mirroring the harness generator's fixture pattern: the generator only analyzes packages under a <root>/packages/ tree, so the script copies the package source into that layout and resolves @deepseek-ai/dsh-typert-protocol through a local declaration shim. Set DSH_HARNESS_ROOT to your harness checkout if it is not /home/cheng/git-project/deepseek-harness.
Known Limitations and Deferred Work
- Session disposal is not yet tracked: a deleted session's usage lingers until a forced full rescan.
- Cost estimation uses the pricing preset and user-configured per-model prices; models without a configured price are counted as zero.
- The heatmap capacity adapts to the container width at render time; a very narrow pane falls back to a 7-column minimum.
