Yee-h/dsh-zen-proxy
A DeepSeek Harness (dsh) plugin: an in-process, OpenAI-compatible proxy that injects the official OpenCode Zen client headers on upstream requests, enabling Zen free models in dsh without the 429 FreeUsageLimitError.
catalog 简介 / catalog descriptioncatalog description:dsh plugin: in-process proxy that injects official OpenCode Zen client headers, enabling Zen free models in dsh without the 429 FreeUsageLimitError
项目介绍Project Overview
dsh-zen-proxy 是 DeepSeek Harness 进程内代理插件,将官方 OpenCode Zen 客户端的 User-Agent 与 x-opencode-* 头注入上游请求,让 dsh 在配置 opencode 提供商时能获得官方免费配额而不再被 429 拒绝。适用于在 dsh 中调用 Zen 免费模型(如 deepseek-v4-flash-free)。需注意免费额度仍受 IP 与指纹限制,超载时可能仍出现 429,且只代理聊天补全与模型列表接口。
dsh-zen-proxy is an in-process DeepSeek Harness plugin that injects the official OpenCode Zen User-Agent and x-opencode-* headers on upstream requests, so dsh traffic is recognized as the official client and avoids the FreeUsageLimitError 429. Use it when routing dsh through the opencode provider to access Zen free models like deepseek-v4-flash-free. Note: the free per-IP, per-fingerprint quota still applies, occasional 429s can occur under server load, and only /v1/chat/completions and /v1/models are proxied.
请帮我了解并安装插件:【dsh-zen-proxy】【https://github.com/Yee-h/dsh-zen-proxy】
把上面这条消息直接发给当前会话里的 DSH,让它帮你了解并安装。安装命令不一定准确,发给 DSH 更稳。Send this message to DSH in your current session. CLI install commands may not be accurate across systems — DSH will figure it out for you.
或使用命令行安装(适合开发者)Or use CLI install (for developers)
命令行安装CLI Install
dsh plugin --profile web add "https://github.com/Yee-h/dsh-zen-proxy.git"
把 Yee-h/dsh-zen-proxy 加入你的 DSH 配置(web profile)即可启用。
READMEREADME
dsh-zen-proxy
A DeepSeek Harness (dsh) plugin: an in-process, OpenAI-compatible proxy that injects the official OpenCode Zen client headers on upstream requests, enabling Zen free models in dsh without the 429 FreeUsageLimitError.
Why
OpenCode Zen's free-tier gateway rate-limits third-party clients by fingerprinting HTTP identity headers. Requests that look like the official opencode CLI get the normal free quota; anonymous or third-party clients are pinned to a very low fallback bucket and immediately rejected with:
{"type":"FreeUsageLimitError","message":"Rate limit exceeded. Please try again later."}
dsh's LLM adapters (e.g. dsh-llm-pi-ai) are designed to always send their own attribution User-Agent (deepseek-harness/<version> ...) and filter any configured user-agent out — so no dsh configuration can make the gateway see the official client. This plugin closes that gap with a tiny local proxy that lives inside the dsh process (started/stopped with the profile) and rewrites the identity headers before forwarding to https://opencode.ai/zen/v1.
Verified behavior
Smoke-tested against https://opencode.ai/zen/v1/chat/completions:
| Headers sent | Result |
|---|---|
| no official headers | 429 FreeUsageLimitError |
x-opencode-* only |
429 ❌ |
x-opencode-* + official User-Agent |
200 ✅ |
x-opencode-* + dsh's own UA |
429 ❌ |
The gateway validates the
User-Agentcontent, not just its presence. Thex-opencode-*headers alone are not enough.
Install
dsh plugin --profile web add "https://github.com/Yee-h/dsh-zen-proxy.git"
Or from a local checkout:
dsh plugin --profile web add "file:C:/path/to/dsh-zen-proxy"
Configure
1. Register the plugin (profile patch)
Add to $DSH_HOME/profiles/<profile>/cordis.patch.yml:
- insert:
- id: zen-proxy
name: 'dsh-zen-proxy'
config:
host: 127.0.0.1
port: 4097
upstreamHost: opencode.ai
upstreamBasePath: /zen/v1
2. Point the opencode provider at the proxy
In $DSH_HOME/settings.yaml:
llm-pi-ai:
providers:
opencode:
apiKeyEnv: OPENCODE_API_KEY
baseURL: http://127.0.0.1:4097/v1
Keep your sk-zen-* key in $DSH_HOME/.credentials.yaml (or the environment variable named by apiKeyEnv).
Restart dsh. The proxy listens on http://127.0.0.1:4097/v1 for as long as the profile runs and closes automatically on shutdown — no external process, no startup scripts.
How it works
dsh (dsh-llm-pi-ai)
│ POST http://127.0.0.1:4097/v1/chat/completions
▼
dsh-zen-proxy (in-process)
│ rewrites identity headers, forwards to https://opencode.ai/zen/v1
▼
OpenCode Zen gateway → official-client quota → 200
Headers injected on every upstream request:
| Header | Value |
|---|---|
User-Agent |
opencode/1.15.5 ai-sdk/provider-utils/4.0.23 runtime/bun/1.3.14 |
x-opencode-client |
cli |
x-opencode-project |
global |
x-opencode-session |
ses_ + random (per request) |
x-opencode-request |
msg_ + random (per request) |
The Authorization header and the request body (model, messages, stream: true, etc.) pass through unchanged; SSE streaming responses are relayed as-is.
Configuration reference
| Field | Default | Description |
|---|---|---|
host |
127.0.0.1 |
Bind address |
port |
4097 |
Listen port |
upstreamHost |
opencode.ai |
Zen upstream host |
upstreamBasePath |
/zen/v1 |
Zen upstream base path |
userAgent |
opencode/1.15.5 ai-sdk/provider-utils/4.0.23 runtime/bun/1.3.14 |
Official CLI user-agent |
clientHeader |
cli |
x-opencode-client value |
projectHeader |
global |
x-opencode-project value |
Smoke test
$body = '{"model":"deepseek-v4-flash-free","messages":[{"role":"user","content":"hi"}],"max_tokens":16}'
Invoke-RestMethod -Uri "http://127.0.0.1:4097/v1/chat/completions" -Method Post `
-Headers @{ "Authorization" = "Bearer sk-zen-你的密钥" } `
-ContentType "application/json" -Body $body
Expect HTTP 200 with a real completion.
Notes & limitations
- Free-tier quota still applies: the free allowance is shared per IP + client fingerprint (community reports ~200 requests/day) and is managed dynamically by OpenCode. Headers only restore the official-client tier; they cannot create quota.
- Occasional 429s can still happen when the server is overloaded even with correct headers — retry or switch to another free model.
- Recharging does NOT unlock free models (known issue): it only unlocks paid models.
- Only the tool-calling HTTP surface (
/v1/chat/completionsandGET /v1/models) is proxied; resources and prompts are out of scope. - This plugin deliberately keeps dsh's own attribution mechanism intact: dsh still sends its real identity to the local proxy; the identity rewrite happens at the network boundary.
License
MIT
ruvnet/ruflo
amruthpillai/reactive-resume
volcengine/OpenViking
Molunerfinn/PicGo
titanwings/colleague-skill
nocobase/nocobase
Tencent/WeKnora