Skip to content

Releases

@subrouter/opencode@0.5.1

Choose a tag to compare

  1. Show the cooldown fallback route as a TUI toast instead of injecting a session message. When a preferred subscription is rate limited and the request continues on a lower-ranked model, the plugin now uses client.tui.showToast. Before, it wrote the notice with session.prompt, which persisted a role: user message that could enter model context. The toast is display-only and never reaches the model.

    tui.toast.show is a global event with no session field, so the plugin appends the OpenCode session id to the toast text. Kimaki routes the toast to the matching Discord thread by that marker and strips it before display. Plain OpenCode TUI shows the toast for the active session. Notices are still deduplicated per session for the preferred model's cooldown window.

  2. Includes @subrouter/cli 0.6.1: fixed Claude Pro/Max login and token refresh, Claude Code 2.1.280 user-agent, and retries for OpenAI WebSocket 1006 drops.

@subrouter/cli@0.6.1

Choose a tag to compare

@remorses remorses released this 23 Sep 08:32
  1. Fixed Claude Pro/Max login and token refresh inside OpenCode. Bun sends User-Agent: opencode/<version> by default, and the Claude OAuth token endpoint answers it with a fake rate limit, so every login and refresh failed:

    token endpoint returned 429: {"error": {"type": "rate_limit_error", "message": "Rate limited. Please try again later."}}
    

    Harnesses like the Kimaki Discord bot showed this as Authorization code was invalid or expired. Token requests now send the Claude Code user-agent, the same one Anthropic API calls already use.

  2. Advertise Claude Code 2.1.280 on Anthropic OAuth requests. Anthropic returns 400 when the Claude Code client is older than 2.1.280:

    Claude Code 2.1.257 does not support this model; version 2.1.280 or newer is required.
    

    The Anthropic adapter now sends user-agent: claude-cli/2.1.280 (external, cli).

  3. Retry OpenAI WebSocket 1006 drops instead of rotating the account. A code 1006 abnormal close (OpenAI WebSocket failed: closed before response completed) is a transient network failure, not a quota or auth rejection. Subrouter no longer cools down the account for 5 minutes. It is wrapped as a retryable APICallError, so OpenCode retries the turn on the same subscription with its normal backoff. A code 1008 policy-violation close is still terminal.

@subrouter/pi@0.3.0

Choose a tag to compare

@remorses remorses released this 14 Sep 15:07
  1. Pin reasoning effort from preset #variant entries. Pi maps the same pin onto native reasoning. A session reasoning setting still wins over the preset pin.

  2. Keep each user message on the subscription that accepted it. Tool-result follow-ups stay on that provider, model, and account even if a higher-ranked subscription leaves cooldown mid-run.

  3. Persist the in-flight route per session so other processes can read the live model until the session goes idle.

  4. Send x-opencode-session on OpenCode Go inference requests. The plugin copies Pi's sessionId onto that header. Calls without a harness session id get a random UUID so the request still succeeds.

  5. Force Responses store: false on OpenAI and xAI so long Grok replies no longer fail with Response is too large to store.

@subrouter/opencode@0.5.0

Choose a tag to compare

  1. Pin reasoning effort from preset #variant entries. OpenCode applies that pin on the live SDK unless the session already set --variant or subrouter/<name>#high. The plugin publishes the first live candidate's variants so the OpenCode picker can change effort per session. If the live fallback does not list that session variant, Subrouter uses the candidate pin or the provider default.

  2. Show the in-flight routed model through resolveLiveModel({ preset, sessionID }). The powered-by system line uses the provider/model that accepted the current run. After failover, later calls in the same session keep showing that fallback until idle.

  3. Keep each user message on the subscription that accepted it. Tool-result follow-ups stay on that provider, model, and account even if a higher-ranked subscription leaves cooldown mid-run.

  4. Prefer apply_patch when Subrouter routes to GPT. Presets that would otherwise look like openai-only now spoof a unique gpt-* API id so OpenCode hides edit/write. Custom agent prompts also get the apply_patch constraint when the live model is GPT.

  5. Replay encrypted reasoning on Codex and Grok follow-up turns. The plugin marks a preset as a reasoning model when the first live candidate is one, so thinking variants stay available. RouterModel copies Subrouter provider options onto the live SDK and requests reasoning.encrypted_content with store: false.

  6. Persist cooldown fallback notices during the active run using OpenCode's noReply and ignored-text pattern. The notice no longer races session.idle and cannot become the parent of another assistant turn.

@subrouter/cli@0.6.0

Choose a tag to compare

@remorses remorses released this 14 Sep 15:07
  1. Import matching OpenCode logins instead of repeating subrouter login for every provider.

    npx @subrouter/cli import opencode
    npx @subrouter/cli import opencode --from ~/.local/share/opencode/auth.json

    Only providers Subrouter supports are copied into ~/.subrouter/auth.json. Existing accounts with the same identity are updated. The auth file schema is at https://subrouter.org/auth.schema.json.

  2. Split tokens from runtime config. Tokens now live in ~/.subrouter/auth.json. Presets, cooldowns, and live routes stay in ~/.subrouter/config.json. Older combined config.json files split on the next write.

    Editors can autocomplete both files from $schema:

    https://subrouter.org/schema.json still serves the config schema.

  3. Pin reasoning effort on preset entries with #variant. preset create accepts ranked entries like openai/gpt-5.5#high and anthropic/claude-opus-4-6#max. Unknown or unsupported variants fail at create time against models.dev reasoning_options.

    npx @subrouter/cli preset create work --models 'anthropic/claude-opus-4-6#max,openai/gpt-5.5#high'

    A harness session --variant still wins over the preset pin. If the live fallback does not list that session variant, Subrouter uses the candidate pin or the provider default instead of sending an unsupported effort.

  4. Keep each user message on the provider, model, and account that accepted it. Tool-result follow-ups no longer jump back to a higher-ranked subscription when its cooldown expires mid-run. New user messages still start from the preset ranking.

  5. Persist the in-flight route per session. resolveLiveModel({ preset, sessionID }) returns the provider/model that accepted the current run. After failover, later calls in the same session keep showing that fallback until the session goes idle.

  6. Replay previous thinking on Codex and Grok follow-up turns. RouterModel copies providerOptions.subrouter onto the live SDK (openai / xai / anthropic), forces Responses store: false on OpenAI and xAI, and asks for reasoning.encrypted_content. Long Grok replies no longer fail with Response is too large to store. Without the encrypted blob, Codex still drops summary-only thinking. That is required: store: false cannot point at rs_* ids.

  7. Prefer OpenCode apply_patch when the live model is GPT. GPT presets now spoof a unique gpt-* API id so OpenCode hides edit/write and loads the Codex system prompt. The provider maps that id back to the preset.

  8. Send x-opencode-session on OpenCode Go inference requests. RouterModel copies the harness session id onto that header. Calls without a harness session id get a random UUID so the request still succeeds.

  9. Retry provider timeouts in OpenCode instead of killing the session. Network failures such as The operation timed out, connect timeouts, and undici header/body timeouts are thrown as retryable APICallErrors. Subrouter does not rotate or cool down on a timeout.

  10. Shorten two cooldown defaults. Balance / quota exhausted (402) now cools for 10 minutes instead of 6 hours. Overloaded / at-capacity messages cool for 1 minute. retry-after / retry-after-ms still win when the provider sends them. A normal 429 without those headers still defaults to 5 minutes.

  11. Preserve structured provider stream errors instead of displaying [object Object]. OpenAI Responses API errors keep their nested message so Subrouter can classify rate limits and report the real provider error.

@subrouter/pi@0.2.1

Choose a tag to compare

@remorses remorses released this 01 Sep 08:10
  1. Keep Claude Pro/Max OAuth requests on subscription usage. The extension removes Pi's self-identifying system prompt and documentation block before Anthropic receives the request. The Claude Code identity block, tools, working directory, skills, and --append-system-prompt remain intact, so Anthropic no longer rejects the request as a third-party app that requires extra usage.

  2. Let pi -p exit after a Codex turn. The extension now closes its own Codex WebSockets on Pi session shutdown.

  3. Keep runtime logging isolated and silent. Subrouter no longer writes to stdout or stderr when Pi loads the extension or routes a request. Separate harness and provider instances cannot leak log destinations into each other.

@subrouter/opencode@0.4.0

Choose a tag to compare

  1. Show when a message starts on a fallback model. If the preferred subscription is already rate limited, OpenCode adds an ignored notice after the turn finishes:

    Subrouter: openai/gpt-5.5 was rate limited. This message started with anthropic/claude-opus-4-6.
    

    The notice stays visible in session history, is never sent to the model, and cannot start another model turn. Preset labels now stay stable, such as build, instead of showing a stale startup candidate.

  2. Route PDFs and other media through compatible fallbacks. OpenCode model metadata now uses the input modalities published by models.dev instead of claiming every provider supports every attachment. Mixed presets advertise the union of usable candidates, and Subrouter skips candidates that cannot accept the current prompt while preserving the configured ranking. Registered metadata also preserves models.dev input-token limits.

  3. Keep plugin runtime logs inside OpenCode. Subrouter no longer writes to stdout or stderr when OpenCode loads the plugin or routes a request. Logs use an instance-specific callback passed through provider options, so separate provider instances cannot leak log destinations into each other.

@subrouter/cli@0.5.0

Choose a tag to compare

@remorses remorses released this 01 Sep 08:10
  1. Route media inputs only through compatible subscriptions. Subrouter reads input modalities from models.dev and skips candidates that cannot accept the current prompt while preserving the configured ranking. A PDF request can now fail over from OpenAI without reaching a provider that cannot transport PDFs. Registered model metadata also preserves models.dev input-token limits.

  2. Retry failures that happen before semantic stream output. OpenAI WebSocket code 1006 disconnects and routed 401, 403, 429, usage-limit, and spending-limit failures now cool down the failed account and reach OpenCode as retryable API errors. OpenCode can restart the turn on the next subscription instead of ending the session.

    Failures after text, reasoning, or tool output still cool down the account but never replay the turn. This prevents duplicate output and repeated tool side effects.

  3. Keep runtime logging local to each router instance. createSubrouter() and RouterModel now accept a log callback, and cooldown fallback routing can be observed through onCooldownFallback. Subrouter no longer writes to stdout or stderr when a harness loads it or routes a request. Separate harnesses and provider instances cannot leak log destinations into each other.

@subrouter/pi@0.2.0

Choose a tag to compare

@remorses remorses released this 31 Aug 10:15
  1. Show the provider as subrouter.org in Pi, matching OpenCode. Preset model ids stay subrouter/<preset>.

  2. Use opencode-go for the OpenCode Go plan. Pi now has a native OpenAI-compatible provider for that id. Existing opencode accounts are copied to opencode-go on first load.

@subrouter/opencode@0.3.0

Choose a tag to compare

  1. Log which subscription is tried when OpenCode prints logs:

    opencode run --print-logs --log-level INFO -m subrouter/default 'Reply with one word: ping'
    trying openai/gpt-5.5 #1 (work@x.com)
    failover openai/gpt-5.5 #1 (work@x.com) error="The usage limit has been reached"
    trying openai/gpt-5.5 #2 (personal@x.com)
    
  2. Show the live routed model as subrouter.org. Preset names include the current candidate, for example default (claude-opus-4-6). Context limits follow that candidate. The powered-by system line uses the live provider/model id, not the preset name.

  3. Wait out cooldowns instead of dying when every Subrouter account is cooling down. OpenCode receives a retryable 429 with retry-after and continues the session after the wait.

  4. Pass image and PDF inputs through OpenCode so attachments reach the routed provider.

  5. Use opencode-go for the OpenCode Go plan. Existing opencode accounts are copied to opencode-go on first load.