← 返回文章列表

只填三格的客户端,怎么用上 opencode 订阅:一个 40 行的本机转发器

面板只能填地址、Key 和模型名,直连订阅网关却报 400 MissingSessionID。用 Windows 自带 PowerShell 在本机回环起一个转发器,补上缺的那个请求头,其余原样透传,含流式。

opencode 的 Zen / Go 订阅走自家网关,请求必须带一个请求头 x-opencode-session(值随便填),不带就直接拒绝:

{"error":{"type":"server_error","message":"MissingSessionID"}}

HTTP 400。问题在于,很多客户端面板只让你填三样东西:接口地址、API Key、模型名,没地方加自定义请求头。于是直连必然 400,而报错信息里根本看不出「少了一个头」,只说 MissingSessionID。

这篇记录一个很小的解法:在本机回环上起一个转发服务,自动补上这个头,其余原样透传。

扁平卡通插画:侧身机位,使用者面对右侧显示器,桌角小盒子连着云朵
面板只有三格,中间就差一个「补头」的环节

思路

客户端 ──普通 HTTP──> 127.0.0.1:8788 ──补 x-opencode-session──> https://opencode.ai/zen/go/v1/...

转发器只做三件事:收下请求、补一个头、原样转发回去(含流式 SSE)。不碰请求体、不缓存、不解析内容,所以它不需要也不应该知道你的 Key。

为什么用 PowerShell

Windows 自带 HttpListener(底层是 http.sys)和 Invoke-WebRequest,一个 .ps1 就够,不需要 Node、Python、.NET SDK,也不需要装服务、改注册表。Win7 到 Win11 都能跑(Win7 需要 .NET 4.6.2+ 与 KB3140245 补丁才有 TLS 1.2)。

配置全在一个 config.txt 里:

BIND_HOST=127.0.0.1     # 只允许本机使用
BIND_PORT=8788          # 端口被占用时改这里
UPSTREAM=https://opencode.ai/zen/go   # Go 订阅;Zen 订阅改成 https://opencode.ai/zen
SESSION_HEADER=x-opencode-session
SESSION_VALUE=ses_local_forwarder    # 值随便
TIMEOUT_SECONDS=600

三步跑起来

  1. 双击启动脚本,出现黑窗口并打印 started 和 listen : http://127.0.0.1:8788/ 即成功。窗口最小化放着,关掉就等于停止。
  2. 双击自检脚本,看到 RESULT : OK HTTP 200 说明服务活着。
  3. 客户端里填:地址 http://127.0.0.1:8788/v1、Key 填你自己的 oc_sk_...、模型 ID 填网关认的名字(如 deepseek-v4.1-flash)。
扁平卡通插画:桌面上一个白色小盒子,指示灯亮着,数据包飘向右上角的云朵
本机那个不占地方的小盒子,负责把请求送出最后一段路

地址那一格最容易错

不同客户端对 Base URL 的处理不一样,三种写法都得知道:

客户端行为 该填什么
自动在后面拼 /chat/completions(多数) http://127.0.0.1:8788/v1
认为地址就是完整接口 http://127.0.0.1:8788/v1/chat/completions
自动拼 /v1/chat/completions http://127.0.0.1:8788

判断依据只有两条:回 404 说明路径拼重了或拼漏了,换一种;回 400 MissingSessionID 说明请求根本没走转发器,地址里还留着 opencode.ai,这是最典型的「以为在用转发器其实在直连」。

报错对照

报错 真正原因 处理
400 MissingSessionID 地址填的是官方域名 改成本机地址
连接被拒绝 转发器没启动,或端口与配置不一致 启动它、跑自检
401 Invalid credential Key 错/过期,或粘贴时带了空格引号 重新复制
402 Insufficient account funds 网关走错:Go 的 Key 打到了 Zen(少了 /go),或额度耗尽 改回 zen/go,再看额度
429 FreeUsageLimitError 免费模型当日额度用完 换付费模型或隔天
一直转圈到超时 客户端自身超时偏短,或上游慢 把超时提到 900 秒

日志按天切分,每行一次请求:

[16:14:21]     19 ms  GET    /healthz  -> 200
[16:20:02]   8841 ms  POST   /v1/chat/completions  -> 200

判断口诀很干净:日志里没有你的请求 = 请求没到转发器;有请求但 4xx = Key/模型/网关问题;有请求且 200 = 转发器这头全程无事。

安全边界

  • Key 只存在客户端里。转发器把 Authorization 原样往后传,自己不存不打印,日志里只有方法、路径、状态码、耗时——所以整个文件夹和日志都可以直接发给别人排错。
  • 默认监听 127.0.0.1,是回环,不是监听网卡,局域网里谁也连不进来,也不需要开防火墙端口。
  • 改成 0.0.0.0 才允许同网段设备借用这条通道;不要做公网端口映射,真要远程用就走 SSH 隧道或带鉴权的反向代理。

验证到什么程度

测试项 结果
/healthz 健康检查 200
补头后上游不再报 MissingSessionID 通过
300 KB 随机二进制请求体,SHA-256 对比 字节完全一致
2 MB 大请求体 正常吞吐
流式 SSE 逐块回吐(上游每 1s 一块) 首字节 1.0s / 总 3.0s
中文、emoji、大 body 编码 无乱码

唯一没法替你验证的是「用你的真 Key 拿到 200」——Key 只在你自己手里。

整套东西不到 100 KB,纯文本可审,删掉文件夹即彻底卸载,不写注册表、不装服务、不改环境变量。遇到只能填三格的面板,这类「本机补一个头」的做法比重写客户端划算得多。

▍ 本文由自建 Agent 调度内容流水线自动完成:写稿 → 模型 API 生图 → R2 图床 → 排版 → MCP 落站。 ▍ 配图由模型 API 生成、托管在对象存储上;内容仅供参考。