Repository navigation
Description
Description
Summary
When configuring a custom provider with a different npm package (e.g. switching ZAI/ZhipuAI from the default @ai-sdk/openai-compatible to @ai-sdk/anthropic), setting only provider.<id>.npm and provider.<id>.options.baseURL has no effect — opencode silently keeps using the catalog/discovery-provided npm package (e.g. @ai-sdk/openai-compatible) and sends requests in the wrong protocol. There is no warning, error, or log line indicating that provider.npm was ignored.
The user must additionally enumerate every model under provider.<id>.models: { ... } for provider.npm to take effect on those entries. Provider-level npm is only read inside the loop over provider.models, so models pre-populated by the discovery plugin keep their original npm package.
Reproduction
Configure ZAI to use Anthropic's /v1/messages endpoint:
// opencode.jsonc
{
"provider": {
"zai": {
"npm": "@ai-sdk/anthropic",
"options": {
"baseURL": "https://open.bigmodel.cn/api/anthropic/v1"
}
}
}
}Run opencode run -m zai/glm-4.5 "hi".
Expected
provider.npm applies provider-wide; all zai models (including those from the discovery plugin) use @ai-sdk/anthropic and hit /v1/messages.
Actual
- The
npmfield is silently ignored. - Requests go to
https://open.bigmodel.cn/api/anthropic/v1/chat/completions(OpenAI path, because@ai-sdk/openai-compatibleis still in use). - For this URL ZAI's gateway returns either:
- HTTP 200 with body
{"code":500,"msg":"404 NOT_FOUND","success":false}(business-layer 500 that the SSE parser silently swallows), or - HTTP 404
{"detail":"Not Found"}(when/v1is in the path) — which surfaces as a stream error.
- HTTP 200 with body
- No warning is emitted that
provider.npmhad no effect.
Workaround
Enumerate every model:
"models": {
"glm-4.5": {}, "glm-4.6": {}, "glm-5": {}, "glm-5.2": {}
}Cumbersome when the provider exposes many models.
Root cause
packages/opencode/src/provider/provider.ts:1394-1414:
for (const [providerID, provider] of configProviders) {
const existing = database[providerID]
const parsed: Info = {
// ...
models: existing?.models ?? {}, // catalog/discovery models, with their own npm
}
for (const [modelID, model] of Object.entries(provider.models ?? {})) { // ← only iterates user-listed models
const apiNpm =
model.provider?.npm ??
provider.npm ?? // ← only consulted inside this loop
existingModel?.api.npm ??
modelsDev[providerID]?.npm ??
"@ai-sdk/openai-compatible"
// ...
}
}Proposal
Either (or both):
- Make
provider.npmprovider-wide. When set, overrideapi.npm(and optionallyapi.urlfromprovider.api) for allexisting.modelsentries that don't have an explicit per-model override. - Warn when
provider.npmis set butprovider.modelsis empty (the user almost certainly intended provider-wide application and will get silently wrong behavior).
Environment
- opencode 1.17.10
- platform: linux
- relevant source:
packages/opencode/src/provider/provider.ts
Plugins
No response
OpenCode version
No response
Steps to reproduce
No response
Screenshot and/or share link
No response
Operating System
No response
Terminal
No response
Activity
github-actions commentedon Jun 25, 2026
This issue might be a duplicate of existing issues. Please check:
npmoverride in custom provider config is ignored — related bug where thenpmfield at different levels of the provider config is not applied correctly. Your issue focuses on provider-levelnpmbeing ignored for discovery-populated models, while Per-model npm override in custom provider config is ignored #31919 covers per-modelnpmoverrides being ignored. These may share the same root cause inprovider.ts.github-actions commentedon Aug 25, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.