Back to home

htq20080119

dsh-token-stats

Token usage statistics plugin for DeepSeek Harness — per-window consumption metrics with an enable/disable switch, right in Settings.----------DeepSeek Harness 的 Token 用量统计插件:按时间窗统计消耗指标,设置页内随时启停。

Stars
0
Language
JavaScript
Created
Aug 15, 2026
Updated
Aug 15, 2026

Introduction

📊 dsh-token-stats

Token usage statistics plugin for the DeepSeek Harness web profile

English · 简体中文

license version platform language PRs welcome

A Settings-page plugin that shows token consumption across all sessions, bucketed into time windows — with an enable/disable switch that persists to settings.yaml and hot-applies. No restart required.

🛡️ Community plugin — this is an independent, community-maintained plugin for the DeepSeek Harness. It is not an official DeepSeek project and is not affiliated with or endorsed by DeepSeek / the DeepSeek Harness team.


✨ Features

🪟 8 time windowstoday · 3d · 7d · 15d · 30d · half-year (180d) · 1 year (365d) · all-time
📈 9 metrics per windowtotal, input, output, cache-read, cache-write, requests, cache-hit requests, cache-hit rate
🗂️ Summary cardsall-time totals: input / output / cache read / cache write / hit rate / requests
🎚️ Enable / disable switchright in the page — persisted to settings.yaml, hot-applied in seconds
🔄 Auto refreshpolls every 30s, plus a manual refresh button
📚 Official accountingsame (turn, step) dedup as the built-in tokenUsage session projection

📸 Preview

Screenshot placeholder — replace with a capture of Settings → "Token 用量".

⚠️ Sample data below is illustrative only — not real usage.

The page shows summary cards (all-time totals) plus a per-window table:

Time windowTotalInputOutputCache readCache writeRequestsHit requestsHit rate
Today1.24M1.18M56.2K1.12M0878596%
3 days3.87M3.71M161K3.55M025424896%
7 days8.93M8.62M312K8.31M058957797%
15 days19.4M18.8M641K18.3M01,2431,22197%
30 days38.7M37.5M1.22M36.7M02,4672,43197%
Half year214M208M5.9M205M013,98813,81298%
1 year412M401M10.8M396M026,53126,21498%

📦 Installation

The plugin is an external DSH package loaded through the web profile.

1. Make the package resolvable

Add it to the profile's package.json with pnpm:

# local development (symlinks the source — edits apply immediately)
pnpm --dir "C:\Users\<you>\.dsh\profiles\web" add "link:<path-to-this-repo>"

# or straight from GitHub (installs a packed copy)
pnpm --dir "C:\Users\<you>\.dsh\profiles\web" add "github:<owner>/dsh-token-stats"

The web profile lives under %USERPROFILE%\.dsh\profiles\web by default.

2. Mount the entry

Append one entry to the profile's patch layer (cordis.patch.yml):

- insert:
    - id: token-stats
      name: dsh-token-stats
      config: {}

The patch layer is hot-watched — the plugin mounts within seconds, no restart.

🚀 Usage

  1. Open Settings → "Token 用量" (refresh the page once so the client bundle is picked up)
  2. Read the summary cards and the per-window table (auto-refreshes every 30s)
  3. Use 停用 / 启用 in the page header to toggle aggregation:
ActionEffectPersisted to
停用 (disable)stops aggregating; page shows the disabled statesettings.yamltoken-stats: { enabled: false }
启用 (enable)resumes aggregation and the stats tablesettings.yamltoken-stats: { enabled: true }

The switch applies immediately — no restart needed.

🛠️ Development

# smoke test: host fold logic + client bundle registration
node smoke-test.mjs
FileRole
lib/index.jsHost half — zero third-party imports (see Architecture)
lib/client.jsClient bundle — classic window.__ModuleLoader__.load({ id, factory }) script; the id must equal the loader entry name

Applying changes: host code sits behind Node's ESM cache (keyed by resolved URL) — restart the web app to pick up host changes; client bundle changes only need a page refresh.

🧱 Architecture

  • Data sourceassistant/message events carry data.usage { inputTokens, outputTokens, cacheReadTokens? } (the opencode-go gateway reports no cacheWriteTokens); uncachedInput = inputTokens - cacheReadTokens.
  • Host endpointsGET /token-stats{ enabled, generatedAt, windows[] }; POST /token-stats/config {"enabled": bool} flips the switch through the ctx.settings service into the hot-watched settings.yaml.
  • Zero-dependency host — profile plugins resolve bare specifiers with no fallback, so lib/index.js imports nothing (the settings namespace schema is a hand-rolled, schemastery-compatible object).
  • package.json must export ./package.jsondsh-client-modules resolves the client bundle via require.resolve("<pkg>/package.json"); without that export the package is negative-cached and the client bundle 404s until a web-app restart.

🤖 Model Experience

None — the plugin never assembles or sends a provider request. It only reads persisted session logs and serves a Settings page, so it adds no prompt, message, schema, tool, or model call.

KV Cache effect

None — no provider request is made; cache-read / cache-write figures are read-only metrics reported by the gateway in session logs.

⚠️ Known Limitations

  • web/deepseek-search-llm-request events carry no usage — search-tool tokens are not counted (matches the official projection).
  • Cache-write shows 0 when the gateway does not report it.

📄 License

MIT © 2026 本源不爱onani