dsh-plugin-balance-panel

September 2, 2026 · View on GitHub

DeepSeek Harness cordis 插件:通用型多 provider 余额/用量面板 —— 查询各主流 API 账户余额与 Coding Plan 用量,并统计每日金额花费与 Token 消耗,右下角挂一枚液态玻璃气泡(点击展开明细面板)。

  • /balance [KEY_ENV] — 汇总所有已配置余额 provider 的余额(指定 KEY_ENV 时按 DeepSeek 格式查询单个凭证)
  • /balance alert [<金额>|off] — 查看 / 设置 / 关闭每日花费告警阈值(越过阈值时面板顶部红色横幅 + console 告警 + 桌面系统通知,同一 provider 同日同阈值只告警一次)
  • /plan — 汇总所有已配置的 Coding Plan 用量(OpenCode Go / Z.ai / Kimi:5h 滚动 / 每周 / 每月窗口 + 重置时间)
  • /stats [days=7] — 读取历史统计:每日 Token 消耗 + 各 provider 金额花费(本地数据,无需联网;1-60 天)
  • /cost [<会话ID前缀>]会话级成本统计:无参看近 7 天按会话汇总的金额(未定价模型列出 token 数),带前缀看单会话明细(调用次数、输入/缓存命中/缓存写入/输出/推理 token 分量、按模型金额与合计)
  • /cost price — 查看/管理模型单价表:/cost price sync 一键同步 DeepSeek 官方价目(各模型峰时单价 USD + 官方峰谷规则;手动设置的单价不被覆盖,冲突时列出);/cost price <模型前缀> <缓存命中> <未命中> <输出> [币种=CNY] 手动设单价(每 1M tokens),/cost price <前缀> off 删除覆盖;改价后整个历史按新价重算
  • /cost export [csv|json] [天数=60]用量/成本导出:CSV=逐调用明细(五路 token 分量、峰谷系数、现算金额,电子表格友好),JSON=全量(价表分层 + 峰谷 + 会话聚合 + 明细);写入 $DSH_HOME/exports/ 并返回路径
  • 右下角气泡 + 点击展开的明细面板(按 provider 分区)
  • 每日消费估算图(近 14 天,金额;按余额差分估算,非平台账单)与每日 Token 用量图(近 14 天,所有对话合计的 tokens),悬浮柱子即时显示当日数值
  • DSH 设置页「余额面板」分区:开关消费/Token 图表与悬浮数值,改动即时生效并持久化

支持的 provider

只需在 $DSH_HOME/.credentials.yaml 或进程环境变量里配置对应凭证,插件自动探测并显示已配置的 provider(未配置的自动隐藏,无需任何插件配置):

provider类型凭证环境变量余额/用量端点(默认)baseUrl 覆盖
DeepSeek API余额DEEPSEEK_API_KEYGET /user/balanceDEEPSEEK_API_BASE
Moonshot (Kimi)余额MOONSHOT_API_KEYGET /v1/users/me/balanceMOONSHOT_API_BASE
智谱 GLM余额ZHIPU_API_KEYGET /api/paas/v4/balanceZHIPU_API_BASE
OpenRouter余额OPENROUTER_API_KEYGET /api/v1/creditsOPENROUTER_API_BASE
OpenCode GoCoding Plan 用量OPENCODE_GO_API_KEYGET /v1/usageOPENCODE_GO_API_BASE
Z.ai / 智谱 GLM Coding PlanCoding Plan 用量ZAI_CODING_CN_API_KEYGET /api/monitor/usage/quota/limit(5h 滚动 / 每周 / 每月)ZAI_CODING_API_BASE
Kimi Coding Plan(Kimi Code 平台)Coding Plan 用量KIMI_CODING_API_KEYGET /usages(5h 滚动 + 每周;密钥须为 sk-kimi- 前缀)KIMI_CODING_API_BASE

Z.ai / Kimi 的 Coding Plan 用量密钥与按量付费密钥不通用(Kimi 须 Kimi Code 控制台创建的 sk-kimi- 密钥); 月度会员额度(Kimi 订阅页额度)无公开 API,Kimi 只展示 API 可查的 5h 滚动 + 每周窗口。

OpenAI / Anthropic / Gemini 等按量后付费服务没有公开的余额查询端点,无法内置; 如需展示,可先用任一余额 provider 的网关/中转(如 OpenRouter、Kimi、智谱)。

GUI

  • 气泡(折叠态):液态玻璃质感(毛玻璃 + 高光),内装水;水位 = Coding Plan 剩余用量(100 − 月用量;无月窗口的 provider 用 5h 滚动,如 Kimi),未配置 plan 时显示第一个余额 provider 的余额;水色按剩余量渐变(充足蓝 → 告警黄 → 耗尽红);DSH 推理/流式输出期间水面波动;可拖动(位置记忆),点击打开面板(Enter/Space 键盘亦可)。金额一律以符号展示(¥38.17),币种代码(CNY)只出现在接口/存储层。
  • 面板(展开态):按 provider 分区排列 —— 每个余额 provider 一张卡片(账户可用状态 + 各币种总额/赠送/充值 + 该 provider 的每日消费估算图),每个 Coding Plan provider 一组用量窗口(进度条 + 重置倒计时);面板底部是所有对话合计的每日 Token 用量图;头部可拖动,位置独立记忆(默认右下角锚定,不超出屏幕;记忆位置超出视口时自动钳回);Esc 或 × 收起。面板金额以「符号 + 缩写」展示(¥ CNY / ¥6.9 CNY),气泡保持纯符号(¥36.70)。
  • 柱状图悬浮数值:鼠标悬停在柱子上即时显示该日数值(消费图「5-28 · 估算 ¥3.33」、Token 图「5-28 · 12345 tokens」),fixed 层跟随指针并钳制在视口内(portal 到 body,不受面板 overflow 裁剪);设置页关闭后回退为原生 title 提示。
  • DSH 设置页「余额面板」分区:三个布尔开关 —— 显示「每日消费估算」图 / 显示「每日 Token 用量」图 / 悬浮柱状图显示数值;改动即时生效(面板与设置页共享同一 settings scope 实例),持久化到 settings 域(settings.json)。host 侧经 ctx.settings 注册 balance-panel namespace(schemastery schema),settings 服务为可选依赖:缺失时插件其余功能不受影响,面板按默认值(全部开启)渲染。
  • 每 30s 自动刷新(失败时 10s 快速重试,恢复后回到 30s;已有数据时后台刷新不闪烁「加载中」),可手动刷新;页面隐藏时暂停轮询,恢复可见立即刷新
  • 陈旧回退:某 provider 上游查询失败但上次有成功数据时,面板继续显示上次数据并提示「数据可能已过期」,而不是整块报错;从未成功过才显示错误。
  • 每日消费估算:每次成功拉到余额时记录采样点(1 小时节流、保留 60 天,含总额/赠送/充值三字段),按相邻采样差分解算:消费估算 = max(0, 注入 − Δ总额),其中 注入 = max(0,Δ充值) + max(0,Δ赠送) —— 消费无论从充值金还是赠送金扣减都能正确计入,充值/发放本身不计为花费;页面未打开的断档日按覆盖天数均摊,不会把整段花费堆到恢复日造成虚假尖峰。每个余额 provider 各自统计。(观测极限:充值/发放与消费同日发生时低估;赠送金回收会虚增——平台不提供逐笔账单时的固有近似。)
  • 每日 Token 用量统计:监听 DSH 会话事件里 provider 报告的真实 token 用量(assistant/messageusage),按自然日聚合,所有对话合计显示在一起(不区分 provider)。
  • 每日花费告警/balance alert <金额> 设置每日花费阈值(0/off 关闭、无参查看)。面板每次拉到新鲜余额后检查:某 provider 今日花费越过阈值即 console 告警 + 面板顶部红色横幅(列出所有越界的 provider 与金额)+ 桌面系统通知(写共享配置 $DSH_HOME/desktop-shell.jsonnotifyRequest,由 dsh-desktop-shell Electron 外壳弹出并清空;协议与 dsh-plugin-desktop-control 一致但互不依赖代码,未装外壳时写入无害),同一 provider 同日同阈值只告警一次(改阈值当天重新武装)。口径与花费图表一致(余额差分估算、断档按日均摊),阈值按各 provider 币种比较。
  • 会话级成本统计(/cost:每次模型调用的 usage 分量(未命中输入/缓存命中/缓存写入/输出/推理)连同模型名(data.message.source.model)按 session 落库(保留 60 天,与统计存储同文件);金额不落库,查询时按当前单价表现算 —— 改单价后历史整体重算。单价按模型前缀最长匹配(大小写不敏感),单位为每 1M tokens,与社区插件 dsh-cost-tracker 的口径对齐(未命中=inputTokens、命中=cacheReadTokens,推理 token 已含在输出里不另计价)。内置 DeepSeek 估算价(命中 0.5 / 未命中 2 / 输出 4 CNY,建议 /cost price sync 校准为官方价),其余模型默认未定价(照常记 token,提示补价)。峰谷计费(官方 2026-09 规则):工作日(周一至五)峰时窗口 09:00-12:00、14:00-18:00(UTC+8)内按标价,其余时段含整个周末 ×0.5(谷时窗口与系数随 /cost price sync 从官方页自动更新;旧版「夜间谷窗」口径已落盘的配置保持兼容,sync 后升级);窗口换算不随宿主机时区变化。
  • 官方价目同步与导出/cost price sync 拉取 api-docs.deepseek.com 静态价目页,解析各模型峰时单价(USD)与峰谷规则写入价目表——不覆盖手动设置的单价synced 标记区分来源,冲突时跳过并列出,手动设价即接管);/cost export [csv|json] [天数] 把逐调用明细(CSV)或全量数据(JSON,含价表分层/峰谷/会话聚合)写到 $DSH_HOME/exports/
  • 统计数据持久化在 $DSH_HOME/plugins/dsh-plugin-balance-panel/spend-history.json(v2:按 provider 分桶 + tokens + calls + cost 字段,旧版自动迁移;可用 DSH_BALANCE_SPEND_FILE 覆盖),纯本地、不上传、无需平台 token。

数据来自插件注册的 GET /plugins/balance/state(exact 路由,优先于 client-modules 的 /plugins 前缀):每个 provider 独立容错(一个查询失败不影响另一个分区),结果带 5s TTL 内存缓存 + 并发 single-flight(多视图轮询不会重复打上游),响应带 cache-control: no-store,非 GET 请求返回 405。

凭证

  • 通过 DSH 的 credentials 服务解析(ctx.credentials.resolve),支持 $DSH_HOME/.credentials.yaml 与进程环境变量;密钥绝不出现在对话、日志或任何 HTTP 响应中。
  • 自动探测:插件用 ctx.credentials.describe(只返回是否已配置,不暴露值)判断每个 provider 是否启用 —— 配置了凭证的 provider 才会被查询与展示。
  • 各 provider 的端点 baseUrl 可用上表的环境变量覆盖(如 MOONSHOT_API_BASE),无需改代码。

输出示例

DeepSeek API:账户可用:是
  ¥:总额 110.00(赠送 10.00 + 充值 100.00)
Moonshot (Kimi):账户可用:是
  ¥:总额 55.50(赠送 5.00 + 充值 50.50)
OpenCode Go:每月 97%(5h 16% / 每周 12%)
Z.ai Coding Plan(lite):每月 100%(5h 0% / 每周 —%)
OpenCode Go 套餐用量:
5h 滚动:16%,2026-08-14 11:54 重置
每周:12%,2026-08-17 08:00 重置
每月:97%,2026-08-21 19:08 重置

Z.ai Coding Plan(lite) 套餐用量:
5h 滚动:0%,重置时间未知
每月:100%(exhausted),2026-08-24 15:44 重置
== 会话成本(近 7 天)==
  a1b2c3d4  ¥4.50 · 12 次 · 最近 9-1 11:00
  e5f6a7b8  未定价 · 6 次 · 最近 9-1 10:30
  合计 ¥4.50
未定价模型(已计 token 未折算金额):glm-4.7 3,000,000 tokens
提示:/cost price sync 同步官方价目;/cost price <模型前缀> <缓存命中> <未命中> <输出> 手动设单价(每 1M tokens)
== 会话 sess-alpha 成本 ==
  时间 9-1 10:12 ~ 9-1 11:00 · 15 次调用
  输入 1,000,000 · 缓存命中 1,000,000 · 缓存写入 0 · 输出 500,000 · 推理 0 tokens
  deepseek-chat:9 次,¥4.50
  合计 ¥4.50

实现机制

  • host half/balance/plan 命令(dsh-commands 契约,{ kind, text } 结果)+ 数据路由(dsh-host-webserver 的 exact 路由)。所有注册(命令、路由、session/event 监听)包在 ctx.effect 生命周期里 —— 插件停止 / HMR 重载时自动注销,重载不会因 exact 路由重名而失败。
  • 适配器表:每个 provider 一个适配器(id/label/kind/keyEnv/path/defaultBase/parse),baseUrl 支持 <ID>_API_BASE 覆盖;响应解析统一为 balances[] / windows[] 两种结构,解析失败只影响该 provider。
  • client half:注册进 shell.overlay(list/root,order: 110)与 settings.section(DSH 设置页「余额面板」分区,id: balance-panel);服务声明 inject: ['slots', 'locale', 'settingsScope'];样式用 DSH 设计 token(--dsw-alias-*)自动适配深浅主题,<style> 注入带 data-plugin 去重守卫;插件自身 DOM 的 mutation 被过滤,不干扰推理中检测。面板偏好通过 ctx.settingsScope.bind({ namespace: 'balance-panel' }) 绑定 host 注册的 namespace。
  • 取消语义:命令调用方的 AbortSignal 与 10s 上游超时合并(AbortSignal.any),取消时返回「操作已取消」。

与同品类插件的差异(调研结论)

对 DSH / cordis / 相邻生态(Koishi、OpenCode、Pi)的同类余额插件调研后,本插件的定位与取舍:

能力本插件说明
多 provider 余额(DeepSeek/Kimi/智谱/OpenRouter)凭证自动探测,未配置即隐藏
Coding Plan(OpenCode Go / Z.ai / Kimi)用量窗口✅ 独有5h 滚动 / 每周 / 每月 + 重置倒计时;Z.ai 含套餐档位(lite/pro…)
气泡 + 可拖拽面板形态✅ 独有其他插件走统计条/侧边栏/文字命令
provider 独立容错 + 陈旧回退失败时回退上次成功数据并标记 stale,不把面板打成错误态
每日消费估算图(近 14 天)✅ 本地估算差分口径 max(0, 注入−Δ总额):消费扣充值金/赠送金均正确计入,断档日均摊
每日 Token 用量图(近 14 天,所有对话合计)✅ 真实数据来自 DSH 会话事件中 provider 报告的 usage
会话级成本(/cost,按模型单价 + 峰谷)按调用分量落库、改价重算历史;对标 dsh-cost-tracker / dsh-session-cost
官方价目一键同步 + 数据导出/cost price sync(不覆盖手动价、峰谷窗口随官方更新)+ /cost export CSV/JSON;对标 dsh-cost-meter / dsh-ui-usage-billing
i18n(zh/en 随 DSH 语言切换)见「国际化」一节
设置页分区(图表开关 + 悬浮数值)✅ 独有settings.section + settingsScope(设置页与面板共享 scope,实时生效)
页面隐藏时暂停轮询恢复可见立即刷新

调研对象(同品类):npm dsh-balance(统计条余额 + 会话估算)、dsh-balance-meterkoishi-plugin-deepseek-usage(花费图表)、opencode-provider-balance(TUI 侧边栏)。注意 npm 上的 dsh-balance 已被同名插件占用,本插件按 DSH 生态惯例命名为 dsh-plugin-balance-paneldsh-plugin-* 前缀)。

国际化(i18n)

  • GUI 全量中英双语:气泡与面板的所有文案走 DSH 的 locale namespace(balance,zh 为键集源、en 逐键对照,与上游 dsh-client-locale 约定一致);槽位注册声明 locale: 'balance',框架把绑定该 namespace 的 t() 注入组件 props,随 DSH「设置 → 语言」即时切换,无需重启。
  • 用量窗口标签按 keyrolling / weekly / monthly)翻译,不直接展示 host 下发的 label。
  • host 命令输出保持中文:上游 DSH 没有 host 侧运行时 i18n 服务(官方插件同样硬编码),按仓库 Chinese-first 约定以中文为命令输出语言;命令 description 为英文(命令注册表发现 UI 的惯例)。

兼容性

  • 平台:DSH web(dsh web),dsh.client.platform = "web"
  • peerDependencies:
    • @deepseek-ai/cordis ^4.0.1
    • @deepseek-ai/dsh-commands ^0.1.0-rc.6/balance/plan 注册契约)
    • @deepseek-ai/dsh-credentials ^0.1.0-rc.6(凭证解析)
    • @deepseek-ai/dsh-host-webserver ^0.1.0-rc.6(数据路由)
    • @deepseek-ai/dsh-client-locale ^0.1.0-rc.6(locale namespace / t() 注入)
    • @deepseek-ai/dsh-client-ui-slots ^0.1.0-rc.6(槽位契约)
    • @deepseek-ai/dsh-client-ui-settings ^0.1.0-rc.6(settingsScope 服务)
    • @deepseek-ai/dsh-settings ^0.1.0-rc.6(host 侧 settings 域;可选服务)
    • dependencies:@deepseek-ai/schemastery ^3.18.1(面板偏好 schema)
  • client 声明:inject: ['slots', 'locale', 'settingsScope'](服务级依赖),包级 dsh.client.inject 指向 @deepseek-ai/dsh-client-locale@deepseek-ai/dsh-client-ui-slots(模块表静态词)。
  • 对上游的依赖仅限上述公开契约与各家官方余额/用量接口(见「支持的 provider」表);接口端点或格式变化时,该 provider 独立报错并可用 baseUrl 环境变量覆盖。

安装

方式一:DSH CLI 安装(推荐)

dsh plugin add dsh-plugin-balance-panel

(使用特定 profile 时加 --profile <name>;该命令依赖 pnpm,环境里没有时改用方式二。)

方式二:从 npm 安装

npm install -g dsh-plugin-balance-panel   # 或装进 profile 的 node_modules

方式三:手动拷贝

构建后把整个插件目录复制到 profile node_modules:

cp -r dsh-plugin-balance-panel ~/.dsh/profiles/node_modules/

然后在 cordis.patch.yml 追加:

- insert:
    - id: balance
      name: dsh-plugin-balance-panel

重启 DSH 后输 /balance/plan 验证;右下角气泡与面板共用同一数据路由。

开发与构建

client half 必须打包成 window.__ModuleLoader__.load({ id, factory }) 形式才能被 web 前端加载(dsh-client-modules 的 Node half 会扫描 loader 树里 enabled 插件, resolve exports["./client"] 并 serve 进 /plugins boot graph)。

npm install            # devDependencies: esbuild(+ host 测试所需的 dsh-credentials/cordis)
npm run bundle         # scripts/bundle.mjs:esbuild 打包 → lib/client.js
npm test               # node --test:host 命令/路由契约测试 + client bundle 契约测试
npm run check          # node --check index.js + lib/client.js 语法校验
npm run preflight      # 发布/部署前预检(files 完整性 / bundle 契约 / 陈旧产物守卫 / i18n 键集)
npm run smoke          # 冒烟:mock ctx 实测已安装到 ~/.dsh/profiles 的实例(真实网络,需凭证文件)

host 测试不依赖真实网络:用 mock cordis ctx + mock fetch 实测命令、路由缓存、 single-flight、provider 独立容错与陈旧回退;client 测试在 vm 沙箱里验证 __ModuleLoader__ 契约。

本地验证(改完即见)

把构建产物原子化同步到运行中的 DSH profile 并刷新页面(npm run sync: 先写临时文件再按「元数据先、bundle 后」顺序 rename,避免热载不一致的半成品; 可用 DSH_PROFILE_NODE_MODULES 覆盖 profile 路径):

npm run sync

刷新浏览器后 boot manifest 的 rev 变化即说明新 bundle 已被 serve(同步时可传 web 地址作为参数,脚本会打印新旧 boot rev)。

发布

当前状态:测试期私密发布。 package.json 标记了 "private": true, 不会(也不应)发布到公共 npm。测试期请用本地路径或 git 依赖安装:

dsh plugin --profile web add file:<本仓库路>          # 本地路径安装
# 或作为 git 依赖(私有仓库需 npm 凭证):
npm install git+https://<私有仓库地>.git

插件转入稳定后:移除 "private": true,再执行 npm publishprepublishOnly 自动执行 preflight + 全量测试,未通过会中止发布)。

发布内容由 files 字段控制:index.jslib/client.jsREADME.mdLICENSE (源码与构建脚本、测试不随包发布)。

文件

index.js                 host half(命令 + 数据路由 + 凭证解析 + 缓存/陈旧回退/并发控制)
src/client.jsx           client 源码(气泡 + 面板 + zh/en 字典)
lib/client.js            client bundle(构建产物,勿手改)
scripts/bundle.mjs       本地构建脚本(esbuild)
scripts/preflight.mjs    发布/部署预检(含陈旧 bundle 守卫与 i18n 键集一致性)
scripts/sync-profile.mjs 原子化同步到 DSH profile
test/host.test.mjs       host 契约测试(mock ctx + mock fetch)
test/client.contract.test.mjs  client bundle 契约测试(vm 沙箱)
LICENSE                  MIT