dsh-quota-guard
Verifieddsh-quota-guard · v0.1.3 · MIT
Usage metering, daily/per-minute budgets and automatic account failover for DeepSeek Harness model calls.
Install
dsh plugin add dsh-quota-guard Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Published to npm without a public repository. Inspect the package contents before installing.
Tags
Readme
dsh-quota-guard
用量计量、每日/每分钟限额、OpenAI 兼容账号池自动切换——一个可以直接装进 DeepSeek Harness 的组合包(bundle)。
English: README.md
它解决什么
- 看得见:每一次
llm/stream都记账——请求数、输入/输出/缓存 token、首字延迟、按模型与提供方拆分、最近 32 天趋势。 - 花不超:今日 token 上限、今日请求上限、每分钟请求上限;到顶后在下一次请求发出前拦住,不会先发出去再后悔。
- 不断线:把多个 OpenAI 兼容账号/模型配成一条路由,遇到 429、401、欠费、5xx 自动换下一个;已经开始输出后不重放,避免重复内容。
安装
# 发布到 npm / GitHub 之后
dsh plugin --profile desktop add dsh-quota-guard
# 本地 checkout
dsh plugin --profile desktop add ./dsh-quota-guard
dsh --profile desktop --dump-config # 应能看到 "# == dsh-quota-guard" 这一层
cordis.patch.yml 会插入一行 id: llm-guard,默认配置下只计量、不拦截(所有上限为 0),装上是安全的。
配置
写在 profile 的 cordis.patch.yml 里,或作为 profile 自己的 patch 层叠加:
- insert:
- id: llm-guard
name: dsh-quota-guard
config:
limits:
dailyTokens: 2000000 # 每天 token 上限,0 = 不限
dailyRequests: 1500 # 每天请求数上限,0 = 不限
perMinuteRequests: 30 # 每分钟请求数上限,0 = 不限
warnAt: 0.8 # 用到 80% 开始告警
onExceed: block # block = 拦截;warn = 只告警照常放行
prices: # 元 / 百万 token,可选;不配则只计 token 不算钱
deepseek-chat: { in: 2, out: 8 }
'qwen-*': { in: 1.2, out: 6 }
pool:
provider: guard-pool
accounts:
- id: bailian-main
baseURL: https://dashscope.aliyuncs.com/compatible-mode/v1
apiKeyEnv: DASHSCOPE_API_KEY
models: [qwen3.8-flash, qwen3.6-flash, qwen-plus]
- id: glm-backup
baseURL: https://open.bigmodel.cn/api/paas/v4
apiKeyEnv: ZHIPU_API_KEY
models: [glm-4-flash]
fallback:
qwen3.8-flash: [qwen3.6-flash, glm-4-flash]
| 键 | 默认 | 说明 |
|---|---|---|
enabled |
true |
关掉后完全放行、不记账 |
stateFile |
$DSH_HOME/llm-guard/usage.json |
账本路径 |
limits.* |
全部 0(不限) |
上限为 0 表示不启用该项 |
prices |
空 | 键支持 模型名 或 前缀*;单位:元 / 百万 token |
pool.accounts[].apiKeyEnv |
— | 推荐:密钥放环境变量,插件只读 process.env |
pool.accounts[].apiKey |
— | 直接写密钥,仅方便本地试;会被状态/日志排除,但仍不建议提交到仓库 |
pool.fallback |
空 | 显式模型降级链;不配就不会偷偷换模型 |
pool.maxAttempts |
6 |
单次请求最多试几个候选 |
pool.cooldownMs |
60000 |
限流/5xx/传输错误的冷却基准(限流至少等 Retry-After);鉴权、欠费、模型不存在冷却 10 分钟 |
pool.timeoutMs |
300000 |
单次上游请求总时长上限 |
pool.contextWindow |
0 |
声明给 UI 的上下文窗口;0 = 不声明 |
pool.allowAnyModel |
false |
请求的模型池里没有时,是否允许用池内其它模型顶上 |
让 agent 走账号池
账号池注册成提供方 guard-pool 之后,把默认模型指过去即可(覆盖 profile 里已有的 agent-default-model 行):
- id: agent-default-model
name: "@deepseek-ai/dsh-agent-default-model"
config:
provider: guard-pool
model: qwen3.8-flash
不配账号池时,本插件只做全局计量与限额,对现有提供方零侵入。
报告工具
llm_guard_report(参数 days,1–32,默认 7)返回只读快照:今日与累计计数、限额剩余、按模型/提供方拆分、最近 N 天趋势、账号池冷却状态,以及今天/累计/分模型的平均首字延迟 avgLatencyMs。它只读本地账本,不发起任何模型请求。
行为边界(请先读)
- token 来自上游
usage。上游不返回 usage 时 token 记 0,不会拿字符数瞎估。 - 限额在请求发出前判定。单次超大请求可能把当日额度顶穿——这是拦截式限额的固有极限,不是 bug。
- 自动切换只在吐出第一个分片前。一旦向调用方输出过内容就不再重试,否则会重复内容;此时的错误按协议以
errorfinish 结束。 - 不支持图片输入:图片块会以
UNSUPPORTED_OPTION明确报错,不会静默丢图。 - 未定价 ≠ 免费:
prices为空时报告的costCny是 0、priced: false;请自己按厂商当前报价填写。 - 账本是本地估算,用于自我约束,不是厂商账单。
- 按请求开始日归档:跨零点的长流记在开始那天;延迟样本只来自真正输出过首字的请求。
- 损坏的账本会被保留:
usage.json解析失败或版本不符时另存为usage.json.corrupt,不会静默清空。 - 冷却状态只在内存里,重启后清零;账本持久化在
stateFile。
与旧版 dsh-free-quota 相比砍掉了什么
砍掉:探测全部模型、用量面板 UI、按 YAML 改默认模型、解析第三方账本、模型偏好评分。留下的是可发布、可测试、对宿主零侵入的三件事:计量、限额、切换。
开发
npm test
# 可选:对着真实宿主核对 @deepseek-ai/dsh-llm 的导出名
DSH_HOST_LLM=/path/to/dsh/node_modules/@deepseek-ai/dsh-llm/lib/index.js node --test test/host-compat.test.js
测试不需要网络:test/adapter.test.js 起本地 HTTP 服务模拟 429 与 SSE 流。运行时代码只依赖 Node 内置模块与宿主提供的 @deepseek-ai/dsh-llm(peer dependency),没有第三方依赖。
发布清单
npm test全绿;npm pack --dry-run只包含index.js、lib/、test/之外的运行文件。- 建公开 GitHub 仓库,仓库 Topics 加上
dsh-plugin(市场抓取依据)。 - 在
package.json补repository、homepage、author(发布前留空会被市场页显示成空白)。 npm publish(若用@scope需公开访问权限)。- 到 dsh-plugin.org、DSH Plugin Hub、
awesome-dsh-plugin提交仓库地址。 - 版本遵循 SemVer:行为变更升 minor,修复升 patch,并在
CHANGELOG.md记一笔。
License
MIT