dsh-balance-bar
Manifest validDeepSeek Harness Web plugin: live account balance as a colour-banded vertical progress bar on the right edge of the GUI, with an animated wave above the threshold.
dsh-balance-bar
A DeepSeek Harness Web plugin that shows your model-provider account balance as a vertical progress bar pinned to the right edge of the GUI, with colour bands that tell you how much runway you have left — and a persistent animated wave for whatever you hold above the healthy threshold.
┌──┐
│≈≈│ ← balance > 50: light blue-violet waves, always moving
│≈≈│
│▓▓│
│▓▓│ ← 30 – 50: green
│▓▓│
│▓▓│ ← 10 – 30: yellow
└──┘ ← < 10: red
¥10.06 ╯
The bar itself stays vertical; the amount is a horizontal chip pinned to its left, so
¥1234.56 reads normally instead of stacking one digit per line.
| Balance (CNY) | Fill |
|---|---|
< 10 | red — time to top up |
10 – 30 | yellow |
30 – 50 | green |
> 50 | green pinned at the 50 scale mark, and every yuan above it is drawn as an animated light blue-violet wave layer |
Hover the bar (or the chip) for a card with the exact amount, the scale position, the
topped-up / granted split, and how old the reading is. Click to refresh immediately. With no
reading yet the chip shows 读取中…; if the provider call fails it keeps the last good figure
and reports the error in the card instead of going blank.
中文速览
一个 DeepSeek Harness Web 插件:在界面最右侧贴边显示一根竖直的账户余额进度条。
- 红色:余额 < 10 元
- 黄色:10 – 30 元
- 绿色:30 – 50 元
- 浅蓝紫色波纹:超过 50 元的部分——绿色填满到 50 元刻度,超出部分画成持续流动的波浪
进度条本身保持竖直,数字是横向显示的:金额做成一个横向胶囊标签贴在竖条左侧,所以
¥1234.56 正常一行读完,不会竖排。鼠标悬停竖条或标签都会弹出卡片,显示精确金额、刻度百分比、
充值/赠送拆分和读数新鲜度;点击立即刷新。每 60 秒自动更新一次,Host 侧还有 5 分钟的兜底刷新。
安装(插件不在 npm 上,直接从仓库加载):
git clone https://github.com/hfdsdfgr/123.git dsh-balance-bar
# 方式一:单次启动时挂载
dsh web --patch /绝对路径/dsh-balance-bar/cordis.patch.yml
# 方式二:写进 profile 的补丁层(Web profile 会热重载,刷新页面即可生效)
node scripts/install.mjs
API Key 走 Harness 的凭据体系(默认引用 DEEPSEEK_API_KEY),永远不会进入浏览器;浏览器
只拿到一个同源 JSON 快照。阈值、刻度、波纹颜色、刷新间隔都是 src/client.js 顶部的具名常量。
Highlights
- No build step. The browser half is one plain CommonJS file wrapped in the client module
table's registration contract. The file in
src/is the file the browser downloads. - The API key never reaches the browser. The Host half resolves it through the Harness credential seam and calls the provider; the page only ever sees a small JSON snapshot on a same-origin route.
- First-frame correct. The Host embeds the last snapshot into the served index, so the bar paints a real number before its first poll instead of flashing an empty bar.
- Polls, caches, and degrades. 60 s freshness window, 5 min background cadence, hover/click for an on-demand read, and stale-but-labelled data when the provider is unreachable.
- Does not get in your way. The overlay row is
pointer-events: noneexcept for the 16 px bar itself, so nothing in the GUI becomes unclickable. Honoursprefers-reduced-motion: reduce.
Install
This plugin is not published to npm; it loads straight from a checkout.
git clone https://github.com/hfdsdfgr/123.git dsh-balance-bar
Then either pass the overlay for one run:
dsh web --patch /absolute/path/to/dsh-balance-bar/cordis.patch.yml
…or make it permanent by appending the row to your profile's own patch layer, which the Web profile reloads live (no restart, just reload the page):
node scripts/install.mjs # writes $DSH_HOME/profiles/web/cordis.patch.yml
node scripts/install.mjs --dry-run # show the exact result first
cordis.patch.ymlships a machine-specific absolute path. The loader row names the Host half by absolute file URL, so edit that line (or letinstall.mjswrite it) to point at wherever you cloned this repository. There is deliberately nopnpm addstep and nonode_modulesentry to create.
Requirements: a DSH Web profile and a DeepSeek API key configured as the credential
DEEPSEEK_API_KEY (the same key the Harness already uses).
Configuration
Every key is optional; the defaults are shown here and live in cordis.patch.yml.
| Key | Default | Meaning |
|---|---|---|
credentialRef | DEEPSEEK_API_KEY | Credential reference holding the provider key |
endpoint | https://api.deepseek.com/user/balance | Balance endpoint (any DeepSeek-compatible one works) |
cacheTtlMs | 60000 | How long a reading is served before re-fetching |
pollIntervalMs | 300000 | Background refresh cadence |
timeoutMs | 10000 | Per-request timeout |
Architecture
Two halves, one plugin, no overlap between them.
Host half (src/index.ts)
ctx.credentials.resolve(credentialRef) → the API key, Host-side only
GET https://api.deepseek.com/user/balance → provider truth
├─ GET /dsh-balance/snapshot → same-origin JSON the page polls
└─ globalThis.__DSH_BALANCE__ → index-injection row for first paint
Browser half (src/client.js)
window.__ModuleLoader__.load({ id, factory }) → the whole transport contract
require('react') → the shell's platform seed
ctx.slots.inject('shell.overlay') → the fixed bar + hover card
Why an HTTP route instead of @Remote? Remote methods are generated by the Typert build
pipeline from Host decoration. A plugin that lives outside the Harness build must describe its
own wire protocol, so this one publishes on ctx.webServer with an exact named route. It is
deliberately not under /api: that carrier belongs to the Connection plugin, which
authenticates and would reject every route it does not own. What crosses the wire is a
display-only reading, and the shipped Web composition binds loopback only.
Why shell.overlay? It is the layout package's root-scope list slot — the only place a
plugin can put something at the shell edge without taking over a column. ctx.slots.inject
waits for the declaration, reruns after a redeclaration, and removes the contribution when
this plugin unloads.
Tests
Four checks, plain Node, no test framework:
node scripts/client-spec.mjs # colour bands, scale, wave geometry, payload projection
node scripts/client-smoke.mjs # loads the bundle through a stubbed window.__ModuleLoader__
node scripts/theme-tokens.mjs # every var(--dsw-*) reference resolves in the real theme
node scripts/balance-smoke.mjs # mounts the Host half and drives the live provider
node scripts/verify-deployed.mjs # read-only probe of a running GUI
client-spec pins the product rule at its boundaries — 10 is yellow, 30 is green, 50 is
still green, anything above turns the wave on — and proves the wave path closes its phase, so
the animation loops without a visible jump.
theme-tokens exists because a CSS custom property that does not exist fails silently: the
declaration is dropped and the hardcoded fallback paints instead, which looks like a design
choice rather than a bug. This plugin's hover card shipped that way once — four references
(--dsw-alias-bg-elevated, --dsw-alias-text-primary, --dsw-alias-text-secondary,
--dsw-alias-border-subtle) were never defined by ui-theme, so the card rendered with a
washed-out hardcoded grey that read as permanently half-transparent. The check extracts the
stylesheet the bundle actually installs, compares every --dsw-* reference against the names
ui-theme declares in the DSH checkout, and also asserts the value chip is horizontal.
verify-deployed mints the browser-session cookie, reads window.__DSH_BOOT__ from the served
index, and downloads the bundle route the browser will actually use: it is the difference
between "the files are correct" and "the GUI is running them".
Tuning the look
Thresholds, scale, wave colours, and refresh cadence are named constants at the top of
src/client.js:
| Constant | Default | Meaning |
|---|---|---|
SCALE_LIMIT | 50 | Yuan at which the fill tops out |
RED_LIMIT | 10 | Upper bound of the red band (exclusive) |
YELLOW_LIMIT | 30 | Upper bound of the yellow band (exclusive) |
REFRESH_MS | 60000 | Browser polling interval |
PALETTE | red / yellow / green gradients | Fill colours |
WAVE_CREST, WAVE_BODY | #cddcff, #8fb0ff | The light blue-violet wave |
Layout lives in the STYLES block in the same file: the vertical bar is 16 px wide at
right: 12px, and the horizontal value chip is pinned to its left at right: 34px, both
widening/shifting slightly on hover. Colours come from the theme's semantic tokens
(--dsw-alias-label-*, --dsw-alias-bg-layer-1, --dsw-elevation-*) so the plugin follows
light and dark mode; the band colours are literal, because they are the product rule rather
than the theme's.
License
MIT — see LICENSE.
Comments
Loading…
Similar plugins
by JavierNier
Balance & usage card plugin built on the DeepSeek Harness for its Web GUI: DeepSeek account balance with color tiers, plus live per-conversation token usage and cost (peak/off-peak priced).
★ 0
MIT
JavaScript
Sep 16, 2026
dsh plugin --profile web add @javierni/balance-showby btbxbob
DeepSeek Harness side-bar balance badge: show DeepSeek account balance and estimated depletion time (dual-half cordis plugin)
★ 0
JavaScript
Sep 14, 2026
dsh plugin --profile web add dsh-balanceby shxiaooo
DeepSeek Harness web plugin: an ambient balance/usage reading under the composer, with a clickable per-provider detail panel. Every figure is upstream-reported.
★ 0
MIT
JavaScript
Sep 11, 2026
dsh plugin --profile web add dsh-account-quotaby zhouchengke2046
DeepSeek Harness plugin that shows the DeepSeek API account balance and OpenCode Go plan usage (consumption ring, hover details) in the sidebar footer, with adaptive polling and zh/en locale support.
★ 0
↓ 66/wk
MIT
JavaScript
Aug 21, 2026
dsh plugin --profile web add dsh-sidebar-balanceby LucienLL
DeepSeek Harness plugin: peak/off-peak price watch, live account balance with tiered low-balance alerts, and a top-up button for the main web UI
★ 0
MIT
JavaScript
Aug 26, 2026
dsh plugin --profile web add dsh-peak-price-panelby qschen86
DSH web plugin: DeepSeek API balance & today usage badge in the sidebar rail
★ 0
MIT
JavaScript
Aug 19, 2026
dsh plugin --profile web add dsh-deepseek-balance