# NousResearch/hermes-agent · Minimax M3 model support and aux model alignment

## Open now

- Nothing open on GitHub.

These items concern adding support for the MinimaxM3 model and fixing the default auxiliary model to align with the M3 frontier for minimax and minimax-cn providers. Multiple fix attempts address the same alignment issue.

## TL;DR

- 3 member(s): 0 open issue(s), 1 closed issue(s), 0 open PR(s), 1 merged PR(s), 1 PR(s) closed without merging.
- A fix was merged to main in PR #39024. Verify it addresses your case.
- **Recommended:** read PR #39024 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `unresolved`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_SPANNING`): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
- Pairwise link density `0.67`: the share of member pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. `1.00` means every pair is linked.

## Closed / duplicate issues

- #36196: \[Feature\]: MinimaxM3 model support

## Prior & competing PRs

- **#39024: fix(minimax): align default_aux_model with M3 frontier (salvage #37664)**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`
  - files: `agent/auxiliary_client.py`, `plugins/model-providers/minimax/__init__.py`, `tests/agent/test_minimax_provider.py`, `tests/hermes_cli/test_api_key_providers.py`, `tests/plugins/model_providers/test_minimax_profile.py`
  - fix hunks:
  - `agent/auxiliary_client.py`

    ```diff
    @@ -265,9 +265,6 @@ def _get_aux_model_for_provider(provider_id: 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",
    ```
  - `plugins/model-providers/minimax/__init__.py`

    ```diff
    @@ -14,7 +14,7 @@
         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(
    ```

    ```diff
    @@ -24,7 +24,7 @@
         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(
    ```

    ```diff
    @@ -37,7 +37,7 @@
         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)
    ```
  - `tests/agent/test_minimax_provider.py`

    ```diff
    @@ -141,14 +141,37 @@ def test_thinking_still_works_for_claude(self):
     
     
     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):
    +        # Import model_tools to trigger plugin discovery so the
    +        # ProviderProfile objects are registered in the providers
    +        # registry before _get_aux_model_for_provider() is called.
    +        # Without this, profile-based resolution can be order-dependent
    +        # or fail outright in isolation (the minimax-* entries are
    +        # no longer in _API_KEY_PROVIDER_AUX_MODELS_FALLBACK after the
    +        # minimax-M3 default-aux-model cleanup, so the profile is
    +        # the only path to a non-empty aux value).
    +        import model_tools  # noqa: F401
             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):
    +        import model_tools  # noqa: F401
             from agent.auxiliary_client import _get_aux_model_for_provider
             assert "highspeed" not in _get_aux_model_for_provider("minimax")
             assert "highspeed" not in _get_aux_model_for_provider("minimax-cn")
    ```
  - `tests/hermes_cli/test_api_key_providers.py`

    ```diff
    @@ -1279,6 +1279,20 @@ def test_minimax_oauth_has_models(self):
             assert len(models) >= 1
     
         def test_minimax_oauth_aux_model_registered(self):
    -        from agent.auxiliary_client import _API_KEY_PROVIDER_AUX_MODELS
    -        assert "minimax-oauth" in _API_KEY_PROVIDER_AUX_MODELS
    -        assert _API_KEY_PROVIDER_AUX_MODELS["minimax-oauth"]  # non-empty
    +        # Aux model for the minimax-oauth provider now lives on the
    +        # ProviderProfile (plugins/model-providers/minimax/__init__.py),
    +        # not the legacy _API_KEY_PROVIDER_AUX_MODELS dict in
    +        # agent/auxiliary_client.py. The profile layer is the source
    +        # of truth; _get_aux_model_for_provider() reads from it first
    +        # and only falls back to the dict when no profile is registered.
    +        import model_tools  # noqa: F401  -- triggers plugin discovery
    +        import providers
    +
    +        profile = providers.get_provider_profile("minimax-oauth")
    +        assert profile is not None, "minimax-oauth provider profile must be registered"
    +        assert profile.default_aux_model, (
    +            "minimax-oauth profile must advertise a non-empty default_aux_model "
    +            "so the auxiliary client (compression / vision / session-search) "
    +            "doesn't fire the 'No auxiliary LLM provider configured' warning "
    +            "for every minimax-oauth session."
    +        )
    ```
  - `tests/plugins/model_providers/test_minimax_profile.py`

    ```diff
    @@ -0,0 +1,120 @@
    +"""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
    +
    +
    [redacted:email](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`` in
    +    ``hermes_cli.models._PROVIDER_MODELS['minimax']`` 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."
    +        )
    ```
- **#37664: fix(minimax): align default_aux_model with M3 frontier on minimax + minimax-cn**. closed without merge
  - maintainer direction: category `merged_via`; implication `superseded`; refs `3d1d0a49f`, `b531b5d12`, `fa8e2f935`, `#39024`

## Fix status

- Merged to main in PR #39024 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-06-04`.
