Skip to content

fix(provider): preserve user-defined model variants from config#12170

Open
monotykamary wants to merge 1 commit intoanomalyco:devfrom
monotykamary:fix/provider-variants-merge
Open

fix(provider): preserve user-defined model variants from config#12170
monotykamary wants to merge 1 commit intoanomalyco:devfrom
monotykamary:fix/provider-variants-merge

Conversation

@monotykamary
Copy link
Contributor

Summary

Fixes a subtle bug where model.variants could be unintentionally overwritten when ProviderTransform.variants() returns {} for certain models (kimi, deepseek, minimax, etc.).

The Problem

In provider.ts, the previous code would:

  1. Overwrite model.variants with ProviderTransform.variants(model) result (which is {} for kimi models)
  2. Then conditionally merge with configVariants

While this currently works, it has a subtle issue: if configVariants lookup fails or if variants were set in a previous processing step, they would be lost.

The Fix

Instead of overwriting then merging, we now merge directly:

  • ProviderTransform.variants() provides the base defaults
  • model.variants (from user config) is merged on top, taking precedence
  • User-defined variants are always preserved

Changes

  • Modified packages/opencode/src/provider/provider.ts (lines 925-932)
  • Simplified variant merging logic
  • Ensures user config always takes precedence over ProviderTransform defaults

Testing

  • Tested with custom provider configs (e.g., kimi-for-coding with kimi-k2.5 model)
  • Verified that user-defined variants in config are properly preserved
  • No breaking changes to existing behavior

Related

Closes #12169

The previous code would unconditionally overwrite model.variants with
ProviderTransform.variants() result, which returns {} for kimi and other
models. This caused user-defined variants from config to be lost.

The fix merges ProviderTransform variants with existing model.variants
instead of overwriting, ensuring user config always takes precedence.

Subtle bug: In the rare case where both ProviderTransform and user config
define a variant with the same name, the old merge order could cause
unexpected behavior when configVariants lookup failed.
Copilot AI review requested due to automatic review settings February 4, 2026 18:16
@github-actions
Copy link
Contributor

github-actions bot commented Feb 4, 2026

The following comment was made by an LLM, it may be inaccurate:

No duplicate PRs found

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request attempts to simplify the variant merging logic in the provider initialization code. The stated goal is to preserve user-defined model variants from config and fix a "subtle bug" where variants could be unintentionally overwritten. However, the implementation introduces a critical bug that breaks the handling of disabled variants.

Changes:

  • Modified variant merging logic in packages/opencode/src/provider/provider.ts (lines 925-932)
  • Removed direct access to configProvider?.models?.[modelID]?.variants
  • Changed from a two-step process (overwrite then merge) to direct merging

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't u just change the conditional here to be if (configVariants) because model.variants should always be "defined" as in {} at worst right

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- if (configVariants && model.variants)
+ if (configVariants)

Oh you mean this; it would probably be simpler. This would work if the configProvider lookup reliably returns the variants, but:

  • it would require looking up the config twice
  • if the config loading has any edge cases, variants could still be lost
const baseVariants = ProviderTransform.variants(model)
const mergedVariants = mergeDeep(baseVariants, model.variants ?? {})

The subtle bug is overwriting then re-merging from config again, which this fix would hopefully future proof to:

  • preserve whatever is already in model.variants
  • merge ProviderTransform defaults underneath
  • no double config lookup (i think)
  • should be a bit more predictable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Subtle bug: model.variants can be unintentionally overwritten when ProviderTransform.variants() returns {}

2 participants