DSH Plugins Marketplace

DSH Plugins

Plugins

/

dsh-token-bill

S

dsh-token-bill

Manifest valid

Live DeepSeek balance and per-hour token costing for DSH: two agent tools read the live balance and the ledger-observed daily charge, then write Markdown/HTML/JSON statements.

hasBundlePatch

dsh-token-bill

English | 中文

Real-time token billing for DeepSeek Harness (DSH): the live account balance, today's actual spend, per-hour token counts folded into cost bars, and a Markdown / HTML / JSON statement you can keep.

Two model-facing tools, no UI required, no extra daemon:

  • token_status — live balance, today's observed spend, today's token buckets.
  • token_bill — hourly bar charts, peak/valley split, per-hour detail table, and a written statement.
📊 2026-09-28 token bill
Balance ¥52.9100 · Today ¥4.6900 (ledger-observed)
Tokens 79.65M (input 1.02M · cache hit 78.14M · output 492.7K) · 98.1% cache hit · 716 calls
Busiest hour 15:00 (29.00M tokens) · Costliest hour 15:00 (¥2.3380)

Tokens per hour (6 hours with usage)
00:00 │█████████▃                │ 9.89M
01:00 │███████▂                  │ 7.72M
11:00 │██▆                       │ 2.92M
12:00 │██████████████▇           │ 15.80M
13:00 │█████████████▄            │ 14.33M
15:00 │██████████████████████████│ 29.00M

Cost per hour (calibrated to the observed daily charge)
00:00 │██████▃                   │ 0.5607
01:00 │██▅                       │ 0.2259
...

Why this plugin exists

DSH deliberately treats token counts as measurement, not as a billing record: ctx.tokenMeter reports request pressure, nothing in the harness converts tokens into money, and it ships no price table at all. Meanwhile the three things you actually want are scattered:

What you wantWhere it livesAuthority
Account balanceGET https://api.deepseek.com/user/balance (API-key auth)live, authoritative
What today actually cost$DSH_HOME/.dshw-usage.json balance ledgerobserved, authoritative
Tokens per hour$DSH_HOME/sessions/**/session.v*.jsonl.zstdprovider-reported, exact

dsh-token-bill joins them under one rule: money is observed, tokens are measured. The day's charge comes from the account's own balance movement, and the price table is used only to spread that observed total across the day's hours.

Features

  • 💰 Live balance from the official balance endpoint, falling back to the ledger's last observation (explicitly labelled) when the network fails.
  • 📊 Per-hour token counts read from durable session logs — the four disjoint provider buckets (inputTokens, cacheReadTokens, cacheWriteTokens, outputTokens), not a character heuristic.
  • 🧾 Statements on disk: self-contained HTML with inline SVG bar charts, Markdown for archiving, raw JSON for scripting.
  • ⛰️ Peak/valley aware: Beijing-time peak windows, weekend and statutory-holiday valley rates, and a peak-vs-valley split in the report.
  • 🎯 Exact arithmetic: money is carried as integer 1e-8 units, so sum(hourly amounts) === daily amount is an identity rather than a rounding accident.
  • 🔒 Read-only: the plugin never writes to your ledger, session logs, or credentials.

Install

# from a registry, once published
dsh plugin --profile web add dsh-token-bill

# from a local checkout
dsh plugin --profile web add link:/absolute/path/to/dsh-token-bill

Both tools then appear to the model in new sessions. If your profile does not reload on its own, restart the DSH web server afterwards.

Requirements: Node ≥ 22.12 (the plugin resolves its DSH peers through require(esm)), and a DSH profile with the tools service mounted (any standard Web profile).

The balance ledger

Today's actual charge comes from a ledger at $DSH_HOME/.dshw-usage.json, written by the excellent dsh-whale-widget balance widget — not by this plugin. Each day row records an opening balance, the last observed balance, and accumulated debits and credits:

{
  "openingUnits": 760000000,
  "lastUnits": 5525000000,
  "debitUnits": 388000000,
  "creditUnits": 5000000000,
  "firstAt": 1790529962822,
  "lastAt": 1790580387568
}

Amounts are integer 1e-8 CNY units. The observed charge is the sum of balance decreases, so a top-up adds to creditUnits and can never inflate your spend. If the row also closes (opening − debits + credits = last), a top-up is reported as information; if it does not close, something moved the balance that the ledger could not classify, and the plugin says so rather than quietly reporting a wrong number.

If you do not run that widget, the ledger is simply absent and the plugin degrades to price-table estimates, clearly labelled as estimates — the balance still comes from the live endpoint.

Tools

token_status

ParameterTypeDefaultMeaning
includeLedgerbooleantrueAppend the ledger's path, age, and event count.
includePricingbooleanfalseAppend the peak/valley price table.

Returns day, balance, currency, balanceSource (api or ledger), balanceStale, todayObserved, todayTokenEstimate, totalTokens, inputTokens, cacheReadTokens, outputTokens, calls, ledgerPath, text.

token_bill

ParameterTypeDefaultMeaning
daystringtodayStatement date, YYYY-MM-DD, Beijing time.
daysinteger1Also include a per-day summary for the last N days.
costModeledger | token | bothledgerSee Cost model.
writebooleantrueWrite the statement files to disk.
formatsarray of html | md | json["html","md"]Which statement files to write.

Returns day, amount, amountSource (ledger or token-estimate), currency, balance, totalTokens, calls, activeHourCount, peakTokens, valleyTokens, files, and the full text rendering.

Files are written to $DSH_HOME/token-bill/ as token-bill-<day>.{html,md,json}. The host process's working directory is the DSH installation itself, so the default is deliberately not process.cwd(); override it with DSH_TOKEN_BILL_DIR or the outDir config.

Data sources

api.deepseek.com/user/balance ──► live balance ─┐
                                                ├──► report ──► bar charts + statement
$DSH_HOME/.dshw-usage.json ─────► observed ¥  ──┤
$DSH_HOME/sessions/**/*.zstd ───► exact tokens ─┘

Balance — GET https://api.deepseek.com/user/balance with Authorization: Bearer <DEEPSEEK_API_KEY>, returning balance_infos[] with total_balance / granted_balance / topped_up_balance per currency. This needs no browser session. The key is read from the DEEPSEEK_API_KEY environment variable (also DSH_DEEPSEEK_API_KEY, DEEPSEEK_KEY) or from refs.DEEPSEEK_API_KEY in $DSH_HOME/.credentials.yaml.

Token usage — every durable assistant/message event carries the adapter-reported usage alongside an epoch-millisecond time, which is what makes hourly accounting possible. Buckets are disjoint exactly as the provider reports them:

  • inputTokens — uncached prompt input (a cache miss)
  • cacheReadTokens — prompt input served from cache (a cache hit)
  • cacheWriteTokens — prompt tokens written into the cache
  • outputTokens — completion tokens, reasoning already included

Session logs are session.v<generation>.jsonl.zstd under $DSH_HOME/sessions/<projectKey>/<sessionId>/, header line first, with each append written as its own checksummed Zstandard frame. Older uncompressed session.v<generation>.jsonl logs are read too.

Cost model

costMode decides where the money number comes from:

ModeDaily amountPer-hour amountstoken estimate column
ledger (default)observed charge from the ledgerapportioned, calibrated to that totalshown
tokenprice-table estimateprice-table estimaten/a
bothobserved charge from the ledgerapportioned, calibrated to that totalshown

In ledger mode the per-hour amounts are computed by largest-remainder apportionment at the statement's own precision, so the hours a statement prints always add up to the total it prints. When the ledger has no observation for a day, the plugin falls back to a price-table estimate and labels it as such — it never presents an estimate as an observed charge.

Peak / valley pricing

Beijing time. Peak (standard) rates apply Mon–Fri 09:00–12:00 and 14:00–18:00. Every other hour, plus all weekend days and all statutory holidays, bills at the valley rate (half the peak rate). Prices are CNY per million tokens, shown as valley / peak:

ModelCache hitCache missOutput
deepseek-flash, deepseek-v4-flash, deepseek-v4-flash-vision-exp, deepseek-chat0.02 / 0.041 / 24 / 8
deepseek-pro, deepseek-v4-pro, deepseek-reasoner0.15 / 0.34.5 / 913.5 / 27

An unrecognised model name falls back to the Flash series so a new model still produces a usable estimate. The statutory holiday list (HOLIDAYS_2026, 34 days) lives in lib/pricing.mjs and can be extended through config when a new State Council calendar is published.

Configuration

Add a config block to the plugin's row in your profile's cordis.patch.yml:

- id: token-bill
  name: dsh-token-bill
  config:
    costMode: ledger        # ledger | token | both
    decimals: 4             # decimals used in printed amounts
    chartWidth: 26          # bar width in terminal charts
    historyDays: 1          # days included in the per-day summary
    writeFiles: true        # set false to never write statements
    timeoutMs: 10000        # live balance request timeout
    outDir: !!js dshHomePath('token-bill')
    sessionsRoot: !!js dshHomePath('sessions')
    # Override or extend the price table (CNY per million tokens):
    # models:
    #   my-model: { hit: { off: 0.01, peak: 0.02 }, miss: { off: 1, peak: 2 }, out: { off: 4, peak: 8 } }
    # Extra statutory holidays, billed at the valley rate all day:
    # holidays: ['2027-01-01']
FieldDefaultMeaning
dshHome$DSH_HOME or ~/.dshDSH home directory.
profile$DSH_PROFILE or webProfile whose in-profile ledger path is also checked.
sessionsRoot<dshHome>/sessionsRoot of the session logs.
outDir$DSH_TOKEN_BILL_DIR or <dshHome>/token-billStatement output directory.
decimals4Decimal places in printed amounts.
chartWidth26Bar width for terminal charts.
costModeledgerMoney source, as above.
historyDays1Days in the per-day summary.
maxBytes134217728 (128 MB)Skip any single session log larger than this.
timeoutMs10000Balance request timeout.
writeFilestrueWhether statements may be written.
modelsbuilt-in tablePrice table override.
holidaysHOLIDAYS_2026Statutory holiday day keys billed at the valley rate.

Architecture

lib/index.js      Plugin entry: name / inject / Config / apply, registers both tools
lib/service.mjs   Orchestration: resolve config -> gather -> fold -> report -> write
lib/account.mjs   API-key discovery, balance endpoint, live-to-ledger fallback policy
lib/ledger.mjs    Read-only reader for $DSH_HOME/.dshw-usage.json
lib/logs.mjs      Session enumeration, multi-frame zstd decode, hourly/daily folds
lib/pricing.mjs   Peak/valley schedule and the DeepSeek price table
lib/money.mjs     Exact decimal money (integer 1e-8 units)
lib/report.mjs    Report assembly, terminal charts, HTML statement
lib/markdown.mjs  Markdown statement
lib/chart.mjs     Terminal bar charts

Implementation notes worth knowing:

  • Money never touches a binary float. Every amount is an integer number of 1e-8 units. Model unit prices are tiny and accumulate over thousands of calls — exactly where floats drift — which is why the reconciliation identity holds.
  • Session logs are multi-frame Zstandard. Node's zstdDecompressSync decodes only the first frame and reports no consumed length, so a naive read silently truncates a log to its header line. decodeZstdFrames() locates frames by their magic sequence and validates each slice by decoding it; a torn final append simply ends the scan, which is the correct behaviour for a log being written while it is read.
  • The ledger is read, not polled. A balance widget is already observing your account on a timer; reusing its record avoids two writers racing over one file, and only the balance display makes a network call.
  • Only recently touched logs are opened, filtered by mtime, so a one-day statement does not pay to decompress the whole history.

Privacy

Everything stays local. The only network request is the balance query to api.deepseek.com, authenticated with your own API key and sent directly from the DSH host process. Statements are written under $DSH_HOME/token-bill/. Nothing is uploaded to the plugin author, and the plugin contains no telemetry.

Testing

node test/unit.mjs     # 21 pure-function tests: money precision, peak hours, zstd frames, ledger rows
node test/report.mjs   #  8 report tests: apportionment identity, precision grids, HTML escaping
node test/smoke.mjs    # end-to-end against your real ledger, balance endpoint, and session logs
node test/verify.mjs   # drives the real execute(), checks output schemas and HTML structure

npm test runs the three dependency-free suites (docs, unit, report). smoke and verify read your real DSH data and write statements to the package-local .dsh-token-bill/ (gitignored), so they need a working DSH home and are best run from a source checkout — test/ is not part of the published package (files ships lib/, the patch, the READMEs, and the license).

Known limitations

  • The ledger depends on the balance widget. Without it, the money columns become price-table estimates rather than observed charges. The balance itself is always live.
  • Session logs are appended to disk, so the newest turn may not be written yet. token_status is as fresh as the log and the ledger, not instantaneous.
  • Per-hour amounts assume one price table for the whole day. On a day the provider changes prices, the hourly split is an apportioned share of the observed total, not a per-call reconciliation.
  • The holiday calendar is maintained by hand. A statutory holiday missing from the list is billed at the peak rate.
  • Only DeepSeek is supported. The balance source and price tables are DeepSeek-specific; another provider would need its own balance source plus a models entry.

License

MIT.

Comments

Loading…

Similar plugins

dsh-token-viewer

by qwert702

Developer tool: live token usage & cost monitoring for DeepSeek Harness - consumed tokens for the current session and across all sessions, read from token-meter projections. No model calls.

Tools & CapabilitiesModels & ProvidersManifest valid

★ 7

MIT

TypeScript

Sep 19, 2026

dsh plugin --profile web add dsh-token-viewer

Real-time DeepSeek API balance (official endpoint) and today-spend estimate (this DSH instance session-log usage x per-model price table) for the DSH web: composer dock strip, always-on floating badge

Tools & CapabilitiesModels & ProvidersManifest valid

★ 0

dsh plugin --profile web add dsh-deepseek-cost-live

by dog-lin

Real-time session cost meter for the DeepSeek Harness web GUI: folds provider token usage into a per-session cost projection and displays it live under the composer.

Terminal & ClientsManifest valid

★ 0

MIT

JavaScript

Aug 18, 2026

dsh plugin --profile web add dsh-session-cost

by EasyTZ

余额与费用:DeepSeek 余额、日/周/月花费、各模型用量与实时单价。Balance and cost panel for DeepSeek Harness: balance, spend, per-model usage, live pricing.

Models & ProvidersTerminal & ClientsManifest valid

★ 0

MIT

JavaScript

Sep 10, 2026

dsh plugin --profile web add @easytz/dsh-ui-balance

by nonewind

Token usage & cost monitor for DeepSeek Harness — floating widget with multi-dimensional stats, time-series charts, auto-detected billing plans (Code/Token) and estimated spend.

Tools & CapabilitiesModels & ProvidersManifest valid

★ 8

↓ 256/wk

MIT

JavaScript

Sep 7, 2026

dsh plugin --profile web add dsh-spend

by YZz-S

Community plugins for DeepSeek Harness (DSH) Web GUI: session token cost meter with official dynamic pricing, DeepSeek & Volcengine billing balance, and update checker. Plain JavaScript, no build requ

Tools & CapabilitiesModels & ProvidersManifest valid

★ 3

MIT

JavaScript

Aug 15, 2026

dsh plugin --profile web add dsh-token-cost-meter