Bundle
@linshule/dsh-balance
DeepSeek API 账户余额 + OpenCodeGo 余量实时显示:左下角悬浮徽章(可拖拽,双段显示)+ 两个设置页;Host 经 curl 调用官方余额/余量接口,API Key 持久化在 ~/.dsh/ds-balance.json,OpenCodeGo Key 自动读取 DSH 凭据。
- Source
- linshule
- stars
- 5 stars
- License
- MIT
- Updated
- Updated 24 days ago
Readme
# dsh-balance
> DeepSeek API 账户余额 + OpenCodeGo(opencode.ai Go 计划)余量 · dsh web GUI 常驻插件
一个为 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(dsh)Web GUI 打造的**双指标监控插件**:
左下角悬浮徽章同时显示 **DeepSeek 账户余额**(人民币/美元)与 **OpenCodeGo 计划余量**(近 5 小时 / 近 7 天 / 近 30 天三窗口),点击可展开详情、就地管理 Key,并支持自动刷新。

> 上图为示意渲染。实际徽章位于左侧边栏左下角、设置按钮上方,可拖拽。
---
## 功能特性
### 徽章(左下角悬浮,可拖拽)
- **双段显示**:`DeepSeek 余量 ¥4.92 · Go 余量 100%`
- **状态圆点**:🟢 可用 / 🟡 偏低(剩余 20–50%)/ 🔴 不可用或出错 / ⚪ 未配置
- **可拖拽**:按住拖动调整位置,松手记忆(浏览器 localStorage,默认 `left:12, bottom:110`)
- **点击弹层**:DeepSeek 余量明细(总余额 / 充值 / 赠金、可用状态)+ OpenCodeGo 三窗口进度条(已用 % · 剩余 % · 重置时间)+ Key 内联保存 / 清除 + 立即刷新
### 设置页(设置 → 两个独立分区)
- **DeepSeek 余额**:API Key 管理(保存 / 清除)、自动刷新间隔(30 秒 / 1 分钟 / 5 分钟)、余额明细
- **OpenCodeGo 余量**:Key 管理(选填,留空自动读取 DSH 凭据)、三窗口余量明细与重置时间
### 刷新策略
- 模块级轮询:插件存活期间始终按设定间隔刷新**余额 + 余量**(与哪个界面挂载无关)
- 默认 1 分钟,可调;刷新间隔跨重启记忆
- 网络抖动自愈:curl 走 HTTP/1.1 + 自动重试(规避 Windows schannel 瞬时断连 exit 56)
### 安全
- 所有 `/api/ds-balance/*` 路由**仅回环地址(127.0.0.1 / localhost)可访问**,Key 绝不离开本机
- Key 以 `0600` 权限持久化在 `~/.dsh/ds-balance.json`(仅本机可读)
- 设置页在线保存后重启不丢失
---
## 安装
### 方式一:从 GitHub 仓库安装(推荐)
```bash
dsh plugin --profile web add github:linshule/dsh-balance
```
### 方式二:本地链接(开发模式)
```bash
# 克隆到 web profile 同盘目录(pnpm 在 Windows 上对跨盘 link: 绝对路径会拼接错误)
git clone https://github.com/linshule/dsh-balance.git <profile>/plugins/ds-balance
dsh plugin --profile web add link:./plugins/ds-balance
```
### 方式三:npm 包(发布后可用)
```bash
dsh plugin --profile web add @linshule/dsh-balance
```
安装后**重启 `dsh web`** 生效(插件行由包内 `cordis.patch.yml` 的 `dsh.bundle.patch` 声明)。
---
## 快速开始
1. 重启后点击左下角徽章(或 设置 → DeepSeek 余额)
2. 粘贴 `sk-...` DeepSeek API Key 保存 —— 持久化到 `~/.dsh/ds-balance.json`,重启无需重填
3. **OpenCodeGo 余量零配置**:默认自动读取 `~/.dsh/.credentials.yaml` 中的 `OPENCODE_GO_API_KEY`
(仅当默认提供商为 `opencode-go` 时;也可在设置页单独指定一个 Key 覆盖)
4. 拖动徽章调整位置,松手自动记忆
---
## OpenCodeGo 余量详解
### 数据来源
官方接口:`GET https://opencode.ai/zen/go/v1/usage`(Bearer 认证)
前端域名备选:`https://opencode.ai/api/v1/usage`、`https://api.opencode.ai/v1/usage`
接口实现见官方仓库
[anomalyco/opencode `packages/console/app/src/routes/zen/go/v1/usage.ts`](https://github.com/anomalyco/opencode/blob/dev/packages/console/app/src/routes/zen/go/v1/usage.ts)。
### 响应语义
```json
{
"usage": {
"rolling": { "status": "ok", "percent": 0, "resetsAt": "2026-08-16T15:49:42.289Z" },
"weekly": { "status": "ok", "percent": 0, "resetsAt": "2026-08-17T00:00:00.289Z" },
"monthly": { "status": "ok", "percent": 0, "resetsAt": "2026-09-16T10:44:14.289Z" }
}
}
```
| 字段 | 含义 |
|---|---|
| `percent` | **已用百分比**(官方 `usagePercent`,0–100;剩余 = 100 − percent) |
| `status` | `ok` 正常 / `rate-limited` 额度耗尽(视为剩余 0) |
| `resetsAt` | 该窗口重置(滚动)时间,ISO 8601 |
| 兼容 | 旧式 `used` / `limit` 数值对结构同样可解析(已用 = used,剩余 = limit − used) |
### 徽章颜色规则
按三窗口中**最低剩余占比**着色(百分比为剩余):
| 剩余占比 | 颜色 |
|---|---|
| > 50% | 🟢 绿 |
| 20–50% | 🟡 黄 |
| < 20% | 🔴 红 |
| `rate-limited` / 查询失败 | 🔴 红 |
### Key 解析优先级
1. 设置页 / 徽章弹层保存的 Key(`ds-balance.json` 的 `opencodeGoKey`)
2. DSH 凭据服务:`llm-pi-ai.providers['opencode-go'].apiKeyEnv`
(默认 `OPENCODE_GO_API_KEY`,位于 `~/.dsh/.credentials.yaml`;仅当默认提供商为 opencode-go 时读取)
3. 进程环境变量 `OPENCODE_GO_API_KEY`
---
## 配置文件
`~/.dsh/ds-balance.json`(权限 `0600`):
```json
{
"apiKey": "sk-...(DeepSeek)",
"opencodeGoKey": "sk-...(OpenCodeGo,可选)",
"refreshIntervalMs": 60000
}
```
浏览器本地状态(localStorage):徽章位置 `dsh-balance.pos`、刷新间隔 `dsh-balance.intervalMs`。
---
## API 路由(仅回环)
| 路由 | 方法 | 说明 |
|---|---|---|
| `/api/ds-balance/status` | GET | 配置状态:DS / Go 是否有 Key(含掩码,如 `sk-****1670`) |
| `/api/ds-balance/balance` | GET | DeepSeek 余额实时查询(并发去重) |
| `/api/ds-balance/opencodego` | GET | OpenCodeGo 余量实时查询(并发去重,Key 自动解析) |
| `/api/ds-balance/key` | PUT | 保存 Key:`{ "key": "...", "target": "deepseek" \| "opencodego" }`(target 缺省 deepseek) |
| `/api/ds-balance/key` | DELETE | 清除 Key:`?target=opencodego` 时只清 Go Key(缺省清 DeepSeek Key) |
防护:非回环地址一律 `403`;请求体 ≤ 16 KiB;`sec-fetch-site: cross-site` 拒绝。
---
## 架构
```
┌─ dsh web profile(host 进程)─────────────────────────────┐
│ lib/index.js(cordis 插件, bundle patch 装配) │
│ ├─ subprocess → curl.exe │
│ │ ├─ GET https://api.deepseek.com/user/balance │
│ │ └─ GET https://opencode.ai/zen/go/v1/usage │
│ └─ /api/ds-balance/{status,balance,opencodego,key} │
├─ 浏览器(web GUI)─────────────────────────────────────────┤
│ lib/client.js(window.__ModuleLoader__ 模块) │
│ ├─ shell.overlay → 左下角可拖拽双段徽章 + 弹层 │
│ ├─ settings.section → 「DeepSeek 余额」设置页 │
│ └─ settings.section → 「OpenCodeGo 余量」设置页 │
└───────────────────────────────────────────────────────────┘
```
- **Host**:不依赖 dsh 源码改动;`cordis.patch.yml` 把插件行插入 web profile roster
- **Client**:同源 fetch 调 /api/ds-balance 路由;挂载失败仅 console 告警,不影响 GUI
- 并发去重:同一路由的并发请求共享同一次远端查询(`pending` / `pendingGo`)
---
## 常见问题(FAQ)
| 现象 | 原因与处理 |
|---|---|
| 徽章显示「未配置」 | 两个 Key 都未配置:点击徽章内联填入 DeepSeek Key;Go 余量会自动读凭据 |
| Go 弹层显示「Key 无效(HTTP 401)」 | `OPENCODE_GO_API_KEY` 与 opencode.ai 账户不匹配,更新凭据或设置页覆盖 |
| Go 弹层显示「无 OpenCode Go 订阅权限(HTTP 403)」 | 该 Key 无 Go 计划;需在 opencode.ai 开通 |
| Go 圆点变红但 percent 正常 | 三窗口中有窗口 `rate-limited` 或低于 20% 剩余 |
| balance 查询报「curl 退出码 56」 | Windows schannel 瞬时断连:插件已用 HTTP/1.1 + 重试自愈,持续出现请检查网络/代理 |
| 改了 client.js 但 GUI 没变化 | 浏览器缓存:强制刷新(Ctrl+F5);host 改动需重启 `dsh web` 或热重载 |
| 徽章位置/间隔「丢了」 | localStorage 被清空;属预期(默认 left:12 bottom:110 / 1 分钟) |
---
## 开发与构建
```bash
# 依赖仅 node 内置模块 + cordis/dsh web 运行时服务,无第三方运行时依赖
node --check lib/index.js && node --check lib/client.js
# 打包(发布 npm / GitHub Release 用)
npm pack # 产出 @linshule/dsh-balance-<version>.tgz
# 热重载 host(免重启,DSH 开发工具)
# 在 DSH 会话中调用 dev_reload_package(packageName: ds-balance)
```
`dsh.client` 声明(package.json)使浏览器半端在 GUI 侧自动加载;`lib/client.js` 为
`window.__ModuleLoader__` 形态,遵循 dsh web client plugin 规范。
---
## 版本记录
| 版本 | 内容 |
|---|---|
| v0.1.0 | 首发:DeepSeek 余额徽章 + 设置页,curl 走官方余额接口 |
| v0.2.0 | 新增 OpenCodeGo 余量:双段徽章、三窗口进度条、Key 凭据自动解析、新设置页 |
| v0.2.1 | UI 对称:弹层补「DeepSeek 余量」标题、徽章首段同措辞 |
| v0.3.0 | 包名 scope 与 GitHub 统一:`@linxin666/dsh-balance` → `@linshule/dsh-balance` |
---
## License
MIT © 2026 linshuleInstall
dsh plugin --profile web add github:linshule/dsh-balance
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 linshule-dsh-balance from the hub
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.