feat: add multi-key support with automatic rate-limit rotation #11

Merged
opencode merged 1 commit from renekv/ocgo:feat/multi-key-rotation into main 2026-05-26 10:58:06 +00:00
Contributor

Summary

Add multi-key API key support with automatic rate-limit rotation for the ocgo proxy. When an upstream request returns HTTP 429 (Too Many Requests), the proxy automatically rotates to the next API key and retries the request before returning an error to the client. Key index is persisted to ~/.config/ocgo/key-index so the rotation state survives process restarts.

Changes

Config (cmd/ocgo/main.go — +138/-44 lines)

Area Before After
Config struct APIKey string APIKey string (backward compat, omitempty) + APIKeys []string
Request dispatch Inline http.NewRequestWithContext + client.Do in 3 proxy functions Shared postWithRetry() method with 429 detection and auto-rotation
Key selection Fixed single key readKeyIndex() % len(keys) — persisted round-robin
Key rotation Manual config edit rotateKey() increments index, writes to key-index file (0600)

Key Rotation Flow

Request → postWithRetry(key[i]) → 429 → rotateKey() → writeKeyIndex(i+1) → postWithRetry(key[i+1])
  • Rotation only at request start (never mid-stream)
  • Single-key configs behave identically to before (no-op rotation)
  • postWithRetry iterates through all keys before returning 429 to caller

Environment Variables (precedence order)

  1. OCGO_API_KEYS — comma-separated, highest precedence
  2. OCGO_API_KEY — single key, backward compat
  3. Config file api_keys array or api_key string

Setup Command

  • ocgo setup accepts comma-separated keys via --api-keys flag or stdin prompt
  • --api-key flag retained as backward-compat alias
  • Falls back through: --api-keys--api-keyOCGO_API_KEYSOCGO_API_KEY → stdin prompt

Backward Compatibility

  • Old api_key config field still works (treated as single-element api_keys array)
  • saveConfig writes first key as api_key for older ocgo versions
  • OCGO_API_KEY env var still supported
  • All existing proxy functions (proxyMessages, proxyChatCompletions, proxyResponses) refactored to call postWithRetry — same behavior for non-429 responses

Validation

Check Result
go vet ./cmd/ocgo/ Pass
go test ./cmd/ocgo/ Pass (existing tests)
go build -o /dev/null ./cmd/ocgo/ Pass

Constraints Honored

  • No mid-stream rotation (429 only at request start)
  • Translation/streaming logic untouched
  • Single-key configs behave identically
  • Tests pass without modification
  • Key-index file with restricted permissions (0600)
  • Silent rotation (only logged via existing proxy log mechanism)

Fixes #115

## Summary Add multi-key API key support with automatic rate-limit rotation for the ocgo proxy. When an upstream request returns HTTP 429 (Too Many Requests), the proxy automatically rotates to the next API key and retries the request before returning an error to the client. Key index is persisted to `~/.config/ocgo/key-index` so the rotation state survives process restarts. ## Changes ### Config (`cmd/ocgo/main.go` — +138/-44 lines) | Area | Before | After | |------|--------|-------| | Config struct | `APIKey string` | `APIKey string` (backward compat, omitempty) + `APIKeys []string` | | Request dispatch | Inline `http.NewRequestWithContext` + `client.Do` in 3 proxy functions | Shared `postWithRetry()` method with 429 detection and auto-rotation | | Key selection | Fixed single key | `readKeyIndex() % len(keys)` — persisted round-robin | | Key rotation | Manual config edit | `rotateKey()` increments index, writes to `key-index` file (0600) | ### Key Rotation Flow ``` Request → postWithRetry(key[i]) → 429 → rotateKey() → writeKeyIndex(i+1) → postWithRetry(key[i+1]) ``` - Rotation only at request start (never mid-stream) - Single-key configs behave identically to before (no-op rotation) - `postWithRetry` iterates through all keys before returning 429 to caller ### Environment Variables (precedence order) 1. `OCGO_API_KEYS` — comma-separated, highest precedence 2. `OCGO_API_KEY` — single key, backward compat 3. Config file `api_keys` array or `api_key` string ### Setup Command - `ocgo setup` accepts comma-separated keys via `--api-keys` flag or stdin prompt - `--api-key` flag retained as backward-compat alias - Falls back through: `--api-keys` → `--api-key` → `OCGO_API_KEYS` → `OCGO_API_KEY` → stdin prompt ### Backward Compatibility - Old `api_key` config field still works (treated as single-element `api_keys` array) - `saveConfig` writes first key as `api_key` for older ocgo versions - `OCGO_API_KEY` env var still supported - All existing proxy functions (`proxyMessages`, `proxyChatCompletions`, `proxyResponses`) refactored to call `postWithRetry` — same behavior for non-429 responses ## Validation | Check | Result | |-------|--------| | `go vet ./cmd/ocgo/` | ✅ Pass | | `go test ./cmd/ocgo/` | ✅ Pass (existing tests) | | `go build -o /dev/null ./cmd/ocgo/` | ✅ Pass | ## Constraints Honored - ✅ No mid-stream rotation (429 only at request start) - ✅ Translation/streaming logic untouched - ✅ Single-key configs behave identically - ✅ Tests pass without modification - ✅ Key-index file with restricted permissions (0600) - ✅ Silent rotation (only logged via existing proxy log mechanism) Fixes #115
renekv added 1 commit 2026-05-26 09:39:12 +00:00
Support multiple API keys via `api_keys` array in config or `OCGO_API_KEYS`
env var. On HTTP 429, automatically rotate to the next key and retry.
Key index persisted to `~/.config/ocgo/key-index` for restart safety.
Backward compatible with existing single-key `api_key` configs.

Fixes #115

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
renekv force-pushed feat/multi-key-rotation from 5354905c82 to 643efdabb6 2026-05-26 09:44:58 +00:00 Compare
renekv changed title from feat: add multi-key support with automatic rate-limit rotation to WIP: feat: add multi-key support with automatic rate-limit rotation 2026-05-26 09:48:54 +00:00
opencode changed title from WIP: feat: add multi-key support with automatic rate-limit rotation to feat: add multi-key support with automatic rate-limit rotation 2026-05-26 10:57:52 +00:00
opencode merged commit 39c415ebaa into main 2026-05-26 10:58:06 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: opencode/ocgo#11
No description provided.