dsh-quota-takeover:Our Free Model 之上的额度接力层

前言

做智能体开发的人,多半会遇到同一类问题:免费的模型平台有几个,各自额度不同,收尾时间也不同。跑在某个平台时中间触发额度上限,整个任务就断了,前面的上下文都白跑。手工盯着换平台、换模型,能解决但不可持续,尤其当平台会增减、模型名在不同渠道叫法不一致时。

puppy-bai/dsh-quota-takeover 处理的就是这件事:在 Our Free Model(下称 OFM)之上加一层「接力」逻辑——平台额度不够按你设定的顺序换下一个,某个平台没有你要的模型就跳过,全都没有就换下一档模型再遍历一遍,任务因额度中断时自动切到新平台并往中断的会话里发一条「继续」。维护者是 puppy-bai,分类是模型推理。

本文只依据插件 README 与 package.json 中已有的内容介绍,不涉及未公开功能。

它解决什么问题

OFM 负责把多个平台的账号、模型和剩余额度聚合起来。它的短板是顺序固定:一个平台额度用完后,接力不会自动发生。本插件把「平台顺序 × 模型档」编译成一条有序候选链,写回 OFM 的 combo(auto:main),由 OFM 的 fallback 策略逐项尝试。

也就是说,插件本身不直接调用模型,它做的是编译计划和写回计划。

核心能力

下面按需求逐条列出已实现的行为,来源是 README 的「它做什么」表。

  1. 额度耗尽换下一个平台:把「平台顺序 × 模型档」编译成候选链,写回 OFM 的 combo(auto:main)。
  2. 模型不存在则跳过:每个模型档有别名表,平台模型清单匹配不到记为 missing 并跳过。别名匹配先精确比较,再去 -free/-preview/eac: 前缀小写比较,最后按 id 最后一段比较——聚合渠道的 siliconflow/deepseek-ai/DeepSeek-V3 能被 DeepSeek-V3 命中。
  3. 全部换完还没有就换档重遍历:遍历形状为 tier-major(档优先),先全平台找第 1 档,再全平台找第 2 档。
  4. 兜底:finalResort.fallbackModels(如 groq/llama-3.3-70b)非空时编译兜底链;为空则进入「等待恢复」。
  5. 中断续跑:监听 llm/stream 的错误终点,分类为额度/限流后写冷却、重编译计划、向该会话 agent.followup(一条「继续」消息)。
  6. 平台表自动维护:平台来源有三处——channel-pack 账号池、OFM 聚合渠道 /providers、catalog 里的新通道(如 subscription:magpie/siliconflow/…)。每轮同步重新读。连续 platformPolicy.pruneAfterMisses(默认 3)轮读不到的平台从顺序里清掉;pruneZeroAccounts(默认开)会把账号数为 0 的渠道隐藏,之后补上账号会自动回来;也可以在设置页每行手动删除平台,写进 hiddenPlatforms 和 excludePlatforms,底部「已隐藏 N 个」点 ↺ 可放回。

为什么是两个半身

OFM 的 API 挂在 harness 的信任围栏后,插件进程内的 fetch 一律返回 401(README 提到实测,详见设计文档 §12.1)。所以读账号/额度、写 combos 这两件事只能由浏览器侧代劳,host 侧负责编译计划。

浏览器(带 DSH 认证 cookie)                插件 host 进程
  │ ① GET /api/our-free-model/combos         │
  │ ① GET /api/our-free-model/subscriptions  │
  │ ② POST /api/quota-takeover/snapshot ────▶│ 编译计划(平台顺序 × 模型档 × 额度 × 冷却)
  │ ③ GET /api/quota-takeover/pending ◀──────│ 待写回的 combos
  │ ④ POST /api/our-free-model/combos        │   (只有浏览器有写权限)
  │ ⑤ POST /api/quota-takeover/applied ─────▶│ 记录已写回

续跑不受这个限制影响,因为它是进程内 agent.followup(),不经过 HTTP。

安装与启用

前提:先装好 Our Free Model。没有 OFM 时,本插件只剩续跑能力,没有可接力的平台。

从市场装(发布后可用):

DSH → Plugins → Discover 里搜 quota-takeover

手动装(开发或未发布时),README 给出的命令如下:

cd ~/.dsh/profiles/desktop
npm i /path/to/dsh-quota-takeover-0.1.1.tgz   # 或把源码目录拷到 node_modules/dsh-quota-takeover

# 然后在 package.json 的 dsh.profile.bundles 数组里追加 "dsh-quota-takeover"
# 被 bundles 引用的包,其自带 cordis.patch.yml 自动生效;
# 别再往 cordis.patch.yml 手写同名条目,否则报 duplicate loader entry id

装完要完全退出 DeepSeek Harness 再打开。host 半身只在进程启动时 apply 一次,刷新页面只重载浏览器半身。

三个检查点:

检查点 期望
设置 → 「额度接力」 页面出现,且没有红色「宿主半身没有加载」告警
平台顺序 / 模型档 列出 channel-pack 里启用的平台与它们的真实模型
~/.dsh/quota-takeover/journal.jsonl 有 api-mounted;发生过失败时有 failure / resume

运行期数据放在 ~/.dsh/quota-takeover/{config,plan,bench,resume,platforms}.json 和 journal.jsonl。

配置

配置文件是 ~/.dsh/quota-takeover/config.json,也可以由设置页「额度接力」写入。README 提供的样例:

{
  "enabled": true,
  "platformOrder": ["trae", "minimax", "zcode", "loomy", "raccoon", "gemini"],
  "platformPolicy": {
    "unknownTail": true,
    "excludePlatforms": [],
    "pruneMissing": true,        // 读不到的渠道自动从顺序里清掉
    "pruneAfterMisses": 3,       // 连续缺席几轮才清(防一次探测失败误删)
    "pruneZeroAccounts": true    // 0 账号的空渠道自动隐藏(有账号后自动回来)
  },
  "modelTiers": [
    { "id": "deepseek-flash", "label": "DeepSeek V4.1 Flash", "pinned": true,
      "aliases": ["deepseek-v4.1-flash", "deepseek-v4-flash-0731", "deepseek-flash"] },
    { "id": "glm-flash", "label": "GLM 5.3 Flash", "aliases": ["glm-5.3-flash"] }
  ],
  "traversal": { "order": "tier-major", "maxChainLength": 16, "optimisticOnUnknown": true },
  "finalResort": { "fallbackModels": [], "retryAfterMinutes": 10 },
  "resume": { "enabled": true, "onlyQuotaLike": true, "maxPerSession": 5, "requireCandidateChange": true }
}

几个容易踩的点:

  1. platformOrder 没列出的平台排在后面(受 platformPolicy.unknownTail 控制)。
  2. pruneMissing / pruneAfterMisses 决定撤掉的渠道何时被清理,缺席次数记在 platforms.json。一轮读不到任何平台时整轮跳过,README 解释这是为了区分中继故障和渠道被删。
  3. optimisticOnUnknown:平台模型清单未知时先把格子放进链,真没有会让 OFM 的 combo 自然失败并前进——未知不等于不存在。
  4. resume.requireCandidateChange 是核心防呆:候选链没变化就不重复注入「继续」,避免握着同一个额度耗尽的平台反复触发。

HTTP API

以下接口在浏览器侧使用,需要带 DSH 认证 cookie:

方法 路径 作用
GET /api/quota-takeover/status 计划 + 桥状态 + 配置
POST /api/quota-takeover/compile 手动重编译
POST /api/quota-takeover/snapshot 浏览器推账号/额度/模型快照
GET /api/quota-takeover/pending 取待写回的 combos
POST /api/quota-takeover/applied 回报写回成功
GET /api/quota-takeover/bridge 中继健康状况
POST /api/quota-takeover/config 改配置(合并后重编译)
POST /api/quota-takeover/bench/clear 清空冷却表

开发者自测

README 里给的几条命令,适合改完代码后自己跑一遍:

node --test tests/*.test.js     # 单测(编译器 / 分类器 / 续跑状态机,README 写 32 个)
node probes/smoke-host.mjs      # 假 ctx 装载 host 半身,跑通中继闭环
node probes/plan-preview.mjs    # 用本地 state.json 预演一次编译
node probes/ofm-probe.mjs <gui 地址>   # 探针:OFM API 可达性(预期 401)

已知限制

按 README「已知限制」一节列出:

  1. 写回依赖 GUI 打开。浏览器关掉时链停在旧计划上;候选里已带 resolved 模型 id,旧链仍能跑。
  2. 默认不直接改 OFM 的 settings.json(除显式 writeBack.mode: "file")。OFM 把设置常驻内存,改盘不热生效且会被下次保存覆盖。
  3. 续跑只在「额度/限流」类失败上生效(onlyQuotaLike);用户主动 abort 绝不续跑。
  4. llm/stream 目前只观察不改道(探针 4 未验),改道能力留作 M2。

适用场景与注意

适合已经在用 OFM 聚合多个免费或低价平台的开发者:想把平台增减、模型档顺序和额度中断后的续跑交给插件维护,而不是手改 combo。平台多、模型名在各渠道写法参差、经常碰到额度用完时,这层接力能明显减少人工介入。

需要注意:

  • 插件以当前 dsh 进程的权限运行,安装前应检查源码与许可证(README 的 license 字段写的是 MIT)。
  • 它是 OFM 之上的一层,前提是 OFM 已正确配置并启用了 channel-pack 等渠道;没有 OFM 时只剩续跑能力。
  • 写回依赖浏览器半身,长期运行的环境里 GUI 不能随便关。

结尾

dsh-quota-takeover 的价值在于把「额度耗尽 → 换平台 / 换模型档 → 继续跑」这条链路自动化,并且用 resume.requireCandidateChange 等配置把误续跑控制住。如果你的需求正好在 OFM 的射程之外,可以先看插件目录页和源码再决定:

  • 目录页:https://www.skillhub.cn/plugins/puppy-bai/dsh-quota-takeover
  • GitHub:https://github.com/puppy-bai/dsh-quota-takeover

目录站是独立站点,与 DeepSeek / 幻方无官方从属关系。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜