前言¶
DeepSeek Harness(DSH)在接入 OpenCode Go 网关时,官方 opencode-go 路由无法实时获取新增模型,这是因为 @deepseek-ai/dsh-llm-pi-ai 的 discoverModels() 对已知的 provider 直接返回构建期快照,不会发网络请求。这个快照是打进包里的 JSON,没有 TTL,不会刷新。手动添加也过不去,因为该目录横跨三种协议,sharedCatalogApi() 返回 undefined,设置页只对不认识的路由提供协议下拉框。声明 api: 会让 session 头消失,网关回 400 MissingSessionID。dsh-opencode-live 插件提供一条独立的路由,把这三件事都自己回答。
插件定位¶
paurika1113/dsh-opencode-live 是一个 DSH 路由插件,用于 OpenCode Go 和 Zen,以网关实时列表为准的模型清单,并为每个模型使用它真正支持的那套线路协议拨号。插件挂载在 opencode-live 路由上,由维护者 Paurika1113 开发,版本 0.2.0,采用 MIT 许可证,分类为模型推理。
核心能力¶
插件自己 GET {prefix}/v1/models,注册在独立的 settings 命名空间下,与 pi-ai 目录无关。一次请求约 1 秒。每个模型一个复选框,列表始终展示网关完整目录,取消勾选只是隐藏,随时可勾回。已勾选的模型浮到列表顶部,下方分出一条「未显示的模型」;组内保持网关原顺序。设置页为每个模型提供下拉框,选中即保存。
网关的 /models 只返回 id 和 owned_by,不含协议。同一路由下不同模型接受的协议不同(2026-10-21 实测 37 个模型)。插件内置一张实测表,用同一句提问分别发纯红与纯蓝的 PNG,只有两次都答对颜色才算「真能看图」。按模型家族给出该厂商文档里真正存在的档位,不认识的家族不显示档位。
安装与启用¶
DSH 没有「扫描目录自动加载插件」,插件是 profile 包的 pnpm 依赖,dsh.profile.bundles 决定哪些依赖被挂载。
1. 取得代码¶
git clone https://github.com/Paurika1113/dsh-opencode-live.git
2. 挂进 profile¶
~/.dsh/profiles/<profile>/package.json:
{
"dependencies": {
// 换成你 clone 到的绝对路径
"dsh-opencode-live": "link:<clone 到的绝对路径>"
},
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"dsh-opencode-live"
]
}
}
}
cd C:\Users\<你>\.dsh\profiles\<profile>
pnpm install
插件自己的 peerDependencies 不会被自动安装,保持不声明即可,宿主提供这些包。
3. 在 cordis.patch.yml 里配置¶
fiber 本体由插件自带的 cordis.patch.yml 创建,你只需覆写它的 config:
- id: opencode-live
config:
baseURL: https://opencode.ai/zen/go/v1 # 前缀;填完整端点也会被归一化
apiKeyEnv: OPENCODE_GO_API_KEY
4. 重启 DSH¶
重启 DSH,在模型选择器里选「OpenCode Go · 实时目录」下的模型。
配置项¶
| 字段 | 默认值 | 说明 |
|---|---|---|
enabled |
true |
关闭后不注册任何路由 |
route |
opencode-live |
注册的路由 ID。不能是 opencode-go(已归 pi-ai 适配器) |
displayName |
OpenCode Go · 实时目录 |
选择器里显示的名称 |
baseURL |
https://opencode.ai/zen/go |
网关前缀。/v1 会补齐;完整端点会被裁掉;前后空格会被清掉 |
apiKey |
'' |
填了就一定用它,优先于凭据库 |
apiKeyEnv |
OPENCODE_GO_API_KEY |
凭据库引用名 |
credentialRefs |
[] |
按顺序尝试的引用名 |
apiKeyHeader |
authorization |
密钥放在哪个请求头 |
apiKeyPrefix |
Bearer |
密钥前缀;留空表示原样发送 |
fingerprint |
false |
是否补齐 bash/glob/grep/read 四件套。Go 订阅通道实测不需要(免费通道才校验) |
headers |
{} |
附加静态头。x-opencode-session 会被丢弃 |
discoveryTimeoutMs |
15000 |
拉列表超时 |
autoRefreshMinutes |
0 |
自动刷新间隔,0 关闭 |
models |
[] |
手工声明的模型(带 protocol 时优先于页面选择) |
默认 models 是空的,这条路由的前提就是「网关说了算」。内置一份清单等于把那份会过期的快照搬进来,正是本插件要消除的东西。fingerprint 默认关,2026-10-21 实测,minimax-m3.1-flash-free 在 Go 订阅通道上带不带四件套工具都是 200,四件套是免密 free 通道的门,不是这条通道的。
三种线路协议¶
网关的 /v1/models 只给 id,不给协议。同一路由下不同模型接受的协议完全不同(2026-10-21 实测 37 个模型):
| 模型 | chat-completions | responses | anthropic-messages |
|---|---|---|---|
minimax-m3.1-flash-free |
✅ | ✅ | ✅ |
deepseek-v4.1-flash |
✅ | ✅ | ✅ |
grok-4.6 / grok-4.7 |
❌ | ✅ | ❌ |
claude-haiku-5-5 |
❌ | ❌ | ✅ |
minimax-m2.7 |
❌ | ❌ | ✅ |
glm-* / kimi-* / qwen-* |
✅ | ✅ | ❌ |
beam-free / muse-spark-* |
区域封锁 | 区域封锁 | 区域封锁 |
所以协议是按模型的属性,不是按路由的。设置页为每个模型提供一个下拉框,选中即存进 ~/.dsh/opencode-live/config.json 的 modelProtocols。
认证头也不同:anthropic-messages 用 x-api-key(实测 Bearer 会 401),两种 OpenAI 方言用 authorization: Bearer。
每个模型的详细设置¶
每行右侧有个 +,展开后是这个模型自己的四项设置。它们和协议下拉框一样,都是用户说了算——插件不猜,也不在后台测。
| 设置 | 存进 | 不设置时 |
|---|---|---|
| 上下文窗口 | modelSettings[id].contextWindow |
平台默认 204800 |
| 最大输出 token | modelSettings[id].maxTokens |
平台默认 131072,且永远不超过上下文窗口 |
| 输入类型(文本/图片) | modelSettings[id].inputModalities |
回落到图片实测表(modelVision 布尔仍生效) |
| 思考档位 | modelSettings[id].reasoningEfforts |
回落到按模型家族匹配的厂商文档表 |
容量输入接受 128K / 1M / 200000 三种写法,留空就是继承。输入类型至少要留一种——取消最后一个勾选框是禁用状态,因为「不给模型任何输入方式」不是配置。
思考档位是一张「档位 → 实际发送值」的表,和官方模型编辑器同形。null 值有确切含义:该档不发任何思考参数(官方叫 off,这里叫「默认」)。这不是「关闭思考」——对 MiniMax 来说不发参数就是它文档里的 max。要真正关掉思考得用字面量 none,而只有 OpenAI 系模型接受它。
零档位也是合法指令:声明一个空表等于要求「这个模型不要显示思考控件」,插件照办,不回落文档表。但如果你输入的全是非法的值(空串、数字),那不是「我要零档」,插件会整条丢弃——否则一次打字错误就会静默关掉一个控件。
设置页接口¶
插件挂在 /api/opencode-live:
| 路径 | 方法 | 作用 |
|---|---|---|
/view |
GET | 当前状态、完整目录(含每行的协议/图片/容量/档位与它们的继承值)、上次刷新结果 |
/refresh |
POST | 重新拉列表,只拉列表,不探测任何协议 |
/update |
POST | 合并写入配置:modelProtocols、modelVision、modelSettings、visibleModels 与标量字段 |
/probe |
POST | 对某个模型发一个最小请求({"model":"..."}) |
/health |
GET | 存活检查 |
/update 的四张表都是合并语义,删一个键要显式传 null:
{ "modelProtocols": { "grok-4.7": "responses" }, "modelVision": { "minimax-m3": null } }
modelVision 只接受 true/false;null 表示「清除这个模型的覆盖,回落实测表」——注意它不等于 false。
modelSettings 有三层清空语义,因为界面能表达三种不同的意图:
{ "modelSettings": { "m": null } } // 忘掉这个模型的全部设置
{ "modelSettings": { "m": { "maxTokens": null } } } // 只清这一个字段,其余留着
{ "modelSettings": { "m": { "reasoningEfforts": {} } } } // 零档位,这是真实指令
适用场景与注意¶
插件以当前 DSH 进程权限运行,安装前应检查源码与许可证。适合需要实时获取 OpenCode Go 网关新增模型、需要为不同模型配置不同协议的用户。插件通过用户手动选择协议和图片能力,避免自动探测带来的延迟和错误。
总结¶
dsh-opencode-live 解决了 DSH 接入 OpenCode Go 时无法实时获取模型、手动添加困难、协议配置混乱的问题。通过独立路由、实时列表、按模型配置协议和图片能力,让开发者能够更灵活地管理网关模型,避免配置错误导致的 400 错误。