dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
English | 简体中文
已发布到 npm:dsh-balance-inquiry (npm i dsh-balance-inquiry / pnpm add dsh-balance-inquiry)。
在 DSH 左侧边栏底部、「上下文洞察」的上面加一行按钮:
💰 剩余额度:12.34 ¥每个套餐一张圆角长方形卡片(套餐名称 / 剩余额度 / 上次查询时间)。
按 Esc 或点遮罩关闭;要看/改某个套餐就去 设置 → 余额查询 里点它的长条按钮。
按量计费(API Key)还是 Token Plan / Coding Plan,再选厂商;点长条按钮进入二级编辑页 (改名称 / 厂商 / 令牌 / 接口地址 / 官网地址,或删除套餐)。
OpenRouter、Novita AI 六类原生余额接口,以及自定义用量脚本 (({ request: {…}, extractor: function (response) {…} }),支持 {{baseUrl}} / {{apiKey}} / {{accessToken}} / {{userId}} 占位符)。
智谱 GLM 团队版、MiniMax、ZenMux、火山方舟(Agent / Coding Plan)、OpenCode Go、Command Code; 显示每个时间窗口(5 小时 / 周 / 月)的已用百分比与剩余百分比,剩余不足 10% 时变黄。
GET {baseUrl}/api/user/self,显示值 = data.quota ÷ 换算比例(默认 500000,也就是 1 ¥ = 500000 quota);按积分 / credits 计的套餐不显示换算比例。
官方登录 `deepseek-official`、账号登录 `deepseek-account`,以及 cordis.patch.yml 里 llm-pi-ai 配置的自定义路由(如 cotton-api)。 绑定通过一个独立弹窗完成:列出所有已添加的供应商,支持搜索、全选与逐个勾选,可多选。 当您在 DSH 中切换到其中任意一个供应商时,左下角自动感知并显示该套餐的余额;未匹配或未绑定时回退展示所有套餐中最紧急的一项。
(含每个套餐的各档位名称与重置时间)。
tooltip 标注「上次成功:…」;鉴权失败等确定性失败立即透出并清掉旧值,避免显示过期额度。
baseURL 等敏感网络信息的行为;仅通过受约束的本机路由读取 provider id 用于匹配。dsh plugin --profile desktop add dsh-balance-inquiryprofile 的依赖列表和 bundles 是启动时读取的,所以装好后要重启 DSH 桌面端
(Web 版则重启 dsh web)。重启后侧边栏底部就会多出这一行。打开 设置 → 余额查询(一级页):
插件不预设任何站点:接口地址与官网地址都是空的,也不会自动去查任何第三方服务。
第一次使用请点「添加套餐」自己填;两个地址都为空时,看板卡片不会跳转。
字段 · 说明 套餐名称 · 看板卡片与侧边栏 tooltip 上显示的名字,留空则用厂商名 计费类型 · 按量计费(API Key) 或 Token Plan / Coding Plan,决定可选的厂商与要填的字段 厂商 · 按量计费:New API / One API、DeepSeek、StepFun、SiliconFlow(国内 / 国际)、OpenRouter、Novita AI、自定义脚本;编程套餐:Kimi For Coding、智谱 GLM、智谱 GLM 团队版、MiniMax、ZenMux、火山方舟、OpenCode Go、Command Code 接口地址 · 例如 https://api.example.com,末尾不要带 /;原生厂商用官方地址、不显示该字段 用量接口地址 · 编程套餐用;ZenMux 必填,火山方舟用来推断区域(形如 https://ark.cn-beijing.volces.com/api/plan/v3) 访问令牌 / 控制台令牌 · New API 用控制台「系统访问令牌」(不是 sk- 开头的 API Key),作为 Authorization: Bearer … 发送;官方厂商 / 编程套餐填对应平台的令牌 用户 ID · 作为 New-Api-User 请求头发送,部分站点必填 组织 ID / 项目 ID · 选「智谱 GLM 团队版」时出现,分别作为 bigmodel-organization / bigmodel-project 请求头发送 AccessKey ID / SecretAccessKey · 选「火山方舟」时出现,用于 OpenAPI 签名(不是推理用的 API Key) 官网地址 · 看板卡片左键打开的网址;留空则改用接口地址 供应商ID · 绑定当前套餐到 DSH 的 provider id,可多选。点「选择供应商」打开独立弹窗,里面列出全部已添加的供应商(官方 API Key 是 deepseek-official、官方账号登录是 deepseek-account,自定义供应商是 cordis.patch.yml 里 llm-pi-ai 路由的 id,如 cotton-api),支持搜索、全选、逐个勾选。切换到其中任意一个供应商时,左下角自动显示这个套餐的余额;一个都不选则始终按最紧急额度展示 额度换算比例 / 货币单位 · 只有 New API 与自定义脚本显示;按积分 / credits 计的套餐不显示 自定义脚本 · 选「自定义脚本」时出现,旁边有「填入 New API 模板 / 通用模板」按钮 自动刷新间隔 · 分钟,0 = 不自动查询;默认 5 分钟(通用设置) 请求超时 · 秒,2–30,默认 10(通用设置)
配置存在 DSH 主目录下的两个 YAML 文件里(默认 $DSH_HOME/dsh-balance-inquiry/, 没设置 DSH_HOME 时退回 ~/.dsh/dsh-balance-inquiry/):
文件 · 内容 config.yml · 通用设置、套餐列表(不含任何密钥)、每个套餐最近一次读数 credentials.yml · 每个套餐的密钥,按套餐 id 分组:访问令牌、用户 ID、组织 / 项目 ID、AccessKey 等
拆成两个文件是为了让 config.yml 可以放心分享或提交到仓库,密钥单独收好即可。 两个文件都是普通 YAML,可以直接用编辑器改;插件每次写入都是「先写 .tmp 再改名」的原子写, 不会因为中途崩溃留下半个文件。目录里只有这两个文件,没有别的。
老版本(0.6.0 及以前)把配置放在渲染进程的 localStorage(dsh-balance-inquiry:accounts / :settings / :results),升级后第一次打开会自动搬到 config.yml,之后 localStorage 只在宿主路由不可用(纯浏览器环境)时作为兜底。设置页底部会显示当前实际使用的目录。
计费类型 / 厂商 · 端点 · 取值 按量计费 · New API · GET {baseUrl}/api/user/self · data.quota ÷ 换算比例 DeepSeek · GET https://api.deepseek.com/user/balance · balance_infos[].total_balance(每个币种一条) StepFun · GET https://api.stepfun.com/v1/accounts · balance(CNY) SiliconFlow · GET https://api.siliconflow.{cn,com}/v1/user/info · data.totalBalance OpenRouter · GET https://openrouter.ai/api/v1/credits · total_credits - total_usage Novita AI · GET https://api.novita.ai/v3/user/balance · availableBalance ÷ 10000(USD)
响应解析、错误文案(Network error: … / Authentication failed (HTTP 401) / Failed to parse response: …)、脚本引擎的字段校验与 200 字符错误体预览,都由插件自己实现, 可以在「设置 → 余额查询」里看到每次查询的具体原因。
在「添加套餐」弹窗里选 Token Plan / Coding Plan,再选厂商(不再有自动识别)。 编程套餐没有"余额"这个概念,所以显示的是每个时间窗口的用量百分比:看板卡片取最紧急的一项 (已用最多 / 剩余最少),tooltip 与编辑页列出全部窗口。
厂商 · 端点 · 需要填写 Kimi For Coding · GET https://api.kimi.com/coding/v1/usages · 访问令牌 智谱 GLM · GET {open.bigmodel.cn \ · api.z.ai}/api/monitor/usage/quota/limit · 访问令牌(按接口地址判断国内 / 国际站) 智谱 GLM 团队版 · GET https://open.bigmodel.cn/api/monitor/usage/quota/limit?type=2 · 访问令牌 + 组织 ID + 项目 ID(不参与自动识别,需手动选) MiniMax · GET {api.minimaxi.com \ · api.minimax.io}/v1/api/openplatform/coding_plan/remains · 访问令牌(按接口地址判断国内 / 国际站) ZenMux · GET {接口地址}/api/usage · 访问令牌 + 接口地址(或用 ZenMux 的用量脚本地址) 火山方舟(Agent / Coding Plan) · POST https://open.volcengineapi.com/?Action=GetAFPUsage\ · GetCodingPlanUsage&Version=2024-01-01 · AccessKey ID + SecretAccessKey(OpenAPI 签名,按接口地址推断区域) OpenCode Go · GET https://opencode.ai/zen/go/v1/usage · 访问令牌 Command Code · GET https://api.commandcode.ai/alpha/...(串行 4 次:whoami → credits → subscriptions → usage/summary) · 访问令牌
limits[](5 小时)与 usage(周),智谱的 TOKENS_LIMIT / CREDIT_LIMIT(按 unit 3 = 5 小时、6 = 周),MiniMax 的 model_remains[](general 模型的区间 / 周),ZenMux 的 quota_5_hour / quota_7_day, 火山的 AFPFiveHour / AFPWeekly / AFPMonthly + QuotaUsage[],OpenCode Go 的 rolling / weekly / monthly,Command Code 的 windowLimits + 月度池。
两者都没有时才报「没有找到活跃订阅」。
并在提示里带上服务端返回的原因。
「厂商」选「自定义脚本」后,可以粘贴一段求值后返回对象的脚本,用来适配任何站点:
({
request: {
url: "{{baseUrl}}/api/user/self",
method: "GET",
headers: { "Authorization": "Bearer {{accessToken}}", "New-Api-User": "{{userId}}" }
},
extractor: function (response) {
return {
planName: response.data.group || "默认套餐",
remaining: response.data.quota / {{rate}},
used: response.data.used_quota / {{rate}},
total: (response.data.quota + response.data.used_quota) / {{rate}},
unit: "CNY"
};
}
}){{baseUrl}}、{{apiKey}} / {{accessToken}}(当前令牌)、{{userId}}、{{rate}}(换算比例)。extractor 可以返回一项或一项数组(多套餐 / 多币种),字段:{ planName, remaining, used, total, unit, isValid, invalidMessage }。
http://localhost 除外);脚本语法错误、extractor 抛错、返回数字等原始值,都会在设置页给出中文原因;extractor 返回 isValid: false 时按钮上显示为「无效」而不是硬错误。
插件默认把请求交给宿主进程发出(Node,不受浏览器同源策略约束),但仍可能遇到这些情况:
现象 · 原因 · 处理 网络错误 Network error: 无法连接 · 域名解析不了 / 网络不通;或请求走了浏览器直连通道,而目标站没返回 Access-Control-Allow-Origin · 完全退出并重开 DSH 让宿主通道生效;确认地址本身可用 请求超时 Request failed: timeout after Ns · 目标站响应慢或不可达 · 把「请求超时」调大(2–30 秒) Authentication failed (HTTP 401) / 无权进行此操作,access token 无效 · 令牌不对:New API 要的是控制台「系统访问令牌」,不是 chat 用的 API Key;有的站点还要「用户 ID」 · 重新复制令牌、补上用户 ID,点「立即查询」 Failed to parse response: 缺少字段 … · 地址指向的不是该供应商的余额接口,或站点字段不同 · 把「厂商」改成「自定义脚本」,自己写取值规则 一直显示「上次成功」的旧余额 · 最近一次是瞬时失败,10 分钟内继续展示上次成功的值 · 看设置页状态行的原因,或点「立即查询」重试 设置页底部写「查询通道:浏览器直连」 · 宿主路由没生效(多半是没重启 DSH,或 webserver 被禁用) · 完全退出并重新打开 DSH
宿主通道的原理:
渲染进程 宿主进程(Node,不受 CORS 限制)
POST /plugins/dsh-balance-inquiry/proxy ───────► dsh-balance-inquiry/lib/index.js
{ url, method, headers, body, │ fetch(url, …)
timeoutSeconds } ▼
◄─────── { ok:true, status, body } 目标站点
(同源请求,不经网络,也没有 CORS 问题)lib/index.js 用 dsh-host-webserver 注册成 exact 路由/plugins/dsh-balance-inquiry/proxy(exact 表优先于 dsh-client-modules 的 /plugins// 前缀路由)。
dsh-app://app/plugins/... 会被 Electron 主进程的 protocol.handle原样转发给宿主 webserver(方法、自定义头、请求体都会保留,并注入会话 cookie), 所以渲染进程只要用相对路径 fetch 即可;Web 版是普通的 http 同源请求。
http://localhost 除外)、URL 里带用户名密码、内网 / 回环 IP。它不是开放代理。
User-Agent 等)写在自定义脚本里也能真的发出去。功能不会因为宿主侧缺失而不可用。
查询通道:DSH 宿主进程代理(不经过浏览器,无跨域限制)或 查询通道:浏览器直连(目标站必须允许跨域,否则会被拦)。
dsh-balance-inquiry/
├── package.json # dsh.bundle.patch + dsh.client.platform = web
├── cordis.patch.yml # 插入 Loader 条目
├── CHANGELOG.md # 中文更新日志
├── CHANGELOG_en.md # 英文更新日志
├── docs/ # README 顶部的截图
├── icon.svg
├── LICENSE # MIT
├── locale/{zh,en}.json # 文案(同一份也内联在 client.js 里)
├── README.md # 中文说明
├── README_en.md # 英文说明
├── NOTICE.md # 许可证与版权说明
├── scripts/ # 维护脚本(不会随安装复制进 profile)
│ ├── publish.mjs # 发布前检查 + npm publish
│ └── sync-locale.mjs # 把 client.js 里的文案同步到 locale/*.json
├── *.mjs # 自测(npm test 依次跑这五个)
│ ├── selftest.mjs # 文案键一致性 + 字段归一化 + 匹配逻辑
│ ├── dialog_test.mjs # 弹窗行为
│ ├── render_test.mjs # 侧边栏 / 看板渲染结构
│ ├── form_test.mjs # 设置页表单
│ └── config_test.mjs # 配置文件路径、读写、迁移与 /config 路由
└── lib/
├── index.js # 宿主半边:proxy / whoami / providers / config 四个路由
├── index.d.ts
├── yaml.js # 极简 YAML 读写(零依赖)
└── client.js # 全部界面与查询逻辑:侧边栏条目 + 设置页 + 查询引擎 + 代理优先 / 直连回落版本变更见 CHANGELOG.md(中文)· CHANGELOG_en.md(English)。