DSH Plugins Marketplace

DSH Plugins

Plugins

/

dsh-qiniu-usage

w

dsh-qiniu-usage

Manifest valid

Usage display for Qiniu Cloud, made for dsh — so you don't have to keep going to the official website to check.

UI (client)hasBundlePatchMachine translated

dsh-qiniu-usage

English | 中文

A DSH Web GUI plugin for Qiniu Cloud (七牛云). It answers two questions without leaving the browser:

  • How much did each model cost me today? — per-model token usage (input / output / total), for one API key or the whole account, for today, yesterday or any past date.
  • How much resource-pack quota is left this month? — per-billing-item capacity / used / remaining, plus per-pack used amount and expiry date.

It renders as a 「七牛云用量」 section in Settings and as a glance card below the left session list. The plugin is read-only against Qiniu — it never creates, modifies or bills anything. The UI ships in Chinese and English and follows the host theme.

Settings → 七牛云用量
Settings → 七牛云用量 · credentials, key roster, auto-refresh
Details · model usage
Details · model usage
date / key filters, per-model input / output / total
  Details · resource packs
Details · resource packs
month-to-date utilisation, per-pack detail
Sidebar glance card
Sidebar glance card · one line collapsed, the three largest models plus Details / Refresh expanded

Requirements

DSH>= 0.1.5-rc.1 (dsh --version), on a profile that boots the Web app — usually web
Node^22.19.0 || >=24.0.0
QiniuAn AccessKey / SecretKey pair. A sk- token alone is not enough: the resource-pack (finance) API only accepts management credentials, and that AK needs billing/IAM financial permission. Without it the resource-pack cards show a targeted hint while the usage half keeps working.

Install

The package is not published to npm — install it from a local checkout. lib/ is gitignored, so build it first:

cd /path/to/dsh-qiniu-usage
npm install && npm run build
dsh plugin --profile web add link:$PWD
dsh web

Open Settings → 七牛云用量. That is the whole install.

dsh plugin is a thin pnpm forwarder running inside the profile directory. It records the dependency in $DSH_HOME/profiles/web/package.json and, because the package declares dsh.bundle.patch, appends the package name to dsh.profile.bundles automatically — no manual patch-layer editing, and the web app is not rebuilt (the shell serves exports["./client"] at /plugins/<id>/client.js).

Other install sources, updating, uninstalling
# copy instead of symlink (live edits no longer picked up)
dsh plugin --profile web add file:/path/to/dsh-qiniu-usage

# a packed tarball
cd /path/to/dsh-qiniu-usage && npm run build && npm pack
dsh plugin --profile web add /path/to/dsh-qiniu-usage-<version>.tgz

# update
cd /path/to/dsh-qiniu-usage && git pull && npm install && npm run build && dsh web

# uninstall
dsh plugin --profile web remove dsh-qiniu-usage

A git+… install arrives without lib/ and the package has no prepare script, so it will not load — build it yourself and add link:$PWD instead.

To install without the CLI, add the dependency to $DSH_HOME/profiles/web/package.json and append the package name (matching its name field, not the path or git URL) to dsh.profile.bundles, then run dsh plugin --profile web install.

Uninstalling drops the dependency and the bundle entry, but credentials you saved through the GUI live in the DSH credential store and are not removed. Clear them in Settings → 七牛云用量 → 凭据 first if you want them gone.

With a link: install the profile keeps pointing at the same checkout. Restart dsh web after host-half changes; after client-half changes a rebuild plus a page refresh is enough.

Configure

Credentials

The plugin reads credentials by reference name — a POSIX environment-variable name — never by value. Two ways to supply them:

A. Environment variables (read-only). Export them in the environment that launches dsh:

export QINIU_ACCESS_KEY=...
export QINIU_SECRET_KEY=...
dsh web

DSH does not read a .env file automatically — see .env.example for the variable names. Environment-backed entries can only be read, so the GUI form is greyed out and reports 来源:环境变量 QINIU_ACCESS_KEY · 只读.

B. The GUI credential form. In Settings → 七牛云用量 → 凭据, type the AK and SK and save; they land in the DSH credential store, and rotating a key takes effect on the next request — no restart. The form shows the reference names (read-only) above the value inputs, because that is the actual split: the config holds the name, the store holds the value.

Settings

SettingDefaultMeaning
enabledtrueMaster switch. When off, no routes are registered and no upstream request is ever made.
accessKeyRefQINIU_ACCESS_KEYName of the store entry holding the AccessKey
secretKeyRefQINIU_SECRET_KEYSame, for the SecretKey
timezoneAsia/ShanghaiUpstream accepts IANA names only (Local is rejected)
pollIntervalSec5Client auto-refresh interval in seconds; 0 = manual refresh only
sidebarCardtrueShow the glance card at the sidebar foot; off keeps the panel settings-only

Everything has a default, so an empty config is valid. The rest (apiKeys[], defaultDay, defaultKey, the cache TTLs, the API base URLs) is documented in DESIGN.md §10.1.

Edit these through the profile's plugin config, like any other DSH plugin setting. pollIntervalSec and sidebarCard are picked up live; the rest apply on the next dsh web boot.

Usage

The settings page holds configuration only — the 凭据 form, a display-only key roster (name / masked / today's status, which doubles as "does this AK/SK work and which keys can it see"), and the auto-refresh interval.

The sidebar glance card sits at the foot of the left column (it hides itself when the sidebar collapses to the 56px rail). Collapsed it is one line — icon, title, today's total; expanded it shows the three largest models plus a 「其余 N 个模型合计」 line, with Details and Refresh buttons.

Details opens a centred dialog with two tabbed sections:

  • Model usage — date (today / yesterday) and key (all keys combined / a single key) filters plus the per-model input / output / total table.
  • Resource packs — month-to-date utilisation per billing item plus per-pack detail.

The card title follows those filters: switch to yesterday and it reads 昨日用量, filter a key and it appends the key name — card and dialog share one store, so the number on the card can never mean something other than what it says. The expanded state is remembered per browser (localStorage, key dsh-qiniu-usage:sidebar-card:expanded).

Security & privacy

  • Credentials never reach the browser. AK/SK exist only in the host process; the routes only ever return { configured, source, writable }, a shape with no slot for a value.
  • Loopback-fenced routes. Every route checks the socket, host and origin, ignores X-Forwarded-For, and responds with cache-control: no-store.
  • Redacted logs. The AccessKey appears as its first four characters; the SecretKey is never logged. Credentials are written only through the DSH credential store, never to the plugin's own config file.

Troubleshooting

SymptomCause / fix
The 「七牛云用量」 section does not appearThe bundle is not in dsh.profile.bundles. Check that dsh plugin --profile web add … succeeded, then restart dsh web.
Cannot find module …/lib/index.js on bootlib/ was never built. Run npm install && npm run build in the checkout.
cannot get property "webServer" without injectTwo copies of the plugin mounted at once. Keep a single entry in dsh.profile.bundles.
Panel loads but every figure is an auth errorCredentials missing or wrong. Check the 凭据 card for configured / source.
Resource-pack cards error, usage is fineThe AK lacks billing/IAM financial permission.
Key list is emptyThe roster could not be fetched: credentials missing or invalid, or the AK has no usage-query permission.
No glance card in the sidebarsidebarCard is false, or the sidebar is collapsed to the 56px rail.
The Details dialog is covered by another overlayThe dialog uses z-index: 60; a host overlay above that covers it.

Known limitations

  • Per-key filtering is unavailable for today. Upstream has not attributed the current day's usage to individual keys yet and returns a single api_key: "unknown" aggregate group. The key roster therefore comes from a "last 30 days, up to yesterday" window, and selecting a key while viewing today says plainly that the figures are account-wide. Query yesterday or earlier for per-key numbers.
  • Today's data is delayed. The panel pins a standing warning and shows the data watermark.
  • Zero-usage keys cannot be enumerated. The upstream usage response only lists keys that had usage in the queried window.
  • Lifetime vs month-to-date scope. A pack's used_amount is lifetime cumulative while month-overview's month_used is month-to-date; the panel labels both.
  • The sidebar card depends on shell class names. The plugin injects its container straight into the shell's footArea (substring-matched on [class*=sidebarCol] / [class*=footArea] / [class*=settingsArea]), because the foot's only extension seat (sidebar.footer.action) is a flex row that cannot host a block. If the shell renames those classes the card has no seat (no error; a body-level observer waits for one to appear).
  • Not yet verified against a real account. Every upstream fact in this plugin comes from documentation and fixtures. If something is off with real data, scripts/smoke.mjs is the tool that shows it.

Development

npm install
npm run build      # lib/index.js, lib/client.js, lib/types/**
npm run check      # tsc --noEmit
npm test           # vitest

The build emits two artifacts with different contracts, asserted by scripts/build.mjs before either is written:

  • lib/index.js — host half, self-contained ESM; the only import is node:crypto.
  • lib/client.js — browser half, a self-contained window.__ModuleLoader__.load({ id, factory }) bundle with react as the only external.

src/qiniu/respack.ts looks pure but reaches node:crypto through sign.ts, so the client half may only take values from react, src/client/** and src/qiniu/usage.ts — one bad value import breaks the whole client bundle. Type-only imports are fine.

node scripts/preview.mjs renders the panel to HTML (--theme dark|light, ?w=<px>), node scripts/screenshots.mjs regenerates the images in this README, and node scripts/smoke.mjs prints a normalised snapshot using AK/SK from the environment only. smoke.mjs is also the fastest way to verify upstream behaviour: with deliberately fake credentials it shows that the usage API reports authentication failure as HTTP 200 + {"status":false,"error":"UNAUTHENTICATED"} rather than a 401 — which is why the error classifier keys off the code text as well as the HTTP status.

DESIGN.md is the full design record — upstream API facts, signing traps, route contract, data model, caching, and a log of the real problems hit during implementation. Read it before contributing.

License

Apache-2.0. See LICENSE and NOTICE for attribution.

Comments

Loading…

Similar plugins

dsh-token-usage

by LaoYueHanNi

贴近 DSH 原生设计风格的 token 用量统计插件:实时记录每次请求的用量与费用,在 Web UI 中提供趋势图表、按模型定价明细和供应商配额显示。

UI & ExperienceManifest valid

★ 13

MIT

TypeScript

Oct 11, 2026

dsh plugin --profile web add @laoyuehanni/dsh-token-usage

by better-er

dsh·去重复 diff 展示插件

UI & ExperienceManifest valid

★ 12

↓ 480/wk

MIT

TypeScript

Oct 2, 2026

dsh plugin --profile web add dsh-edit-diff

by xinmo114514

DSH(DeepSeek Harness)Web 插件:设置页 Token 消耗仪表盘 —— 指标卡、近 7 天/逐时趋势图、按模型/会话分布,数据全部来自本机会话日志,零外部请求。

Manifest valid

★ 0

Unlicense

TypeScript

Aug 15, 2026

dsh plugin --profile web add dsh-usage-dashboard

by qxcool

DSH Desktop plugin: usage stats, plan quotas, custom HTTPS balance, 26-week heatmap

Manifest valid

★ 0

Apache-2.0

TypeScript

Sep 13, 2026

dsh plugin --profile web add dsh-usage-plus

by jieguanya

DeepSeek Harness (DSH) 余额插件:实时余额/今日消耗/7-30天趋势图

UI & ExperienceManifest valid

★ 0

MIT

JavaScript

Aug 22, 2026

dsh plugin --profile web add tugu-dsh-balance-widget

by xfpuls

DSH 用量与费用统计 + 提问置顶:本轮花费、今日 token 与消费、空闲/高峰时段,并钉住最新提问

Manifest valid

★ 0

MIT

JavaScript

Oct 6, 2026

dsh plugin --profile web add dsh-usage-suite