- Startseite
- Plugins
- Nutzung & Abrechnung
- dsh-usage-meter
dsh-usage-meter
gaolin89898/dsh-usage-meter
Sidebar widget that follows the session's current service and shows its plan quota or balance — OpenCode GO rolling, weekly and monthly windows with time bars, MiniMax usage, and DeepSeek, OpenRouter or Moonshot balances.
Installation
dsh plugin --profile web add github:gaolin89898/dsh-usage-meterREADME
把额度放进侧边栏
dsh-usage-meter 是 DSH(DeepSeek Harness)的侧边栏小组件:跟随会话当前所用服务,实时显示对应的额度或余额——OpenCode GO 的 5 小时 / 周 / 月用量窗口,MiniMax 的滚动与周用量,DeepSeek / OpenRouter / Moonshot 的可用余额。每条用量条下再叠一条时间条——额度花得快还是慢,一眼可见。
DSH ≥ 0.1.7 · MIT License · ● v1.0.0
第一次装 DSH 插件?直接看使用者指南,一步步照做即可。
01 快速开始
三步,从安装到看到第一条用量。
从本地源码目录安装
# install into the web profile
$ dsh plugin --profile web add ./dsh-usage-meter
# GO key → ~/.dsh/.credentials.yaml
OPENCODE_GO_API_KEY: sk-...
# restart the web service
$ dsh web
- 安装到 web profile ——
--profile web添加本地目录(desktop 同理,换成你实际用的 profile 名);依赖 pnpm,没有就先corepack enable。dsh plugin add会自动把包的dsh.bundle.patch合并进 profile 的 bundle 层栈,不需要手改 cordis.patch.yml,也不需要软链。 - 写入 API key —— 在
~/.dsh/.credentials.yaml里加一行OPENCODE_GO_API_KEY: sk-...,key 在 opencode.ai/auth 创建。即使走默认的dsh-opencode-go来源也要配好这一步:一旦回退到内置提供商,用的正是这个 credential。 - 重启并硬刷新 —— 完全退出 DSH 再启动(不是刷新页面),浏览器再
Cmd/Ctrl+Shift+R。装完侧栏底部即出现小组件;任意对话输入/opencode-go可输出同样的数字。
本地目录是
link:安装,依赖从项目真实路径解析。若启动报Cannot find package '@deepseek-ai/schemastery',按本地 link 安装的依赖解析建一个 junction 即可。
02 功能一览
一个小组件,覆盖用量、服务到状态的完整反馈。
| 三条窗口,一条时间轴 5h / 周 / 月三条用量条,各带重置倒计时;侧栏收起时收缩为紧凑百分比徽标。 |
额度与时间对照 用量条下再叠一条时间条:灰段是已流逝,蓝段是剩余;快慢一眼可见。与用量条同高同圆角,悬停显示两侧百分比,窗口重置时灰段占满归零。 |
| 跟随当前服务 切换模型或会话,侧栏即时换成对应服务的额度或余额;旧请求不会覆盖新服务的数据。 |
密钥不出端 同源代理:浏览器只访问本插件在 host 注册的路由,API key 永不离开 host,也没有 CORS 问题。 |
03 服务覆盖
同一个接口,按当前服务返回最合适的数字。Host 实时解析凭据,密钥不会进入浏览器。
| 服务 | 显示内容 | 来源 |
|---|---|---|
| OpenCode GO | 滚动、周、月用量与重置时间 | ● 双来源 |
| MiniMax 国内 · 国际 | Coding Plan 的滚动与周用量;不补造月额度或重置时间 | ○ 内置 |
| DeepSeek API · 登录账号 | 按币种显示可用余额;登录账号合计充值与赠送钱包 | ○ 内置 |
| OpenRouter | 总充值减去已用金额 | ○ 内置 |
| Moonshot 国内 · 国际 | 可用余额 | ○ 内置 |
| 其他服务 · 自定义代理 | 提示暂不支持查询 | — |
来源图例:● 双来源 = 可经 dsh-opencode-go 插件或内置提供商两条路径查询(见 04 额度来源与回退);○ 内置 = 本插件按该服务自己的接口直连(见 HTTP 接口);— = 无查询路径。
小组件通过 GET /opencode-go/usage?provider=<服务路由>&model=<模型> 查询。Host 根据当前服务的实时配置解析凭据,不按模型名称猜测服务;缓存按服务、模型、凭据分别隔离。未配置凭据、未登录、接口失败各有对应状态——小组件显示对应状态,而不是空白。
llm-pi-ai 配置的 GO 路由优先使用该路由自己的凭据;仅当它与额度来源中的账号及网关一致时才复用原有 GO 来源设置。旧版 DSH(没有模型选择服务)、不带查询参数的请求以及 /opencode-go 命令,继续使用原有 GO 来源配置。
04 额度来源与回退
配置项 quotaSource 决定数字从哪里来。默认先问 dsh-opencode-go 的当前账号,失败时回退内置提供商,并在面板上标注原因。
quotaSource | 行为 |
|---|---|
opencode-go(默认) | 读取插件当前账号,账号切换时自动跟随;失败 → builtin,标注「内置」 |
builtin(固定) | 始终走 baseUrl + /v1/usage,不探测插件;不会触发回退,也没有徽标 |
opencode-go 模式下,host 按以下顺序探测,任一步失败都会记录原因:
- 存在实时 loader 条目
opencode-go(或dsh-opencode-go); - 该条目未被禁用;
ctx.get("opencodeGoUsage")能解析出服务且带read();await read()返回三个窗口(rolling / weekly / monthly);- 从该条目的实时配置解析当前账号(
apiKeyEnv,再按同一apiKeyEnv匹配accounts[]),并从可解析的dsh-opencode-go/package.json读版本号。
回退原因
fallback.reason | 含义 |
|---|---|
not-installed | 未安装,或尚未加载(装好后重启) |
entry-disabled | profile 中条目被禁用 |
service-unavailable | 服务缺失或版本过旧(没有 opencodeGoUsage,或其缺少 read()) |
read-failed | 插件读取时报错,原文见 fallback.message |
invalid-response | 没有三个有效窗口 |
任一步失败时,GET /opencode-go/usage 仍返回 HTTP 200,带 source: "builtin"、requested: "opencode-go"、fallback 对象与 opencodeGo 诊断块——小组件显示内置数字并加以标注。只有两个来源都失败才返回 502;quotaSource: builtin 不探测,因此 fallback 恒为 null、也没有徽标。
账号显示
- 当前账号有名字时,小组件标题变为
OpenCode GO · <账号名>(展开面板与收起后的徽标都是);没有名字时保持OpenCode GO。 - 只有真的发生回退(请求
opencode-go、实际builtin)才显示「内置」徽标,tooltip 里带原因与信息。主动固定builtin不算回退,不显示徽标;接口里的source始终表示实际生效的来源。
设置页
插件在 DSH 官方 plugins.bundle.config 槽位注册了配置页,以包名为 key:侧栏 →「插件」面板 → @astervolans/dsh-opencode-go-usage 卡片 → 配置页。
页面提供:
- 两个来源的选择——优先 dsh-opencode-go(当前账号) 或 DSH 内置提供商,默认取当前
quotaSource; - 由
GET /opencode-go/settings驱动的状态面板:是否检测到dsh-opencode-go、其版本、当前账号、服务可用性 / 兼容性、生效来源、回退原因与信息; - 保存(
POST /opencode-go/settings,带{ patch: { quotaSource }, expectedRevision })与重新加载按钮,以及成功 / 失败 / 冲突提示。出现 revision 冲突说明配置在别处被改过(另一个标签页、设置表单、profile)——先重新加载再保存。
它与 设置 → 插件 → 插件配置 并存:两处改的是同一份条目配置,任一处保存都即时生效、无需重启;保存成功后 host 会让额度缓存失效,下一次小组件轮询即反映新来源。该路由只接受 quotaSource。若 DSH 无法描述本插件的设置(条目 id / schemastery),该路由返回 503、页面会提示——此时改用 profile patch 配置 quotaSource。
配置项
所有字段都是 volatile:出现在 设置 → 插件 → 插件配置(quotaSource 还会出现在设置页),改完即时生效、无需重启。
| 键 | 默认 | 说明 |
|---|---|---|
quotaSource | opencode-go | 额度数字来源:opencode-go(优先 dsh-opencode-go 当前账号,失败自动回退内置)或 builtin;未知值归一化为 opencode-go |
apiKeyEnv | OPENCODE_GO_API_KEY | API key 的 credential 引用 / 环境变量名(内置路径;opencode-go 模式回退时也用它) |
baseUrl | https://opencode.ai/zen/go | 网关 base URL(内置路径) |
cacheMs | 30000 | host 端上游缓存 TTL |
updateCheck | false | 检查 npm 新版本(组件与命令只提示,插件不会自行升级) |
injectSessionHeader | true | 为 GO 网关聊天请求注入运行时 x-opencode-session 头 |
也可以直接在 profile patch 里配置:
- id: dsh-opencode-go-usage
config:
cacheMs: 60000
quotaSource: builtin # 可选:强制走内置提供商
volatile 标记需要 schemastery ≥
3.18.4;profile 里若 hoist 着旧副本(3.18.2),插件照常启用并从条目读配置,只是不生成设置页、不能热改。详见兼容性。
HTTP 接口
上游用量 API
GET https://opencode.ai/zen/go/v1/usage,带 Authorization: Bearer <key>:
{
"usage": {
"rolling": { "status": "ok", "percent": 0, "resetsAt": "2026-08-14T07:51:13Z" },
"weekly": { "status": "ok", "percent": 1, "resetsAt": "2026-08-17T00:00:00Z" },
"monthly": { "status": "ok", "percent": 22, "resetsAt": "2026-08-21T13:05:13Z" }
}
}
同源路由
小组件与命令从不直接访问网关,由 host 代理并附加信息。
GET /opencode-go/usage —— 返回 usage(三个窗口)、update(更新提示)、sessionHeader(会话头注入诊断),以及:
| 字段 | 含义 |
|---|---|
source | usage 里数字的实际来源:opencode-go 或 builtin |
requested | 配置的 quotaSource |
account | dsh-opencode-go 的当前账号:{ ref, id, name }(builtin 模式下为配置的 ref) |
fallback | null;或插件路径失败改用内置时的 { from: "opencode-go", reason, message } |
opencodeGo | 检测信息:{ detected, version, entryFound, enabled, service, compatible, reason, message } |
lastSwitch | dsh-opencode-go 最近一次账号切换(fromRef、toRef、reason、at),没有则为 null |
两个来源都失败时返回 HTTP 502——{ error, requested, opencodeGo, fallback }。
GET /opencode-go/settings —— 返回 { ok, namespace, revision, value, base, user, detection };value 是脱敏后的配置,detection 另含 dsh-opencode-go 的账号列表与生效来源。DSH 无法描述本插件设置时返回 503。
POST /opencode-go/settings —— 请求体 { patch: { quotaSource }, expectedRevision } → { ok, revision, detection }。只接受 quotaSource;expectedRevision 过期返回 409,请求体 / 取值非法返回 400,跨源 Origin 返回 403。
x-opencode-session 修复
OpenCode GO 网关拒绝缺少 x-opencode-session 头的聊天补全请求(HTTP 400 MissingSessionID),而 DSH 的 llm-pi-ai 适配器从不发送该头。与其修改 DSH 安装目录里的文件(每次升级都会被覆盖),本插件改为运行时注入:
- 一次性包装
globalThis.fetch; - 监听 DSH 官方
llm/streamwaterfall 事件,获取每次调用的会话 ID(options.sessionId,由dsh-agent-loop填充)。
网关 base 从被调用 provider 自身的实时配置解析(llm-pi-ai.providers.<route>.baseURL,缺省回退本插件的 baseUrl)——代码不硬编码任何域名——因此只有发往该调用对应网关的请求才会收到该头,且值为真实的会话级 ID。
- 开关:配置项
injectSessionHeader(默认true)。 - 可观测性:
GET /opencode-go/usage返回sessionHeader: { active, count, diag };diag报告运行时观测,如streamSeen(处理过的llm/stream调用数)、lastStream(provider、session-id 是否存在、base 及其来源)、requests/injected/missed(带上下文的 wire 请求数 / 实际注入数 / 因 URL 不匹配未注入数)。
工作原理
这是一个双端 DSH 插件包:
| 端 | 文件 | 职责 |
|---|---|---|
| host(Node) | lib/index.js | 注册 GET /opencode-go/usage 与 GET / POST /opencode-go/settings 路由(ctx.webServer),以及 /opencode-go 命令(ctx.commands);解析额度来源(优先 dsh-opencode-go 的 opencodeGoUsage 服务,失败回退内置)并经 DSH credentials 解析 key;上游调用带缓存(默认 30s,按来源 + 账号区分) |
| 浏览器 | lib/client.js | 手写的 window.__ModuleLoader__.load({ id, factory }) bundle,等待 sidebar.footer.action 列表槽与 plugins.bundle.config 槽就绪后注册,每 60s 轮询同源路由 |
侧边栏小组件如何加载
DSH 0.1.7-rc 起通过官方 client-modules 扫描装载组件:包的 dsh.client 声明 + exports["./client"] 按 loader entry 自动识别,bundle 由 /plugins/... 组合路由提供,boot graph 行由 host 自己写进 window.__DSH_BOOT__ 清单——无需手工打包或注入 index。(更早的 0.1.1 / 0.1.2 线用自托管 /dsh-opencode-go-usage/client.js 路由 + webServer.tapIndex 行注入;该机制已移除,因为 0.1.7-rc 把数组形 boot 清单改成了 { rev, entries, batches } 对象,只能由 client-modules 生成。)
兼容性
兼容 DSH 0.1.7 及以上(含 0.2.x 线,已在 0.2.2-rc.2 验证)。范围声明在 peerDependencies,宿主在条目启用前强制校验——0.2.0 起是硬闸门,不匹配则整行被禁用:
"peerDependencies": {
"@deepseek-ai/schemastery": "^3.18.4",
"@deepseek-ai/dsh": ">=0.1.7-rc.1 <0.2.0-0 || >=0.2.0 <0.3.0-0 || >=0.2.2-rc.1 <0.3.0-0"
}
运行时不在范围内时,改装对应版本的插件,或显式接受风险后重启:
dsh plugin allow-version # 为 name@version 在本 dsh 版本上授予精确版本豁免
两点运行时说明:
- volatile 配置字段(设置页 / 热改)需要 schemastery ≥
3.18.4;profile 里若 hoist 着旧副本(3.18.2),插件照常启用并从条目读取配置,只是不生成设置页、不能热改(见配置项)。 - 若运行时不提供
plugins.bundle.config槽位,设置页不可用——改用 设置 → 插件 → 插件配置 或 profile patch 配置quotaSource;小组件与/opencode-go命令不受影响。
dsh-opencode-go 是可选的:opencode-go 模式下 host 运行时探测它,没装属于正常回退(not-installed),不是错误。想让小组件跟随其当前账号,就在同一个 profile 里装上它。
开发
- 测试:
npm test(即node test/run.mjs,全部离线运行)。 - 浏览器端是手写的 factory bundle(
window.__ModuleLoader__.load),因为目前第三方 client 插件还没有公开的构建流水线。它只能require()shell 模块表里的模块(react、react/jsx-runtime以及已注册的 client 包)。直接改lib/client.js,重启 DSH 并刷新页面——bundle 的 revision hash 会变化,shell 自动加载新文件。 - host 端(
lib/index.js)的改动只需重启 DSH。 - 应用包设置页是同一个 bundle 里的第二处注册(
plugins.bundle.config,以包名为 key)。组件按props.view分支:summary必须返回纯字符串(插件面板卡片内联渲染),page才挂载设置组件。两端都走同一组/opencode-go/...路由——设置页不直接读配置,而是经GET/POST /opencode-go/settings。
本地 link 安装的依赖解析
dsh plugin add <本地目录> 以 pnpm link: 协议挂载,模块从项目真实路径解析依赖,而 lib/index.js 引用了 @deepseek-ai/schemastery(peer)。若从项目路径向上找不到该包,导入会报 ERR_MODULE_NOT_FOUND。解决办法是在项目里建一个 junction 指向 profile 的 hoisted 副本(Windows 示例,无需管理员权限):
node -e "const fs=require('fs');fs.mkdirSync('node_modules/@deepseek-ai',{recursive:true});fs.symlinkSync(process.env.USERPROFILE+'/.dsh/profiles/<profile>/node_modules/@deepseek-ai/schemastery','node_modules/@deepseek-ai/schemastery','junction')"
node_modules/ 已在 .gitignore 中,不会进入仓库。验证:node --input-type=module -e "await import('@astervolans/dsh-opencode-go-usage')"(在 profile 目录执行)。
常见问题
- 重启后小组件不出现 → 硬刷新页面(
Cmd/Ctrl+Shift+R);启动图是按页面加载注入的。 /opencode-go/usage返回 502 且提示 no API key → 在~/.dsh/.credentials.yaml配置 key。- 网关 401 / 403 → key 无效或订阅过期;检查 credential。
- 小组件显示错误串 → 悬停收起态徽标,或展开态小组件里的错误行。
- 装了
dsh-opencode-go但仍回退到内置 →curl -s http://127.0.0.1:3080/opencode-go/usage看source、fallback与opencodeGo块,按fallback.reason处理(见回退原因)。不想让它探测就设quotaSource: builtin。 - 小组件标题没有账号名 → 正常现象:
dsh-opencode-go缺失(回退)或其当前账号没有name;可看接口里的account.name确认。 - 启动失败,日志有
Identifier 'PACKAGE_NAME' has already been declared→ 客户端 bundle 在 shell 的共享脚本作用域里声明了顶层同名常量(多个 client 插件同名冲突时会发生),整个 web boot 会被判定失败。当前源码已把该名称移入 factory 内部;重新安装本源码并完全重启 DSH 即可。
License
MIT
Ähnliche Plugins
DeepSeek-Balance-Whale-Widget
meteornox/deepseek-balance-whale-widget
dsh-context
bowenliang123/dsh-context
dsh-cost-meter
han-1413141/dsh-cost-meter
dsh-damage-pulse
wssfk12138/dsh-damage-pulse