dsh-plugin-provider-quota
DeepSeek Harness(DSH) 的 Web 插件:在侧边栏底部展示模型 Provider 的订阅额度、限流窗口与账户余额(如 DeepSeek),点击读数即可查看详情。读数注册在 sidebar.footer.action(root 作用域),新会话页面与所有页面常驻,切换会话不重挂载、不闪烁。
功能特性
- 紧凑额度读数:侧边栏展开时每个 Provider 一行,显示订阅周期和最短限额窗口的剩余比例,例如
Kimi 66% · 5h 34%、Codex 5h 94%、DeepSeek ¥110.00;侧边栏收起为窄栏时退化为单个指示灯圆点(颜色取所有 Provider 的最差状态)。
- 可视化详情:点击读数在浮层中展示会员等级、剩余额度、已用进度、重置时间、路由状态、更新时间,以及余额型 Provider 的币种总余额与充值/赠送明细。浮层渲染在
shell.overlay 图层,不会被侧边栏裁剪。
- 额度预警:剩余比例高于 35% 显示绿色,高于 10% 且不超过 35% 显示黄色,10% 及以下显示红色;存在多个 Provider 或窗口时采用最差状态。余额型 Provider 在账户余额不足(
is_available: false)时读数变红并在详情中提示。
- 回合末刷新:每轮对话结束后 2 秒静默全量刷新一次额度(读数在 root 作用域拿不到聊天节点,无法精准定位本轮 Provider,故退化为全量刷新)。
- 自动轮询:每 5 分钟更新一次,Host 端使用 30 秒缓存以减少外部请求;客户端保留最近一次成功结果,任何重挂载都先渲染缓存、后台静默刷新,不会闪烁。
- 安全凭据解析:通过 DSH
credentials 服务读取 apiKeyEnv 引用,原始凭据不会发送到浏览器,也不会写入响应或日志。
支持的 Provider
| Provider | 路由 ID | 额度接口 | 凭据说明 |
|---|
| Kimi For Coding | kimi-coding | https://api.kimi.com/coding/v1/usages(另请求 /coding/v1/me 取会员等级展示名 user_level_name) | 使用该路由 apiKeyEnv 引用的凭据,通常为 KIMI_API_KEY。 |
| OpenAI Codex | openai-codex | https://chatgpt.com/backend-api/wham/usage | 使用 CODEX_OAUTH_ACCESS_TOKEN;建议由 dsh-plugin-llm-codex 完成 OAuth 登录和自动刷新。 |
| DeepSeek | deepseek-official | https://api.deepseek.com/user/balance | 由 DSH 自带的 dsh-llm-deepseek 插件注册,凭据缺省引用 DEEPSEEK_API_KEY(可在 llm-deepseek.apiKeyEnv 覆盖)。余额是货币金额而非百分比订阅额度,详情展示各币种总余额与充值/赠送明细。 |
插件只展示同时满足以下条件的 Provider:
- 已在本插件的 Provider 注册表中支持;
- 已在 DSH 中配置对应路由 ——
providers 型(Kimi/Codex)在 llm-pi-ai.providers 配置;命名空间型(DeepSeek)由 dsh-llm-deepseek 注册、路由激活即展示,无需额外配置。
dsh-plugin-provider-quota · DSH Hub如果路由已配置但凭据缺失、无法解析或额度接口报错,徽标与详情面板会显示该 Provider 的错误状态。
快速开始
1. 获取并构建
需要已安装 DSH、Node.js 和 pnpm。
git clone https://github.com/jasper-zsh/dsh-plugin-provider-quota.git
cd dsh-plugin-provider-quota
pnpm install
pnpm install 会通过 prepare 脚本自动生成 lib/;也可以随时运行 pnpm build 手动构建。
2. 安装到 Web profile
dsh plugin --profile web add "$PWD"
node /lib/bin.js plugin --profile web add "$PWD"
3. 挂载插件
编辑 $DSH_HOME/profiles/web/cordis.patch.yml(默认路径为 ~/.dsh/profiles/web/cordis.patch.yml),将以下内容合并到现有顶层数组:
- insert:
- id: provider-quota
name: dsh-plugin-provider-quota
如果文件当前内容为 [],直接用上面的内容替换;如果已有其他 patch,请保留原内容并追加该项。
4. 配置 Provider
可以通过 DSH Web 的模型设置添加 Provider 和凭据,也可以编辑 $DSH_HOME/settings.yaml。以下示例同时配置 Kimi 和 Codex:
llm-pi-ai:
providers:
kimi-coding:
apiKeyEnv: KIMI_API_KEY
openai-codex:
apiKeyEnv: CODEX_OAUTH_ACCESS_TOKEN
apiKeyEnv 是 DSH 的凭据引用,不是要写入 settings.yaml 的密钥明文。只需保留实际使用的 Provider:
- Kimi:确保
KIMI_API_KEY 能由 DSH credentials 服务或进程环境解析。
- Codex:先安装并登录
dsh-plugin-llm-codex,由它维护 CODEX_OAUTH_ACCESS_TOKEN;本插件只读取消费该令牌,不参与令牌生命周期。
- DeepSeek:无需在
llm-pi-ai.providers 中配置 —— 路由 deepseek-official 由 DSH 自带的 dsh-llm-deepseek 插件注册,默认读取 DEEPSEEK_API_KEY 凭据;本插件调用 GET /user/balance 只读展示余额,不消耗余额。如需覆盖凭据引用,可在 llm-deepseek 命名空间设置 apiKeyEnv。
5. 启动并验证
首次安装后重启 dsh web。侧边栏底部应出现额度读数(新会话页面同样可见);也可以直接检查 Host 端点:
curl http://127.0.0.1:3080/provider-quota/quota.json
使用方式
- 将鼠标悬停在读数上,可查看各额度窗口的剩余、已用和重置时间。
- 点击读数,可展开 Provider 详情浮层(渲染在
shell.overlay 图层,侧边栏收起为窄栏时同样可用)。
- 点击详情底部的“刷新”,可绕过 Host 缓存执行全量刷新。
- 一轮响应完成或被中断后,插件会自动静默刷新一次额度。
HTTP API
所有响应均设置 Cache-Control: no-store。no-store 用于阻止浏览器和代理缓存;插件内部仍保留 30 秒 Host 缓存。
| 请求 | 说明 |
|---|
GET /provider-quota/quota.json | 返回完整额度视图;30 秒内可命中 Host 缓存。 |
GET /provider-quota/quota.json?force=1 | 绕过缓存,强制刷新所有已配置且受支持的 Provider。 |
GET /provider-quota/quota.json?provider= | 已有完整缓存时,仅刷新指定 Provider 并合并结果;首次请求无缓存时会先执行全量刷新。 |
如果同时传入 provider 和 force=1,定向刷新逻辑优先,force 不会触发额外的全量刷新。
curl 'http://127.0.0.1:3080/provider-quota/quota.json?provider=kimi-coding'
curl 'http://127.0.0.1:3080/provider-quota/quota.json?provider=deepseek-official'
curl 'http://127.0.0.1:3080/provider-quota/quota.json?force=1'
项目结构
src/
├── index.ts # Host 入口和 HTTP 端点
├── quota.ts # 凭据解析、额度查询与缓存策略
├── services.ts # Host 服务类型
├── types.ts # Host/Client 共享响应类型
├── providers/ # Provider 定义、归一化逻辑与注册表
└── client/
├── index.tsx # Web 插件入口与槽位注册
├── api.ts # 同源额度请求(含客户端缓存与并发去重)
├── store.ts # 读数 ↔ 浮层跨槽位状态桥
├── hooks.ts # 轮询、会话运行态与回合末刷新
├── format.ts # 格式化与状态计算
├── components.tsx # 侧边栏读数与详情浮层
└── styles.ts # 插件样式
lib/index.js:Host ESM;
lib/client.js:DSH Web 使用的 Client bundle。
开发
pnpm install # 安装依赖并执行 prepare 构建
pnpm build # 一次性构建
pnpm dev # 监听源码并持续构建
pnpm typecheck # TypeScript 严格类型检查
扩展新的 Provider
当前通用查询引擎固定使用 GET 和 Authorization: Bearer 。以下扩展方式适用于兼容该请求模型的 Provider;其他认证或请求方式需要先扩展查询引擎。
- 在
src/providers/ 新建 Provider 文件并实现 ProviderDef:
id:DSH 中的 Provider 路由 ID;
name / short:详情标题与徽标短名;
settingsNs:Provider 配置所在的 settings 命名空间;profile 在 providers 字典(默认)或命名空间自身(settingsShape: 'self',如 DeepSeek)时无需设置;
usagesUrl:额度(或余额)查询地址;
normalize(payload, extra?):将原始响应转换为统一的 NormalizedQuota。
- 如果请求需要从凭据派生额外 Header,实现可选的
headers(key)。
- 如果展示还需要另一个只读端点(如 Kimi 的
/me 会员展示名),实现可选的 extraUrls(键名会出现在 normalize 的 extra 参数中;请求失败只让对应键缺席,不中止查询)。
- 在
src/providers/index.ts 的 SUPPORTED 数组中注册该定义。
百分比型 Provider 填充 usage/windows;货币余额型 Provider(如 DeepSeek)把数据放入 balance({ available, entries: [{ currency, total, granted, toppedUp }] }),usage/windows 置空。Client 端由统一数据结构驱动,两类 Provider 都会自动渲染,不需要为新 Provider 修改组件。
常见问题
侧边栏底部没有额度读数
确认至少一个受支持的 Provider 已在 DSH 中配置(Kimi/Codex 在 llm-pi-ai.providers;DeepSeek 由 dsh-llm-deepseek 插件注册路由即可)。如果接口返回的 providers 数组为空,插件会隐藏读数。
Provider 显示警告标记
- 路由没有配置
apiKeyEnv;
- 凭据引用未写入 DSH credentials,也不存在于进程环境;
- 凭据已过期或额度接口返回 HTTP 错误;
- Codex access token 不是包含
chatgpt_account_id 的 OAuth JWT;
- DeepSeek 余额不足(
is_available: false)时读数变红、详情显示“账户余额不足”,需前往 DeepSeek 开放平台充值。
详情显示“路由未激活”
额度查询依据 settings 中的 Provider 配置执行;“路由未激活”表示该路由当前没有注册到 DSH llm 服务,请同时检查模型路由配置及对应模型插件。
安全说明
- Provider 凭据只在 Host 进程内存中解析和使用。
- 浏览器只接收归一化后的额度、计划、窗口和错误信息。
- 本插件不会保存、刷新或返回原始令牌。
- 请仅在可信环境中运行 DSH Web,不要把额度端点直接暴露给不受信任的网络。