API Balance Ring

August 15, 2026 ยท View on GitHub

A tiny, real-time DeepSeek API balance meter that lives inside the DeepSeek Harness composer. Hover the ring for your live balance, click it for today's spend, request count and token consumption โ€” priced per model, straight from your real session logs.

๐Ÿ‡จ๐Ÿ‡ณ ไธญๆ–‡็‰ˆ README

Demo


โœจ Highlights

  • ๐Ÿ”ด Live balance at a glance โ€” a progress ring right next to the send button, exactly like the built-in context meter. The arc shows your balance against a ยฅ50 full ring and shifts green โ†’ amber โ†’ red as it drains.
  • ๐Ÿ–ฑ Hover โ€” see APIไฝ™้ข๏ฟฅ6.45 the moment your cursor touches the ring.
  • ๐Ÿ“Š Click โ€” a breakdown panel with today's spend, API request count and tokens consumed, plus an updated-at timestamp. Refreshes every 60 seconds (and on every click).
  • ๐Ÿงฎ Priced per model, not per day โ€” every request is priced with the official deepseek-v4-flash or deepseek-v4-pro rate recorded in your session log, so switching models mid-session stays accurate.
  • โฑ Peak / off-peak aware โ€” the official peak/off-peak pricing schedule (effective 2026-08-16) is built in and switches automatically by request time.
  • ๐Ÿ”’ Provider-filtered โ€” only requests routed through deepseek-official count. Usage from other providers (e.g. an Aliyun pi-ai model) never pollutes your DeepSeek bill.
  • ๐ŸŽจ Native look & feel โ€” same slot, same geometry, same theme tokens as the shipped context-occupancy ring. Zero dependencies, pure JavaScript, no build step.

๐Ÿ–ผ Screenshots

The three states โ€” idle, hover, and the click-open panel:

Idle ยท Hover ยท Panel

The breakdown panel up close:

Panel

๐Ÿงฉ How it works

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Browser (Client half) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  conversation.input.right slot (composer, left of the send button)              โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚  BalanceRing component                                                     โ”‚  โ”‚
โ”‚  โ”‚   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    host.call('api-balance') โ”‚  โ”‚
โ”‚  โ”‚   โ”‚ ring + tooltip + panel  โ—€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”      โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜                      โ”‚      โ”‚  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                                                          โ”‚ JSON-RPC
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Host process โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                                                                          โ–ผ      โ”‚
โ”‚  harness.handle('api-balance')      โ†’ GET https://api.deepseek.com/user/balanceโ”‚
โ”‚                                        (Authorization: Bearer $DEEPSEEK_API_KEY)โ”‚
โ”‚                                                                                โ”‚
โ”‚  harness.handle('api-usage-today')  โ†’ scan every session log (sessionQuery)    โ”‚
โ”‚                                        ยท count assistant/message events today  โ”‚
โ”‚                                        ยท sum input + output + cache tokens     โ”‚
โ”‚                                        ยท price each request by its model       โ”‚
โ”‚                                          (request/header event) and UTC hour   โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ“ฆ Installation

Prerequisites

  • DeepSeek Harness (the web GUI) running locally.
  • A DeepSeek API key stored as the DEEPSEEK_API_KEY credential โ€” the harness's normal credential store (~/.dsh/.credentials.yaml or environment).

Steps

  1. In the harness web UI, open Developer โ†’ Dynamic Plugin โ†’ New.
  2. Name: API Balance Ring (anything you like).
  3. Host code: paste the entire contents of plugin/host.js.
  4. Client code: paste the entire contents of plugin/client.js.
  5. Create the plugin, then Run it and approve the activation request in the UI.
  6. The ring appears in the composer, left of the send button, within a second.

The plugin is a dynamic plugin: it is process-local and disappears on restart. Re-create it after a restart, or copy the two files into your own agent preset if you want it always on.

๐ŸŽฏ Usage

ActionResult
Hover the ringTooltip with the live balance, e.g. APIไฝ™้ข๏ฟฅ6.45
Click the ringPanel: balance + ยฅ50 progress bar + today's cost / requests / tokens
Click elsewhere / EscPanel closes
AutomaticValues refresh every 60 s; clicking the ring also refreshes immediately

The ring arc = balance รท ยฅ50 (full ring at ยฅ50). Color thresholds: โ‰ฅ ยฅ5 green, โ‰ฅ ยฅ1 amber, < ยฅ1 red.

๐Ÿงฎ Data & accuracy

StatSource
BalanceOfficial https://api.deepseek.com/user/balance endpoint, authenticated with your stored DEEPSEEK_API_KEY
Requests / TokensYour own session logs โ€” every assistant/message event carries the real API usage (inputTokens, outputTokens, `cacheReadTokens$)
\text{Cost}\text{Official} \text{per}-\text{model} \text{pricing} \times \text{request} \text{time} (\text{flat} \text{now}, \text{peak}/\text{off}-\text{peak} \text{from} 2026-08-16), \text{converted} \text{at} \text{a} \text{fixed} \text{USD}โ†’\text{CNY} \text{rate}

\text{Pricing} \text{table} (\text{USD} \text{per} 1\text{M} \text{tokens})

\text{Model}\text{Cache}-\text{hit} \text{input}\text{Cache}-\text{miss} \text{input}\text{Output}
$deepseek-v4-flash`$0.0028$0.14$0.28
deepseek-v4-pro$0.003625$0.435$0.87

From 2026-08-16 16:00 UTC, peak hours (01โ€“04 & 06โ€“10 UTC) charge double the off-peak rates; the plugin selects the rate per request automatically.

What counts

  • โœ… Only requests with provider === 'deepseek-official' โ€” those are the ones that spend your DeepSeek balance.
  • โœ… Requests whose model is deepseek-v4-flash or deepseek-v4-pro are priced individually, so a mid-session model switch is billed correctly on both sides of the switch.
  • โœ… "Today" is your local calendar day (00:00 โ†’ now).
  • โš ๏ธ If a request used a model outside the pricing table, the cost shows a ~ prefix โ€” the number is an under-count, never a silent wrong one.
  • โš ๏ธ The USDโ†’CNY rate is a fixed constant (6.76) โ€” official pricing is USD-denominated, so the ยฅ figure can drift by ~1% from the platform's own conversion.

โš™๏ธ Configuration

Everything lives in the CONFIG block at the top of each file.

ConstantFileDefaultMeaning
referenceBalanceclient.js50ยฅ amount that fills the ring and the bar
refreshMsclient.js60000background refresh interval
warnBelow / dangerBelowclient.js5 / 1ring color thresholds (ยฅ)
tooltipDelayMsclient.js200hover delay before the tooltip
usdCnyRatehost.js6.76USDโ†’CNY conversion for the cost readout
PRICINGhost.jsโ€”per-model rate table (add new models here)
PRICING_EFFECTIVEhost.js2026-08-16T16:00Zwhen peak/off-peak pricing starts

โ“ FAQ

Why does the panel show ~ before the cost? A request ran with a model not in the pricing table (e.g. a brand-new release). Requests and tokens still count; the cost is marked approximate.

Why is my "today" lower than the platform dashboard? The plugin reads your harness's session logs. Usage from other tools or direct API calls is not in those logs, and small differences in the day boundary can shift the count by a couple of requests.

Is my API key exposed? No. The key is resolved from the harness credential store at runtime and only ever appears in the Authorization header of the balance request. Nothing is stored in this repo.

Does it work with deepseek-v4-pro? Yes โ€” that's exactly why pricing is per request. Switch your default model in Settings and the cost readout follows immediately.

๐Ÿšง Known limitations

  • Dynamic plugins are process-local; the ring needs to be re-created after a harness restart (see Installation).
  • The USDโ†’CNY rate is a constant, not live-quoted.
  • Usage is aggregated from session logs โ€” it reflects the harness, not your whole API account.

๐Ÿค Contributing

PRs are welcome! Ideas we'd love:

  • Live USDโ†’CNY rate via a lightweight quote fetch.
  • A config UI (reference balance, thresholds) instead of code constants.
  • An installable static plugin bundle so the ring survives restarts without re-pasting.

Please keep the plugin halves dependency-free so they stay paste-able.

๐Ÿ“„ License

MIT ยฉ EdwinZDZ

Visual language (ring geometry, panel surface, tooltip plate) is adapted from the DeepSeek Harness built-in context-occupancy meter, MIT licensed.