From 3d1d0a49fe9000f632f4739ac21e490bf367dcec Mon Sep 17 00:00:00 2001 From: Fearvox Date: Tue, 2 Jun 2026 14:39:31 -0700 Subject: [PATCH] fix(minimax): align default_aux_model with M3 frontier on minimax + minimax-cn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The minimax / minimax-cn / minimax-oauth profiles still advertised M2.7 (and M2.7-highspeed for OAuth) as their default_aux_model, predating the M3 release (2026-06-01). The user-facing _PROVIDER_MODELS['minimax'] catalog top entry is M3, and the recommended config for a Token-Plan install now sets model.default: MiniMax-M3, so the aux default was the only remaining drift. Updates: * minimax default_aux_model: M2.7 -> M3 * minimax-cn default_aux_model: M2.7 -> M3 * minimax-oauth default_aux_model: M2.7-highspeed -> M2.7 (M3 is not on the OAuth / Coding Plan tier per platform docs as of this PR; the highspeed variant was the 2x-cost regression from #4082 that PR #6082 collapsed to plain M2.7 for minimax / minimax-cn but missed OAuth) * agent/auxiliary_client.py: drop the three legacy _API_KEY_PROVIDER_AUX_MODELS_FALLBACK entries for the minimax family. _get_aux_model_for_provider() reads from ProviderProfile.default_aux_model first (line 250) and only falls back to the dict when the profile has no aux model or the profile import fails. With the profile now set, the dict entries are dead code and a drift hazard. Mirrors the deepseek cleanup in 773a0faca. * tests/agent/test_minimax_provider.py: update the existing TestMinimaxAuxModel assertions from MiniMax-M2.7 to MiniMax-M3 (the intent — 'standard, not highspeed' — is unchanged; the pin value is). * tests/plugins/model_providers/test_minimax_profile.py: new file mirroring tests/plugins/model_providers/test_deepseek_profile.py. Pins each of the three profiles' default_aux_model and asserts _get_aux_model_for_provider() returns it. A second class guards against the highspeed regression coming back. Refs: - Closes #36196 in spirit (M3 support — the catalog half of that issue is #36212; this PR covers the profile half) - Related: #4082 (M2.7-highspeed 2x-cost), #6082 (previous M2.7-highspeed -> M2.7 fix that missed OAuth + the auxiliary_client.py fallback dict) - Pattern: 773a0faca (same profile-layer fix for deepseek) --- agent/auxiliary_client.py | 3 - plugins/model-providers/minimax/__init__.py | 6 +- tests/agent/test_minimax_provider.py | 19 ++- .../model_providers/test_minimax_profile.py | 119 ++++++++++++++++++ 4 files changed, 138 insertions(+), 9 deletions(-) create mode 100644 tests/plugins/model_providers/test_minimax_profile.py diff --git a/agent/auxiliary_client.py b/agent/auxiliary_client.py index 360b487b6..d6af62210 100644 --- a/agent/auxiliary_client.py +++ b/agent/auxiliary_client.py @@ -265,9 +265,6 @@ _API_KEY_PROVIDER_AUX_MODELS_FALLBACK: Dict[str, str] = { "stepfun": "step-3.5-flash", "kimi-coding-cn": "kimi-k2-turbo-preview", "gmi": "google/gemini-3.1-flash-lite-preview", - "minimax": "MiniMax-M2.7", - "minimax-oauth": "MiniMax-M2.7-highspeed", - "minimax-cn": "MiniMax-M2.7", "anthropic": "claude-haiku-4-5-20251001", "opencode-zen": "gemini-3-flash", "opencode-go": "glm-5", diff --git a/plugins/model-providers/minimax/__init__.py b/plugins/model-providers/minimax/__init__.py index f29eb1aa0..6d77536ac 100644 --- a/plugins/model-providers/minimax/__init__.py +++ b/plugins/model-providers/minimax/__init__.py @@ -14,7 +14,7 @@ minimax = ProviderProfile( env_vars=("MINIMAX_API_KEY",), base_url="https://api.minimax.io/anthropic", auth_type="api_key", - default_aux_model="MiniMax-M2.7", + default_aux_model="MiniMax-M3", ) minimax_cn = ProviderProfile( @@ -24,7 +24,7 @@ minimax_cn = ProviderProfile( env_vars=("MINIMAX_CN_API_KEY",), base_url="https://api.minimaxi.com/anthropic", auth_type="api_key", - default_aux_model="MiniMax-M2.7", + default_aux_model="MiniMax-M3", ) minimax_oauth = ProviderProfile( @@ -37,7 +37,7 @@ minimax_oauth = ProviderProfile( env_vars=(), # OAuth — tokens in auth.json, not env base_url="https://api.minimax.io/anthropic", auth_type="oauth_external", - default_aux_model="MiniMax-M2.7-highspeed", + default_aux_model="MiniMax-M2.7", ) register_provider(minimax) diff --git a/tests/agent/test_minimax_provider.py b/tests/agent/test_minimax_provider.py index 73e8034dd..bed3c1166 100644 --- a/tests/agent/test_minimax_provider.py +++ b/tests/agent/test_minimax_provider.py @@ -141,12 +141,25 @@ class TestMinimaxThinkingSupport: class TestMinimaxAuxModel: - """Verify auxiliary model is standard (not highspeed) — now reads from profiles.""" + """Verify auxiliary model is the current frontier standard (not highspeed). + + As of M3's release (2026-06-01) the minimax / minimax-cn provider + profiles advertise ``MiniMax-M3`` as their ``default_aux_model`` (the + same model users see in ``_PROVIDER_MODELS["minimax"]`` and in the + user-facing ``model.default`` for a Token-Plan install). The OAuth + / Coding Plan path sticks with M2.7 because M3 is not on that + tier — see ``test_minimax_profile.py`` for the per-provider split. + + The historical concern this class guards is the #4082 / #6082 + regression: the highspeed variant costs 2x with no model-quality + benefit, so we still assert that no aux choice contains the substring + ``"highspeed"``. + """ def test_minimax_aux_is_standard(self): from agent.auxiliary_client import _get_aux_model_for_provider - assert _get_aux_model_for_provider("minimax") == "MiniMax-M2.7" - assert _get_aux_model_for_provider("minimax-cn") == "MiniMax-M2.7" + assert _get_aux_model_for_provider("minimax") == "MiniMax-M3" + assert _get_aux_model_for_provider("minimax-cn") == "MiniMax-M3" def test_minimax_aux_not_highspeed(self): from agent.auxiliary_client import _get_aux_model_for_provider diff --git a/tests/plugins/model_providers/test_minimax_profile.py b/tests/plugins/model_providers/test_minimax_profile.py new file mode 100644 index 000000000..495c125ce --- /dev/null +++ b/tests/plugins/model_providers/test_minimax_profile.py @@ -0,0 +1,119 @@ +"""Unit tests for the MiniMax provider profile. + +Three MiniMax provider profiles (`minimax` direct API, `minimax-cn` China direct +API, `minimax-oauth` browser OAuth) all advertise a `default_aux_model` on +their `ProviderProfile`. The previous M2.7 / M2.7-highspeed values were +stale relative to the current frontier model (M3, released 2026-06-01) and +inconsistent with the `_PROVIDER_MODELS["minimax"]` catalog top entry in +`hermes_cli/models.py`. + +This file pins the new defaults so the choice is reviewable and any future +revert shows up in a failing test rather than silent behavior drift. + +Refs: + - Issue #36196: M3 support request + - PR #36205 (closed unmerged): Csrayz's M3 + 1M context work + - PR #36212 (open): adds M3 to `_PROVIDER_MODELS["minimax"]` catalog + - PR #6082: M2.7-highspeed → M2.7 for aux model (half-price fix) + - Commit 773a0faca: same profile-layer fix pattern for `deepseek` +""" + +from __future__ import annotations + +import pytest + + +@pytest.fixture(params=["minimax", "minimax-cn", "minimax-oauth"]) +def minimax_profile(request): + """Resolve each registered MiniMax profile. + + Going through ``providers.get_provider_profile`` keeps the test honest — + if someone later replaces the registered class with a plain + ``ProviderProfile``, every assertion below collapses. + """ + import model_tools # noqa: F401 -- triggers plugin discovery + import providers + + profile = providers.get_provider_profile(request.param) + assert profile is not None, f"{request.param} provider profile must be registered" + return profile, request.param + + +class TestMinimaxAuxModelM3: + """MiniMax profile aux model is the new frontier M3, not the stale M2.7. + + The catalog top entry is ``MiniMax-M3`` (hermes_cli/models.py:298) and + the user-facing ``model.default`` for a Token-Plan install is M3, so + pinning the aux default to the same model keeps the runtime consistent + (same auth, same billing pool, same rate limits, no surprise 2x-cost + highspeed variant). M3 was released 2026-06-01 — picking it as the + aux default matches the forward-looking catalog order rather than the + pre-M3 era. + """ + + @pytest.mark.parametrize( + "provider_id,expected", + [ + ("minimax", "MiniMax-M3"), + ("minimax-cn", "MiniMax-M3"), + # minimax-oauth sticks with M2.7: the OAuth / Coding Plan + # tier historically used -highspeed (PR #6082 collapsed that + # to plain M2.7 to avoid the 2x TPS surcharge). M3 is not on + # the OAuth/Coding Plan tier per platform docs as of this PR, + # so the safe choice is the cheapest generally-available + # M2.7 — matching PR #6082's intent. + ("minimax-oauth", "MiniMax-M2.7"), + ], + ) + def test_profile_advertises_expected_aux_model( + self, provider_id, expected + ): + import model_tools # noqa: F401 + import providers + + profile = providers.get_provider_profile(provider_id) + assert profile is not None + assert profile.default_aux_model == expected, ( + f"{provider_id} default_aux_model drifted to " + f"{profile.default_aux_model!r}, expected {expected!r}" + ) + + def test_consumer_api_returns_non_empty_for_each_provider(self, minimax_profile): + from agent.auxiliary_client import _get_aux_model_for_provider + + profile, provider_id = minimax_profile + resolved = _get_aux_model_for_provider(provider_id) + assert resolved != "", ( + f"_get_aux_model_for_provider({provider_id!r}) returned empty — " + "the 'No auxiliary LLM provider configured' warning will fire on " + f"every {provider_id} session even though the profile advertises " + f"default_aux_model={profile.default_aux_model!r}" + ) + assert resolved == profile.default_aux_model, ( + f"_get_aux_model_for_provider({provider_id!r}) returned " + f"{resolved!r} but profile advertises {profile.default_aux_model!r} " + "— the consumer API and the profile have drifted out of sync" + ) + + +class TestMinimaxAuxModelNotHighspeed: + """Regression guard against re-introducing the M2.7-highspeed aux default. + + PR #6082 collapsed the highspeed aux choice to plain M2.7 because the + highspeed variant costs 2x with no real benefit for compression / vision / + session-search aux tasks. None of the three MiniMax profiles should + silently re-introduce that 2x-cost path. + """ + + @pytest.mark.parametrize("provider_id", ["minimax", "minimax-cn", "minimax-oauth"]) + def test_default_aux_model_is_not_highspeed(self, provider_id): + import model_tools # noqa: F401 + import providers + + profile = providers.get_provider_profile(provider_id) + assert profile is not None + assert "highspeed" not in profile.default_aux_model.lower(), ( + f"{provider_id} default_aux_model={profile.default_aux_model!r} " + "is a -highspeed variant — that costs 2x for the same model and " + "broke #4082 the first time. Revert to plain M2.7 or M3." + )