- Главная
- Плагины
- Использование и биллинг
- dsh-usage-badge
dsh-usage-badge
ai-written/dsh-usage-badge
DeepSeek Harness 的用量徽标插件:侧边栏底部一行显示当天的 token 总量与估算费用,点开可看 24 小时 / 近 7 日 / 近 30 日 / 近 12 个月 / 按年用量,按 provider 筛选,并按 DeepSeek 官方定价与中国法定节假日计价。A usage badge plugin for DeepSeek Harness: today's tokens and estimated spend in the sidebar, with 24h / 7d / 30d / 1
Установка
dsh plugin --profile web add github:ai-written/dsh-usage-badgeREADME
dsh-usage-badge
DeepSeek Harness 的用量徽标插件:侧边栏底部一行「今日用量」显示当天的 token 总量与估算费用,点开可看 24 小时 / 近 7 日 / 近 30 日 / 近 12 个月 / 按年的用量与活跃度热力图,并按 DeepSeek 官方定价和中国法定节假日计价。

零依赖、零构建:宿主半只用 Node 内建模块,浏览器半是手写的单文件 bundle,折线图是手写 SVG。
安装
需要 Node ≥ 22.15,以及带 dsh plugin 命令的 DSH。
# 从 npm 安装
dsh plugin --profile web add dsh-usage-badge
# 或者从本地源码路径安装(把 <本仓库路径> 换成实际路径)
dsh plugin --profile web add <本仓库路径>
装完重启客户端。卸载:
dsh plugin --profile web remove dsh-usage-badge
用起来
侧边栏底部、就在「设置」上方那一行,从左到右是:「今日用量」标签 · 峰谷圆点 · 当天 token 总量 · 当天金额。每 5 秒自动刷新,鼠标移上去看明细(金额 / token / 请求数 / 当前档位),点一下打开弹窗。侧边栏收起时这一行缩成一个小方块。
峰谷圆点:谷时灰色,峰时橙色 —— 鼠标停在圆点上会显示 峰时 ×2 / 谷时 ×1 / 国庆节 · 全天空闲。
弹窗有两个页签:
-
用量 —— 五个时间区间(
24 小时/近 7 日/近 30 日/近 12 个月/按年)、按 provider 筛选(候选来自今天的 provider,但筛选同时作用于所有区间与热力图,所以只在历史里出现过的 provider 选不到)、金额/请求数/Token/缓存命中率四项合计,以及一张四序列折线图(金额、token 总量、请求数、缓存命中率)。鼠标移到图上显示该点的四项数值和参考线。点图例可以单独看某一条:点掉其余三条,它就会按自己的刻度铺满整张图;有隐藏项时图例尾部出现「全部显示」。区间按自然日 / 自然月切分:
近 7 日就是最近 7 个连续自然日,没有用量的那天保留自己的空槽位,不会把窗口拉长成 8 天。按年选一年,看那一年的 12 个自然月与年度合计 —— 年份下拉里的选项来自缓存里真实有数据的年份(新的年份第一次有用量就自己出现,不用改配置、也不用维护一份列表),跨年时不用等一年。这一年是直接向 SQLite 查询的,所以比快照窗口更早的年份也读得到;下面的热力图也跟着变成那一年的自然年格子(1 月 1 日 → 12 月 31 日,53 列正好一年;当年则画到今天)。折线图下面是近一年活跃度热力图,GitHub 贡献图那种方格:一列一周(周一起)、一行一个星期、每格一天,按当天金额分五档着色(可切 Token / 请求数)。鼠标停在格子上弹出和折线图同一张卡片:金额(¥)/ token 总量 / 请求数 / 缓存命中率(%)四行,标题是「日期 + 星期」(节假日带节日名,当天没用量则标「无用量」);标题右侧给出近一年的合计与「有用量的天数」。没有用量的那天照样占着自己的浅色格子,所以空白是真的空白。
-
单价配置 —— 官方定价、法定节假日日历、当前生效单价(覆盖行与兜底行都能在面板里增删改)。
单价:官方定价 + 你自己的覆盖行
官方单价来自 DeepSeek 官方定价页。 打开「单价配置」时抓取一次并解析中文页(人民币)—— 每个页面只抓这一次,切走再切回来不会重新联网,要更新点「重新获取」;表下面那行写着这份列表是什么时候抓的,超过 10 分钟会标出「几小时前」。确认无误后点「应用官方价格」写入 —— 它会覆盖官方页面点名的那些同名行,其余行原样不动。(键名匹配不区分大小写,但写入时用官方页面的拼写;所以你手写的大写变体如 DeepSeek-Flash 不会被合并,而是和官方行并存、在表里都看得到。)
官方页面没点名的模型(网关上的 gpt-5.6-*、glm-5.3-flash 之类),就在「当前生效单价」那张表里自己维护:新增一行 / 编辑 / 删除都在面板里点,每行可以写键、四个单价、倍率,以及这一行的峰谷规则(跟随表级 / 不参与峰谷 / 自定义)。表里会显示每一行当前怎么参与峰谷,所以「某一行有没有被乘峰谷」不用去翻 JSON。等价于直接改下面那个 pricing.json,两边是同一份文件。
币种就是人民币,面板里没有币种选项(徽标、合计、官方单价全是人民币,也没有汇率要配);另外两个开关——前缀回退和未匹配模型是否计价——在面板里点一下就能改(见下)。三个区块的说明性文字都收进了标题旁的 ⓘ 图标里,鼠标停上去才展开 —— 面板本身只留数字和你按得到的按钮。
价格表的键不区分大小写,四种写法:模型名 / provider|模型名 / provider|* / *|模型名。官方生成的 deepseek-flash 这一行会自己兜住 deepseek-flash-preview / deepseek-flash-opencode 这类带后缀的变体,不用你再加一行 —— 只要前缀后面是分隔符(- _ . : / @)就算命中,所以 gpt-4 不会吞掉 gpt-4o。想关掉这个回退,在面板里点一下**「关闭前缀回退」**就行(等价写法 "modelPrefixFallback": false);也可以用 deepseek-flash-* 这样的显式家族行自己划定范围(精确行永远优先于前缀行)。
一行都没匹配上的模型,默认按 default(兜底行)计价。兜底行的编辑/删除也在面板里:表里有 default 行时它列在表中(带编辑、删除);没有时表格下方是一行提示写明现在用的是内置模板的哪个费率,并给一个「添加兜底行」按钮。删掉之后表回到内置模板、面板会写明「当前 default 来自内置模板」,而下次点「应用官方价格」会按官方列表第一条重新生成(第一条就是它最便宜的那档 deepseek-flash;官方页面第一条最便宜这件事有测试钉着)。你自己写过的兜底行不会被 应用官方价格 覆盖 —— 它只补「没有」这件事。不想给未知模型估价,就在面板里点一下**「改为不计价」:它们的 token 与请求数照常统计,金额记 0,而且用量面板会列出具体是哪些模型**,所以那个 0 不会被误读成免费(等价写法是 "priceUnmatchedModels": false)。
官方页面改版导致解析失败时,面板会报错并保留原价格,不会静默算错。想核对线上页面是否还能解析:node test/official-pricing.live.mjs。
峰谷与节假日
官方规则:周一至周五(不含中国法定节假日)9:00-12:00、14:00-18:00 是高峰时段,其余时段 —— 包括周末和法定节假日全天 —— 都按空闲价。
插件内置了中国法定节假日日历(2025–2026,取自国务院办公厅的放假安排通知)。但它是价格表里 holidays.source 这个开关:写 "cn"(或点一次「应用官方价格」,它会自动打开)才算数,缺省时工作日节假日会被当成普通工作日按峰价计费 —— 面板在未启用时会这么写明。
峰谷对价格表里的每一行都生效,包括你后来手写加的行 —— 不用每行都写一遍 timeOfUse。想让某一行完全不参与峰谷(比如网关那边已经是固定折后价),在行编辑器里把「峰谷」选成不参与峰谷;想让它按别的倍率算,选自定义并写一整套 timeOfUse(写全:行内规则是整体替换表级规则的,漏了 peakMultiplier 就等于那一行不加价)。周末用 days 逐行控制,编辑器给的是 周一至周五 / 周末 / 每天 三档,数组写法([6,7])要手写 JSON;法定节假日用 "honorHolidays": false 逐行关掉(有些网关在国庆照样按自己的峰时收费),这个勾选框在峰谷选成「自定义」后出现。
周末永远按空闲价,即使国务院把它调休成上班日也一样:官方原文是把「周末」整体划作空闲时段的,调休后的周日仍然是周日。
文件放在哪
~/.dsh/storages/usage-badge/
├── pricing.json 价格表(「应用官方价格」写的就是它)
└── cache.sqlite 会话日志的折叠缓存(可以随时删,会自动重建)
缓存用的是 Node 内建的 SQLite(node:sqlite,随运行时一起提供,不需要装任何东西):一次保存只写「变化的那几天」,历史留在库里,内存里只装最近一年多。代价跟那个会话的大小有关、跟库里存了多少年无关 —— 实测(同一个会话只有一天变化时):1 天的会话 0.12 ms、30 天 0.82 ms、400 天 4.98 ms;旧的单文档缓存每存一次都要重写全部历史(两年历史时约 19 ms,且随年数线性增长)。常驻内存同样不随年数增长:实测两年历史 +6 MB(旧缓存 +14 MB)。运行时不提供 node:sqlite 时自动退回旧的 cache.json 单文档格式;从旧版本升级时会把 cache.json 改名为 cache.json.migrated 保留下来(不删),并在启动日志里写明 —— 那个文件之后再也不会被读,确认新版本没问题后可以随手删掉(它只是万一要退回旧版本时用的副本)。全新安装时没有 cache.json 也完全正常:直接建一个空的 cache.sqlite,从会话日志折一遍。
cache.sqlite 万一读不出来(写坏了、是别的程序的文件、备份只拷了一半),插件会把它改名成 cache.sqlite.corrupt-<时间戳> 并新建一个能用的,而不是从此退化到慢的那条路 —— 原始文件保留着可以事后检查。但如果它只是写不进去(只读属性、ACL 变了、盘满了、另一个宿主正锁着它),那就按只读使用、原样不动:为了一个权限问题把几年的历史挪走,是比慢得多的错误。如果它其实是更新版本写的(你降级了插件),同样原样放着、只按只读使用,绝不覆盖 —— 字节级不变,有测试钉住。
插件只读DSH 的会话日志(~/.dsh/sessions),不改动它们;jsonl 和 jsonl.zstd 都支持。日志被删掉后,那段历史靠缓存继续计入(缓存也丢了才会消失)—— 面板的 ⓘ 里写明了当前用的是哪种缓存。
已知限制
- 首次启动要冷扫一遍全部会话日志(200 多份实测约 10 秒;分片让出事件循环,界面不会卡住)。之后走增量,几乎瞬时。
- 历史依赖日志:日志被删掉后靠缓存继续计入;缓存也丢了,那段历史就没了。(日志不是被删掉而是变短/还原成更早的备份时,那个会话的历史会跟着变少 —— 折叠按当前文件内容重建该会话。)
- 日粒度区间仍只覆盖最近一年:
近 7 日/近 30 日/近 12 个月与它们下面的滚动热力图都基于快照的最近 400 天。要看更早的日子,用按年:那一档的月度合计、年度总额与自然年热力图都是直接查缓存库的,任何一年都在。 - 只统计 DSH 记进日志的调用:某个东西直接请求外部 API 且不向 DSH 上报 usage,这部分统计不到。
- 数字是估算:token 口径和官方账单的列数不同,对账请以金额为准。
开发
npm install # 只为测试装 react / react-dom
npm test # 6 个套件:包契约、定价、节假日、官方定价解析、缓存存储、浏览器半渲染
改了东西怎么生效:
| 改了哪里 | 要做什么 |
|---|---|
lib/client.js(界面、图表) | 刷新页面即可 |
lib/index.js 等宿主半 | 重启客户端 |
宿主半和界面半各带一个版本号(HOST_API_VERSION / REQUIRED_HOST_API),对不上时面板顶部会直接说明该「重启客户端」还是该「刷新页面」—— 不用再靠「按钮点了没反应」去猜:宿主半装载在进程启动时,只刷新页面拿到的是新界面配旧宿主,而旧宿主不认识的新写入会返回 200 并什么都不做。
更详细的东西(实现取舍、官方政策原文、路由清单、配置字段语义、当年的踩坑记录)在 docs/design-notes.md。
License
MIT
Похожие плагины
DeepSeek-Balance-Whale-Widget
meteornox/deepseek-balance-whale-widget
dsh-context
bowenliang123/dsh-context
dsh-cost-meter
han-1413141/dsh-cost-meter
TokenLedger
zh667/tokenledger