Skip to content

fix(providers): surface OpenCode Zen short-window rate limits - #1330

Merged
Wibias merged 3 commits into
lidge-jun:devfrom
Wibias:wibias215/ocx-56-opencode-zen-rate-limit-15-20-rpm-is-silent-no-header-no-doc
Aug 9, 2026
Merged

fix(providers): surface OpenCode Zen short-window rate limits#1330
Wibias merged 3 commits into
lidge-jun:devfrom
Wibias:wibias215/ocx-56-opencode-zen-rate-limit-15-20-rpm-is-silent-no-header-no-doc

Conversation

@Wibias

@Wibias Wibias commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Document the community-measured OpenCode Zen free-model burst ceiling (~15–20 RPM) on the keyed opencode-zen provider note (and cross-link it from opencode-free), since OpenCode does not publish RPM or rate-limit headers.
  • When Zen returns an opaque rate-limit 429, enrich the client-facing error with that guidance and a parseable Try again in 15s hint so Retry-After is useful for Codex-shaped clients.
  • Update providers docs (EN + locales) so the Zen vs free-quota distinction is visible without waiting for a silent wall.

Validation

  • bun test tests/opencode-zen-rate-limit.test.ts tests/opencode-free-provider.test.ts tests/retry-after-429.test.ts — pass
  • bun run typecheck — pass
  • Pre-open bug + security gate (upstream/devHEAD) — decision ready after lens/surface evidence

Review notes

  • Synthetic Retry-After: 15 only applies when Zen omits a header and the body looks like a generic rate-limit 429; a real upstream Retry-After still wins.
  • Does not invent X-RateLimit-* remaining counts (would be dishonest without a probe).
  • Dashboard key-cooldown watchdog / notify-on-reset stays on [Feature]: provider/key cooldown recovery notifications #1146.

Limitations

  • No live RPM probe or pre-wall client throttle; this makes the existing limit understandable and backoffable, not predictive.
  • Combo failure path does not yet carry provider name into the same enrichment helper (primary Codex Responses path does).

Fixes #1145

Summary by CodeRabbit

  • New Features

    • Added clearer OpenCode Zen and keyless OpenCode Free rate-limit guidance.
    • Added helpful details to applicable 429 errors, including observed limits and a suggested 15-second retry delay when no retry guidance is provided.
    • Preserved upstream retry timing and optional same-key retry behavior through retryOn429.
  • Documentation

    • Updated provider guidance in English, Japanese, Korean, Russian, and Simplified Chinese.
    • Documented shared endpoints, separate quotas, free-tier limits, and data-use considerations.

Document the observed ~15-20 RPM burst ceiling on opencode-zen (and cross-link it on opencode-free), and enrich opaque Zen 429s with guidance plus a parseable Retry-After so Codex clients can back off.
@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c5871622-679b-4552-824e-5632883e472c

📥 Commits

Reviewing files that changed from the base of the PR and between 6d7c26a and 15850a3.

📒 Files selected for processing (3)
  • src/providers/opencode-zen-rate-limit.ts
  • src/server/responses/core.ts
  • tests/opencode-zen-rate-limit.test.ts

📝 Walkthrough

Walkthrough

OpenCode Zen and OpenCode Free now document shared endpoints, quotas, and 429 behavior. Zen 429 responses receive provider-specific guidance and synthetic retry timing when upstream retry headers are absent. The response pipeline passes authentication and transport metadata to this logic.

Changes

OpenCode Zen rate-limit handling

Layer / File(s) Summary
Provider detection and message enrichment
src/providers/opencode-zen-rate-limit.ts, src/providers/registry.ts
The helper detects Zen and Free providers, validates same-key retry support, preserves valid upstream Retry-After values, adds a synthetic 15-second hint when needed, and prevents duplicate annotations. Registry notes describe both provider tiers.
Response pipeline integration
src/server/responses/core.ts
The upstream non-2xx error path passes provider metadata, authentication state, upstream retry information, and HTTP retry support to the enrichment helper before calculating client retry timing.
Localized documentation and validation
tests/opencode-zen-rate-limit.test.ts, docs-site/src/content/docs/guides/providers.md, docs-site/src/content/docs/{ja,ko,ru,zh-cn}/guides/providers.md
Tests cover provider matching, registry note propagation, retry guidance conditions, upstream header precedence, no-op cases, and duplicate-enrichment prevention. Documentation describes quotas, shared endpoints, synthetic Retry-After, and retryOn429.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant OpenCodeZen
  participant handleResponses
  participant enrichOpenCodeZenRateLimitMessage
  participant RetryCalculator
  OpenCodeZen-->>handleResponses: Return upstream 429 response
  handleResponses->>enrichOpenCodeZenRateLimitMessage: Pass provider, auth, transport, and Retry-After metadata
  enrichOpenCodeZenRateLimitMessage-->>handleResponses: Return enriched message and retry guidance
  handleResponses->>RetryCalculator: Calculate client retry delay
  RetryCalculator-->>handleResponses: Return retry timing
Loading

Possibly related issues

Possibly related PRs

Suggested reviewers: ingwannu, lidge-jun

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the main change: surfacing OpenCode Zen short-window rate limits.
Linked Issues check ✅ Passed The changes address issue #1145 by documenting the burst limit, enriching generic 429 errors, preserving upstream retry data, and adding targeted tests.
Out of Scope Changes check ✅ Passed The documentation, provider metadata, error enrichment, and tests are directly related to the OpenCode Zen rate-limit objectives.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Wibias

Wibias commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator Author

Tracking: Fixes #1145 (OCX-56). Auto-close keyword is in the PR body; Development sidebar may lag on fork heads.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs-site/src/content/docs/guides/providers.md`:
- Around line 279-287: Clarify the OpenCode Zen rate-limit documentation and
registry notes to say Zen may return generic 429 responses without rate-limit
headers, rather than never returning them; document that opencodex adds the
synthetic 15-second Retry-After only when upstream omits Retry-After, while
preserving upstream-header precedence. Apply the equivalent “headers can be
absent” wording in docs-site/src/content/docs/guides/providers.md (279-287),
src/providers/registry.ts (2040 and 2060),
docs-site/src/content/docs/ja/guides/providers.md (206-207),
docs-site/src/content/docs/ko/guides/providers.md (206-207),
docs-site/src/content/docs/ru/guides/providers.md (217-223), and
docs-site/src/content/docs/zh-cn/guides/providers.md (194-195).
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 10a5f899-5a8c-4b65-9f82-d0c785aa0bba

📥 Commits

Reviewing files that changed from the base of the PR and between 3e5cd53 and 97aced7.

📒 Files selected for processing (9)
  • docs-site/src/content/docs/guides/providers.md
  • docs-site/src/content/docs/ja/guides/providers.md
  • docs-site/src/content/docs/ko/guides/providers.md
  • docs-site/src/content/docs/ru/guides/providers.md
  • docs-site/src/content/docs/zh-cn/guides/providers.md
  • src/providers/opencode-zen-rate-limit.ts
  • src/providers/registry.ts
  • src/server/responses/core.ts
  • tests/opencode-zen-rate-limit.test.ts

Comment thread docs-site/src/content/docs/guides/providers.md
@Wibias Wibias linked an issue Aug 9, 2026 that may be closed by this pull request
2 tasks
CodeRabbit: Zen may omit Retry-After / X-RateLimit headers on generic 429s; synthetic backoff is only added when upstream omits Retry-After.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/providers/opencode-zen-rate-limit.ts (1)

63-65: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Do not add the 15-second hint when upstream Retry-After exists.

The guard checks only the message text. If the upstream response contains Retry-After: 120 but the body has no Try again in N text, this function still appends Try again in 15s. The response pipeline may preserve the upstream header, but the client error then contains conflicting retry guidance and can cause premature retries.

Pass the resolved upstream retry value into this function, or perform enrichment only after checking the upstream header. Add a regression test that verifies an upstream value does not produce the synthetic 15-second hint.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/providers/opencode-zen-rate-limit.ts` around lines 63 - 65, Update the
retry-hint enrichment logic in the rate-limit handling function to skip the
synthetic 15-second message whenever a resolved upstream Retry-After value
exists, regardless of message text. Pass that value into the function or move
enrichment after the header check, and add a regression test confirming upstream
retry values do not append the synthetic hint.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/providers/opencode-zen-rate-limit.ts`:
- Line 71: Update the rate-limit guidance helper in opencode-zen-rate-limit.ts
to accept authentication and transport context, and append the retryOn429
message only for key-authenticated HTTP routes. Exclude keyless opencode-free
routes and custom runTurn transports while preserving the existing guidance for
supported paths.

---

Outside diff comments:
In `@src/providers/opencode-zen-rate-limit.ts`:
- Around line 63-65: Update the retry-hint enrichment logic in the rate-limit
handling function to skip the synthetic 15-second message whenever a resolved
upstream Retry-After value exists, regardless of message text. Pass that value
into the function or move enrichment after the header check, and add a
regression test confirming upstream retry values do not append the synthetic
hint.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d96ad8fc-2e54-4fc5-8146-5215b58c84d5

📥 Commits

Reviewing files that changed from the base of the PR and between 97aced7 and 6d7c26a.

📒 Files selected for processing (8)
  • docs-site/src/content/docs/guides/providers.md
  • docs-site/src/content/docs/ja/guides/providers.md
  • docs-site/src/content/docs/ko/guides/providers.md
  • docs-site/src/content/docs/ru/guides/providers.md
  • docs-site/src/content/docs/zh-cn/guides/providers.md
  • src/providers/opencode-zen-rate-limit.ts
  • src/providers/registry.ts
  • tests/opencode-zen-rate-limit.test.ts

Comment thread src/providers/opencode-zen-rate-limit.ts Outdated
Skip the synthetic 15s message when Zen already sent Retry-After, and only suggest retryOn429 on key-authenticated HTTP routes.
@Wibias
Wibias merged commit a51c549 into lidge-jun:dev Aug 9, 2026
26 checks passed
@Wibias
Wibias deleted the wibias215/ocx-56-opencode-zen-rate-limit-15-20-rpm-is-silent-no-header-no-doc branch August 9, 2026 04:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

opencode-zen rate limit (~15-20 RPM) is silent: no header, no doc, no client warning

1 participant