Skip to content

fix(core): map MiniMax Messages effort ladders to variants - #62265

Closed
isHeSatoshi wants to merge 1 commit into
anomalyco:devfrom
isHeSatoshi:minimax-effort-variants
Closed

isHeSatoshi wants to merge 1 commit into
anomalyco:devfrom
isHeSatoshi:minimax-effort-variants

Conversation

@isHeSatoshi

@isHeSatoshi isHeSatoshi commented Nov 6, 2026 •

Copy link
Copy Markdown

Issue for this PR

Closes #62264

Related: #54801 (same root cause on the MiniMax Messages route), #61521 (closed as a duplicate of #54801).

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

The MiniMax Messages route dropped every declared effort ladder, so MiniMax-M3.1-Flash exposed no reasoning variants on the minimax (minimax.io API), minimax-coding-plan (Token Plan), minimax-cn and minimax-cn-coding-plan providers. Since MiniMax defaults output_config.effort to max, the model always reasoned at maximum depth.

packages/core/src/variant.ts maps a catalog effort ladder to no variants at all:

const configurable = support.type === "toggle" || (support.type === "effort" && support.values === undefined)
if (!configurable) return []

Variant.supports() produces { type: "effort", values: [...] } for these models, so support.values !== undefined and the route returned []. This PR adds the missing branch and spells the ladder the way the Messages protocol spells effort, so the Anthropic protocol emits output_config.effort itself:

if (support.type === "effort" && support.values !== undefined)
  return efforts(
    support.values.filter((value) => value !== "none"),
    (effort) => ({ settings: { effort } }),
  )
  • settings: { effort } is the same spelling the other Anthropic-compatible route uses (moonshotMessages), so the effort travels as a typed provider option instead of an opaque body overlay. A request-level providerOptions.effort therefore still wins over the variant, which a body overlay cannot do.
  • none is filtered out because MiniMax answers 400 model "MiniMax-M3.1-Flash" requires adaptive thinking for it, and thinking cannot be turned off on this model.
  • MiniMax-M3 keeps its none/thinking toggle, and the M2.x guard is untouched.

packages/ai/src/providers/minimax.ts now advertises effort on the Messages route, which is what the variants set.

The catalog is not the problem here — packages/core/src/models-dev/snapshot.txt and the live catalog already declare effort: ["low", "medium", "high", "xhigh", "max"] for this model.

Note on #56510

#56510 fixes the same branch with a body: { output_config: { effort } } overlay. That produces the same request body, but as a transport-level overlay it overrides anything the protocol or a per-request option produces. This PR uses the protocol option instead and adds coverage for both providers the report names. If you prefer #56510's implementation, this PR can be closed in its favour — the variant mapping and the request body are equivalent.

How did you verify your code works?

  • packages/core/test/variant.test.ts — the ladder resolves to the five effort variants, M3 keeps its toggle, M2.x stays variant-free.
  • packages/core/test/model-resolver.test.ts — resolving a variant for minimax and minimax-coding-plan produces a request body with output_config: { effort: "low" } and no thinking toggle.
  • packages/ai/test/provider/minimax.test.ts — the Messages route turns the effort provider option into output_config.effort.
  • Decoding the live catalog (ModelsDev.decodeSnapshot) now yields the five variants for MiniMax-M3.1-Flash on all four MiniMax providers.
  • bun test in packages/core (6971 pass, 2 pre-existing environment failures in vcs.test.ts and preload.test.ts, both failing on a clean tree too) and in packages/ai (2049 pass, 0 fail).
  • bun run check from the repository root: 35/35 tasks successful.

Visual

No visual change: the variant list already exists in the model selector, it now lists the MiniMax effort levels.

Screenshots / recordings

Not a UI change.

Checklist

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

@opencodejr

opencodejr Bot commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Thanks for tracking this down and for the thorough write-up, @isHeSatoshi!

I think this duplicates #56510, which is still open and fixes the same thing:

The main difference is how the effort is sent: a typed settings: { effort } option here, a body.output_config.effort overlay there. That's a good point to raise in a review on #56510. Your extra test coverage for the minimax and minimax-coding-plan providers could be useful there too, as a suggestion or a test report.

@isHeSatoshi

Copy link
Copy Markdown
Author

Thanks for the pointer. The difference is real, so it is worth spelling out — I left the details in a review on #56510.

Summary: settings: { effort } goes through the Anthropic Messages protocol, so the model option is merged under the request options and a per-request providerOptions.effort still wins. A body: { output_config: { effort } } overlay is merged on top of the protocol body at transport time, so it silently overrides it. It is also the spelling the sibling Anthropic-compatible route already uses (moonshotMessages → settings: { effort }, with effort declared on MessagesOptionsInput).

Happy to consolidate either way:

The variant list is identical in both cases: low, medium, high, xhigh, max, with no none step (MiniMax answers 400 … requires adaptive thinking for it), MiniMax-M3 keeping its none/thinking toggle and the M2.x guard untouched.

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.

MiniMax M3.1 Flash exposes no reasoning effort variants on the minimax.io API and Token Plan providers

1 participant