Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions agent/auxiliary_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Comment on lines 265 to 270
Expand Down
6 changes: 3 additions & 3 deletions plugins/model-providers/minimax/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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(
Expand All @@ -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)
Expand Down
1 change: 1 addition & 0 deletions scripts/release.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,7 @@
"harish.kukreja@gmail.com": "counterposition",
"nidhi2894@gmail.com": "nidhi-singh02",
"35294173+Fearvox@users.noreply.github.com": "Fearvox",
"fearvox1015@gmail.com": "Fearvox",
"hypnus.yuan@gmail.com": "Hypnus-Yuan",
"15558128926@qq.com": "xsfX20",
"binhnt.ht.92@gmail.com": "binhnt92",
Expand Down
29 changes: 26 additions & 3 deletions tests/agent/test_minimax_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Comment on lines 159 to +171

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")
Expand Down
20 changes: 17 additions & 3 deletions tests/hermes_cli/test_api_key_providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."
)
120 changes: 120 additions & 0 deletions tests/plugins/model_providers/test_minimax_profile.py
Original file line number Diff line number Diff line change
@@ -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


@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`` 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."
)
Loading