omp packages

@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

yugimob Published 7 days ago MIT ~466 downloads/mo

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.

Did it work for you?

Result

One report per person. A new report replaces your old one.

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:

  1. 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 a rate-limited window 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.
  2. 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.
  3. Silent stalls: when an opencode-go provider 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-go provider 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 reset or /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 add are stored in plaintext. The config file is created and maintained with 0600 permissions.

License

MIT