跳过主要内容
P

dsh-quota-takeover

puppy-bai/dsh-quota-takeover

额度接力:在 Our Free Model 之上按你设定的平台顺序与模型档编排一条有序接力链,缺该模型、平台冷却、额度耗尽的格子自动跳过,结果写回 OFM 的 combos;因额度或限流中断后重新编排并向中断的会话补一条「继续」,让回合在下一个平台接着跑,链尾可选聚合渠道兜底模型或 DeepSeek 官方额度。

安装

dsh plugin --profile web add github:puppy-bai/dsh-quota-takeover

README

dsh-quota-takeover · 额度接力

在 Our Free Model 之上加一层「接力」: 一个平台额度不够就按你设定的顺序换下一个平台;某个平台没有你要的模型就跳过; 全都没有就换下一档模型再遍历一遍;实在不行用你指定的兜底模型。 任务因额度中断时,自动切到新平台并往中断的会话里发一条「继续」。

设计文档(含需求分析、失败分类表、风险对策、能力边界、终局兜底): docs/quota-takeover-plugin-design.md 上架市场的步骤:docs/SUBMISSION.md

它做什么

你的需求本插件的实现
平台额度不够 → 按我设定的顺序换下一个把「平台顺序 × 模型档」编译成一条有序候选链,写回 OFM 的 combo(auto:main),由 OFM 的 fallback 策略逐项尝试
我一直用的模型,别的平台没有就跳过每个「模型档」有别名表;平台模型清单里匹配不到 → 记为 missing 并跳过
全都换完还没有 → 换模型再遍历一遍遍历形状 tier-major(档优先):先全平台找第 1 档,再全平台找第 2 档……
最后兜底finalResort.fallbackModels(如 groq/llama-3.3-70b)非空 → 编译兜底链;为空 → 进入「等待恢复」
因额度中断 → 自动换平台并续跑监听 llm/stream 的错误终点,分类为额度/限流后写冷却、重编译计划、向该会话 agent.followup(一条「继续」消息)
新接入的平台自动出现平台表有三处来源:channel-pack 账号池、OFM 聚合渠道 /providers、catalog 里的新通道(如 subscription:magpie/siliconflow/… → 「Magpie(硅基流动等)」);每轮同步重新读
撤掉的平台自动消失连续 platformPolicy.pruneAfterMisses(默认 3)轮读不到就从顺序里清掉;关掉 pruneMissing 则只标记不删
0 账号的空渠道自动消失platformPolicy.pruneZeroAccounts(默认开):账号数为 0 的渠道直接隐藏;哪天给它加了账号,会自动放回来(只自愈「自动隐藏」的,用户手动删的保持删除)
手动删除任意平台每行常驻红色「删除」;写进 hiddenPlatforms + excludePlatforms,底部「已隐藏 N 个」点 ↺ 可放回

两个半身(为什么必须这样)

浏览器(带 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 ─────▶│ 记录已写回

OFM 的 API 挂在 harness 的信任围栏后,插件进程内的 fetch 一律 401(实测,见设计文档 §12.1)。 所以读账号/额度、写 combos 这两件事只能由浏览器半身代劳;续跑不受影响——它是进程内 agent.followup(),不经过 HTTP。

安装

前提:先装好 Our Free Model。本插件从它那里取「平台 × 模型 × 剩余额度」,并把接力链写回它的 combos;没有 OFM 时只剩续跑能力,没有可接力的平台。

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

DSH → Plugins → Discover 里搜 quota-takeover

手动装(开发/未发布时):

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(也可由设置页「额度接力」写入):

{
  "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 }
}
  • platformOrder:没列出的平台排在后面(platformPolicy.unknownTail)。
  • platformPolicy.pruneMissing / pruneAfterMisses:撤掉的渠道会一直留在顺序里,所以连续 若干轮读不到就自动清理(写入 platforms.json 记录缺席次数)。一轮读不到任何平台时整轮跳过, 因为那说明中继断了、不是渠道被删了。
  • modelTiers:aliases 是同一模型在各平台的叫法;匹配时先精确、再去 -free/-preview/eac: 前缀小写比较, 最后还能按 id 的最后一段比(聚合渠道的 siliconflow/deepseek-ai/DeepSeek-V3 能被 DeepSeek-V3 命中)。
  • optimisticOnUnknown:平台模型清单未知时(本地 state.json 不存模型表)先把格子放进链, 真没有会让 OFM 的 combo 自然失败并前进——未知 ≠ 不存在。
  • resume.requireCandidateChange:核心防呆,候选没变就不重复注入「继续」。
方法路径作用
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清空冷却表

开发

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

已知限制

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

相关插件