@kt11/dsh-deepseek-balance
@kt11/dsh-deepseek-balance
DeepSeek Harness (dsh) plugin — a real DeepSeek API balance and daily-spend card, pinned to the sidebar footer.
The card shows your DeepSeek API account balance and how much you've spent today, pulled from real sources (not mock data). Clicking the card opens a detail popup with your balance breakdown, the current session's usage, and a recent-session spend list.
- Zero runtime dependencies — only Node builtins + global
fetch. - Keys never leave the process — the API key / platform token stay server-side; the browser only talks to the loopback dsh web server.
- No build step — the browser bundle is hand-written lazy-CJS (
window.__ModuleLoader__.load).
Features
| Feature | Source |
|---|---|
| Account balance (total / topped-up / granted) | DeepSeek GET /user/balance |
| Today's spend ("今日已消耗") | DeepSeek platform usage API, else local token×price estimate |
| Current session usage (turns/steps, wall time, tokens) | dsh sessionStats + tokenUsage projections |
| Recent session spend list | Aggregate over dsh sessions, costed with the official price table |
| Auto-refresh (60s) + manual refresh + detail popup | Client-side polling |
How it works
The plugin has two halves, matching the dsh plugin protocol:
- Host half (
dsh/index.js) — a cordis service registered viacordis.patch.yml(id: deepseek-balance). It injects onwebServerand registers these routes:GET /dsh-balance/deepseek— DeepSeek account balance (proxied toapi.deepseek.com/user/balance).GET /dsh-usage/details?session=<id>— balance + one session's usage.GET /dsh-usage/sessions?tz=<seconds>— recent-session list + aggregated "today" spend.
- Client half (
dsh/client.js) — awindow.__ModuleLoader__.loadbundle registering asidebar.footer.actionentry (order1, above the session-manager card and the Settings trigger). It polls the routes and renders the card + a portal popup.
Services (sessions, sessionProjections, credentials) are resolved lazily from the plugin ctx at request time, so the routes never stall if a service is missing, and the browser half degrades gracefully (the card still renders without the sessions service).
Installation
Install it as a dsh web-profile bundle (the dsh Desktop "plugin center" or a manual file: dependency). Because it declares dsh.client.platform: "web" and immediately: true, the browser half is served by dsh's client module system at /plugins/@kt11/dsh-deepseek-balance/client.js.
// profile package.json (dsh.profile.bundles)
"dsh": {
"profile": {
"bundles": ["@kt11/dsh-deepseek-balance"]
}
}
Configuration
The plugin reads credentials from the dsh credentials service first, then the process environment, then a ~/.dsh/.credentials.yaml fallback.
| Variable | Purpose | Required |
|---|---|---|
DEEPSEEK_API_KEY |
DeepSeek API key, used for the balance call (Authorization: Bearer) |
|
DEEPSEEK_PLATFORM_TOKEN |
Browser session token (userToken) of platform.deepseek.com; enables the exact platform "today" cost. Optional — without it the card falls back to a local estimate. |
Optional |
# ~/.dsh/.credentials.yaml
DEEPSEEK_API_KEY: sk-xxxxxxxxxxxxxxxxxxxxxxxx
DEEPSEEK_PLATFORM_TOKEN: eyJhbGciOi... # optional; the platform userToken
Getting
DEEPSEEK_PLATFORM_TOKEN: log in to https://platform.deepseek.com, open DevTools → Application → Local Storage →https://platform.deepseek.com, copy theuserTokenvalue. It is a login-session token and expires; re-copy it when the card falls back to "估算". The plugin also tolerates the value arriving as the raw string or wrapped in{"value":"...","__version":"0"}.
Accuracy of "today's spend"
The card shows 今日已消耗 with one of two sources:
- 平台 (platform) — when
DEEPSEEK_PLATFORM_TOKENis configured, it replays the platform page's own queries (/api/v0/usage/by_api_key/cost+/amount) for the current day in the browser timezone, restricted to the current key's maskedsensitive_id. This matchesplatform.deepseek.com. - 估算 (estimate) — otherwise, it folds the in-process dsh session logs for the local calendar day and prices them with the built-in price table (
PRICING). This counts only session logs visible to the process, so it is usually lower than the platform's full-account number — it is labeled估算in the UI for that reason.
Development
The package has a zero-dependency unit suite over the pure helper functions (pricing, daily fold, platform parsing, key masking) using node:test.
node --test dsh/index.test.js
There is also a dev-only "on账" script (not shipped — scripts/ is outside the package files) that fetches the platform usage payloads with the plugin's own parser and prints both the raw structure and the computed total:
node scripts/verify-platform.mjs # uses your system timezone
node scripts/verify-platform.mjs -28800 # explicit tz seconds-east (e.g. Beijing +8h)
Stability notes
- The daily "today" fold is memoized per session (keyed by local day + log length), so unchanged logs are not re-walked on every 60s poll; it recomputes only on new events or a day roll.
- Platform usage is cached for 60s and falls back to the local estimate on any platform error (missing/invalid token, 401/403, malformed response).
License
MIT