Перейти к основному содержимому
I

dsh-model-surplus

itchenshi/dsh-model-surplus

Shows the active model's usage and remaining balance in the session header: OpenCode Go plan usage (rolling, weekly, monthly) with the selected model's monthly cap, and DeepSeek account balance.

Установка

dsh plugin --profile web add github:itchenshi/dsh-model-surplus

README

dsh-model-surplus

English 中文

DeepSeek Harness会话标题右侧显示 当前模型的用量 / 账户余额 —— 用到哪个模型,就显示哪一份,不用切页面去查。

┌─ 会话标题栏 ───────────────────────────────────────────────────────────────┐
│  我的对话     [OpenCode Go 滚动 18% 周 82% 月 42% 上限 $60]        打开功能 ▾ │
│  另一个对话   [DeepSeek ¥110.00]                                   打开功能 ▾ │
└────────────────────────────────────────────────────────────────────────────┘
当前模型路由显示什么数据从哪来
opencode-go / opencode套餐用量:滚动 / 周 / 月百分比 + 重置时间,外加所选模型的月度上限(上限 $60GET https://opencode.ai/zen/go/v1/usage + 单模型上限表
deepseek-official账户余额:总 / 赠送 / 充值(余额不足时显示「余额不足」)GET https://api.deepseek.com/user/balance

只有当会话选中的模型属于受跟踪的 provider 时它才出现 —— 切模型就立刻显示/隐藏,不用刷新。

装上就能用

  • 用 DSH Ready GUI(推荐):插件随 GUI 内置。打开 GUI → 设置窗口 → 第三方插件 → 勾选 模型余量,装完按提示重启引擎、按提示刷新页面(它带页面部分)。

  • 其它 DSH 宿主dsh web / CLI):

    git clone https://github.com/itchenshi/dsh-model-surplus.git
    dsh plugin --profile web add file:<clone 出来的绝对路径>
    

    装到的是磁盘上的真实目录,所以以后 git pull 更新的就是同一份代码;反过来,目录被移动或删掉 会让这条依赖失效(重新 add 一次即可)。

npm 上暂时没有这个包:注册账号那一环走不通(www.npmjs.com 返回 Cloudflare 托管挑战),包发不 出去。所以现在只能按上面两种方式装。等注册通了会照常发布。

要配的只有密钥,插件通过引擎的凭据服务按引用读取,密钥不会下发到浏览器

路由凭据名
OpenCode GoOPENCODE_GO_API_KEY
DeepSeekDEEPSEEK_API_KEY

两个分区各自独立上报结果:只配了其中一个密钥,另一半照样能用,缺的那半显示一条原因 (no-key / unauthorized / network / timeout / bad-payload),而不是把整个小组件藏起来。

单模型月度上限是怎么来的

OpenCode Go 的用量接口按账户统计,忽略单模型参数;而官方「使用限制」 里写的单模型月度上限没有 API(例如 DeepSeek V4.1 Flash $60/月、DeepSeek V4 Pro $15/月)。所以:

  1. 内置一张表BUILTIN_MODEL_LIMITS),
  2. 自动刷新:抓公开文档页(服务端渲染、不需要 JS、不需要密钥),把限制表和模型 id 表解析成 模型 id → 月度 $
  3. 结果缓存$DSH_HOME/logs/model-surplus-limits.json,重启不必重抓,
  4. 任何抓取/解析失败都回退:缓存 → 内置表。

刷新时机:插件启动时一次,之后每 24 小时一次。tooltip 会列出推导出的各档上限(5h = 20% · 周 = 50% · 月 = 100%)、数据来源(文档 / 本地缓存 / 内置表),并说明百分比是账户级的、上限是单模型的。

配置(cordis.patch.yml 的行 config,全部可选)

- insert:
    - id: model-usage
      name: dsh-model-surplus
      config:
        enabled: true

        opencodeGo:
          baseUrl: https://opencode.ai/zen/go/v1   # 上游根地址
          apiKeyRef: OPENCODE_GO_API_KEY           # 凭据引用
          providers: [opencode-go, opencode]       # 视为 OpenCode Go 的路由

        deepseek:
          baseUrl: https://api.deepseek.com        # 上游根地址
          apiKeyRef: DEEPSEEK_API_KEY              # 凭据引用
          providers: [deepseek-official]           # 引擎的 DeepSeek 路由

providers 就能把别的路由划进某个分区,不用改页面代码——供应商到分区的映射由宿主端每次 轮询时下发。顶层直接写 baseUrl / apiKeyRef / providers 仍按 opencodeGo 分区读(本插件早期 只有 OpenCode Go)。

权限与边界(给会静态扫描的商城看的)

会锁定 commit 审查的商城会静态扫描运行时代码,这里把事实一次写清:

  • 运行依赖:无。 只用 Node 内建模块(node:pathnode:fs/promises);宿主半边是纯 ESM, 自身不要求 node_modules
  • 对外网络:有,三个主机,全部来自宿主端(页面端只调下面那条本地路由):
    • GET https://opencode.ai/zen/go/v1/usage —— OpenCode Go 套餐用量(OPENCODE_GO_API_KEY
    • GET https://api.deepseek.com/user/balance —— DeepSeek 账户余额(DEEPSEEK_API_KEY
    • GET https://opencode.ai/docs/zh-cn/go/ —— 文档里的单模型月度上限;之所以要抓页面,是因为网关 自己的 /models 响应不带任何上限信息
  • 本机路由:一条。 宿主注册唯一一条面向页面的路由,页面以同源方式调用;它走引擎自己的信任围栏 (Host 白名单 + 浏览器会话 cookie),围栏拿不到时失败即关闭不带 cookie 的裸 curl 会得到 401(修复前返回 200 —— 任何本机进程、被 DNS rebinding 的页面都能读到你的用量和余额)。
  • 文件:一个缓存。 <DSH_HOME>/logs/model-surplus-limits.json 存抓到的上限表,其余不读不写, 也从不碰你的文件。
  • 凭据: 只在宿主端经 ctx.credentials 读取,绝不出现在任何返回给页面的响应里。
  • 命令 / 原生制品 / 生命周期脚本:无。
  • 失败边界: 两个分区各自独立上报,缺密钥或上游不可达只会让那一半降级并说明原因;插件从不阻塞 引擎启动,卸载即恢复原来的标题栏。

两部分构成

部分文件运行于职责
宿主端lib/index.jsNode按分区抓上游数据,经一条同源 JSON 路由提供出去
页面端client/client.js浏览器注册标题栏小组件;轮询宿主路由;按当前模型门控

宿主路由的返回形状(手工调试用;记得带引擎的会话 cookie):

GET /model-usage
{
  "ok": true,
  "sections": { "opencode-go": { "providers": ["opencode-go","opencode"], "keyRef": "OPENCODE_GO_API_KEY" },
                "deepseek":    { "providers": ["deepseek-official"],    "keyRef": "DEEPSEEK_API_KEY" } },
  "opencode-go": { "ok": true, "usage":   { "rolling": {…}, "weekly": {…}, "monthly": {…} } },
  "deepseek":    { "ok": true, "balance": { "isAvailable": true, "infos": [ { "currency":"CNY", "total":"110.00", … } ] } },
  "limits": { "deepseek-v4.1-flash": { "hours5": 12, "weekly": 30, "monthly": 60 } }
}

宿主会归一化并钳制用量百分比(0–100),也接受上游发来的十进制字符串金额;每个分区缓存 60 秒, 失败后最快 30 秒才重试。

开发

node --check lib/index.js
npm test        # 本地行为测试(不联网、不需要引擎)

tests/e2e.cjs 是针对真实引擎 + 浏览器的完整集成检查(需要跑着的 profile,所以不在 npm test 里)。

许可

MIT

Похожие плагины