Skip to content

fix(core): don't clobber model variants supplied by earlier transforms - #59835

Open
PranjalAgarwal01 wants to merge 4 commits into
anomalyco:devfrom
PranjalAgarwal01:fix/preserve-plugin-supplied-model-variants
Open

PranjalAgarwal01 wants to merge 4 commits into
anomalyco:devfrom
PranjalAgarwal01:fix/preserve-plugin-supplied-model-variants

Conversation

@PranjalAgarwal01

@PranjalAgarwal01 PranjalAgarwal01 commented Oct 28, 2026 •

Copy link
Copy Markdown

Issue for this PR

Closes #59836

Type of change

  • Bug fix

What does this PR do?

OpenCode 2.2.0's late config transform (packages/core/src/config/plugin/provider.ts) re-resolves model.variants with the generic ["low","medium","high"] effort list whenever a configured model has neither config.variants nor config.capabilities.reasoning. This overwrites variants supplied by an earlier model transform (e.g. a spec-pack plugin such as opencode-model-specs), so custom reasoning tiers disappear on fresh locations.

This change skips the re-resolution when the model already has variants and was not repackaged for a different package, so externally supplied tiers survive. Config-level variants / capabilities.reasoning still take precedence.

A follow-up rebuilds variants when a custom model's package changes via config (treats a config-level package override like a repackaging), so stale variants spelled for the old package are not kept. The check compares the normalized post-overlay package against the pre-overlay package and applies only to models without a catalog base; repackaged continues to handle catalog models (preserves the fast variant and the empty-variants case).

How did you verify your code works?

Could not type-check the full monorepo locally (shallow clone, no node_modules). A maintainer independently reproduced the bug on 2.2.0 and latest dev, confirmed the approach fixes it, and verified that test/config/provider.test.ts passes on both the base and with this PR, and that typecheck:tsc passes for packages/core. Manually verified the symptom and the workaround (config-level variants) against a live 2.2.0 service before submitting.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Added by the opencode bot (AI-generated).

Fixes #59836

Related: #55979

The late config transform re-resolves model.variants with the generic
low/medium/high effort list whenever a configured model has no explicit
variants or capabilities.reasoning. This overwrites variants supplied by
an earlier model transform (e.g. a spec-pack plugin such as
opencode-model-specs), causing custom reasoning tiers to disappear on
fresh locations.

Skip the re-resolution when the model already has variants and was not
repackaged for a different package, so externally supplied tiers survive.
Config-level variants/capabilities.reasoning still take precedence.
@github-actions github-actions Bot added needs:issue needs:compliance This means the issue will auto-close after 2 hours. labels Oct 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@opencodejr opencodejr Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The fix works: with this change, variants that a plugin adds to a configured custom model survive the late config transform. I checked it with a throwaway test against the base:

  • On the base, an earlier model transform's none/xhigh variants were replaced by the generated list.
  • With this PR, they are kept.

test/config/provider.test.ts passes on both, and typecheck:tsc passes for packages/core.

Public API: unchanged.

One regression should be fixed before merge: when config also sets the model's package, the plugin's variants are now kept even though they are spelled for the old package (see the inline comment).

Fixes #59836
Related: #55979

Follow-up to preserve-plugin-supplied-model-variants: the guard only
considered source.base when deciding whether inherited variants are stale,
so a config-level package override (config.package) on a custom model (no
catalog base) kept variants spelled for the old package. Treat a config
package change like a repackaging.
@github-actions github-actions Bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Oct 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for updating your PR! It now meets our contributing guidelines. 👍

@opencodejr opencodejr Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The earlier point is addressed: a custom model whose package config changes now gets fresh variants for the new package. The #59836 reproduction is fixed when run from source. The plugin's none/low/medium/xhigh are kept, where the base shows low/medium/high.

Public API: unchanged.

The new check breaks catalog models (see the inline comment):

  • test/config/provider.test.ts now fails "keeps a moved catalog model without reasoning variants free of variants". It passes on the base.
  • A catalog model whose config package is the same package in its aisdk: form, as the v1 npm setting migrates to, loses its catalog variants.

agarwa_p added 2 commits October 28, 2026 12:04
Use the normalized post-overlay package instead of raw config.package,
and only for models without a catalog base. Raw aisdk: prefixed values
never equal the normalized pre-overlay package, which rebuilt variants
for catalog models that repackaged already handles and clobbered their
fast variants.

@opencodejr opencodejr Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Both earlier points are addressed:

  • A custom model whose package config changes gets fresh variants for the new package.
  • The package check now applies only to models without a catalog base, so catalog variants and the empty-variants case are kept again.

I re-ran the #59836 reproduction from source. The plugin's none/low/medium/xhigh are kept, where the base shows low/medium/high. I also re-ran my earlier package-move and same-package cases. test/config/provider.test.ts passes 39/39, and typecheck:tsc passes for packages/core.

Public API: unchanged.

No further concerns.

@Antonio-Faure

Copy link
Copy Markdown

Flagging for triage: #60097 (fix(core): preserve plugin-supplied model variants) merged on 2026-10-30 and closed #59836. This PR targets the same variants bug and is now DIRTY; it looks redundant with the merged fix.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Model variants supplied by plugins are clobbered by late config transform

2 participants