Repository navigation
Releases
@subrouter/opencode@0.5.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 withsession.prompt, which persisted arole: usermessage that could enter model context. The toast is display-only and never reaches the model.tui.toast.showis 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. -
Includes
@subrouter/cli0.6.1: fixed Claude Pro/Max login and token refresh, Claude Code2.1.280user-agent, and retries for OpenAI WebSocket 1006 drops.
@subrouter/cli@0.6.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. -
Advertise Claude Code
2.1.280on Anthropic OAuth requests. Anthropic returns 400 when the Claude Code client is older than2.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). -
Retry OpenAI WebSocket 1006 drops instead of rotating the account. A
code 1006abnormal 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 retryableAPICallError, so OpenCode retries the turn on the same subscription with its normal backoff. Acode 1008policy-violation close is still terminal.
@subrouter/pi@0.3.0
-
Pin reasoning effort from preset
#variantentries. Pi maps the same pin onto nativereasoning. A session reasoning setting still wins over the preset pin. -
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.
-
Persist the in-flight route per session so other processes can read the live model until the session goes idle.
-
Send
x-opencode-sessionon OpenCode Go inference requests. The plugin copies Pi'ssessionIdonto that header. Calls without a harness session id get a random UUID so the request still succeeds. -
Force Responses
store: falseon OpenAI and xAI so long Grok replies no longer fail withResponse is too large to store.
@subrouter/opencode@0.5.0
-
Pin reasoning effort from preset
#variantentries. OpenCode applies that pin on the live SDK unless the session already set--variantorsubrouter/<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. -
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. -
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.
-
Prefer
apply_patchwhen Subrouter routes to GPT. Presets that would otherwise look likeopenai-onlynow spoof a uniquegpt-*API id so OpenCode hidesedit/write. Custom agent prompts also get the apply_patch constraint when the live model is GPT. -
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_contentwithstore: false. -
Persist cooldown fallback notices during the active run using OpenCode's
noReplyand ignored-text pattern. The notice no longer racessession.idleand cannot become the parent of another assistant turn.
@subrouter/cli@0.6.0
-
Import matching OpenCode logins instead of repeating
subrouter loginfor every provider.npx @subrouter/cli import opencode npx @subrouter/cli import opencode --from ~/.local/share/opencode/auth.jsonOnly 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. -
Split tokens from runtime config. Tokens now live in
~/.subrouter/auth.json. Presets, cooldowns, and live routes stay in~/.subrouter/config.json. Older combinedconfig.jsonfiles split on the next write.Editors can autocomplete both files from
$schema:https://subrouter.org/schema.json still serves the config schema.
-
Pin reasoning effort on preset entries with
#variant.preset createaccepts ranked entries likeopenai/gpt-5.5#highandanthropic/claude-opus-4-6#max. Unknown or unsupported variants fail at create time against models.devreasoning_options.npx @subrouter/cli preset create work --models 'anthropic/claude-opus-4-6#max,openai/gpt-5.5#high'A harness session
--variantstill 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. -
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.
-
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. -
Replay previous thinking on Codex and Grok follow-up turns. RouterModel copies
providerOptions.subrouteronto the live SDK (openai/xai/anthropic), forces Responsesstore: falseon OpenAI and xAI, and asks forreasoning.encrypted_content. Long Grok replies no longer fail withResponse is too large to store. Without the encrypted blob, Codex still drops summary-only thinking. That is required:store: falsecannot point atrs_*ids. -
Prefer OpenCode
apply_patchwhen the live model is GPT. GPT presets now spoof a uniquegpt-*API id so OpenCode hidesedit/writeand loads the Codex system prompt. The provider maps that id back to the preset. -
Send
x-opencode-sessionon 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. -
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 retryableAPICallErrors. Subrouter does not rotate or cool down on a timeout. -
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-msstill win when the provider sends them. A normal429without those headers still defaults to 5 minutes. -
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
-
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-promptremain intact, so Anthropic no longer rejects the request as a third-party app that requires extra usage. -
Let
pi -pexit after a Codex turn. The extension now closes its own Codex WebSockets on Pi session shutdown. -
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
-
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. -
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.
-
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
-
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.
-
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.
-
Keep runtime logging local to each router instance.
createSubrouter()andRouterModelnow accept alogcallback, and cooldown fallback routing can be observed throughonCooldownFallback. 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
-
Show the provider as
subrouter.orgin Pi, matching OpenCode. Preset model ids staysubrouter/<preset>. -
Use
opencode-gofor the OpenCode Go plan. Pi now has a native OpenAI-compatible provider for that id. Existingopencodeaccounts are copied toopencode-goon first load.
@subrouter/opencode@0.3.0
-
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) -
Show the live routed model as
subrouter.org. Preset names include the current candidate, for exampledefault (claude-opus-4-6). Context limits follow that candidate. The powered-by system line uses the liveprovider/modelid, not the preset name. -
Wait out cooldowns instead of dying when every Subrouter account is cooling down. OpenCode receives a retryable 429 with
retry-afterand continues the session after the wait. -
Pass image and PDF inputs through OpenCode so attachments reach the routed provider.
-
Use
opencode-gofor the OpenCode Go plan. Existingopencodeaccounts are copied toopencode-goon first load.