@yugimob/pi-opencode-go-rotation1.7.1
Rotate between multiple OpenCode Go API keys with reactive 429, rate-limit, and watchdog stall detection, plus live footer usage for the active key
Untested on omp
This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.
Reports 0
No reports yet.
Readme
pi-opencode-go-rotation
Rotate between multiple OpenCode Go API keys. The extension checks OpenCode Go usage when a 429 response arrives, verifies a candidate key's usage before switching to it, rotates around quota-blocked and cooling-down keys, and recovers silent stalls detected by the watchdog.
Fork of lnilluv/pi-opencode-go-rotation. This fork adds a live footer status line for the active key's OpenCode Go usage.
Install
pi install npm:@yugimob/pi-opencode-go-rotation
Setup
Add your API keys:
/opencode add personal sk-xxxx
/opencode add work sk-yyyy
/opencode add backup sk-zzzz
The first key added becomes active immediately.
The extension never imports keys from auth.json automatically. When no keys are configured, /opencode offers to import the auth.json key once; declining is remembered and it is not asked again.
Interactive key manager
In interactive mode, /opencode (or /opencode config) opens the key manager overlay. It lists every key with its active, cooldown, or quota-blocked state, and lets you:
- Activate a key and clear its cooldown and quota block
- Rename a key or replace its secret
- Remove a key
- Add a key without remembering the command syntax
- Check a key's usage after the window closes
- Change the cooldown duration and the watchdog settings
- Clear every cooldown and quota block
Changes are saved as soon as they are confirmed. Outside interactive mode the command prints the text status instead.
How it works
The extension sets the active key as a runtime override, which takes priority over OPENCODE_API_KEY environment variables and auth.json credentials.
The extension has three recovery paths:
- Usage-verified Go quota exhaustion: when OpenCode Go returns HTTP 429, the extension sends the active key only to
https://opencode.ai/zen/go/v1/usage. A key with arate-limitedwindow or a window at 100% is blocked until the latest reported reset, and the next candidate is activated. Candidate keys are verified the same way before they are selected, so an exhausted key is blocked and skipped instead of being tried. Rotation prefers keys outside transient cooldown, but can clear a cooldown rather than keep using an exhausted key. When every key is quota-blocked, rotation stops and reports the earliest reset instead of cycling. - Transient limit errors: when the usage endpoint is unavailable, does not report an exhausted window, or does not finish within 10 seconds, the extension preserves the existing transient 429 behavior. It aborts a timed-out usage request, marks the current key as on cooldown, verifies and switches to the next key that is not quota-blocked, and applies it via
setRuntimeApiKey. - Silent stalls: when an
opencode-goprovider request has no response or stream activity for the watchdog window, the extension rotates to an eligible key, aborts the hung turn, and rewrites the abort as a retryable timeout error.
Checks happen at decision points only: a candidate is verified when it is about to be selected, and a key with a recorded block is left alone until its stored reset passes. Normal requests are not pre-checked. With the interactive footer active, the periodic footer refresh also re-checks the active key and records a block if a window is full, so the next request rotates before it fails.
Fixed-window Go plan quota errors reported at message end follow the same rotation path. A parseable reset timestamp is authoritative; otherwise the configured cooldown duration is used as the block duration. A response-hook rotation is deduplicated so the matching message-end error cannot rotate twice.
Pi's built-in auto-retry picks up the new key on the next request.
Cooldowns default to 60 minutes. Quota blocks expire at their persisted deadline. Manual /opencode use <n> and /opencode next clear both restrictions on the selected key.
Usage commands use https://opencode.ai/zen/go/v1/usage and stop waiting after 10 seconds. A timeout reports Usage request timed out after 10s..
Footer usage
While the selected model uses the opencode-go provider, the extension keeps a status line in pi's footer with the active key's name, the weekly and monthly usage windows, and the monthly renewal date:
personal: wk 40% · mo 55% | ↻ Nov 12
The rolling 5-hour window is omitted from the footer.
It refreshes on session start, model changes, turns, key rotations, manual key commands, and every 5 minutes. If that check finds a window at 100% or rate-limited, the active key is blocked until the window's reset, and the next request moves to another key. The active key's name leads the line, and switching to another provider clears it.
Commands
| Command | Description |
|---|---|
/opencode or /opencode config |
Open the interactive key manager |
/opencode status |
Show all keys, active key marker, cooldown and quota-blocked status |
/opencode usage or /opencode quota |
Fetch OpenCode Go usage for the active key without showing key material |
/opencode use <n> |
Switch to key number n (1-based) and clear its cooldown and quota block |
/opencode next |
Advance to the next configured key and clear its cooldown and quota block before activating it |
/opencode add <name> <key> |
Add a new key |
/opencode rm <n> |
Remove key number n |
/opencode reset |
Clear all cooldowns and quota blocks |
/opencode cooldown <min> |
Set or view cooldown duration in minutes |
/opencode events |
Show recent watchdog timeout history (last 10) |
/opencode watchdog [status|on|off|<seconds>] |
Configure silent-stall detection |
Configuration
Keys are stored in ~/.pi/agent/opencode-keys.json with file permissions 0600. Status output shows key names only; it does not display key material.
{
"keys": [
{ "name": "personal", "key": "sk-xxx" },
{ "name": "work", "key": "sk-yyy" }
],
"activeKeyIndex": 0,
"cooldownMinutes": 60,
"watchdogEnabled": true,
"watchdogIdleMs": 90000,
"cooldowns": {},
"quotaBlockedUntil": {},
"authImportDeclined": false
}
Retry settings
Pair with pi's auto-retry for best results. In ~/.pi/agent/settings.json:
{
"retry": {
"enabled": true,
"maxRetries": 3
}
}
Set maxRetries to at least the number of keys so all keys get a chance before pi gives up.
Limitations
- The watchdog is scoped to the
opencode-goprovider only. Other providers are not aborted or rotated. - A legitimate long-running request with no stream activity can be treated as stalled; tune with
/opencode watchdog <seconds>or disable with/opencode watchdog off. - When all non-quota-blocked keys are transiently cooling down, the extension may clear the next eligible key's cooldown. It never automatically clears or force-selects a quota-blocked key.
- When all keys are quota-blocked, automatic rotation stops on the current runtime key; each key becomes eligible again automatically when its stored reset deadline passes, or immediately after
/opencode reset. - Recorded blocks are never re-probed before their stored reset, so there is no plan-top-up recovery; use
/opencode resetor/opencode use <n>to clear a block early. - Go plan usage limits are tied to the subscription workspace; multiple keys from one workspace should not be assumed to provide independent quota. See the OpenCode Go documentation.
- Keys added via
/opencode addare stored in plaintext. The config file is created and maintained with0600permissions.
License
MIT