一件订阅凭据是怎么变成 dsh 里的 LLM Provider 的:取凭据、发现模型、读额度、做路由
dsh-plugin-subscriptions 的定位:把 ChatGPT(Codex)、Claude、Grok(X Premium) 这类订阅用作 DeepSeek Harness 的 LLM 提供商,在 Web UI 通过 OAuth 登录,不需要 API 密钥。仓库 V1ki/dsh-plugin-subscriptions,分类 UI / 主题,npm 包版本 0.9.4,站点于 2026-09-16 真实安装成功(L4)。本文不写安装步骤,只讲一件订阅凭据如何被四段流水线加工成 dsh 里一个可路由的 provider。
第一段:OAuth 取凭据
五条登录路径在实现层就已分叉:
- codex、grok、antigravity 走标准 OAuth,在 dsh Web UI 的 Settings → Subscriptions 登录;Antigravity 打开 Google 授权,不需额外 client 配置。
- copilot 走 GitHub OAuth device flow,需在
github.com/login/device输入设备码。 - claude 优先导入已有的 Claude Code 会话凭据(macOS Keychain 或
~/.claude/.credentials.json),读不到才回退到同样的浏览器 OAuth,因此不要求先装 Claude Code CLI。
token 固定在 ~/.dsh/plugins/subscriptions/auth.json,权限 0600,自动刷新。这一步定义信任边界:后三段才能统一假设「账号还在登录态,凭据就可用」。claude 的回退路径用的是本插件自己的临时端口 loopback 回调(host 为 localhost + 随机端口),而非托管的平台回调。
第二段:模型目录发现
插件不造统一目录,按 provider 分别取:codex 取 chatgpt.com/backend-api/codex/models 的 live catalog;claude 是静态目录(Opus / Sonnet / Haiku / Fable),随插件更新;grok 取 api.x.ai/v1/models;copilot 取 api.githubcopilot.com/models;antigravity 取 v1internal:fetchAvailableModels。
live 与静态的差别决定换账号、换档位后的行为:live 的跟着账号可用来变,静态的只能等插件发新版,所以 README 补了一句「Model availability remains account-dependent」。
推论是模型选择器只显示已登录 provider 的模型;未登录时 provider 不入选择器,请求以 MISSING_CREDENTIAL 失败并指向设置页。Vision 模型声明 ['text', 'image'] 输入模态。
第三段:额度读的是 rate-limit 窗口
用量口径是 rate-limit 窗口:5 小时会话窗口、每周窗口,某些计划还有按模型每周窗口(README 原话「A subscription plan is rate-limit shaped by design」)。用户用的是自己的订阅额度,插件只把账号侧窗口读数取出来展示并参与路由。
读数来源按 provider 分:Codex 读 chatgpt.com/backend-api/wham/usage(同时报告 plan),Claude 读 api.anthropic.com/api/oauth/usage,Grok 走 CLI proxy 的 /v1/billing(报告共享 weekly pool 与订阅层级),Antigravity 读 loadCodeAssist / fetchAvailableModels。
重试形态五条路由共用:首次尝试后十次重试,1s 起退避,20% 抖动,60s 上限;只对 429 读取 rate-limit 头,其它失败保持短本地退避——同样的头也出现在瞬时 500 上,若在那里也遵守,会因一个一秒即恢复的过载占满整个窗口。
坑 P1-C:maxWaitMs 抬高的不只是「愿意等多久」
延迟上限与本地退避共享,所以调高 maxWaitMs 不只影响限流,还会加长无关的瞬时故障(TRANSPORT / SERVER / TIMEOUT)的退避时长——十次重试的最后一次可达 512 秒,而非 60 秒上限。
另外,429 未披露 reset 时,本地重试约 17 分钟后该轮失败,wait: false 时约 5 分钟;reset 超出 maxWaitMs 则立即失败并附上 reset 时间。前提是必须装 @deepseek-ai/dsh-llm-retry,否则「nothing waits」。
第四段:pool 路由与账号级配额
多账号以 email / login 为 key:重复登录同一账号原地更新,不同账号追加。默认账号(★)服务直接 provider 路由,pool 路由使用所有账号。第一条硬规则是 families 仅限同一 provider,跨 provider 成员被忽略。
坑 P1-B:跨 provider 组池是静默忽略
它不报错,只忽略:配置不生效也不提示,只有额度始终没被分担才会察觉。判断方法很简单——有效成员一定全来自同一 provider。
第二条硬规则是配额粒度:pool cooldown 的配额是账号级。Claude 的 model-scoped lanes 按成员冷却,而 quota 与 rate-limit 失败会冷却整个账号;成员任一窗口使用率超过 95% 会被 gating out。pool 能摊开窗口内用量,摊不开账号级惩罚。
坑 P1-A:DSH 版本域里没有 0.1.6-alpha
支持的已发布 DSH:0.1.1-rc.2、0.1.2-alpha / rc、0.1.3-alpha、0.1.5-alpha / rc,含 0.1.5-rc.2。其中 0.1.5-alpha.1 的 peer-range 锚点按 semver 规则有意覆盖后续 0.1.5-alpha、0.1.5-rc 与稳定版 0.1.5;而 DSH 0.1.6-alpha 未包含,直到另行验证。跑在 0.1.6-alpha 上时,别假设 peer 没报错就等于验证过。
总结
四段串起来:OAuth 拿到凭据写进 0600 且自动刷新的 auth.json,模型目录按 provider 从 live catalog 或静态目录取,额度按 rate-limit 窗口读数,pool 只在同一 provider 内做账号级分摊。机制不复杂,复杂的是每段的边界条件。想对照同类插件的中文清单见 DeepSeek Harness Hub 插件清单。
适合与不适合
适合:已有 ChatGPT Plus / Pro、Claude Pro / Max、X Premium 或 GitHub Copilot 订阅、想把额度接进 dsh 的人;需要在同一 provider 下挂多账号分摊窗口用量的人。
不适合:无法联网或内网只放行 SOCKS 代理的环境(原话「SOCKS proxies are not supported.」,且无任何离线模式);希望看到「剩余次数」而不是窗口占比的人;跑在 DSH 0.1.6-alpha 上的人;指望跨 provider 混池分摊额度的场景。
标签:dsh-plugin-subscriptions、DeepSeek Harness、订阅账号接入、OAuth provider 路由
本文由 DeepSeek Harness Hub 自动整理,数据来源于插件详情页。