Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dsh-balance

English | 中文

A DeepSeek Harness (dsh) plugin that shows your DeepSeek API account balance and this session's spend in a line below the prompt (composer). The host half fetches the balance and resolves pricing; the browser half renders the readout into the conversation.composer.dock slot under the composer (same band as the built-in stats line).

Layout

dsh-balance/
├── package.json          # dsh.bundle.patch → cordis.patch.yml; exports["."] → host half; dsh.client → browser half
├── cordis.patch.yml      # bundle layer: mounts the plugin into the profile's loader
├── dsh/
│   ├── index.js          # host half: GET /dsh-balance (balance + cache + optional proxy + pricing)
│   └── client.js         # browser half: composer.dock slot entry (balance + session cost, polling + click-to-refresh)
└── smoke.mjs             # smoke tests (fake ctx + stubbed fetch; --live hits the real API)

Zero dependencies — Node built-ins only.

How it works

  1. Host half: a GET /dsh-balance route (registered when the webServer service appears; the headless profile is untouched). Resolves the API key (plugin config apiKey > the DEEPSEEK_API_KEY credential via ctx.credentials > environment variable), calls GET https://api.deepseek.com/user/balance, and caches the result for cacheMs (default 60s); a failed refresh falls back to the previous cached value flagged stale so the readout never blanks on a flaky network. The response also carries the currently effective pricing (peak/off-peak resolved automatically against Beijing time).
  2. Browser half: registers into the conversation.composer.dock slot (order: 10, after the built-in stats line). Shows 余额 ¥48.62 · 本会话 ¥0.006 — the session spend is computed live from useProjection('tokenUsage') (dsh's durable token-usage projection, updated in real time as a turn streams) and the pricing from the response: (uncached input × miss price + cache read × hit price + cache write × miss price + output × output price) / 1e6. Fetches on mount, polls on the response's refreshMs (default 60s), refreshes when the tab becomes visible or the window regains focus, and refetches on click. Hovering shows the token breakdown (input/cache/output) and the peak/off-peak period. Failures degrade to a quiet placeholder (e.g. "未配置 API Key" / "no API key configured") — never a crash.

Install

From GitHub (for everyone):

# Option 1: install as a dependency (recommended)
# 1) add to the dependencies of ~/.dsh/profiles/web/package.json:
#    "dsh-balance": "github:m2lan/dsh-balance"
# 2) add "dsh-balance" to dsh.profile.bundles
# 3) install dependencies:
npx -y @deepseek-ai/dsh plugin --profile web install

# Option 2: add directly (requires pnpm)
npx -y @deepseek-ai/dsh plugin --profile web add github:m2lan/dsh-balance

Local development install (this machine has no pnpm, so the manual three steps mirror gemini-eyes):

  1. Add "dsh-balance": "file:/Users/M2/Documents/ai/harness/h1/dsh-balance" to the dependencies of ~/.dsh/profiles/web/package.json;
  2. Append "dsh-balance" to dsh.profile.bundles;
  3. Symlink ~/.dsh/profiles/node_modules/dsh-balance → this directory.

Restart dsh web afterwards (a new bundle is not hot-loaded into a running instance).

With pnpm you can also use the standard command:

npx -y @deepseek-ai/dsh plugin --profile web add ./dsh-balance

Configuration

Key resolution order: plugin config apiKey > the DEEPSEEK_API_KEY credential (written to ~/.dsh/.credentials.yaml by the web Models page) > environment variable. By default the credential's key is used — no extra configuration needed.

Proxy (optional): Node's global fetch ignores proxy environment variables. DeepSeek is usually reachable directly; if you must go through a proxy, the plugin ships a zero-dependency HTTP CONNECT tunnel, resolving the proxy from plugin config proxy > env vars such as HTTPS_PROXY. Add it to the dsh-balance entry in ~/.dsh/profiles/web/cordis.patch.yml:

- id: dsh-balance
  config:
    # apiKey: 'sk-...'            # explicit key
    # keyRef: 'DEEPSEEK_API_KEY'  # credential/env ref to resolve (default)
    # proxy: 'http://127.0.0.1:7897'
    # cacheMs: 60000              # host-side cache duration (default 60000)
    # refreshMs: 60000            # browser poll interval (default 60000)
    # path: '/dsh-balance'        # served route path (default /dsh-balance)
    # --- session-cost pricing (CNY per million tokens, peak base) ---
    # Defaults follow DeepSeek's official peak/off-peak pricing effective
    # 2026-08-17 (https://api-docs.deepseek.com/quick_start/pricing/):
    # peak hours are Beijing 09:00-12:00 and 14:00-18:00, off-peak = peak ×
    # offPeakFactor. Override here when DeepSeek changes its prices — no code
    # changes needed:
    # pricing:
    #   deepseek-v4-flash: { inputHit: 0.10, inputMiss: 3.0, output: 9.0 }   # peak
    #   deepseek-v4-pro:   { inputHit: 0.30, inputMiss: 9.0, output: 27.0 }
    #   default:           { inputHit: 0.10, inputMiss: 3.0, output: 9.0 }   # fallback for unknown models
    # offPeakFactor: 0.5            # off-peak price factor (default 0.5)
    # peakHours: [[9,12],[14,18]]   # peak windows in Beijing hours (default above)

About the pricing: the session spend is an estimate (for display, not a bill). The token buckets come from dsh's durable usage projection (the same source the stats line reads); the price switches between peak and off-peak automatically according to current Beijing time; DeepSeek bills cache writes at the cache-miss rate, and the plugin does the same. DeepSeek changes its official prices from time to time — always defer to the official pricing page and override via pricing when needed. If you switch to a non-DeepSeek model, add a matching pricing entry (or change default).

Verify

After restart, a line 余额 ¥48.62 appears below the composer; once the session produces tokens it becomes 余额 ¥48.62 · 本会话 ¥0.006 (grows live; click to refresh, hover for the token breakdown and peak/off-peak period). You can also confirm the plugin is mounted in the composed config tree:

npx -y @deepseek-ai/dsh --profile web --dump-config | grep -A3 dsh-balance

Smoke tests (no network):

node smoke.mjs
node smoke.mjs --live   # hits the real DeepSeek balance API (uses the key in ~/.dsh/.credentials.yaml)

Notes

  • The key never leaves the dsh process: the balance is fetched with an Authorization: Bearer header to api.deepseek.com; the browser only receives the balance figure and the pricing, never the key.
  • The balance endpoint is read-only: only GET /user/balance is called — this plugin never spends anything.
  • The session spend is an estimate: token buckets come from dsh's token-meter projection (provider-reported usage with a heuristic fallback), priced with the official peak/off-peak rates that switch over time; reference only, not a billing record.
  • Restart after code changes: changing dsh/index.js or dsh/client.js requires a dsh web restart to take effect (the client bundle's rev changes with its content, so a page refresh picks up the new version).
  • Uninstall: remove the dependency and the bundles entry from ~/.dsh/profiles/web/package.json, delete the ~/.dsh/profiles/node_modules/dsh-balance symlink, revert cordis.patch.yml, and restart.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages