在侧栏浮层集中查看各供应商余额与本机用量
30/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/21 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add Anixuil/dsh-quota-board该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:已验证
是什么
dsh 原生插件 · ui
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 12 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
读写/删除本地文件发起外部网络请求
查看扫描证据(共 11 处,展示前 11 条)
- 发起网络请求index.js:705
fetchImpl: (url, init) => fetch(url, init), - 读取本地文件usage.js:97
names = readdirSync(directory) - 读取本地文件usage.js:108
revision = statSync(path).mtimeMs - 读取本地文件usage.js:109
parsed = JSON.parse(readFileSync(path, 'utf8')) - 读取本地文件usage.js:122
if (!existsSync(path)) return null - 读取本地文件usage.js:125
parsed = JSON.parse(readFileSync(path, 'utf8')) - 读取本地文件bindings.js:61
text = readFileSync(file, 'utf8') - 读取本地文件bindings.js:87
previous = readFileSync(file, 'utf8') - 写入本地文件bindings.js:92
mkdirSync(dirname(file), { recursive: true }) - 写入本地文件bindings.js:94
writeFileSync(temporary, payload, 'utf8') - 写入本地文件bindings.js:95
renameSync(temporary, file)
扫描于 2026/11/1(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/schemastery@deepseek-ai/dsh-credentials@deepseek-ai/dsh-launch-environment@deepseek-ai/dsh-typert-protocol给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
dsh 桌面额度面板
README
由 DeepSeek 最新模型翻译生成dsh-quota-board
一个 DeepSeek Harness 插件:把每个模型供应商的余额、套餐额度和本机 token 用量放进同一个浮层,浮层挂在侧栏底部账号行上方的一个按钮上。DeepSeek 直接读 Harness 已有的登录账号钱包;其余供应商都算「额外」,由通用探测器自己摸出来——摸到的接口会被记住。
一个给 DeepSeek Harness 桌面端的「模型供应商额度看板」:侧栏底部、账号行上方多一个按钮,点开就是一整块看板,把当前 profile 里所有已配置的模型供应商的余额、套餐额度、以及本机的 token 用量摆在一起。看过期就点掉,不用离开正在进行的对话。
只有 DeepSeek 是内置的:登录后直接读 Harness 的账号钱包,和「设置 → 账号与余额」是同一个数字,不用再填 API Key;其余一律算「额外供应商」——火山引擎、中转站、自建网关都一样:插件自己去试接口,试通了就把这个获取方式记下来。配置页的每条供应商都能「测试连接」,拿没保存的值先打一次,不用等看板刷新才知道填错没有。
第三方社区插件。 本项目与 DeepSeek 官方无隶属关系,也不属于官方插件市场。
它是怎么知道「有哪些供应商」的
不读配置文件、也不猜目录结构。
展开完整文档(README 剩余 1 节)
dsh-quota-board
一个 DeepSeek Harness 插件:把每个模型供应商的余额、套餐额度和本机 token 用量放进同一个浮层,浮层挂在侧栏底部账号行上方的一个按钮上。DeepSeek 直接读 Harness 已有的登录账号钱包;其余供应商都算「额外」,由通用探测器自己摸出来——摸到的接口会被记住。
一个给 DeepSeek Harness 桌面端的「模型供应商额度看板」:侧栏底部、账号行上方多一个按钮,点开就是一整块看板,把当前 profile 里所有已配置的模型供应商的余额、套餐额度、以及本机的 token 用量摆在一起。看过期就点掉,不用离开正在进行的对话。
只有 DeepSeek 是内置的:登录后直接读 Harness 的账号钱包,和「设置 → 账号与余额」是同一个数字,不用再填 API Key;其余一律算「额外供应商」——火山引擎、中转站、自建网关都一样:插件自己去试接口,试通了就把这个获取方式记下来。配置页的每条供应商都能「测试连接」,拿没保存的值先打一次,不用等看板刷新才知道填错没有。
第三方社区插件。 本项目与 DeepSeek 官方无隶属关系,也不属于官方插件市场。
它是怎么知道「有哪些供应商」的
不读配置文件、也不猜目录结构。Harness 的 Loader 已经把整个 profile 的层(bundle 层 + profile 层 + !!js 表达式)合成好了,插件直接读已合成的行:
| 行 | 读到的东西 |
| llm-pi-ai | config.providers.<id>:displayName / api / baseURL / apiKeyEnv / models[] |
| llm-deepseek* | 官方 DeepSeek 适配器的 baseURL / apiKeyEnv(默认 DEEPSEEK_API_KEY) |
| agent-default-model | config.provider,用来把某张卡标成「当前默认」 |
这意味着「加一个 provider」在 Harness 里的原有做法(改 profile 里的 llm-pi-ai 行)立刻会反映到看板上,不需要在这里再登记一遍。插件自己的 providers 字段只用来补「profile 里根本没声明的网关」。
内置 vs 额外
| | 谁 | 怎么查额度 |
| 内置 | DeepSeek(llm-deepseek 行) | 登录后直接读 Harness 账号钱包(与「设置 → 账号与余额」同源);未登录才退回 GET {base}/user/balance |
| 额外 | 其余全部,含火山引擎 | 通用探测器按需试探;探到就绑定 |
设置页的「额外供应商」列表上方会列出已经发现的额外供应商(只读,带它当前的查询方式与是否配了密钥);想改哪一条就点它的「覆盖」,这时才会在配置里生成一条条目。所以配置文件里记的是你的决定,而不是 profile 的一份快照。
密钥同样不落盘:每个供应商的 apiKeyEnv 只是一个引用名,宿主按 凭证服务 → 启动环境 → 进程环境变量 的顺序解析,浏览器半侧永远拿不到明文。
DeepSeek 不需要 API Key
登录 Harness 之后,「设置 → 账号与余额」里的充值余额 / 赠金余额就是看板上的那个数字:插件调用宿主已有的 deepseekAccount 服务(getState() 判断是否登录、getBalance() 取钱包),不自己猜、也不重复登录。所以两边永远一致,且不会出现「设置里有余额、看板说未配置」。钱包是充值 + 赠金相加(例:-0.07 + 38.48 = 38.41),两笔明细并排显示,负数标红。
只有三种情况会退回 API Key:
- 没有登录(getState() 不是 credential-stored)——卡片会直接说明去「账号与余额」登录;
- 账号服务不存在(老版本 Harness)——静默走原来的 /user/balance;
- 钱包读取失败(授权损坏、Platform 超时 8 秒)——同样退回 Key,且不会影响其他卡片。
中转站不受影响:只有 api.deepseek.com / api.deepseek.ai 会被当作官方 DeepSeek。一个协议相同、账户不同的中转(比如 relay.example.com)始终用自己的 Key,绝不会拿你的账户余额去顶替。
额度接口:默认通用,探到就记住
只有 DeepSeek 和火山引擎是真的特殊,其余全部走同一个通用探测器。
| 适配器 | 触发条件 | 行为 |
| generic(默认) | 除下面两种以外的一切 | 顺序试常见余额接口,命中即停,并把命中的路径写进 bindings.json |
| deepseek | api 或域名含 deepseek | 官方主机优先读账号钱包;否则 GET {base}/user/balance |
| volcengine | 域名含 volces / volcengine | 签名的 open.volcengineapi.com:billing.QueryBalanceAcct、billing.ListResourcePackages、ark.GetCodingPlanUsage、ark.GetAFPUsage |
| unsupported | 命中跳过名单 | 不发请求,卡片写明「没有可通过 API Key 查询的账单接口」 |
通用探测器按以下顺序试(路径相对于 API 根,/v1 结尾会被归一化,不会拼出 /api/usage 这种):
/v1/usage → /user/balance → /v1/credits → /v1/dashboard/billing/usage → /usage → /api/usage
返回 401/403 就立即中止(Key 有问题,继续试没有意义);404/405 继续下一个;超时则不再往下试(避免变成连续六次超时);全部 404 说明这个平台确实没有账单接口,卡片改成「不支持」并说明怎么手工指定路径——而不是显示一个红色报错让你反复重试。
探到之后绑定,下次直接问
第一次探通就把「哪条路径、返回的是账单还是普通 JSON」记下来:
~/.dsh/storages/quota-board/bindings.json
{
"https://relay.example.com": { "endpoint": "/api/me/quota", "kind": "json", "updatedAt": 1750000000000 }
}
- 键是 API 根(结尾的 /v1 归一化掉),所以 …/v1 换不换写法都是同一个供应商。
- 有绑定就先问绑定的那个;它失败再退回完整列表重探,不会一上来就六连发。
- 写进绑定表的是探测结果,不是用户配置:providers 里没写的供应商也会被记住,升级或换 profile 不受影响(bindings.json 在 ~/.dsh 下,不在 profile 里)。
- 写入是原子的(临时文件 + rename),内容没变就不写;写失败只 warn,不影响这次查询。
要重新探一遍,把对应那一项从 bindings.json 里删掉即可(或在条目里写死 fields.endpoint)。
认得的响应形状
按结构识别,不按域名识别——同一套网关软件跑在几千个域名上,域名匹配等于不匹配:
| 形状 | 例子 | 取值 |
| deepseek-balance | { balance_infos: [{ total_balance, currency }] } | 总余额 |
| one-api | { data: { quota, used_quota } } | quota - used_quota,按 1 USD = 500000 额度换算 |
| credits | { data: { total_credits, total_usage } } | 两者相减 |
| remaining | { remaining } / { balance } / { data: { available } } 等 | 最近的金额字段 |
接一个上面没覆盖的网关
在插件配置的「额外供应商」列表里加一条,不用改代码。设置页是卡片列表:一条一个卡片,有「添加供应商」和「删除」,不用手写 JSON。
存进 profile 的 cordis.patch.yml 是普通的 YAML 列表:
providers:
- id: my-gw
displayName: 我的网关 baseURL: https://gw.example.com/v1 apiKeyEnv: MY_GW_KEY 路径不认识就用 endpoint 钉死;字段不认识就用 fields 映射 fields: endpoint: /api/me/quota remaining: data.credit unit: data.currency 不是 Bearer 的网关:header 名与前缀都可改(前缀留空表示裸 Key) authHeader: x-api-key authPrefix: ''
可用字段:
| 字段 | 作用 |
| adapter | 强制用哪个适配器:generic / deepseek / volcengine / unsupported |
| fields.endpoint | 钉死请求路径,可写绝对 URL;不写就自动探测 |
| fields.remaining / used / unit | 点路径(data.credit、items[0].left),优先于内置形状 |
| fields.scale | 数值倍率,用于单位不同的网关 |
| authHeader / authPrefix | 换成 x-api-key 之类的自定义鉴权头 |
| accessKeyEnv / secretKeyEnv | 火山引擎专用:账户 AK/SK 的凭证名,默认 VOLC_ACCESS_KEY / VOLC_SECRET_KEY |
providers 是逐字段合并的:只改显示名不会清掉探测到的 baseURL 和密钥引用。
三个容易踩的点:
- 火山引擎的 Ark API Key 查不了账单。 那个 key 只能跑模型,账单在 Billing Center。
所以火山走的是账户 AK/SK 签名的 OpenAPI。adapter 选 volcengine 的条目会多出一块「火山账户密钥(AK/SK)」:先填两个引用名,再把值粘进去点保存——值走凭证服务,不落 YAML,也不回显。没配就整张卡提示「需要 AccessKey」,而不是显示 0。
- OpenAI 官方没有公开的 /v1/usage。 通用网关的约定是 /v1/usage 返回「剩余额度」;对不上就回退到 dashboard billing 的两个老接口(total_usage 单位是美分,已换算)。
- 用账号登录的 DeepSeek 不再需要单独配 Key。 桌面端的官方 DeepSeek 通道走的是账号授权,余额在 Platform 内部——插件通过宿主的 deepseekAccount 服务拿到它(见上文)。
如果那个服务不可用,才需要 DEEPSEEK_API_KEY 走 /user/balance。
本机用量从哪来
不重放会话日志(那是 zstd 压缩的),直接读会话投影缓存:
~/.dsh/storages/session_projcache/sessions/<sessionId>.json
取 rows.tokenUsage.totals(未命中缓存的输入 / 输出 / 缓存读 / 缓存写)与 rows.sessionStats,再用 rows.modelSelection.lastUsed.provider 做供应商归因。所以「用量」这一栏 不需要任何网络请求,断网也能看,只是口径和供应商账单不完全一致(缓存计价、赠送额度、按次计费等)。
装
桌面端面板:侧栏「插件」→「+ 添加插件」→ 填 github:Anixuil/dsh-quota-board → 安装 → 立即启用 → 重启 Harness。
本地开发:同一栏填本目录的绝对路径(例如 D:\code\self\all\dsh-quota-board)。
pnpm 记成 link:,此后改 index.js / client.js 只要重启 Harness 就生效。
装完重启 Harness(bundle 类插件不热加载)。
看板在哪
侧栏左下角、账号行上方多出一个「额度看板」按钮,点一下浮窗就贴在这个按钮上展开:
- 浮窗是 portal 到 <body> 的,不挂在侧栏里 —— 侧栏处在 transform 祖先之下, position: fixed 会被那一层的 overflow 裁掉,所以定位按按钮的 getBoundingClientRect() 算好后手动贴边,窗口缩放或侧栏滚动时重算。
- 关闭方式三选一:再点一次按钮、点浮窗外面、按 Esc。
- 按钮上写的是谁:默认显示「默认展示供应商」那一家的名字和它的剩余额度(配额窗口给百分比,钱包给币种金额)。没配置就跟随模型配置里的默认供应商,选中的供应商改了名或没了,也会自动退回默认那个 —— 不会空着。
- 只有浮窗开着才轮询:打开时取一次,之后按 refreshSeconds 轮询;关掉即停表,不会在后台一直打接口。挂载时另有一次安静的首读,好让按钮在没人点开时也有数字可写(宿主有 20 秒缓存,几乎不花钱)。
- 侧栏收起(只剩图标列)时按钮也只留图标,宽度吃满侧栏,不撑破布局。
想改配置:浮窗右上角的齿轮 → 设置 → 插件 → 额度看板。
配色
「可用」用的是 DeepSeek 的品牌蓝 #4d6bfe —— 主题里的 success 是绿色,摆在 DeepSeek 的界面上像是别人家的颜色。只有真的告急时才换色:剩余 ≤30% 转琥珀,≤10% 转红。
配置
设置 → 插件 → 额度看板。八个字段,全部有默认值,多数情况下一个都不用动:
| 字段 | 默认 | 说明 |
| providers | [] | 额外供应商列表,补充或覆盖自动发现的那些(设置页是可增删的卡片列表) |
| defaultProvider | '' | 侧栏按钮显示哪一家(下拉选,空 = 跟随模型配置的默认供应商) |
| lowThreshold | 5 | 金额余额低于此值时标红 |
| refreshSeconds | 60 | 浮窗打开时的轮询间隔(最小 10 秒;宿主管 20 秒缓存) |
| usageDays | 14 | 本机用量柱状图天数(3–60) |
| timeoutMs | 10000 | 单个供应商接口超时(最小 2000) |
| deepseekBaseURL | '' | 所有 DeepSeek 行都没写 baseURL 时的兜底 |
| skipHosts | '' | 额外不探测的域名片段(逗号分隔),追加在内置名单之后 |
火山账户的 AK/SK 不在上面:它是条目自己的字段(见下),这样同一个 profile 里挂两个火山账户也不会互相串。
列表里每条只需要填想改或想加的部分:id 必填(新网关随便起一个,要覆盖已发现的就用它原来的 id),其余留空即用默认。合并是逐字段的 —— 只改显示名时,探测到的 baseURL / apiKeyEnv 不会被清空。
一个最小条目:
providers:
- id: my-gw
displayName: 我的网关 baseURL: https://gw.example.com/v1 apiKeyEnv: MY_GW_KEY
火山账户要带上自己的一对引用名(值本身在凭证服务里,不写在这里):
providers:
- id: ark-second
displayName: 方舟(另一个账户) baseURL: https://ark.cn-beijing.volces.com/api/v3 apiKeyEnv: ARK_API_KEY_2 adapter: volcengine accessKeyEnv: VOLC_ACCESS_KEY_2 secretKeyEnv: VOLC_SECRET_KEY_2
设置页里每条还有「高级」折叠区(协议提示、鉴权头与前缀、字段映射),平时不用展开;「测试连接」就在高级上面,填完值先点一下比保存后再看省事。
降级
| 情况 | 表现 |
| Harness 不带 Typert remote | 浮窗直说「宿主没有提供额度服务」,并给出原因(无 $mount / 被 Gateway 拒绝 / 读不到命名空间 / 没有 load 方法) |
| 没配密钥 | 卡片标「未配置」,其余卡片照常 |
| 某个供应商接口挂了 | 只有那张卡显示错误,整块不塌 |
| 平台没有账单接口 | 卡片标明,本机用量照常统计 |
| 没有投影缓存 | 用量区显示 0 并说明还没记录 |
结构
index.js 宿主半侧:发现供应商、解析密钥、并发查询、聚合用量;暴露 load(force) 与 test(entry) client.js 浏览器半侧:侧栏底部席位 + portal 浮窗 + 三处配置表单 adapters.js 纯函数适配器:路由、HTTP、通用探测器、两个特殊平台 providers.js 纯函数:从已合成的 Loader 行里发现供应商 bindings.js 纯函数:探测结果的持久绑定(读、写、归一化 API 根) usage.js 纯函数:会话投影缓存 → token 用量报告 cordis.patch.yml 只 insert 本包自己的一行(不覆盖别人的行,卸载才干净)
locale/{zh,en}.json 插件页的标题与描述
dev/smoke.mjs 离线冒烟:mock HTTP + 真实模块 + 物化 client.js 渲染 dev/validate.mjs 清单契约:exports / patch 方言 / 两端 Remote 契约 / 槽位 / 词典 dev/preview.mjs 把设置页与浮窗渲染成静态 HTML(含侧栏底部排布、三种测试连接状态)
宿主与浏览器之间只有两条通路,都在 Host 侧发起请求:
| Remote 方法 | 谁调 | 作用 |
| quotaBoard.load(force) | 浮窗、配置页的发现列表 | 整块看板;20 秒缓存 + in-flight 去重 |
| quotaBoard.test(entry) | 配置页的「测试连接」 | 单条未保存条目的试打;不缓存、不写绑定 |
看板不直连供应商接口 —— 跨域、签名、密钥都不该发生在渲染进程里。
测试连接
配置页每个条目都有「测试连接」:拿屏幕上当前的值(还没保存的那些)去打一次真实的额度接口。
[测试连接] 连通 · 12.34 USD 接口 /v1/usage [钉死这个接口]
- 走的是和看板完全相同的代码路径(providerStatus → queryProvider),所以这里绿了,卡片就会亮。
- 密钥由宿主解析,浏览器不碰;条目里的 apiKeyEnv / accessKeyEnv 只是引用名。
- 不写 bindings.json:一次试探不该把接口钉死,你可能还在改 baseURL。
但探到的路径会回显,想固定下来点「钉死这个接口」,它就写进条目的 fields.endpoint。
- 主机不给额度服务、条目没填地址、Key 解析不到,都各有各的说法,不会只给一个「失败」。
- 超时上限压到 8 秒——按钮是要等结果的,不能跟看板一样等 10 秒。
开发
npm install # 只为 dev/ 里的两个脚本:js-yaml、@deepseek-ai/schemastery
node dev/smoke.mjs # 80 项:路由、通用探测、绑定、账号钱包、测试连接、形状识别、发现、用量聚合、席位文案、浮窗开合与表单渲染
node dev/validate.mjs # 44 项:清单、patch、Remote 契约、槽位、词典、账号钱包
node dev/preview.mjs # 生成 dev/preview-config.html 与 dev/preview-board.html:设置页与浮窗的真实渲染结果
smoke.mjs 会起一个本地 mock HTTP 服务,把真实模块跑一遍,再把 client.js 物化到 VM 里、用桩 React 真渲染 —— 因为「组件抛错」在 Harness 里的表现是整块槽位静默空白,不跑一遍根本发现不了。桩 React 会按点击重放一次渲染,所以「点开浮窗 / Esc 关掉」这类状态切换也在断言范围里。
许可
MIT预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
Anixuil/dsh-quota-board
在侧栏浮层集中查看各供应商余额与本机用量
相关插件 · UI / 主题
破甲增强版JeffKeeping/dsh-purge-plus
dsh-purge 的非官方分支fork:适配 DeepSeek Harness 0.2.1-rc.2、破甲内核…
★ 387已汉化DeepSeek 客户端
71.9
无代码业务系统平台nocobase/nocobase
NocoBase 是什么
★ 24,804已汉化DSH
71.8
1Panel 服务器面板1Panel-dev/1Panel
全球 250 万+ 自托管用户共同喜爱。
★ 37,327已汉化DSH
71.5
终端编码代理esengine/DeepSeek-Reasonix
· 指南 · ACP · 扩展开发 · 规格 · 官方网站 · Discord · QQ
★ 36,021已汉化DSH
71.2
工作状态行动态ccch1mneyyy/working-activity
作者:chimney@ccch1mneyyy。社区项目,非 DeepSeek 官方项目。
★ 664已汉化DSH
71.2
多模型配置管家farion1231/cc-switch
跨平台桌面一体化助手,支持 Claude Code、Codex、OpenCode、DeepSeek Harness 等工具,唯一官网 ccswitch.io
★ 150,724已汉化DSH
71.1