前言¶
在 DeepSeek Harness(DSH)里跑 agent 时,模型请求走固定的 provider 路由。若你有多份 OpenCode Go 订阅(每份一把 API key),常见做法是手动换 key 或拆成多条路由,再在客户端或脚本里切换。DSH 的 agent loop 对单次请求的 options 是深冻结的,waterfall 监听器只能读 provider,不能改路由;能随每次请求重新解析的是 provider 的 apiKeyEnv 凭据引用。下面介绍的 dsh-opencode-go-pool(维护者 TianYa-DAO,分类:模型推理)把多把订阅 key 池化在同一条路由后面:请求前选额度最健康的一把,网关因额度拒绝时冷却并 failover,无需你手动换模型或换路由。
这是什么¶
dsh-opencode-go-pool 是 DSH 社区插件(package 名 dsh-opencode-go-pool,DSH 显示名「OpenCode Go 多订阅池」,当前版本 0.1.0,MIT 许可)。它解决的是:多个 OpenCode Go 订阅如何稳定地共用一条 provider 路由,并在 5 小时 / 周 / 月等用量窗口用尽或收到网关额度错误时自动换 key,而不是改路由或改 frozen 的 options。
为什么是「换凭据」而不是「换路由」¶
DSH agent loop 发出的模型请求 options 不可改,改会抛错。本插件让目标路由的 apiKeyEnv 指向一个由插件独占写入的 activeRef(例如 OPENCODE_GO_ACTIVE_KEY);每次请求前插件把当前最健康的订阅 key 写入该引用,从而在不动路由名的前提下切换实际使用的 key。
工作原理¶
- 各订阅 key 存放在 DSH 标准凭据存储(
$DSH_HOME/.credentials.yaml,可在设置页管理),插件按配置里的keys[].ref读取。 - 路由的
apiKeyEnv改为activeRef,由插件在每次请求前写入当前生效 key。 - 插件调用 OpenCode Go 官方用量接口
GET https://opencode.ai/zen/go/v1/usage(仅需 API key,无需 org token),读取 5 小时 / 周 / 月窗口的percent与status;status: "rate-limited"或percent >= 100视为该窗口已用尽。 - 每次请求前:读数缺失时先查一次;读数仅过期时在后台刷新、不阻塞请求;当前 key 已用尽则立刻换成余量最健康的一把。
- 网关返回
HTTP 429、{"error":{"type":"GoUsageLimitError"}}且带Retry-After时(Harness 归类为QUOTA,默认不在重试码内,由插件重发):按Retry-After与窗口重置时刻冷却该 key,换另一把,并在本次请求尚未产出任何 token 的前提下原样重发一次;已有输出则如实报错,不重复生成。
多个决策(激活预热与并发请求)串行执行,避免状态快照交叉。
配置与启用¶
插件本体在 cordis.patch.yml 里只有一行 insert;具体池化参数写在你的 profile patch 层。README 未给出统一的 dsh plugin add … 安装命令;桌面 profile 示例是通过 file: 依赖指向插件目录并在 patch 中 insert 接入(插件源码路径示例:~/.dsh/plugins/dsh-opencode-go-pool)。启用前请在 GitHub 阅读源码与 LICENSE,插件以当前 DSH 进程权限运行。
在 patch 中注册插件并填写池配置:
- insert:
- id: opencode-go-pool
name: 'dsh-opencode-go-pool'
- id: opencode-go-pool
config:
route: opencode-go # 要接管的 provider 路由名
activeRef: OPENCODE_GO_ACTIVE_KEY # 插件独占写入的凭据引用
keys:
- { ref: OPENCODE_GO_API_KEY, label: 订阅A }
- { ref: OPENCODE_GO_API_KEY_B, label: 订阅B }
把被接管路由的 apiKeyEnv 改为 activeRef,例如:
- id: llm-pi-ai
config:
providers:
opencode-go:
apiKeyEnv: OPENCODE_GO_ACTIVE_KEY
api: openai-completions
baseURL: https://opencode.ai/zen/go/v1
可选字段与默认值(资料原文):usageUrl(默认上述用量接口)、usageTtlMs(60000)、cooldownMs(60000,网关未给出窗口时的冷却下限)、maxFailovers(1,单次调用最多切换次数)。keys[].ref 不得与 activeRef 相同,否则插件激活时报错并指出字段名。
凭据示例:各订阅的 ref(如 OPENCODE_GO_API_KEY、OPENCODE_GO_API_KEY_B)由你自行填入;OPENCODE_GO_ACTIVE_KEY 由插件写入,勿手动覆盖为订阅 key。
典型用法与可观察行为¶
配置完成后,走 route 指定的 provider 路由的模型请求会自动选 key 并在额度拒绝时 failover。Host 日志前缀为 opencode-go-pool:,例如:
- 装载成功:
pooling 订阅A, 订阅B behind route "opencode-go" through OPENCODE_GO_ACTIVE_KEY - 首次装填或换 key:
installed 订阅B as the active key - 请求前避开已用尽 key:
switched away from 订阅A (quota spent, resets …) to 订阅B - 429 后切换并重发:
failover 订阅A (quota spent, resets …) -> 订阅B (until …) — Go usage limit exceeded
本地可跑插件自带自检(不依赖真实网关):
node tests/selfcheck.mjs
仓库还提供 e2e overlay 配置(tests/e2e-overlay.yml、tests/e2e-overlay-failover.yml)用于用量驱动切换与 429 驱动切换的回归场景。
适用场景与限制¶
适合:持有多份 OpenCode Go 订阅、希望 DSH 里只维护一条 opencode-go(或同类)路由,并自动按用量与 429 切换 key 的开发者。
注意:
- 只在请求发出前与被拒绝后判断健康度,不预测额度何时耗尽。
- 仅对
config.route指定的那一条路由做逐请求决策;其它路由若共用同一activeRef,只能继承当前生效 key。 - 切换属于传输层,不写会话事件;依据在 Host 日志,不在会话记录里。
- 若 profile 使用
nodeLinker: hoisted且以file:硬链接依赖插件,改index.js一般立即生效;若编辑器替换文件导致 inode 变化,需在 profile 目录执行pnpm install重建链接。改动后通常需重启 DSH 桌面端。
问题反馈可到 GitHub Issues 或邮件 2842425998@qq.com。
结尾¶
dsh-opencode-go-pool 在 DSH「一切皆插件」的生态里,用凭据池化把多订阅 OpenCode Go 收成一条 provider 路由,并对接官方用量 API 与 429 failover。社区目录页(与 DeepSeek / 幻方无官方从属关系):skillhub.cn 插件页;源码与完整说明:GitHub — TianYa-DAO/dsh-opencode-go-pool。