本页所有密钥、口令、会话 ID、服务器地址均已替换为占位符。文中出现的
oc_sk_xxxxxxxx…、sk-xxxxxxxx、dsh-ocg-xxxxxxxx
都是假值,直接复制粘贴不会带来任何风险,也不会生效。真实凭据请只放进
.credentials.yaml 或进程环境变量。
速览:一张表看懂
如果你只想尽快跑起来,看这张表 + 第 03 节的完整配置即可。
| 要素 | 取什么值 | 为什么 |
|---|---|---|
| provider 名 | opencode-go(自己起,前缀会被余额插件匹配) | 三个 wire 协议各是一个 provider |
| 网关基址 | https://opencode.ai/zen/go/v1 | 走 Go 订阅;不是 Console 的 inference 端点 |
协议 api | openai-completions / openai-responses / anthropic-messages | 模型按协议锁定,混用会 400 |
| 密钥 | apiKeyEnv: OPENCODE_GO_API_KEY | 写的是引用,不是密钥本身 |
| 必需请求头 | x-deepseek-harness-session-id: <稳定值> | 缺了直接 400 MissingSessionID |
| 模型清单 | models: 列表 | 它是替换内置目录,不是追加 |
| 套餐 | Go $10/月 或 Go Plus $40/月 | 单价相同,只差月度额度 |
OpenCode Go 是什么
一句话:它是 opencode 提供的一个订阅制推理网关。你按月付费, 换来一张跨厂商模型的配额表,而不是往余额里充钱、按 token 扣费。
Go 订阅走的是 https://opencode.ai/zen/go/v1。另有一个 Console 的
https://opencode.ai/inference/openai/v1/…,它属于服务账号 + 预充值余额,
拿订阅 key 去打会直接失败:
HTTP 402
{"error":{"type":"server_error",
"message":"Upstream request failed: Insufficient account funds"}}
三层结构:凭据 / 线路 / 模型目录
DSH 里接一个第三方网关,本质上只做三件事,且三层是解耦的。
| 层 | 写在哪 | 职责 | 换它意味着 |
|---|---|---|---|
| ① 凭据 | $DSH_HOME/.credentials.yaml 或进程环境变量 |
提供密钥本体,配置里只写「引用名」 | 换 key:只动一处,配置零改动 |
| ② 线路 provider |
settings.yaml → llm-pi-ai.providers.<名> |
声明协议、端点、请求头、以及这条线路能服务哪些模型 | 换网关:改 baseURL 一行 |
| ③ 模型目录 | 同上,providers.<名>.models |
决定模型选择器里出现哪些条目、显示什么名字 | 显示名与顺序:只影响 UI,不影响请求 |
apiKeyEnv 字段是凭据引用,每次请求时才去解析。所以
settings.yaml 可以安全地备份、分享、甚至提交到私有仓库。
完整配置示例
这是把三种协议都接上时的 settings.yaml 写法,可直接照抄(把占位符换掉)。
llm-pi-ai:
providers:
# ── 线路 1:绝大多数模型走 OpenAI Chat Completions ──────────
opencode-go:
displayName: OpenCode Go
apiKeyEnv: OPENCODE_GO_API_KEY # 引用,不是密钥本体
api: openai-completions # wire 协议
baseURL: https://opencode.ai/zen/go/v1
headers:
x-deepseek-harness-session-id: dsh-ocg-xxxxxxxx # 必需,见第 05 节
models:
- id: deepseek-v4.1-flash
name: ocg-ds-v4.1-f # 显示名,只影响 UI
- id: kimi-k3
name: ocg-kimi-k3
- id: deepseek-v4-flash-vision-exp
name: ocg-ds-v4-f-vision
input: [ text, image ] # 声明多模态输入
# ── 线路 2:被协议锁死的模型只能走 Responses ────────────────
opencode-go-responses:
displayName: OpenCode Go (Responses)
apiKeyEnv: OPENCODE_GO_API_KEY
api: openai-responses
baseURL: https://opencode.ai/zen/go/v1
headers:
x-deepseek-harness-session-id: dsh-ocg-xxxxxxxx
models:
# 这些模型会拒绝 reasoning_effort=none,必须显式关掉推理档位
- id: grok-4.7
name: ocg-grok-4.7
reasoningEfforts: false
- id: gpt-5.6-luna
name: ocg-gpt-5.6-luna
reasoningEfforts: false
# ── 线路 3:Anthropic Messages(注意 baseURL 少一段)────────
opencode-go-messages:
displayName: OpenCode Go (Anthropic)
apiKeyEnv: OPENCODE_GO_API_KEY
api: anthropic-messages
baseURL: https://opencode.ai/zen/go # 注意:不带 /v1
headers:
x-deepseek-harness-session-id: dsh-ocg-xxxxxxxx
models:
- id: claude-haiku-5-5
name: ocg-claude-haiku-5.5
- id: minimax-m2.7
name: ocg-minimax-m2.7
# 默认模型:provider 名 + 该 provider 里存在的 model id
agent-default-model:
provider: opencode-go
model: deepseek-v4.1-flash
reasoningEffort: high
settings.yaml 是热重载的(文件监听)。保存后刷新页面即可;
如果改动里有 schema 不合法的地方,DSH 会保留上一份可用配置并打日志,不会把服务带崩。
凭据怎么放
配置里永远只写引用名,密钥本体放下面两处之一。
方式 A:凭据文件(推荐)
OPENCODE_GO_API_KEY: oc_sk_xxxxxxxxxxxxxxxxxxxxxxxx
DEEPSEEK_API_KEY: sk-xxxxxxxxxxxxxxxxxxxxxxxx
方式 B:进程环境变量
# 只对当前进程树生效;systemd 部署写进 unit 的 Environment=
export OPENCODE_GO_API_KEY=oc_sk_xxxxxxxxxxxxxxxxxxxxxxxx
1. 引用解析不到会直接报错。配置了 apiKeyEnv 但环境里没有这个变量,
请求会以 MISSING_CREDENTIAL 失败 —— 这是刻意的,避免拿别的 key 去鉴权。
2. 一条线路一个密钥。同一个 provider 下的所有模型共用一份凭据,没法按模型分 key。
那个文件会被 DSH 的「模型设置」页面回写,也可能被你同步到别处。写引用名,不写密钥。
会话头:少了就 400
这是接 Go 网关时最容易卡住的一步。网关要求每个请求带一个稳定的会话标识, 用来做路由与缓存亲和;缺失会立刻被拒。
# 请求:POST /zen/go/v1/chat/completions(只有 Authorization)
HTTP 400
{"type":"error","error":{"type":"MissingSessionID",
"message":"Request is missing x-opencode-session and cannot be routed efficiently."}}
| 要点 | 说明 |
|---|---|
| 用哪个头名 | DSH 原生的 x-deepseek-harness-session-id 就能被网关接受 |
| 值怎么取 | 一串固定不变的随机串,比如 dsh-ocg-1a2b3c4d。不要每次请求都变 |
| 配在哪里 | provider 的 headers 下,三个 provider 建议写同一个值 |
| 冲突时谁赢 | DSH 自身的应用标识头优先级更高,会覆盖同名配置 |
报错信息里点名的 x-opencode-session
是网关自己的原生头名;照抄那个头名同样可行,但在 DSH 里用原生头更省事,也不用再单独维护一个值。
为什么必须拆成三个 provider
因为网关上的模型是按协议锁定的:同一个 key、同一个 host, 换个模型就得换 wire 协议,不换直接 400。
# 对 gpt-5.6-luna / grok-4.7 发 chat/completions
HTTP 400
{"type":"error","error":{"type":"ModelProtocolUnsupported",
"message":"Model does not support this protocol."}}
# 换成 /zen/go/v1/responses,同一模型 200 OK
官方端点 ↔ 协议对照(从官方文档抄录)
DSH 里的 api | 网关端点 | 包含的模型 |
|---|---|---|
openai-completions |
/zen/go/v1/chat/completions |
DeepSeek 全系、GLM 5.x、Kimi K2.6/K2.7-Code/K3、MiMo 全系、LongCat、Step、Hy3/Hy4、Space Bunny 等 |
openai-responses |
/zen/go/v1/responses |
Grok 4.6 / 4.7、GPT 6 Luna、GPT 5.6 Luna、Muse Spark 1.2 / 1.3 Contributor |
anthropic-messages |
/zen/go/v1/messages |
Claude Haiku 5.5、MiniMax M3 / M2.7、Qwen3.8 Max / Flash、Qwen3.7 Plus |
实测中,官方表里标 /messages 的 Qwen3.8 Max、MiniMax M3、Qwen3.7 Plus
走 chat/completions 也能正常返回 200。也就是说协议锁定是「至少支持」,不是「只能这样」;
真正非拆不可的是 Responses 那一组。想省事,可以只拆两条线路。
baseURL 的两种写法
两个值长得很像,但少一段多一段都会 404,这是最容易配错的地方。
| 协议 | baseURL 写什么 | SDK 实际请求的完整地址 |
|---|---|---|
openai-completions | https://opencode.ai/zen/go/v1 | …/zen/go/v1/chat/completions |
openai-responses | https://opencode.ai/zen/go/v1 | …/zen/go/v1/responses |
anthropic-messages | https://opencode.ai/zen/go ← 不带 /v1 | …/zen/go/v1/messages |
Anthropic 系的客户端会自己补 /v1,所以 baseURL 停在 /zen/go;
OpenAI 系不会补,所以要写全 /zen/go/v1。三条线路最终都落到同一个 /zen/go/v1/… 前缀下。
模型目录语义:models 是替换不是追加
这一条不知道就会踩坑:一旦你写了一个 models 列表,
这条线路的内置目录整体被替换,没列出来的模型全部「不存在」。
| 字段 | 作用 | 不写会怎样 |
|---|---|---|
id | 发给网关的真实模型标识 | 必填 |
name | 仅模型选择器里显示的名字 | 回落显示 id |
contextWindow | 上下文窗口 | 回落线路默认值 |
maxTokens | 输出上限 | 回落线路默认值 |
reasoningEfforts | 推理档位;false 表示关掉档位选择 | 不声明则该模型不暴露推理档位 |
input | 输入模态,如 [text, image] | 默认 [text] |
compat | 方言微调(如 thinkingFormat) | 由网关 URL 猜测,私有网关常猜错 |
reasoningEfforts: falseDSH 在「模型支持推理、但本次没指定档位」时会补一个 reasoning_effort=none;
而 Grok / GPT Luna 这几个模型拒绝 none 这个取值(400)。
显式关掉档位选择,DSH 就完全不发这个字段了,请求恢复正常。
如果这条线路本来就带内置目录,用 modelOverrides 就能「改一个、留其余」,
不必把几十个模型全列一遍。
modelOverrides:
glm-5.3:
name: ocg-glm-5.3 # 只改显示名,其余字段沿用内置目录
拉取实时模型清单
网关模型更新很快,官方文档偶尔滞后。要拿到当下真实可用的清单,直接问接口。
curl -s https://opencode.ai/zen/go/v1/models \
-H "Authorization: Bearer $OPENCODE_GO_API_KEY" \
-H "x-deepseek-harness-session-id: dsh-ocg-xxxxxxxx" \
| python3 -c 'import sys,json;[print(m["id"]) for m in json.load(sys.stdin)["data"]]'
这个端点只回答「有哪些模型」(字段仅有 id / object / created / owned_by),
不含单价、额度、是否免费。价格与额度要另看官方定价表。
在模型设置页新增/编辑一条非内置线路时,DSH 会替你调 GET /models 把候选模型列出来让你勾选,
省掉手抄 id。它只支持 openai-completions 与 openai-responses;
其它协议会退回手工填写。发现结果只是候选,存不存、由你的 settings.yaml 说了算。
额度、峰谷与免费模型
三档额度窗口
| 窗口 | 上限 | 接口字段 |
|---|---|---|
| 5 小时 | 月度额度的 20% | usage.rolling |
| 本周 | 月度额度的 50% | usage.weekly |
| 本月 | 月度额度的 100% | usage.monthly |
curl -s https://opencode.ai/zen/go/v1/usage \
-H "Authorization: Bearer $OPENCODE_GO_API_KEY" \
-H "x-deepseek-harness-session-id: dsh-ocg-xxxxxxxx"
峰谷计价(只对 DeepSeek 系列)
| 时段 | UTC | 北京时间 |
|---|---|---|
| 峰时 | 周一~周五 01:00–04:00、06:00–10:00 | 09:00–12:00、14:00–18:00 |
| 谷时(半价) | 其余全部时段,含周末全天 | 其余全部时段 |
免费模型(限时)
Go 里价格真的为 0、且额度不限的只有两个,官方标注「限时免费」:
名字里带 Contributor 的(如 muse-spark-1.2/1.3-contributor)是
参与训练的折扣档,不是免费;preview 也不等于免费。
判断依据只看定价表的单价列是不是 Free。
把用量接到可视化面板
DSH 本身只显示 token;要把「Go 套餐用了百分之几 / 等价官方多少钱」显示出来, 需要额外挂一个余额插件,并告诉它哪些 provider 算 Go 线路。
- id: dsh-balance
config:
goEnabled: true # 开启 Go 口径;没配密钥时静默跳过
goPlan: go # go ($10/月) | go-plus ($40/月)
# 关键:告诉插件哪些 provider 属于 Go 订阅线路(前缀匹配)
goProviderMatch: opencode-go,opencode-go-responses,opencode-go-messages
goBaseUrl: https://opencode.ai/zen/go/v1
goApiKeyRef: OPENCODE_GO_API_KEY
showGoBadge: true # 统计条显示 🚀 5h·周·月 占比
showOfficialEquivalent: true # 显示「等价官方 DeepSeek ¥x.xx」
accounts:
- id: opencode-go
label: OpenCode Go
kind: opencodogo # 订阅制账户:没有余额,只有用量比例
apiKeyRef: OPENCODE_GO_API_KEY # 复用凭据,不写密钥
baseUrl: https://opencode.ai/zen/go/v1
plan: go
| 配置项 | 作用 |
|---|---|
goProviderMatch | 判定「这次请求走的是 Go」的 provider 前缀。三个协议三个 provider,所以要全列 |
goPlan | 接口推不出你是哪个套餐,只能手动选 |
goOverrides | 微调个别模型的单价 / 月度额度,官方调价时先顶上(未填字段沿用官方值) |
accounts[].kind: opencodogo | 把账户标成订阅制:不计余额,只算三档比例 |
同样这批 token,如果走 DeepSeek 官方直连要花多少钱 —— 用来判断「订阅到底值不值」。 只对 DeepSeek 系列有意义;Kimi / GLM / Grok 这些官方没有对应型号,插件会明确写「无对应模型」, 不会编一个数字出来。
命名规范:让模型名自己说明线路
接了三个网关之后,模型选择器里会出现越来越多同族模型。 给显示名加统一前缀,能省掉大量「这个到底走哪条线」的猜疑。
| 前缀 | 含义 | 示例 |
|---|---|---|
ds- | 官方直连 | ds-v4.1-f |
ocg- | OpenCode Go 订阅网关 | ocg-ds-v4.1-f |
hfsy- | 第三方中转网关 | hfsy-gpt-5.4 |
🆓 | Go 里限时免费的模型 | 🆓 ocg-longcat-2.5-prev |
# 模型显示名约定(只看 name,id 一律不动):
# ds-* → DeepSeek 官方直连
# ocg-* → OpenCode Go 订阅网关
# hfsy-* → 第三方中转
# 缩写:f = flash, pro = pro, prev = preview, c = code, vision = 多模态
# 🆓 前缀 = Go 里限时免费的模型
name 是纯显示层改 name 不影响任何请求:请求里发的是 id。
所以可以放心大胆地按自己的习惯重命名,不用担心「改坏了」。
验证清单
配完按顺序走一遍,每一层都能单独验证。
| # | 验证什么 | 怎么做 | 期望结果 |
|---|---|---|---|
| 1 | 凭据在不在 | 看 .credentials.yaml 是否有该引用名 |
键名与 apiKeyEnv 完全一致 |
| 2 | 网关通不通 | curl …/zen/go/v1/models |
200 + 一串模型 id |
| 3 | DSH 认没认这条线路 | 模型设置页看 provider 分组,或调用 POST /api/llm.models |
分组出现,failures 为空数组 |
| 4 | 显示名对不对 | 同上,看每个模型的 name |
与 settings.yaml 写的一致 |
| 5 | 能不能真跑 | 把默认模型切到该线路,发一句话 | 正常出字,无 4xx |
| 6 | 用量面板对不对 | 看统计条上的 🚀 占比 |
三档百分比 + 重置时间出现 |
# DSH Web 服务的 unary 接口:POST /api/<method>
curl -s -X POST http://127.0.0.1:<port>/api/llm.models \
-H 'Content-Type: application/json' \
-d '{"type":"client-request","rpcId":"probe","method":"llm.models","payload":{}}' \
| python3 -m json.tool
排错速查
| 症状 | 根因 | 处置 |
|---|---|---|
400 MissingSessionID |
请求没带会话头 | 在 provider 的 headers 里补 x-deepseek-harness-session-id |
400 ModelProtocolUnsupported |
模型协议不对 | 查第 06 节的对照表,把它挪到对应 api 的 provider 下 |
402 Insufficient account funds |
用订阅 key 打了 Console 的预充值端点 | 确认 baseURL 是 …/zen/go/v1 |
MISSING_CREDENTIAL |
引用的环境变量/凭据不存在 | 核对 apiKeyEnv 的拼写与凭据文件里的键名 |
UNKNOWN_MODEL |
模型没写进这条线路的 models |
补进列表(记住是替换语义,别把其它模型删了) |
请求 400,提到 reasoning_effort |
模型不接受 none 档 |
给该模型加 reasoningEfforts: false |
| 404 / 路径不对 | baseURL 多写或少写了 /v1 |
OpenAI 系写全 /zen/go/v1;Anthropic 写到 /zen/go |
| 改了配置但页面没变 | 前端缓存 | 刷新页面;文件是热重载的,通常不需要重启服务 |
| 整个 provider 分组消失 | 配置 schema 不合法,DSH 保留了上一份可用配置 | 看服务日志里的 reload 警告,修正 YAML 后会自动恢复 |
缺失 api / baseURL,或 models 里有重复 id,
都会让这条线路在加载时被整体拒绝(而不是忽略坏的那一条)。
改配置时建议先备份,再小步验证。
附录与参考
最小可用配置(只要一条线路)
llm-pi-ai:
providers:
opencode-go:
displayName: OpenCode Go
apiKeyEnv: OPENCODE_GO_API_KEY
api: openai-completions
baseURL: https://opencode.ai/zen/go/v1
headers:
x-deepseek-harness-session-id: dsh-ocg-xxxxxxxx
models:
- id: deepseek-v4.1-flash
name: ocg-ds-v4.1-f
- id: longcat-2.5-preview-free
name: 🆓 ocg-longcat-2.5-prev # 限时免费
agent-default-model:
provider: opencode-go
model: deepseek-v4.1-flash
reasoningEffort: high
想加 Grok / GPT Luna 时,另起一个
api: openai-responses 的 provider,别塞进这条线路。
参考链接
- OpenCode Go 官方文档(模型清单、端点协议、定价与额度):opencode.ai/docs/go
- OpenCode Go 产品页:opencode.ai/go
- DSH
llm-pi-ai适配器文档:$DSH_HOME/profiles/<profile>/node_modules/@deepseek-ai/dsh-llm-pi-ai/README.md - DSH
dsh-balance插件文档:见插件仓库 README 的「OpenCode Go 订阅模式」章
所有断言都来自 2026-10-10 的实测或官方文档抄录:MissingSessionID、
ModelProtocolUnsupported、402 Insufficient account funds
三条报错均为当次真实抓取。定价与模型清单可能随时变动,以官方页面为准。
OpenCode Go × DeepSeek Harness 配置教程 · 已脱敏版本 · 生成于 2026-10-10
页面不含任何真实密钥、口令或会话标识;文中占位符复制后无法使用。