dsh-client-ui-thinking-stats
在底部Dock和每次对话尾部添加模型思考token统计的轻量化插件。A lightweight plugin that adds model thinking token statistics to the bottom Dock and the end of each conversation.
- Stars
- 1
- Language
- JavaScript
- Created
- Sep 3, 2026
- Updated
- Sep 4, 2026
Introduction
dsh-client-ui-thinking-stats
A lightweight plugin that adds model thinking token statistics to the bottom Dock and the end of each conversation. Client-only and zero-cost when idle: it reads the existing conversation snapshot and renders nothing at all when there is no thinking.

It adds two readouts, both of which render nothing when the model has produced no thinking for the relevant scope:
| Surface | Slot | Scope |
|---|---|---|
| Bottom composer dock | conversation.composer.dock | Whole session (cumulative) |
| Each assistant reply (timing row) | conversation.chat.assistant-actions | That single turn |
The per-turn readout is appended to the reply's timing strip — the same hover
row that shows 20:55 · 用时 11秒 · 首token 10秒 · 28 tok/s — so it reads as part
of that same unit.
Each readout shows, left to right, a brain glyph, the thinking-token count, its share of all tokens, and its share of output tokens, each with one decimal place, for example:
💭 15 · 0.2% · 60.0%
Hover for the exact numbers.
How thinking tokens are counted
For every finalized assistant message, in order:
- Provider-reported — if
usage.reasoningTokensis present (DeepSeek, OpenAI o-series, Anthropic, …), it is used as-is. This is exact. - Otherwise — the reasoning blocks are priced with the harness' fixed heuristic (four characters per token), so a provider that returns reasoning text but no token count still gets a figure.
- Neither present → the message counts as zero thinking and contributes nothing.
The two denominators are derived from the same assistant messages, so the percentages always agree with the count on one consistent scope:
- share of all tokens = thinking ÷ (input + output + cache reads + cache writes)
- share of output = thinking ÷ output
Why it's lightweight
- Client-only, zero host behavior. The node half (
lib/index.js) is an emptyapplythat exists only so the package appears in the host Loader. All work is done in the browser. - Read-only. It consumes the existing conversation snapshot; it adds no service, projection, tool, or RPC.
- Self-contained. It depends on no other plugin.
- Zero-cost when idle. When nothing is being thought, both readouts render
null— no element, no layout cost. - Theme-aware. Colors come from the
--dsw-alias-*tokens, so it follows light/dark automatically.
Install
The plugin follows the standard dsh.bundle + dsh.client convention, so it
installs like any DSH plugin. From this repository:
dsh plugin add github:Six6stRINgs/dsh-client-ui-thinking-stats
Then restart dsh web and reload the page. The readouts appear only once the
model starts thinking.
Testing
test/harness.mjs stubs the browser/React environment, runs the real factory
and apply, and renders both entries against sample data (provider-reported and
block-estimated paths, the one-decimal formatting, and the hidden-when-empty
cases). Run with:
node test/harness.mjs
Known limitations
- Figures come from the in-window conversation snapshot. For very long, paged sessions the visible window is the counted scope; the shipped stats line and projections use whole-log folds instead.
- The character-per-token estimate is approximate, exactly as the harness'
fixed heuristic is; provider-reported
reasoningTokensis always preferred.