Skip to content

feat(provider): track and learn per-provider rate limits#1

Merged
TTK95 merged 2 commits into
devfrom
claude/add-rate-limit-tracking-EuuBc
Apr 20, 2026
Merged

feat(provider): track and learn per-provider rate limits#1
TTK95 merged 2 commits into
devfrom
claude/add-rate-limit-tracking-EuuBc

Conversation

@TTK95
Copy link
Copy Markdown
Owner

@TTK95 TTK95 commented Apr 20, 2026

Summary

  • New RateLimit module (packages/opencode/src/provider/rate-limit.ts) that ticks on every outbound request and parses standard rate-limit response headers (x-ratelimit-*, anthropic-ratelimit-*, IETF ratelimit-*) when providers expose them.
  • On the first 429 from a provider, writes the observed per-minute and per-day request counts to ~/.config/opencode/opencode.json under provider.<id>.options.rateLimit. Values only bump upward, so retry-induced floods don't lower a learned limit.
  • Skips the config write if opencode.jsonc is present, to avoid clobbering user comments.
  • Extends ConfigProvider.Info.options with a typed rateLimit: { perMinute?, perDay? } field, so users can also set limits by hand.
  • Logs each provider's rate-limit-related response headers once at info level, which makes it easy to confirm what a proxy like RWTH Aachen returns without adding any provider-specific code.

Motivation: proxies such as the RWTH Aachen OpenAI-compatible API do not surface rate-limit headers, so the client has no way to know the limit until a 429 lands. This gives all providers — RWTH and any other header-less proxy — a learned, persisted limit after the first hit.

Test plan

  • bun typecheck in packages/opencode — clean
  • bun test test/rate-limit.test.ts — 5/5 pass
    • counter tick across both windows
    • header parsing for x-ratelimit-* family
    • persistence to opencode.json on onRateLimitError
    • upward-only learning (existing larger value preserved)
    • .jsonc-present guard skips the write
  • Manual: point a provider at the RWTH endpoint, send one message, inspect ~/.local/share/opencode/log/ for the "provider first response headers" entry to confirm whether RWTH exposes any rate-limit headers.
  • Manual: trigger a 429 against a mock server after N requests, confirm provider.<id>.options.rateLimit.perMinute is written as N in opencode.json.

https://claude.ai/code/session_01Ko79DH9kwztGCe8hQjbvfr

claude added 2 commits April 20, 2026 16:31
Adds RateLimit module that ticks on every outbound request, parses any
known rate-limit response headers (x-ratelimit-*, anthropic-ratelimit-*,
IETF ratelimit-*), and on the first 429 from a provider, writes the
observed per-minute and per-day counts to opencode.json under
provider.<id>.options.rateLimit. This gives proxies like the RWTH Aachen
API — which do not expose rate-limit headers — a persisted limit after
the first hit.
- Inline minute/day cutoffs per style guide.
- Deduplicate the parsed-headers object construction.
- Drop the existsSync TOCTOU in readJsonSafe; handle ENOENT from
  readFileSync instead.
@TTK95 TTK95 merged commit ce628d0 into dev Apr 20, 2026
@TTK95 TTK95 deleted the claude/add-rate-limit-tracking-EuuBc branch April 20, 2026 18:17
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.

2 participants