Skip to content

fix: send opencode User-Agent on upstream requests to avoid Zen free-tier 429 - #138

Open
cheerc wants to merge 1 commit into
routatic:mainfrom
cheerc:fix/opencode-user-agent
Open

fix: send opencode User-Agent on upstream requests to avoid Zen free-tier 429#138
cheerc wants to merge 1 commit into
routatic:mainfrom
cheerc:fix/opencode-user-agent

Conversation

@cheerc

@cheerc cheerc commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

What

Upstream HTTP requests from the opencode-zen and opencode-go providers now carry a User-Agent: opencode/routatic-proxy header. Users can route OpenCode Zen free models (e.g. deepseek-v4-flash-free) through the proxy without hitting 429 FreeUsageLimitError502 all models failed.

Why

Closes #137. opencode.ai's Zen free tier rate-limits by client identity: requests whose User-Agent starts with opencode/ are exempt; anything else (Go's default Go-http-client/1.1, curl) gets HTTP 429 {"type":"FreeUsageLimitError","message":"Rate limit exceeded. Please try again later."}. The proxy never set a User-Agent on upstream requests, so all Zen free-model traffic was throttled even though the same account key works fine from the native opencode CLI. CONFIGURATION.md/MODELS.md advertise Zen free models as supported fallbacks, so this is a documented-behavior violation, not a usage issue.

How

  • Added one shared const upstreamUserAgent = "opencode/routatic-proxy" in internal/provider/opencode_zen.go (the opencode/ prefix is what the free-tier check keys on).
  • Set User-Agent alongside the existing headers at all upstream request construction sites: Zen doRequest (chat completions, stream + non-stream), doJSONRequest (Responses/Gemini), executeAnthropic, streamAnthropic; Go doRequest, executeAnthropic, streamAnthropic.
  • Tests drive the real providers through httptest upstream servers asserting the opencode/ prefix (and existing auth headers) for every wire format / stream variant.

Scope

Verification

  • RED (fix absent): go test ./internal/provider/ -run OpencodeUserAgent -count=1 → 9/9 FAIL, all with User-Agent = "Go-http-client/1.1", want prefix "opencode/".
  • GREEN (fix present): same command → ok 9/9 PASS.
  • Regression: go test ./... -count=1 → all packages ok.
  • gofmt -l internal/provider/ → clean; go vet ./internal/provider/ → ok.
  • Manual (local binary built from this change): proxy-served deepseek-v4-flash-free returns 200; same request was 429/502 before.
  • CI: pending.

Current HEAD: 229fec4

Risks

None known. The header is cosmetic to upstream; no behavior change for users who already use paid opencode-go / Claude / OpenRouter paths. If the upstream free-tier check ever changes, tests at internal/provider/opencode_useragent_test.go will flag it.

Lessons

The free-tier limiter keys on the effective User-Agent of the upstream client, not on the API key alone. Any future proxy client should mirror the first-party client's User-Agent to stay in the same quota bucket.

Closes #137

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] Zen free models 429 FreeUsageLimitError because upstream requests use generic Go User-Agent

1 participant