DeepSeek Harness · Provider 接入指南

把 OpenCode Go 订阅网关接进 DSH

从零讲清三层结构(凭据 / 线路 / 模型目录)、为什么必须拆成三个 provider、 会话头缺失为什么直接 400,以及额度、峰谷、免费模型与可视化用量接入的完整做法。

🔒 本页已脱敏:不含任何真实密钥 实测日期 2026-10-10 wire 协议 3 种 模型清单 38 条(实时拉取) 免费模型 2 个
🔒
脱敏声明

本页所有密钥、口令、会话 ID、服务器地址均已替换为占位符。文中出现的 oc_sk_xxxxxxxx…、sk-xxxxxxxx、dsh-ocg-xxxxxxxx 都是假值,直接复制粘贴不会带来任何风险,也不会生效。真实凭据请只放进 .credentials.yaml 或进程环境变量。

00

速览:一张表看懂

如果你只想尽快跑起来,看这张表 + 第 03 节的完整配置即可。

要素取什么值为什么
provider 名opencode-go(自己起,前缀会被余额插件匹配)三个 wire 协议各是一个 provider
网关基址https://opencode.ai/zen/go/v1走 Go 订阅;不是 Console 的 inference 端点
协议 apiopenai-completions / openai-responses / anthropic-messages模型按协议锁定,混用会 400
密钥apiKeyEnv: OPENCODE_GO_API_KEY写的是引用,不是密钥本身
必需请求头x-deepseek-harness-session-id: <稳定值>缺了直接 400 MissingSessionID
模型清单models: 列表它是替换内置目录,不是追加
套餐Go $10/月 或 Go Plus $40/月单价相同,只差月度额度
DSH 会话→ provider: opencode-go→ Bearer <key>+ session 头→ opencode.ai/zen/go→ 模型
01

OpenCode Go 是什么

一句话:它是 opencode 提供的一个订阅制推理网关。你按月付费, 换来一张跨厂商模型的配额表,而不是往余额里充钱、按 token 扣费。

Go · $10 / 月
入门档。每个模型一份月度额度,额度单位是「美元等价」。
Go Plus · $40 / 月
同样模型的 token 单价完全相同,只是各模型的月度额度更高。
额度窗口
5 小时 = 月度的 20%、本周 = 50%、本月 = 100%,三档同时生效。
⚠️
别把两个端点搞混(实测)

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"}}
02

三层结构:凭据 / 线路 / 模型目录

DSH 里接一个第三方网关,本质上只做三件事,且三层是解耦的。

层写在哪职责换它意味着
① 凭据 $DSH_HOME/.credentials.yaml 或进程环境变量 提供密钥本体,配置里只写「引用名」 换 key:只动一处,配置零改动
② 线路
provider
settings.yaml → llm-pi-ai.providers.<名> 声明协议、端点、请求头、以及这条线路能服务哪些模型 换网关:改 baseURL 一行
③ 模型目录 同上,providers.<名>.models 决定模型选择器里出现哪些条目、显示什么名字 显示名与顺序:只影响 UI,不影响请求
💡
关键设计:配置里没有密钥

apiKeyEnv 字段是凭据引用,每次请求时才去解析。所以 settings.yaml 可以安全地备份、分享、甚至提交到私有仓库。

03

完整配置示例

这是把三种协议都接上时的 settings.yaml 写法,可直接照抄(把占位符换掉)。

$DSH_HOME/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 会保留上一份可用配置并打日志,不会把服务带崩。

04

凭据怎么放

配置里永远只写引用名,密钥本体放下面两处之一。

方式 A:凭据文件(推荐)

$DSH_HOME/.credentials.yaml
OPENCODE_GO_API_KEY: oc_sk_xxxxxxxxxxxxxxxxxxxxxxxx
DEEPSEEK_API_KEY: sk-xxxxxxxxxxxxxxxxxxxxxxxx

方式 B:进程环境变量

shell
# 只对当前进程树生效;systemd 部署写进 unit 的 Environment=
export OPENCODE_GO_API_KEY=oc_sk_xxxxxxxxxxxxxxxxxxxxxxxx
🛡️
两个容易踩的坑

1. 引用解析不到会直接报错。配置了 apiKeyEnv 但环境里没有这个变量, 请求会以 MISSING_CREDENTIAL 失败 —— 这是刻意的,避免拿别的 key 去鉴权。

2. 一条线路一个密钥。同一个 provider 下的所有模型共用一份凭据,没法按模型分 key。

🚫
不要把密钥写进 settings.yaml

那个文件会被 DSH 的「模型设置」页面回写,也可能被你同步到别处。写引用名,不写密钥。

05

会话头:少了就 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 里用原生头更省事,也不用再单独维护一个值。

06

为什么必须拆成三个 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
✅
好消息:只有 Responses 那一组是硬锁

实测中,官方表里标 /messages 的 Qwen3.8 Max、MiniMax M3、Qwen3.7 Plus 走 chat/completions 也能正常返回 200。也就是说协议锁定是「至少支持」,不是「只能这样」; 真正非拆不可的是 Responses 那一组。想省事,可以只拆两条线路。

07

baseURL 的两种写法

两个值长得很像,但少一段多一段都会 404,这是最容易配错的地方。

协议baseURL 写什么SDK 实际请求的完整地址
openai-completionshttps://opencode.ai/zen/go/v1…/zen/go/v1/chat/completions
openai-responseshttps://opencode.ai/zen/go/v1…/zen/go/v1/responses
anthropic-messageshttps://opencode.ai/zen/go ← 不带 /v1…/zen/go/v1/messages
🧭
记忆口诀

Anthropic 系的客户端会自己补 /v1,所以 baseURL 停在 /zen/go; OpenAI 系不会补,所以要写全 /zen/go/v1。三条线路最终都落到同一个 /zen/go/v1/… 前缀下。

08

模型目录语义:models 是替换不是追加

这一条不知道就会踩坑:一旦你写了一个 models 列表, 这条线路的内置目录整体被替换,没列出来的模型全部「不存在」。

字段作用不写会怎样
id发给网关的真实模型标识必填
name仅模型选择器里显示的名字回落显示 id
contextWindow上下文窗口回落线路默认值
maxTokens输出上限回落线路默认值
reasoningEfforts推理档位;false 表示关掉档位选择不声明则该模型不暴露推理档位
input输入模态,如 [text, image]默认 [text]
compat方言微调(如 thinkingFormat)由网关 URL 猜测,私有网关常猜错
🧩
为什么 Responses 那两个模型要写 reasoningEfforts: false

DSH 在「模型支持推理、但本次没指定档位」时会补一个 reasoning_effort=none; 而 Grok / GPT Luna 这几个模型拒绝 none 这个取值(400)。 显式关掉档位选择,DSH 就完全不发这个字段了,请求恢复正常。

📐
只改一两个模型的名字,不用重写整个目录

如果这条线路本来就带内置目录,用 modelOverrides 就能「改一个、留其余」, 不必把几十个模型全列一遍。

settings.yaml 片段
modelOverrides:
  glm-5.3:
    name: ocg-glm-5.3        # 只改显示名,其余字段沿用内置目录
09

拉取实时模型清单

网关模型更新很快,官方文档偶尔滞后。要拿到当下真实可用的清单,直接问接口。

shell · 列出当前所有可用模型
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,没有价格

这个端点只回答「有哪些模型」(字段仅有 id / object / created / owned_by), 不含单价、额度、是否免费。价格与额度要另看官方定价表。

🧠
DSH 的「自动发现模型」功能

在模型设置页新增/编辑一条非内置线路时,DSH 会替你调 GET /models 把候选模型列出来让你勾选, 省掉手抄 id。它只支持 openai-completions 与 openai-responses; 其它协议会退回手工填写。发现结果只是候选,存不存、由你的 settings.yaml 说了算。

10

额度、峰谷与免费模型

三档额度窗口

窗口上限接口字段
5 小时月度额度的 20%usage.rolling
本周月度额度的 50%usage.weekly
本月月度额度的 100%usage.monthly
shell · 查实时用量
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:0009:00–12:00、14:00–18:00
谷时(半价)其余全部时段,含周末全天其余全部时段

免费模型(限时)

Go 里价格真的为 0、且额度不限的只有两个,官方标注「限时免费」:

longcat-2.5-preview-free
单价 Free、额度 Unlimited,限时免费。
step-5-preview-free
单价 Free、额度 Unlimited,限时免费。
额度跑满时的兜底
官方文档明确:达到用量上限后,可以继续使用免费模型。
💸
几个容易误判为「免费」的档

名字里带 Contributor 的(如 muse-spark-1.2/1.3-contributor)是 参与训练的折扣档,不是免费;preview 也不等于免费。 判断依据只看定价表的单价列是不是 Free。

11

把用量接到可视化面板

DSH 本身只显示 token;要把「Go 套餐用了百分之几 / 等价官方多少钱」显示出来, 需要额外挂一个余额插件,并告诉它哪些 provider 算 Go 线路。

$DSH_HOME/profiles/<profile>/cordis.patch.yml
- 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把账户标成订阅制:不计余额,只算三档比例
🧮
「等价官方 DeepSeek」是什么

同样这批 token,如果走 DeepSeek 官方直连要花多少钱 —— 用来判断「订阅到底值不值」。 只对 DeepSeek 系列有意义;Kimi / GLM / Grok 这些官方没有对应型号,插件会明确写「无对应模型」, 不会编一个数字出来。

12

命名规范:让模型名自己说明线路

接了三个网关之后,模型选择器里会出现越来越多同族模型。 给显示名加统一前缀,能省掉大量「这个到底走哪条线」的猜疑。

前缀含义示例
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。 所以可以放心大胆地按自己的习惯重命名,不用担心「改坏了」。

13

验证清单

配完按顺序走一遍,每一层都能单独验证。

#验证什么怎么做期望结果
1凭据在不在 看 .credentials.yaml 是否有该引用名 键名与 apiKeyEnv 完全一致
2网关通不通 curl …/zen/go/v1/models 200 + 一串模型 id
3DSH 认没认这条线路 模型设置页看 provider 分组,或调用 POST /api/llm.models 分组出现,failures 为空数组
4显示名对不对 同上,看每个模型的 name 与 settings.yaml 写的一致
5能不能真跑 把默认模型切到该线路,发一句话 正常出字,无 4xx
6用量面板对不对 看统计条上的 🚀 占比 三档百分比 + 重置时间出现
shell · 第 3/4 步的命令行等价写法
# 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
14

排错速查

症状根因处置
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, 都会让这条线路在加载时被整体拒绝(而不是忽略坏的那一条)。 改配置时建议先备份,再小步验证。

15

附录与参考

最小可用配置(只要一条线路)

settings.yaml · 够用就好
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

页面不含任何真实密钥、口令或会话标识;文中占位符复制后无法使用。