本地轻量桥接代理:让任何 coding agent 顺畅使用 OpenCode Go(Zen API)。
English | 简体中文
OpenCode Go(文档)从 2026-09-06 起强制要求每个请求携带 x-opencode-session 请求头(用于会话亲和与 prompt 缓存路由),否则直接拒绝:
Reason: Failed to get response from the AI model; retried 5 times (total retry wait time: 15.51 seconds)
Last error: 502 Request Failed: 400 {
"type": "error",
"error": {
"type": "MissingSessionID",
"message": "Request is missing x-opencode-session and cannot be routed efficiently."
}
}
而很多 coding agent 的自定义模型通道(BYOK custom endpoint)不发送这个头——VS Code Copilot Chat、Trae 等都中招(完整清单见 兼容性)。本代理在本机充当桥接层:补齐/保留/修复 x-opencode-session,其余一切透明转发。
你的 coding agent(VS Code / Trae / …)
│ HTTP(不发会话头)
▼
opencode-go-session-bridge(127.0.0.1:14731)
│ 注入/保留 x-opencode-session · 自述 UA · 透传 Authorization
▼
https://opencode.ai/zen/go/v1/chat/completions
- 零第三方依赖:Node ≥ 18 标准库,单文件
proxy.mjs,clone 即用; - 会话策略 A–D(见 工作原理):客户端自带会话头 → 原样透传;
x-interaction-id等对话级稳定头 → 确定性 HMAC 派生(重启映射不变);体内非内容信号 → 派生;全缺 → 按模型常量退路(局限如实声明); - 全程流式:SSE 逐块透传、不缓冲、不重排;同时支持
stream: false; - 原样转发:
tool_calls、图片字段、错误状态码原样往返;代理自身不重试; - 安全默认:仅监听
127.0.0.1、上游白名单(仅https://opencode.ai/zen/go/v1/*)、日志脱敏(不记 API Key / Authorization / 请求体 / 对话内容); - 可观测:脱敏访问日志 +
--capture观测模式(只记结构与哈希); - Trae 重名劫持应对:模型 ID 填
proxy-<真实模型名>别名即可绕开 Trae 云端劫持,代理自动剥前缀还原后发上游; - 一键常驻(macOS):launchd 托管(登录自启 + 崩溃自动拉起)。
# 1) 获取
git clone https://github.com/hbpencilw/opencode-go-session-bridge.git
cd opencode-go-session-bridge
# 2) 启动(前台 Ctrl+C 停止;或用脚本后台化)
node proxy.mjs # 默认监听 127.0.0.1:14731
node proxy.mjs --capture # 附带脱敏观测日志
# 3) 验证
./test.sh health # 本地健康检查
./test.sh upstream # 代理→上游连通性(GET /v1/models)
./test.sh text glm-5.3-flash # 无 Key 冒烟:假 Key 预期上游 401(证明会话头已过校验)
# 4) 客户端接入:把自定义模型的 URL 指向本地代理
# http://127.0.0.1:14731/v1/chat/completionsmacOS 想开机常驻:./scripts/install-launchagent.sh(卸载 --uninstall)。
通用规则:客户端自定义模型的请求 URL 改为 http://127.0.0.1:14731/v1/chat/completions,API Key 照旧由各客户端自己的密钥管理提供(代理只透传 Authorization,从不落盘)。
| 客户端 | 配置位置 | 示例 |
|---|---|---|
| VS Code Copilot Chat | chatLanguageModels.json(BYOK customendpoint) |
examples/vscode-chatLanguageModels.example.json |
| Trae | 自定义模型弹窗(OpenAI Chat Completions;URL 填 http://127.0.0.1:14731/v1,Full URL 开关关闭) |
examples/trae-custom-model.md |
| 其他(Claude Code / Codex / …) | 各自的自定义模型/Base URL 设置 | 指向同一地址即可 |
上游要求:x-opencode-session 为任意非空字符串,但同对话同值、不同对话不同值、不含敏感信息。本代理按优先级派生:
| 级别 | 来源 | 行为 |
|---|---|---|
| A | 客户端已带 x-opencode-session |
原样透传(不改写) |
| B | 请求带对话级稳定头(优先 x-interaction-id) |
HMAC-SHA256(信号|model) 确定性派生 vsc-<32hex> |
| C | 请求体内非内容字段(user / metadata.*) |
同上派生 |
| D | 全部缺失(退路) | HMAC("<unknown-window>"|model) |
要点:派生盐持久化(session-secret.key,0600,仅本地 HMAC 盐、非上游凭据),重启后映射不变,老对话的缓存亲和不受影响;不通过读取提示词正文猜测对话归属;不把任何秘密用作会话输入。
已知局限(如实声明):不发送对话级头的客户端(如 Trae)走 D 级——同模型的不同对话共享会话 ID。细节与实测证据见 docs/architecture.md。
| 客户端 | 版本 | 验证来源 | 说明 |
|---|---|---|---|
| VS Code GitHub Copilot Chat | 1.140 | 本项目实测(2026-10-10,44 条请求) | 三模型 200 / SSE,MissingSessionID 消失 |
| Trae | 3.6.1 | 本项目实测(2026-10-10,15 条请求) | UA hertz;会话走 D 级退路 |
| Hermes / Claude Code / Codex / ZCode / Pi / jcode / Kilo Code CLI | 官方文档 Validated | 原生 session header 被 Go 识别(各客户端最低版本见 docs/compatibility.md) | 其中 Codex 部分版本/代理场景仍会丢头,转发时需保留 |
| 客户端 | 现状 | 跟踪 |
|---|---|---|
| DeepSeek Harness | Session 头仅部分模型路径到达;已识别原生 header,待在所有适配器统一发送 | Discussion #5495 |
| GitHub Copilot Chat | 自动 session-header 支持请求中 | VS Code issue #334186 |
| Kimi Code | 自动 session-header 支持请求中 | issue #3506 |
| MiMo Code | proposed fix 待合并 | issue #2317 / PR #2327 |
完整表格、客户端侧坑与上游账户级限制(DeepSeek 区域门等)见 docs/compatibility.md。
代理无必填配置;环境变量(.env.example):
| 变量 | 默认 | 说明 |
|---|---|---|
OPENCODE_GO_PROXY_PORT / --port |
14731 |
监听端口(改后客户端 URL 同步改) |
OPENCODE_GO_PROXY_CAPTURE / --capture |
关 | 脱敏观测日志 capture.jsonl |
OPENCODE_GO_PROXY_NO_INJECT / --no-inject |
关 | 控制组:不注入会话头(A/B 验证用) |
OPENCODE_GO_PROXY_HOME |
脚本同目录 | 数据目录(盐/capture/日志);launchd 场景必须设在 TCC 保护范围外 |
| 报错 | 原因 | 处理 |
|---|---|---|
ERR_CONNECTION_REFUSED |
代理没在运行 | ./start.sh |
400 MissingSessionID |
请求绕过了代理(URL/端口配错、Trae 重名劫持)或注入失效 | 核对 URL;./test.sh text <model> 复测 |
400 ... requires Global regions |
DeepSeek 系的区域门(账户设置) | opencode.ai 控制台 → Privacy → Global |
401/403 Invalid API key |
Key 无效 | 检查客户端密钥配置 |
更多(日志位置、launchd/TCC 坑、端口修改、配置回滚)见 docs/troubleshooting.md。
- 更多客户端逐一实测并在 compatibility.md 记录(欢迎提交验证数据)
- 单元测试 + CI 扩展(目前为冒烟测试)
- 可选注入
x-opencode-request(会话内递增请求号,官方客户端行为观察) - 日志轮转(大小上限 + 保留份数)
欢迎 Issue 与 PR!开发与提交规范见 CONTRIBUTING.md,社区准则见 CODE_OF_CONDUCT.md。