Bundle
dsh-balance-status
在 DSH Web 底部状态行(x 轮 x 步 · tok/s · tok · 缓存命中)之后追加 DeepSeek 账户余额,左键单击弹出用量详情
- Source
- yknBugs
- License
- MIT
- Updated
- Updated yesterday
Readme
# dsh-balance-status
在 DSH Web 界面**底部状态行**(`x 轮 xx 步 · xx tok/s xx M tok · 缓存命中 xx%`)之后追加一枚 **DeepSeek 账户余额**,左键单击弹出用量详情面板。
```
⟳ 1 轮 89 步 · 262 tok/s ⛁ 9.1M tok · 缓存命中 96% 余额 ¥32.49
```
**左键单击余额** → 立即刷新一次并弹出面板(再点一次关闭,点空白处或 Esc 也可关闭):
```
DeepSeek 余额
─────────────────────────
余额 ¥32.49
充值 ¥32.49
赠送 ¥0.00
当前对话已用 ¥0.20
当前进程已用 ¥0.35
点击余额刷新 · 点击空白处或 Esc 关闭
```
不写任何会话历史、不画图、不做动画,就是一行状态文字加一个小面板。
## 前置条件
**必须**在 DSH 凭据里配置 `DEEPSEEK_API_KEY`(余额接口需要它)。没配也能装,状态行会显示 `余额 未配置`。使用方式见 DSH 设置里的凭据页,或直接编辑 `$DSH_HOME/.credentials.yaml`:
```yaml
DEEPSEEK_API_KEY: sk-xxxxxxxx
```
可选:
- 走内部网关时设置 `DEEPSEEK_BASE_URL`(或用 DSH 设置里 `llm-deepseek` 的 `baseURL`),插件会自动跟随;否则用 `https://api.deepseek.com`。
## 安装
### 本机(打包成 tarball 安装:真实复制,推荐)
**不要用 `link:`**。`link:` 是符号链接,源码目录一旦移动或删除,插件就失效。正确做法是先打包再安装,
pnpm 会把文件真实复制进 profile 的 `.pnpm` 目录,装完之后源码目录放哪、删不删都不影响运行:
```powershell
# 1) 在插件目录里打包(只包含 files 字段列出的文件)
cd <插件目录>
pnpm pack # 产出 dsh-balance-status-1.0.0.tgz
# 2) 安装该 tarball
dsh plugin --profile web add file:<插件目录>\dsh-balance-status-1.0.0.tgz
```
装完**重启 `dsh web`**,再 F5 刷新浏览器。
> 直接复制整个 `dsh-balance-status` 目录到别的机器,把上面的路径换掉即可;本地 tarball 安装不需要联网。
### 升级(改了源码之后)
`file:` 依赖指向的是那一次打出来的 tarball 快照,改了源码必须重新打包并覆盖安装:
```powershell
cd <插件目录>
pnpm pack
dsh plugin --profile web add file:<插件目录>\dsh-balance-status-1.0.0.tgz # 覆盖安装
```
然后重启 `dsh web`。
> **移动或删除本目录之后要注意什么**:已装好的副本是独立复制,移动/删除本目录**不影响它继续运行**。
> 但 profile 里记录的依赖 spec 是 `file:<本目录>\...tgz`,所以之后再执行任何 `dsh plugin add/remove/update`
> 时 pnpm 会重新解析这个路径 —— 路径失效会让那次安装失败。因此移动目录后,请从新路径重新执行一次上面的
> `add` 命令覆盖安装即可。
### 开发模式(可选,仅限本机调试)
想边改边看效果可以用链接安装,但**必须记住它是符号链接**:
```powershell
dsh plugin --profile web add link:<插件目录绝对路径>
```
### 其他设备(从 Git 仓库安装)
把本目录推到一个 Git 仓库(仓库根目录就是本目录,即 `package.json` 所在层),然后:
```powershell
dsh plugin --profile web add github:<用户名>/<仓库名>
```
如果 pnpm 提示拦截构建脚本,按提示在 `%USERPROFILE%\.dsh\profiles\web\pnpm-workspace.yaml` 的 `allowBuilds` 下加上本包名再重跑。
### 验证
```powershell
dsh --profile web --dump-config | Select-String dsh-balance-status
```
浏览器 F5 后,状态行末尾应出现 `余额 ¥xx.xx`。
## 卸载
```powershell
dsh plugin --profile web remove dsh-balance-status
```
重启 `dsh web` 后状态行恢复原样。
## 刷新策略
DeepSeek 的余额接口本身**最多可能有 5 分钟延迟**,所以刷得比这更勤只是白打接口。默认策略:
- **自动刷新:5 分钟一次**(与数据延迟对齐,每小时约 12 次请求)。
- **点击余额:强制立即刷新一次**,绕过一切缓存,同时开关详情面板。
- 宿主端另有 **30 秒结果缓存**,只为兜住同一瞬间的重复请求(多标签页等);点击的强制刷新不受它影响。
想调整只改 `lib/client.js` 顶部一个常量,然后重新打包安装:
```js
var REFRESH_MS = 300000 // 自动刷新间隔;设为 0 = 完全关闭自动刷新,只在点击时查询
```
改完记得 `pnpm pack` + 重新 `add` 那个 tarball,再重启 `dsh web`。
## 两个用量数字怎么算的
采用**余额差值记账**,不依赖任何价格表,因此 DeepSeek 调价也不会算错:
- `当前进程已用` = 自 `dsh web` 进程启动后**第一次观测到余额**起,余额**下降部分**的累计;重启进程即归零。
- `当前对话已用` = 自该会话**第一次观测到余额**起,余额下降部分的累计;开新对话(新 sessionId)即归零,F5 刷新页面不会丢。
- 充值造成的余额上升不会记成负数,只是把基准点抬高。
- **全部只存在于宿主进程内存中,绝不写入会话记录**,以保证会话日志格式的向后兼容。代价是重启后这些用量数字永久消失(这是刻意接受的取舍)。
已知限制:余额接口是 0.01 元粒度且可能有延迟,小额消耗要攒到 1 分钱才体现。另外多个对话同时开着时,两个会话各自按自己的基准计算,会互相包含对方的消耗(余额记账法的固有限制)。
## 实现说明
| 半边 | 文件 | 职责 |
| --- | --- | --- |
| 宿主 | `lib/index.js` | 解析凭据与端点、调用 `GET {baseURL}/user/balance`(30 秒缓存)、维护两个内存账本、注册 `/dsh-balance-status/balance` 只读 JSON 路由 |
| 浏览器 | `lib/client.js` | 预构建 bundle,向 `conversation.composer.dock` 注册余额按钮、向 `shell.overlay` 注册详情面板,5 分钟轮询 + 点击强制刷新 |
几个刻意的实现选择:
- **浏览器半边是预构建产物**:DSH 的 `client-modules` 直接按字节提供 `exports["./client"]`,不做转换,所以该文件必须保持 `window.__ModuleLoader__.load({ id, factory })` 工厂格式,并且只 `require` 平台种子模块(`react`)。改它之后要重启 `dsh web` 生效,不需要任何构建步骤。
- **状态行对齐**:自带状态行根节点有 `padding-top: 4px`,所以行内改为 `align-items: flex-start` 并给余额按钮同样的 `4px` 上边距,两者按钮顶边严格落在同一像素行。
- **面板样式逐条照搬**自带状态浮窗(`ui-chat` 的 `stat-dialog.module.css`):`var(--dsw-specific-menu)` 背景、`var(--dsw-elevation-prominent)` 阴影、12px 圆角、12/18 字号行高、`dl/dt/dd` 网格,保证与「缓存命中」浮窗观感一致。
- **关闭面板不用全屏遮罩**:遮罩会吃掉滚轮事件导致无法浏览对话,改为 `document` 上的 `mousedown` / `keydown` 监听。
- **余额查询走宿主进程的 `fetch`**,浏览器半边只访问本地只读路由,密钥永远不进浏览器。
### 安全提示
`/dsh-balance-status/balance` 会返回账户余额(不含密钥)。它由 DSH 的 Web 服务器提供,沿用 DSH 自身的鉴权与监听地址;请保持 DSH 监听在 `127.0.0.1`,不要把它直接暴露到公网。
## 兼容性
按 DSH `0.1.5-rc.2` 编写,依赖以下稳定契约:
- 插槽 `conversation.composer.dock`(自带状态行的位置)与 `shell.overlay`(框架级浮层);
- 宿主服务 `webServer`、`credentials`、`settings`;
- 主题变量 `--dsw-specific-menu`、`--dsw-elevation-prominent`、`--dsw-alias-*`、`--dsh-content-font-size-secondary`。
若将来自带状态行的内边距或插槽键变化,只需相应调整 `lib/client.js` 顶部 `PILL_CSS` 里的对齐规则。
## 来源与许可
MIT。余额接口(`GET /user/balance`)与「余额差值记账」思路参考了开源项目
[DeepSeek-Balance-Whale-Widget](https://github.com/MeteorNOX/DeepSeek-Balance-Whale-Widget)(MIT)。
本插件只保留其核心取数与记账逻辑,去掉了挂件、音效、拖拽与动画,改为挂在状态行上的一行文字。
Install
dsh plugin --profile web add github:yknBugs/dsh-balance-status
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-balance-status from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.