OpenCode determines model context windows by reading limit.context from opencode.json model entries. The provider was not emitting this field, so all OmniRoute models appeared with an unknown (0) context window in OpenCode, preventing proper compaction and overflow detection. - Add limit.context to OpenCodeModelEntry interface - Add OMNIROUTE_DEFAULT_MODEL_CONTEXT_LENGTHS map (200K Claude / 1M Gemini) - Include limit.context when generating model entries - Extend fetchLiveModels to capture context_length from /v1/models - 5 new tests covering context length coverage, JSON serialisation, unknown model fallback, and live model fetch Closes #2481
@omniroute/opencode-provider
Helper for connecting OpenCode to a running OmniRoute AI gateway.
The package emits a schema-valid entry for opencode.json (https://opencode.ai/config.json) that delegates the actual runtime to @ai-sdk/openai-compatible. It does not ship any new HTTP client — OmniRoute already exposes an OpenAI-compatible surface, and OpenCode already speaks it through the AI SDK.
Pre-1.0. The API may still change. See
CHANGELOGin the OmniRoute repo for breaking notes.
Installation
npm install --save-dev @omniroute/opencode-provider
# or
pnpm add -D @omniroute/opencode-provider
You also need OpenCode's own runtime dep, but that's a transitive concern — OpenCode itself ships with @ai-sdk/openai-compatible. This package only generates configuration.
Quick start
1. Scaffold a fresh opencode.json
import { writeFileSync } from "node:fs";
import { buildOmniRouteOpenCodeConfig } from "@omniroute/opencode-provider";
const config = buildOmniRouteOpenCodeConfig({
baseURL: "http://localhost:20128", // or your OmniRoute deployment URL
apiKey: process.env.OMNIROUTE_API_KEY ?? "sk_omniroute",
});
writeFileSync("opencode.json", JSON.stringify(config, null, 2));
The resulting opencode.json:
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"omniroute": {
"npm": "@ai-sdk/openai-compatible",
"name": "OmniRoute",
"options": {
"baseURL": "http://localhost:20128/v1",
"apiKey": "sk_omniroute",
},
"models": {
"claude-opus-4-5-thinking": { "name": "claude-opus-4-5-thinking" },
"claude-sonnet-4-5-thinking": { "name": "claude-sonnet-4-5-thinking" },
"gemini-3.1-pro-high": { "name": "gemini-3.1-pro-high" },
"gemini-3-flash": { "name": "gemini-3-flash" },
},
},
},
}
2. Merge into an existing opencode.json
import { createOmniRouteProvider } from "@omniroute/opencode-provider";
const provider = createOmniRouteProvider({
baseURL: "http://localhost:20128",
apiKey: process.env.OMNIROUTE_API_KEY!,
});
// Place `provider` under provider.omniroute in your opencode.json
If you already have an opencode.json on disk and want a non-destructive merge from the OmniRoute side, use omniroute config opencode from the CLI (ships with the main OmniRoute install) — it preserves comments and unrelated keys.
API
createOmniRouteProvider(options): OpenCodeProviderEntry
Returns the value to place under provider.omniroute inside opencode.json.
| Option | Type | Required | Description |
|---|---|---|---|
baseURL |
string |
Yes | OmniRoute base URL. Accepts http://host:port or http://host:port/v1. Trailing slashes are tolerated. |
apiKey |
string |
Yes | OmniRoute API key. Use sk_omniroute for local installs that have REQUIRE_API_KEY=false. |
displayName |
string |
No | Custom name shown in the OpenCode UI. Default: "OmniRoute". |
models |
string[] |
No | Override the surfaced model catalog. Default: 4 curated models — see OMNIROUTE_DEFAULT_OPENCODE_MODELS. |
modelLabels |
Record<string,string> |
No | Human-readable labels keyed by model id. |
Throws on empty/invalid input — baseURL must be a real URL, apiKey must be a non-empty string.
buildOmniRouteOpenCodeConfig(options): OpenCodeConfigDocument
Same options as above, but returns a full document with $schema and the provider.omniroute wrapper, ready to write to opencode.json.
normalizeBaseURL(input): string
Exported for completeness. Strips trailing /, deduplicates a trailing /v1, and re-appends exactly one /v1. Throws on empty / non-URL input.
Constants
OMNIROUTE_PROVIDER_KEY—"omniroute"(the key used underprovider.*).OMNIROUTE_PROVIDER_NPM—"@ai-sdk/openai-compatible"(the runtime delegate).OPENCODE_CONFIG_SCHEMA—"https://opencode.ai/config.json".OMNIROUTE_DEFAULT_OPENCODE_MODELS— readonly list of 4 default model ids.
Custom model catalog
import { createOmniRouteProvider } from "@omniroute/opencode-provider";
createOmniRouteProvider({
baseURL: "http://localhost:20128",
apiKey: "sk_omniroute",
models: ["auto", "claude-opus-4-7", "gpt-5.5"],
modelLabels: {
auto: "Auto-Combo (recommended)",
"claude-opus-4-7": "Claude Opus 4.7",
"gpt-5.5": "GPT-5.5",
},
});
Duplicates and empty strings are dropped automatically, and order is preserved.
Troubleshooting
- Requests 404 with
/v1/v1/...— you're on an old version (≤1.0.0). Update to≥0.1.0of this re-released package. The new build normalisesbaseURLautomatically. 401 Invalid API key— your OmniRoute instance hasREQUIRE_API_KEY=truebut the key you supplied doesn't exist there. Create one via the dashboard or setREQUIRE_API_KEY=falseand usesk_omniroute.- OpenCode complains the provider has no models — supply an explicit
modelslist; the default 4 may be hidden by your provider visibility settings.
Related
- OmniRoute — the AI gateway this plugin targets.
- OpenCode — the agentic CLI consumer.
@ai-sdk/openai-compatible— the runtime delegate that actually speaks HTTP.
License
MIT — see LICENSE.