README
dsh-balance
DeepSeek API 账户余额 + OpenCodeGo(opencode.ai Go 计划)余量 · dsh web GUI 常驻插件
DeepSeek API 账户余额 + OpenCodeGo(opencode.ai Go 计划)余量 · dsh web GUI 常驻插件
一个为 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 仓库安装(推荐)
dsh plugin --profile web add github:linshule/dsh-balance
方式二:本地链接(开发模式)
# 克隆到 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 包(发布后可用)
dsh plugin --profile web add @linshule/dsh-balance
安装后重启 dsh web 生效(插件行由包内 cordis.patch.yml 的 dsh.bundle.patch 声明)。
快速开始
- 重启后点击左下角徽章(或 设置 → DeepSeek 余额)
- 粘贴
sk-...DeepSeek API Key 保存 —— 持久化到~/.dsh/ds-balance.json,重启无需重填 - OpenCodeGo 余量零配置:默认自动读取
~/.dsh/.credentials.yaml中的OPENCODE_GO_API_KEY(仅当默认提供商为opencode-go时;也可在设置页单独指定一个 Key 覆盖) - 拖动徽章调整位置,松手自动记忆
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。
响应语义
{
"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 解析优先级
- 设置页 / 徽章弹层保存的 Key(
ds-balance.json的opencodeGoKey) - DSH 凭据服务:
llm-pi-ai.providers['opencode-go'].apiKeyEnv(默认OPENCODE_GO_API_KEY,位于~/.dsh/.credentials.yaml;仅当默认提供商为 opencode-go 时读取) - 进程环境变量
OPENCODE_GO_API_KEY
配置文件
~/.dsh/ds-balance.json(权限 0600):
{
"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 分钟) |
开发与构建
# 依赖仅 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 linshule
更多「Web 界面与前端」插件
reactive-resume
作者 amruthpillai
A one-of-a-kind resume builder that keeps your privacy in mind. Completely secure, customizable, portable, open-source and free forever. Try it out today!
petdex
作者 crafter-station
A public gallery of animated pets for Codex, Claude Code, DeepSeek Harness, Hermes, OpenCode, Gemini CLI, and more.
claude-paper
作者 alaliqing
📖 Cross-agent research paper toolkit for Claude Code, Codex, OpenCode, and DeepSeek Harness—quick summaries, deep study materials, code demos, and a local web viewer.
aria
作者 dqsjqian
Modern C++20 MVVM framework — cross-platform, layered, coroutine-first. Reactive DAG (Property/Computed/Effect), Task<T>, and pluggable adapters (Qt6, AppKit, ...).
