Parent
Part of #705.
Summary
OpenCode model availability should come from OpenCode's own catalog command, opencode models [provider], instead of a static Kai model list. OpenCode already owns the provider/model namespace and runtime resolution. Kai should expose that catalog in /models where possible, while keeping direct /model <provider/model> input as the escape hatch.
Current state
Kai's OpenCode backend launches opencode acp and passes the selected model through OPENCODE_CONFIG_CONTENT as {"model":"<provider/model>"}.
OpenCode model validation in Kai currently checks only structural shape: the value must look like provider/model. This is the right runtime escape hatch because OpenCode ultimately decides whether the provider and model can run.
models_for_backend("opencode") currently returns no picker catalog, so OpenCode users get free-text model entry rather than a discoverable model list.
Kai currently has a static OpenCode provider list for first-class provider configuration. That list should not be treated as the complete OpenCode catalog boundary. OpenCode has providers under the backend, and the practical model list depends on OpenCode's installed version, local auth, configured providers, and its upstream model registry.
Problem
OpenCode model freshness has two axes that should not be collapsed into one static Kai table.
First, OpenCode supports providers and model IDs in provider/model form. That catalog is owned by OpenCode and its model source, not by Kai.
Second, Kai only needs to know which provider surfaces it intentionally supports for configuration, auth preservation, documentation, and defaults. Kai does not need to mirror every provider OpenCode could theoretically support.
A static Kai model list would go stale quickly and would duplicate data OpenCode already exposes. Fetching OpenCode's upstream model registry directly from Kai would also bypass the local OpenCode installation, provider config, auth state, and any OpenCode-specific filtering behavior. The safe source of truth is the installed OpenCode CLI under the effective Kai user.
Research notes
OpenCode documents model IDs as provider/model and uses provider-specific catalogs surfaced through the CLI.
OpenCode CLI exposes opencode models [provider] to list available models. It also supports --refresh, which refreshes OpenCode's model cache from its upstream registry, and --verbose, which returns richer metadata for each model.
Local command checks showed opencode models deepseek returning current DeepSeek model IDs in provider/model form. This matches the provider currently relevant to Kai's OpenCode path.
Local command checks also showed that not every provider documented by OpenCode is necessarily available in a given installation or configuration. That reinforces that Kai should ask OpenCode what is available instead of assuming a global provider universe.
Relevant public docs:
Desired behavior
For the OpenCode backend, /models should populate from opencode models [provider] under the same effective OS user and environment that Kai uses to run OpenCode.
When the current OpenCode provider is known, Kai should query opencode models <provider> and show those provider/model IDs.
When no provider filter is available, Kai may either query the unfiltered opencode models output if it is practical for the UI, or present a provider-first selection flow limited to the configured Kai OpenCode providers.
Kai should keep accepting direct /model <provider/model> input even when a model is not present in the discovered picker, because OpenCode can support custom or newly available models before Kai has refreshed.
A user-visible refresh path should call opencode models --refresh [provider] or the equivalent command ordering supported by OpenCode, then rebuild the cached picker list.
If OpenCode returns provider-not-found, auth failure, missing binary, malformed output, or a timeout, Kai should show a clear message and keep free-text /model <provider/model> available.
Scope
- Add an OpenCode model discovery path backed by
opencode models [provider].
- Parse the CLI output into selectable
provider/model IDs for /models.
- Cache discovered results with freshness metadata scoped to the effective Kai user and provider.
- Provide an explicit refresh path that invokes OpenCode's refresh behavior instead of silently refreshing on every picker render.
- Keep structural validation for direct
/model <provider/model> input.
- Document that OpenCode provider availability is owned by the local OpenCode installation and configuration.
- Add tests that mock OpenCode CLI output, refresh behavior, empty results, provider-not-found errors, missing binary, timeout, and malformed output.
Out of scope
- Expanding Kai's OpenCode provider list to every provider OpenCode can document or support.
- Treating OpenRouter or Ollama as active Kai targets for this issue.
- Managing OpenCode provider authentication or creating provider accounts.
- Fetching Models.dev directly as Kai's primary source of truth.
- Changing OpenCode defaults automatically when a new model appears.
- Replacing direct
/model <provider/model> input with picker-only selection.
Acceptance criteria
- OpenCode users can open
/models and see discovered model IDs from opencode models [provider] for the configured provider path.
- The displayed values preserve full
provider/model IDs and selecting one stores the same value Kai passes to OpenCode.
- Direct
/model <provider/model> still works for structurally valid OpenCode model IDs even if discovery is unavailable or stale.
- Discovery and refresh run under the same effective user and environment used for OpenCode execution.
- Discovery failure does not break OpenCode model selection. The UI explains the failure and leaves free-text entry available.
- Cached results are scoped so one user's OpenCode catalog cannot leak into another user's picker.
- Defaults remain curated and stable. Newly discovered models become selectable but do not automatically become defaults.
- Tests cover successful provider-specific discovery, refresh, missing provider, no models, malformed output, missing binary, timeout, and fallback to free-text behavior.
- Documentation explains the three distinct concepts: Kai-supported OpenCode provider configuration, OpenCode-discovered model availability, and curated Kai defaults.
Parent
Part of #705.
Summary
OpenCode model availability should come from OpenCode's own catalog command,
opencode models [provider], instead of a static Kai model list. OpenCode already owns the provider/model namespace and runtime resolution. Kai should expose that catalog in/modelswhere possible, while keeping direct/model <provider/model>input as the escape hatch.Current state
Kai's OpenCode backend launches
opencode acpand passes the selected model throughOPENCODE_CONFIG_CONTENTas{"model":"<provider/model>"}.OpenCode model validation in Kai currently checks only structural shape: the value must look like
provider/model. This is the right runtime escape hatch because OpenCode ultimately decides whether the provider and model can run.models_for_backend("opencode")currently returns no picker catalog, so OpenCode users get free-text model entry rather than a discoverable model list.Kai currently has a static OpenCode provider list for first-class provider configuration. That list should not be treated as the complete OpenCode catalog boundary. OpenCode has providers under the backend, and the practical model list depends on OpenCode's installed version, local auth, configured providers, and its upstream model registry.
Problem
OpenCode model freshness has two axes that should not be collapsed into one static Kai table.
First, OpenCode supports providers and model IDs in
provider/modelform. That catalog is owned by OpenCode and its model source, not by Kai.Second, Kai only needs to know which provider surfaces it intentionally supports for configuration, auth preservation, documentation, and defaults. Kai does not need to mirror every provider OpenCode could theoretically support.
A static Kai model list would go stale quickly and would duplicate data OpenCode already exposes. Fetching OpenCode's upstream model registry directly from Kai would also bypass the local OpenCode installation, provider config, auth state, and any OpenCode-specific filtering behavior. The safe source of truth is the installed OpenCode CLI under the effective Kai user.
Research notes
OpenCode documents model IDs as
provider/modeland uses provider-specific catalogs surfaced through the CLI.OpenCode CLI exposes
opencode models [provider]to list available models. It also supports--refresh, which refreshes OpenCode's model cache from its upstream registry, and--verbose, which returns richer metadata for each model.Local command checks showed
opencode models deepseekreturning current DeepSeek model IDs inprovider/modelform. This matches the provider currently relevant to Kai's OpenCode path.Local command checks also showed that not every provider documented by OpenCode is necessarily available in a given installation or configuration. That reinforces that Kai should ask OpenCode what is available instead of assuming a global provider universe.
Relevant public docs:
Desired behavior
For the OpenCode backend,
/modelsshould populate fromopencode models [provider]under the same effective OS user and environment that Kai uses to run OpenCode.When the current OpenCode provider is known, Kai should query
opencode models <provider>and show thoseprovider/modelIDs.When no provider filter is available, Kai may either query the unfiltered
opencode modelsoutput if it is practical for the UI, or present a provider-first selection flow limited to the configured Kai OpenCode providers.Kai should keep accepting direct
/model <provider/model>input even when a model is not present in the discovered picker, because OpenCode can support custom or newly available models before Kai has refreshed.A user-visible refresh path should call
opencode models --refresh [provider]or the equivalent command ordering supported by OpenCode, then rebuild the cached picker list.If OpenCode returns provider-not-found, auth failure, missing binary, malformed output, or a timeout, Kai should show a clear message and keep free-text
/model <provider/model>available.Scope
opencode models [provider].provider/modelIDs for/models./model <provider/model>input.Out of scope
/model <provider/model>input with picker-only selection.Acceptance criteria
/modelsand see discovered model IDs fromopencode models [provider]for the configured provider path.provider/modelIDs and selecting one stores the same value Kai passes to OpenCode./model <provider/model>still works for structurally valid OpenCode model IDs even if discovery is unavailable or stale.