dsh-status-balance
在 DeepSeek Harness Web UI 的输入框下方显示两个数字:本会话花费和钱包余额。点一下展开今日账本、可用天数和当前峰谷时段。
它是为「不打扰」设计的:一行、无文字标签、无动画、无声音、无通知、不参与对话。
[↗ ¥0.0043] · [👛 ¥6,053.41] ← 输入框下、上下文指示器之后
为什么这么小
- 零依赖、零构建:两个 JS 文件(Host + 浏览器),源码约 86 KB,没有 npm 依赖,没有编译步骤。
- 不花 token:不注册工具、不注入 system prompt、不发起额外模型请求。插件不进入对话链路。
- 不占注意力:一行 22px 的 pill,两个金额,两个小图标。详情只在你点击时出现。
- 按需请求:页面可见时 60 秒轮询一次;页面隐藏不请求。Host 侧 30 秒缓存、单飞、失败退避。
- key 不出 Host:API key 只在 Host 进程解析和使用;浏览器只拿到展示用的字符串。
- 数据最少:一个本地 JSON 账本,只存金额、token 数和 session id;不存 prompt、消息、工具输出。
对比常见的「桌面挂件」方向(角色、音效、气泡、多厂商、订阅额度、Codex 统计),这里刻意只做一件事:让余额和本机消耗一眼可见。
两个数字
| pill | 含义 |
|---|---|
| 左(流出图标) | 本会话消耗:tokenUsage 投影 × 当前峰谷价,随投影实时刷新,不轮询 |
| 右(钱包图标) | 钱包余额:Host 同源 route,60 秒可见轮询 |
点开之后
| 行 | 含义 |
|---|---|
| 账户余额 | 当前钱包总余额 |
| 充值余额 / 赠送余额 | 两者都非零时合并展示,都为零时隐藏 |
| 今日我的消耗 | 本进程按事件时间、峰谷价计算的今日 usage 花费;fork 继承的事件不重复计 |
| 今日余额减少 | 本进程观测到的钱包下降总额;含其他终端、其他会话、其他 key。观测起点晚于 00:00 时标签显示「(自 HH:mm)」 |
| 今日差额 | 余额减少 - 我的消耗,大于 ¥0.01 才显示;提示「钱被别处花了」 |
| 今日充值 | 观测到的钱包上升,非零时显示 |
| 预计可用 | 余额 / 近期日均降幅,显示 ≈ N 天 / >365 天 / —;没有余额历史时先用本机今日消耗外推(tooltip 会标注) |
| 当前时段 | 高峰价 / 谷时价,以及下一次切换时间 |
| 底部 | 更新时间、今日统计起点、错误原因、点击刷新 |
两个「今日」数字口径不同,这是刻意的:我的消耗回答「我花了多少」,余额减少回答「账户少了多少」,差额是发现其他终端/密钥在消耗的线索,不是精确归因。
峰谷价
默认按 DeepSeek 官方价(CNY / 百万 tokens);工作日 09:00–12:00、14:00–18:00(Asia/Shanghai)为高峰,其余与周末为谷时。价格表可用 config.prices 覆盖。
| 模型 | 谷时 输入 / 缓存命中 / 输出 | 高峰 输入 / 缓存命中 / 输出 |
|---|---|---|
deepseek-flash 等 flash 系 |
1 / 0.02 / 4 | 2 / 0.04 / 8 |
deepseek-v4-pro 等 pro 系 |
4.5 / 0.15 / 13.5 | 9 / 0.3 / 27 |
计算方法:(未缓存输入×输入价 + 缓存命中×命中价 + 缓存写入×写入价 + 输出×输出价) / 1_000_000。DeepSeek 不返回单次调用成本,所以这是按标价的估算,不是账单。
更新策略
| 场景 | 行为 |
|---|---|
| 页面打开 | 拉一次余额;会话消耗由投影实时驱动 |
| 页面可见 | 每 60 秒拉一次余额 |
| 页面隐藏 | 停止轮询,保留最后值 |
| 回到前台 / focus | 数据超过 30 秒才重拉 |
| 请求失败 | 30 → 60 → 120 秒退避,成功即重置 |
| 点击 pill | 打开详情并强制刷新余额(Host 端 10 秒下限) |
| Host 缓存 | 30 秒内复用;失败时 5 分钟内保留旧值并标记 stale |
首次启动
重启 Host 后:今日我的消耗会从当天会话回填(上限 400 会话 / 50 万事件,超出标记 partial);今日余额减少从本次进程第一次成功请求开始观测,标签会显示「(自 HH:mm)」;预计可用在既无历史、又无余额降幅时,先用本机今日消耗外推,等观测够久自动切换为余额口径。
安装
需要带 Web UI 的 DSH profile(composer.dock、tokenUsage / modelSelection 投影存在时可用)。
# 本地目录
dsh plugin --profile web add link:/absolute/path/to/dsh-status-balance
# 或从 GitHub
dsh plugin --profile web add github:ashuai/dsh-status-balance
安装后重启 dsh web(Host 半需要重启;只改浏览器半则刷新页面即可)。卸载:dsh plugin --profile web remove dsh-status-balance。
配置
所有键可选,写在 profile patch 该行的 config 下。
| 键 | 默认 | 说明 |
|---|---|---|
balanceUrl |
https://api.deepseek.com/user/balance |
余额接口 |
apiKeyRef |
DEEPSEEK_API_KEY |
凭据引用 |
routePath |
/plugin/dsh-status-balance |
同源 GET 路由 |
cacheTtlMs |
30000 |
成功缓存时长 |
failureBackoffMs |
15000 |
失败后的免请求窗口 |
staleMaxMs |
300000 |
旧值最长保留时间 |
timeoutMs |
8000 |
上游超时 |
minRefreshMs |
10000 |
强制刷新下限 |
prices |
见上 | timezone、peakWindows、weekendOffPeak、models、default;兼容扁平行 |
数据与隐私
- 账本:
$DSH_HOME/.dsh-status-balance.json(未设置时~/.dsh),整数「¥0.0001」单位,14 天历史,原子写 + 2 秒去抖。损坏时改名.corrupt-<ts>后重建,不阻塞。 - Host 只向外提供:余额字符串、时间戳、上游主机名、价格表、聚合金额、错误代码。
- 路由:同源、仅 GET、
Cache-Control: no-store,不加 CORS、不记请求日志。 - 不含 API key、不含会话内容。
边界(已知且刻意)
- 估算不是账单:DeepSeek 不返回单次成本;金额按标价算,折扣/赠送/计费差异不会体现。
- 余额减少依赖观测:从本进程当天第一次成功请求开始累计;重启前当天的变化不可回溯。
- 回填有窗口:只回填当天、创建时间在 24 小时内、最多 200 个会话 / 20 万条事件;超出标记
partial。 - 单进程假设:两个 Host 进程共享同一
DSH_HOME时账本会互相覆盖(无跨进程锁)。 - 路由无鉴权:与其它插件路由一致,只返回展示字段;服务监听在哪个网卡上,它就在哪里可达。
- 不做:多厂商、订阅额度、通知/音效/动画、桌面悬浮挂件、历史趋势图、其它 provider 的余额。
开发
index.js Host:余额 route、缓存、账本、峰谷价、趋势
client.js 浏览器:pill、详情弹层、投影读取、轮询
cordis.patch.yml bundle 挂载
locale/ 插件管理器的标题/描述
docs/DESIGN.md 设计记录(数据模型、状态机、取舍、测试锚点)
无构建步骤。改 client.js 刷新页面即生效;改 index.js 需要重启 dsh web。语法检查:node --check index.js && node --check client.js。
离线断言 109 条(账本状态机、峰谷边界、回填去重、弹层渲染与关闭、格式化);Host 路由在隔离 DSH profile 中验证。
License
MIT
No comments yet. Be the first to write one.