This plugin extends OpenCode with dynamic model discovery for OpenAI-compatible providers, enriched with metadata from models.dev.
π δΈζθ―΄ζ
This repository is a fork of b3nw/opencode-dynamic-custom-providers (v2.2.0). The upstream project is dormant β last code commit
2026-05-30, 4 commits total, 0 open issues.Adds multimodal / vision capability detection for dynamically discovered models, fixing the upstream default that forced any model not found in models.dev to
text-onlyβ which made local / self-hosted vision models (e.g. a vLLM endpoint with a custom--served-model-namelikeqwen3.8-flash-next) reject images. Three new mechanisms, resolved in priority order:
- Endpoint-reported modalities β parse
modalities,capabilities.input, andvision/image_support/supports_visionflags from the/v1/modelsresponse.- Vision probing (
probeVision: true) β send a tiny 1Γ1 PNG and inspect the response (200 = vision, 400/422 with an image-related error = text-only), cached 24h.- User overrides β
defaultModalities(provider-wide) andmodelModalities(per-model, highest priority).Also fixed the merge direction so user-defined model config (e.g. explicit
modalities) is never clobbered by discovered metadata. Full details in CHANGELOG.md.
The server plugin's config hook discovers models from any provider with a baseURL on every OpenCode startup. Models are always up-to-date without manual intervention.
Discovered models are cross-referenced against the models.dev catalog (the same source OpenCode uses natively) to enrich them with accurate context windows, output limits, costs, capabilities (tool calling, reasoning, temperature), and input/output modalities.
An interactive TUI wizard for adding new providers:
- Prompts for Provider ID, Base URL, and API Key
- Validates inputs and checks for duplicates
- Discovers models to confirm the endpoint works before saving
- Writes
dynamic: trueso models are re-discovered on each startup
A TUI slash command (also available as /refresh-models) that re-discovers models from all providers with a baseURL without restarting OpenCode. Clears the models.dev cache and updates the live config in one step.
A server-side tool the AI agent can call to add a new provider programmatically. Works in all interfaces (web, desktop, and TUI). Accepts provider ID, base URL, API key, and display style as arguments, validates the endpoint, discovers models, and persists the provider config.
A server-side tool the AI agent can call to re-discover models from all dynamic providers and update the live config. Clears the models.dev metadata cache, fetches /models from every provider with a baseURL, enriches them, and persists the updated config. Works in all interfaces without restarting.
Discovered models get correct modalities so vision-capable models are usable for image input in OpenCode. Three mechanisms, resolved in priority order (modelModalities > models.dev > endpoint-reported > vision probe > defaultModalities > text-only):
- Endpoint-reported modalities β parsed from
modalities,capabilities.input, orvision/image_support/supports_visionflags in the/v1/modelsresponse. - Vision probing (
probeVision: true) β for models not in models.dev and not self-reported, sends a tiny 1Γ1 PNG and inspects the response (200 = vision, 400/422 with an image-related error = text-only). Results are cached for 24h. - User overrides β
defaultModalities(provider-wide) andmodelModalities(per-model, highest priority).
This fixes the upstream default where any model not found in models.dev was silently forced to text-only β which made local/self-hosted vision models (e.g. a vLLM endpoint with a custom --served-model-name) reject images.
opencode plugin opencode-dynamic-custom-providersopencode plugin git+ssh://git@github.com/b3nw/opencode-dynamic-custom-providers.gitgit clone https://github.com/b3nw/opencode-dynamic-custom-providers
cd opencode-dynamic-custom-providers
npm install
npm run build # dist/ is not committed β build before installing
opencode plugin .Run /add-provider in the OpenCode TUI and follow the interactive prompts. The provider will be added with dynamic: true so models are discovered automatically on each startup.
Ask the AI agent to add a provider. The agent will use the add-provider tool with the parameters you provide. For example: "Add an OpenAI-compatible provider called my-proxy at https://api.proxy.com/v1 with API key sk-..."
Add a provider to opencode.json with a baseURL. Models will be discovered automatically:
{
"provider": {
"my-proxy": {
"name": "My Proxy",
"options": {
"baseURL": "https://api.proxy.com/v1"
}
}
}
}For explicit opt-in, set "dynamic": true:
{
"provider": {
"my-proxy": {
"name": "My Proxy",
"dynamic": true,
"options": {
"baseURL": "https://api.proxy.com/v1"
}
}
}
}API keys can be set in three ways:
- Via the
/add-providerTUI command (stored securely via OpenCode's auth system) - In config under
options.apiKey:{ "provider": { "my-proxy": { "options": { "baseURL": "https://api.proxy.com/v1", "apiKey": "sk-..." } } } } - Via environment variable using the pattern
OPENCODE_LOCAL_<PROVIDER_ID>_API_KEY:export OPENCODE_LOCAL_MY_PROXY_API_KEY=sk-...
For a provider whose models support image input, enable one (or more) of:
modelModalitiesoverrides everything;probeVisiononly runs for models that were neither matched in models.dev nor self-reported by the endpoint.
- On startup, the server plugin's
confighook iterates all providers with abaseURL - For each eligible provider (no models defined, or
dynamic: true), it fetches/v1/models - Each discovered model ID is cross-referenced against the models.dev catalog
- Matching models get enriched metadata (context window, costs, capabilities, modalities)
- Enriched models are injected into the live config before OpenCode loads providers
- The provider is set to use
@ai-sdk/openai-compatibleas the SDK package
A provider is eligible for discovery when it has options.baseURL and either:
- Has
dynamic: trueset in config, or - Has no
modelskey (or empty models) in config
Providers that already have models defined in config are left unchanged unless dynamic: true is set.
- Startup latency: Each dynamic provider adds a network request at startup (15s timeout per endpoint, plus models.dev fetch on first run)
- models.dev coverage: Models not in the models.dev catalog get sensible defaults (128k context window, 4096 output limit, text-only modalities unless
probeVision/defaultModalities/modelModalitiesoverride them) - Capabilities detection: Endpoint-reported capabilities (
supported_parameters,capabilities) are merged with models.dev data; neither source alone is complete for all proxies
git clone https://github.com/b3nw/opencode-dynamic-custom-providers
cd opencode-dynamic-custom-providers
npm install
npm run build
{ "provider": { "my-vision-endpoint": { "options": { "baseURL": "https://api.example.com/v1" }, "dynamic": true, // Option A: auto-detect by probing each unknown model with a 1x1 image "probeVision": true // Option B: declare all models on this endpoint as image-capable // "defaultModalities": { "input": ["text", "image"], "output": ["text"] } // Option C: per-model override (highest priority) // "modelModalities": { // "some-model-id": { "modalities": { "input": ["text", "image", "video"], "output": ["text"] } } // } } } }