Skip to content

fix(minimax): refresh token-plan model availability - #48

Merged
elkaix merged 4 commits into
mainfrom
fix/minimax-token-plan-model-refresh
Jun 1, 2026
Merged

fix(minimax): refresh token-plan model availability#48
elkaix merged 4 commits into
mainfrom
fix/minimax-token-plan-model-refresh

Conversation

@elkaix

@elkaix elkaix commented Jun 1, 2026

Copy link
Copy Markdown
Member

Summary

  • discover MiniMax models from the authenticated Anthropic-compatible model list first, with OpenAI-compatible /v1/models as fallback
  • treat the live MiniMax catalog as authoritative so Token Plan keys only keep models available to that token
  • refresh saved MiniMax models on startup without resetting user preferences, and isolate refresh failures from other providers

Tests

  • make check-pythinker-code
  • make test-pythinker-code

Summary by CodeRabbit

  • Bug Fixes
    • More robust MiniMax model discovery: improved error handling, auth validation, deduplication, and reliable endpoint fallback.
  • New Features
    • Login/startup now refreshes MiniMax token-plan model catalog so keys show only models actually available while preserving user defaults and pruning stale entries.
  • Tests
    • Expanded coverage for discovery, parsing, refresh/apply behavior, default-model preservation, and failure isolation.
  • Documentation
    • Added changelog note about MiniMax token-plan catalog refresh behavior.

@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 0f6a287a-242c-4664-9ec8-825a8bd4b507

📥 Commits

Reviewing files that changed from the base of the PR and between a3fcb22 and cc303d3.

📒 Files selected for processing (2)
  • src/pythinker_code/auth/minimax.py
  • tests/auth/test_minimax_auth.py

📝 Walkthrough

Walkthrough

Adds robust MiniMax model discovery (Anthropic-first, OpenAI-fallback), defensive parsing and deduplication of discovered models, apply/refresh helpers and login behavior changes, integrates MiniMax refresh into the managed-provider flow, and expands tests and changelog.

Changes

MiniMax Model Discovery and Managed Integration

Layer / File(s) Summary
Discovery constants and infra
src/pythinker_code/auth/minimax.py
Define Mapping import, Anthropic/OpenAI model endpoint URLs, MINIMAX_DEFAULT_CONTEXT, token-plan key prefix, discovery timeout; update MiniMaxModel.max_context_size default.
Parsing and model-shape helpers
src/pythinker_code/auth/minimax.py
Add helpers to filter chat-capable model IDs, derive alias_suffix/display_name, extract positive context from multiple fields, defensively validate and deduplicate /models responses into MiniMaxModel tuples.
Dual-endpoint discovery and errors
src/pythinker_code/auth/minimax.py
Use a single timed aiohttp session; attempt Anthropic /models with X-Api-Key first, fall back to OpenAI /models with Authorization: Bearer ...; classify auth (401/403) separately and return empty tuple if no discovery succeeds.
Apply / refresh helpers and login change
src/pythinker_code/auth/minimax.py
Add helper to extract MiniMax API key from Anthropic provider, implement apply_minimax_models to upsert/prune models and adjust config.default_model, add refresh_minimax_models, and change login_minimax_api_key to always assign discovered models.
Managed platform refresh integration
src/pythinker_code/auth/platforms.py
Import MiniMax discovery/apply helpers, skip generic managed discovery for the MiniMax Anthropic provider key, add post-loop MiniMax refresh/apply block, and persist applied MiniMax changes alongside existing OpenCode Go save path.
Unit and integration tests
tests/auth/test_minimax_auth.py, tests/auth/test_platforms.py
Add imports and tests: login discovery for token-plan keys, parsing acceptance and context extraction, apply_minimax_models pruning/preservation/default reassignment, managed refresh tests for authoritative empty catalogs and isolated discovery failures; add _make_minimax_config() helper.
Changelog
CHANGELOG.md
Add Unreleased note describing MiniMax Token Plan catalog refresh behavior and failure isolation.
sequenceDiagram
  participant LoginFlow
  participant MiniMaxDiscovery as _discover_minimax_models
  participant AnthropicAPI as Anthropic_/models
  participant OpenAIAPI as OpenAI_/models
  participant ApplyModels as apply_minimax_models
  participant ConfigStore

  LoginFlow->>MiniMaxDiscovery: call with resolved_key
  MiniMaxDiscovery->>AnthropicAPI: GET /models (X-Api-Key)
  alt Anthropic succeeds
    AnthropicAPI-->>MiniMaxDiscovery: models payload
  else Anthropic fails or non-auth
    MiniMaxDiscovery->>OpenAIAPI: GET /models (Authorization: Bearer)
    OpenAIAPI-->>MiniMaxDiscovery: models payload / error
  end
  MiniMaxDiscovery->>ApplyModels: parsed MiniMaxModel tuple
  ApplyModels->>ConfigStore: upsert/prune models, adjust default_model, persist changes
Loading

🎯 3 (Moderate) | ⏱️ ~22 minutes

Suggested labels

bug

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.38% which is insufficient. The required threshold is 70.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive Description covers main changes and test verification, but missing required checklist items per template, specifically contribution guidelines acknowledgment and changelog/docs generation confirmations. Complete the checklist section confirming CONTRIBUTING review, changelog generation via 'make gen-changelog', and docs update via 'make gen-docs' as required by the template.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed Title follows conventional commits format with 'fix' type and 'minimax' scope, clearly reflecting the core change: refreshing token-plan model availability.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/minimax-token-plan-model-refresh

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai 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.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/auth/test_platforms.py (1)

878-882: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Assert MiniMax state is unchanged in persisted config as well.

This test proves in-memory MiniMax state is retained, but it doesn’t assert the saved config also keeps MiniMax unchanged.

Proposed assertion additions
     assert changed is True
     assert len(saved) == 1
     assert saved[0].models["pythinker-code/pythinker-for-coding"].max_context_size == 200_000
+    assert "minimax/m2.7-highspeed" in saved[0].models
+    assert saved[0].models["minimax/m2.7-highspeed"].provider == "managed:minimax-anthropic"
     assert "minimax/m2.7-highspeed" in config.models
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/auth/test_platforms.py` around lines 878 - 882, Add an assertion to
verify that the MiniMax model state in the saved configuration remains unchanged
by checking that the saved config's MiniMax model settings are equal to those in
the original config. Locate the assertions verifying config models in the test
and add this new assertion after them to confirm MiniMax's state consistency in
the persisted config.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/pythinker_code/auth/minimax.py`:
- Around line 220-221: The discovery path currently treats an empty `models`
list as falsy and falls through to the secondary endpoint, which causes the
result to be collapsed to None and preserves stale aliases; update the logic so
that an empty list is considered authoritative: return the discovered `models`
(including empty list) from the `get`/discovery code path instead of falling
through, and ensure callers (e.g., the place that assigns `minimax_models`)
check `is not None` rather than truthiness before calling
`apply_minimax_models`; update the relevant variables `models`, `minimax_models`
and the call to `apply_minimax_models` (also adjust the code around the block at
the later fallback around lines 294-299) so an empty list is propagated and
handled correctly.

In `@src/pythinker_code/auth/platforms.py`:
- Around line 257-264: The current branch checks for
MINIMAX_ANTHROPIC_PROVIDER_KEY which embeds a transport suffix into the managed
provider identity; change logic so MiniMax is keyed as the canonical managed
provider (use managed_provider_key('minimax') / parse_managed_provider_key())
and stop special-casing MINIMAX_ANTHROPIC_PROVIDER_KEY. Update the condition
that references OPENCODE_GO_PROVIDER_KEYS or MINIMAX_ANTHROPIC_PROVIDER_KEY to
instead only special-case OpenCode Go via OPENCODE_GO_PROVIDER_KEYS, and ensure
any code that previously relied on MINIMAX_ANTHROPIC_PROVIDER_KEY derives the
wire-shape (Anthropic vs OpenAI) from the active model/provider metadata (using
parse_managed_provider_key() and managed_model_key()/managed_provider_key())
rather than a hard-coded provider key.

In `@tests/auth/test_minimax_auth.py`:
- Line 189: The test currently patches the private helper
_discover_minimax_models which couples the test to internal implementation;
instead, mock the external observable boundary used by login_minimax_api_key
(for example the HTTP client or session method it calls, e.g., requests.post or
the session object's post/send method) so the test drives behavior via real
public inputs and responses and asserts outcomes of login_minimax_api_key;
replace
monkeypatch.setattr("pythinker_code.auth.minimax._discover_minimax_models", ...)
with a monkeypatch of the HTTP call used by login_minimax_api_key (or the public
client wrapper it uses), return the same fake HTTP response payload, and keep
assertions against login_minimax_api_key results rather than internal helper
calls.

In `@tests/auth/test_platforms.py`:
- Around line 803-805: The tests currently patch the private method
_discover_minimax_models, which couples them tightly to MiniMax internals and
breaks abstraction. Instead, locate and patch the public method
refresh_minimax_models in the test platform mocks to mock the observable
behavior at the integration boundary. Replace all occurrences where
_discover_minimax_models is patched, including lines 803 and 860-862, to patch
refresh_minimax_models instead to follow the testing guidelines and reduce
coupling to private internals.

---

Outside diff comments:
In `@tests/auth/test_platforms.py`:
- Around line 878-882: Add an assertion to verify that the MiniMax model state
in the saved configuration remains unchanged by checking that the saved config's
MiniMax model settings are equal to those in the original config. Locate the
assertions verifying config models in the test and add this new assertion after
them to confirm MiniMax's state consistency in the persisted config.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 8e7acb4a-cc57-44e0-87cd-733f7ab8aa8f

📥 Commits

Reviewing files that changed from the base of the PR and between df7698f and 9892a42.

📒 Files selected for processing (4)
  • src/pythinker_code/auth/minimax.py
  • src/pythinker_code/auth/platforms.py
  • tests/auth/test_minimax_auth.py
  • tests/auth/test_platforms.py

Comment thread src/pythinker_code/auth/minimax.py Outdated
Comment thread src/pythinker_code/auth/platforms.py
Comment thread tests/auth/test_minimax_auth.py Outdated
Comment thread tests/auth/test_platforms.py Outdated

@coderabbitai coderabbitai 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/pythinker_code/auth/minimax.py (1)

327-344: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Handle successful-but-empty MiniMax discovery during login to avoid pruning MiniMax and hijacking default_model.

When _discover_minimax_models() returns (), models gets overwritten and _apply_minimax_config() deletes all existing MiniMax models (provider MINIMAX_ANTHROPIC_PROVIDER_KEY) and then sets config.default_model to the first remaining non-MiniMax model alias (or ""). login_minimax_api_key then yields "success" even though zero MiniMax models were configured.

Suggested fix
     models = MINIMAX_MODELS
     try:
-        models = await _discover_minimax_models(resolved_key)
+        discovered = await _discover_minimax_models(resolved_key)
+        if discovered:
+            models = discovered
+        else:
+            yield OAuthEvent(
+                "info",
+                "MiniMax returned no models for this key; using the built-in model list.",
+            )
     except aiohttp.ClientResponseError as exc:
         if exc.status in {401, 403}:
             yield OAuthEvent("error", "Invalid MiniMax API key; the key was not saved.")
             return
         yield OAuthEvent(
             "info",
             "MiniMax model listing is unavailable; using the built-in model list.",
         )
     except (aiohttp.ClientError, TimeoutError, ValueError):
         yield OAuthEvent(
             "info",
             "MiniMax model listing is unavailable; using the built-in model list.",
         )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pythinker_code/auth/minimax.py` around lines 327 - 344, The login flow
currently overwrites models with the result of
_discover_minimax_models(resolved_key) even when that call returns an empty
sequence, which causes _apply_minimax_config(...) to prune all MiniMax models
and mis-set config.default_model; change the logic so you only assign models =
discovered if the returned value from _discover_minimax_models(resolved_key) is
non-empty/truthy (otherwise keep the fallback MINIMAX_MODELS), and in the empty
case yield the same OAuthEvent("info", "MiniMax model listing is unavailable;
using the built-in model list.") path so successful-but-empty discovery does not
remove configured MiniMax models or hijack default_model.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/pythinker_code/auth/minimax.py`:
- Around line 327-344: The login flow currently overwrites models with the
result of _discover_minimax_models(resolved_key) even when that call returns an
empty sequence, which causes _apply_minimax_config(...) to prune all MiniMax
models and mis-set config.default_model; change the logic so you only assign
models = discovered if the returned value from
_discover_minimax_models(resolved_key) is non-empty/truthy (otherwise keep the
fallback MINIMAX_MODELS), and in the empty case yield the same
OAuthEvent("info", "MiniMax model listing is unavailable; using the built-in
model list.") path so successful-but-empty discovery does not remove configured
MiniMax models or hijack default_model.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a8af7517-94a1-461b-87b0-0b559d227cd3

📥 Commits

Reviewing files that changed from the base of the PR and between e1debb4 and a3fcb22.

📒 Files selected for processing (4)
  • src/pythinker_code/auth/minimax.py
  • src/pythinker_code/auth/platforms.py
  • tests/auth/test_minimax_auth.py
  • tests/auth/test_platforms.py

@elkaix

elkaix commented Jun 1, 2026

Copy link
Copy Markdown
Member Author

CodeRabbit outside-diff follow-up: fixed the valid default-model part in cc303d3 by preserving an existing non-MiniMax default when login receives an authoritative empty MiniMax catalog. Skipped the suggested built-in fallback because this PR's requirement is that a successful empty authenticated catalog is authoritative; falling back to static models would reintroduce unavailable/stale aliases.

@elkaix
elkaix merged commit 691cc49 into main Jun 1, 2026
23 checks passed
@elkaix
elkaix deleted the fix/minimax-token-plan-model-refresh branch July 17, 2026 20:04
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.

1 participant