DeepSeek Harness plugin

dsh-gauge

Cache-hit rate, token usage, and cost estimates for the DeepSeek Harness Web UI.

Jump to install

Source facts

Repository
noone89A/dsh-gauge
Latest update
Aug 15, 2026
Category
Usage & Billing
GitHub stars
5
Format
plugin
Catalog evidence
Upstream dsh.bundle evidence
Evidence path
package.json#dsh.bundle
Checked against
0.1.0-rc.8
Upstream check date
2026-08-20

This evidence comes from the upstream catalog. This site has not installed, run, or security-reviewed the plugin.

Install

Start with a prompt that asks an agent to review the GitHub repository and source. Switch to the command if you want to install it yourself.

Copy this prompt into DSH, Codex, or another agent and ask it to review the GitHub repository and source first.

Do not install or run any commands yet. Read this plugin's GitHub repository, README, and relevant source code. Then answer the questions below clearly and directly so I can decide whether it fits my needs:

1. What is this plugin, and what problem does it solve?
2. Who is it for, and what are its typical use cases?
3. How is it used after installation? Include one minimal example.
4. What known limitations or privacy, security, compatibility, or maintenance risks does it have?
5. Give a clear recommendation: recommend, conditionally recommend, or do not recommend, with reasons.

Distinguish statements documented by the repository, inferences from source code, and unknowns. If evidence is insufficient, say so explicitly. Do not guess or simply repeat the README.

GitHub: https://github.com/noone89A/dsh-gauge
Plugin: dsh-gauge
Author: noone89A

Check the source files

Read the README and other files from this plugin directory before installing.

File explorer4 files
README.en.mdSource · read only
README language

dsh-gauge

中文 | English

Accurate cache-hit rate, token usage, and cost estimates for the DeepSeek Harness Web UI.

The official stats line rounds the cache-hit rate to an integer — Math.round turns 99.8% into a misleading 100%. dsh-gauge replaces it with a precise one-decimal (configurable) figure, adds a per-bucket token breakdown, a session usage panel, and a session cost estimate that automatically follows the official DeepSeek price changes (using the official API).

Features

  • Precise cache-hit ratecacheRead / (cacheRead + uncached + cacheWrite) with a configurable

number of decimals (default 1), so 99.8% stays 99.8%.

  • Bucket breakdown — cache-hit / cache-miss input tokens and output tokens. The write bucket is

automatically hidden when it is 0 (the opencode-go/pi-ai adapter never reports cache-write tokens, so it is always 0 in practice).

  • Cost estimate + price-change comparison — estimated from actual usage × model prices

(deepseek-v4-flash / deepseek-v4-pro, auto-detected from the conversation). Before the new official prices take effect it shows current cost + upcoming price + projected increase; at the switch moment it automatically moves to the new prices.

  • Per-request peak/off-peak billing — the estimate is not a "current time" snapshot: every

assistant message is priced by its own timestamp, so tokens consumed during peak hours are billed at the peak rate and off-peak tokens at the discounted rate, then summed.

  • Peak-hour badge — Beijing 09:00–12:00 / 14:00–18:00 are DeepSeek's peak-pricing windows. The

stats-row tail shows peak/off-peak according to the current Beijing hour (also after the price switch).

  • Usage panel — a ⓘ trigger in the session header opens the session's model, hit rate, billed

input, per-bucket totals (full numbers by default), context occupancy, and cost estimate (with the post-switch comparison).

  • Dual-row stats (official metrics + precise usage) — the first row keeps the official session

metrics (turns/steps, LLM/tool-call time, TTFT avg, tok/s) in a replica of the official styling (line height deliberately tightened so the two rows read as one block); the second row is the plugin's precise usage (hit rate, buckets, output, cost, peak/off-peak badge). With replaceNativeStatsLine: false the official native row (including its usage segment) stays.

  • Bilingual & currency-aware — when the UI is English, all text switches to English and the cost

is estimated in USD with the international price table. Locale and currency follow live changes, no restart needed.

Screenshots

!Stats line !Usage panel

Install

# One command (recommended): dsh plugin runs pnpm add and automatically
# appends any dependency that declares dsh.bundle to dsh.profile.bundles
dsh plugin --profile web add dsh-gauge

# Manual: cd ~/.dsh/profiles/web && npm install dsh-gauge, then edit
# profiles/web/package.json and add "dsh-gauge" to dsh.profile.bundles

# restart
dsh web

You should see the precise stats row under the composer and the ⓘ usage trigger in the session header.

> Local development: install from source instead — pnpm add file:C:/Object/dsh-plugin/dsh-gauge > (run npm run build after source changes; useful when tuning src/config.ts prices/peak windows).

Works out of the box & the config card

After install and restart everything works with zero configuration:

  • Two stats rows under the composer: the precise cache-hit rate (99.8% stays 99.8%), bucket

breakdown, output tokens, estimated cost, and a peak/off-peak badge;

  • The ⓘ usage panel in the session header: full token totals, context occupancy, model, cost and

the post-switch price comparison;

  • UI copy and the cost currency follow the interface language automatically.

The dsh-gauge card under Settings → Plugins → configurable: current DSH versions hard-code the plugin settings exposed to web clients in an allowlist (dsh-host-apiproxy's WEB_SETTINGS_NAMESPACES), so a third-party plugin needs a one-time gauge allowlist entry for the card to show up (steps in Troubleshooting). Not adding it affects nothing else — alternatively edit cordis.patch.yml directly (see Configuration).

> Local development: replace step ② with pnpm add file:C:/Object/dsh-plugin/dsh-gauge — after > source changes run npm run build and restart; useful when tuning src/config.ts prices/peak > windows.

How it works

  • The metrics row registers into the conversation.composer.dock slot at priority: -1 in the

official stats cell, shadowing the native row; the usage row is added at order: 1. With replaceNativeStatsLine: true (default) the native usage segment is replaced by the precise row; with false the native row (including its usage segment) stays.

  • Token totals come from the tokenUsage projection (@deepseek-ai/dsh-token-meter); context

occupancy from contextPressure.

  • The cost estimate pages the full session history (sessions.history): each finalized assistant

message carries its own completion time and usage, so every request is priced with the rate applicable at that moment (peak or off-peak for the new scheme; flat for the current pre-change prices) and the results are summed — history before "load earlier" is priced precisely too, so a session with 200M hit tokens never shows a few cents of cost.

  • The active model is derived from the last assistant message of the full history (source.model;

without a connection surface it falls back to the trajectory view's requestConfig.model), or fixed via the model config key.

  • After compaction, old events are replaced by summaries: the estimate and the official

tokenUsage projection are based on the same event set, so they stay consistent (the official projection discards compacted usage the same way).

Configuration

Most users need zero configuration — the plugin works out of the box. The keys below can be tweaked through Settings → Plugins → dsh-gauge — saved changes apply immediately, no restart needed (the one exception is replaceNativeStatsLine, which decides the shadow registration and needs a restart), or by patching the gauge row in ~/.dsh/profiles/web/cordis.patch.yml:

KeyDefaultMeaning
showPricetrueShow the cost estimate (stats line + panel)
showPeakBadgetrueShow the Beijing peak-hour badge in the stats line
replaceNativeStatsLinetrueReplace the official stats row (false keeps the official native row)
hitRateDecimals1Decimals for the cache-hit percent (0–2)
tokenDecimals1Decimals for the compact K/M token format (0–2)
panelExactTokenstrueShow full token totals in the panel (false uses K/M abbreviations)
currencyautoauto follows the UI language (English → $ + USD plans, otherwise ¥ + CNY plans); or set ¥ / $ explicitly
modelautoauto derives the model from the session; or set a model id explicitly

Developer-only (not exposed in the UI) — the peak windows peakHours, the CNY price table pricePlans, the USD price table usdPricePlans, the effective-date nextFrom, and the off-peak factor offPeakFactor are built into src/config.ts with DeepSeek-official defaults. Change them by editing that file; ordinary users should not override them.

# ~/.dsh/profiles/web/cordis.patch.yml — flat loader patch entries
- id: gauge
  config:
    showPrice: true
    showPeakBadge: true
    hitRateDecimals: 1
    tokenDecimals: 1
    panelExactTokens: true
    currency: auto

Built-in prices & the price switch — the current flat prices (before the switch) and the new peak/off-peak official prices are baked into src/config.ts (pricePlans for the CNY table; usdPricePlans for the international USD table). The estimate walks each assistant message and prices it by its own timestamp (peak rate during peak windows, half price otherwise), and automatically switches to the new prices at nextFrom. There is no separate "cache write" bucket in the official price list.

> The cost is an estimate; the official bill is authoritative. Patch entries are flat > {id, ...} loader entries — there is no update:/disable: wrapper; writing - update: is > rejected with an error. If the config card is missing, see the whitelist note in Troubleshooting.

Comparison with dsh-usage

dsh-usage (v0.1.0) appeared the same day this plugin was written, so here is an honest, source-level comparison.

Dimensiondsh-usagedsh-gauge
Cache-hit rate (%)— no hit-rate figure at all, only raw cache tokensprecise hit rate with configurable decimals (99.8% stays 99.8%)
Peak/off-peak pricing— no peak/off-peak handling; bundled rates are the 2026-04-24 USD table, so the estimate goes stale after the 2026-08-16 price changeper-message-timestamp peak/off-peak pricing, current-vs-next price comparison with automatic switch at the effective date
Granularityper-turn readout under each assistant message + Settings Usage page (52-week heatmap, provider/model totals, cross-session)session-scoped stats row (replaces the native row) + header ⓘ panel (model, buckets, context occupancy, cost)
Cost accountingreplay-derived modelCost projection, effective-dated rates, coverage notes for unpriced/without-usage callstokenUsage projection × built-in price tables (CNY + USD)
Data sourcedurable log replay (survives paging/compaction)tokenUsage/contextPressure projections
LanguageEnglish-only UI textbilingual (zh/en)
Native rowadds its own rowshadows the official row by default
Cache-write bucketpriced as its own buckethidden while 0

In short: dsh-gauge is a precision/efficiency gauge — the exact cache-hit rate the official UI rounds away, peak-hour awareness, and a live cost check that follows the new peak/off-peak pricing without a maintenance burden. The two are complementary and can be installed side by side — different slots, different ids, no conflict.

Troubleshooting

  • "写入" (write) is always 0 — by design: some adapters never report cache-write tokens, so the

bucket is hidden while zero. If a future provider reports writes, it reappears.

  • Price/cost looks wrong — the estimates use the built-in price tables in src/config.ts; adjust

pricePlans/usdPricePlans there, or set currency/model explicitly. The cost is an estimate; the official bill is authoritative.

  • Changes don't show up — except replaceNativeStatsLine (which decides the shadow

registration), saved config changes apply immediately; if you changed cordis.patch.yml instead, restart dsh web.

  • No dsh-gauge card under Settings → Plugins → configurable — current DSH versions hard-code

the namespaces exposed to web clients in dsh-host-apiproxy's WEB_SETTINGS_NAMESPACES allowlist (the official comment marks plugin self-registration as deferred work); a namespace absent from the allowlist is never returned by settings.describe even when its owner registered it, so the card stays hidden. Add gauge to the allowlist in the host installation and restart dsh web:

``js // <dsh install>/node_modules/@deepseek-ai/dsh-host-apiproxy/lib/index.js const WEB_SETTINGS_NAMESPACES = [ "agent-loop", "shell", "locale", "permission", "ui-conversation", "ui-theme", "web-search-deepseek", "gauge", // ← add this line ]; ``

Without the allowlist entry the stats row and usage panel still work — only the config card is hidden (you can still configure via cordis.patch.yml). The requirement disappears once DSH opens plugin self-registration.

  • The page fails to boot — make sure lib/client.js is the bundled client artifact (run

npm run build, which produces the __ModuleLoader__.load format; a raw tsc ESM output breaks the page).

Development

pnpm install
pnpm run typecheck
pnpm test
pnpm run build

npm run build compiles with tsc and then bundles the client entry with scripts/build-client.mjs into the DSH client-module loader format.

License

MIT