feat(cli): add minimax-oauth provider with PKCE browser flow + full OAuth integration (salvage #15203)#17524
Merged
Merged
Conversation
Add MiniMax OAuth (minimax-oauth) as a first-class provider using a
PKCE device-code flow ported from openclaw/extensions/minimax/oauth.ts.
Changes:
- hermes_cli/auth.py:
- Add 8 MINIMAX_OAUTH_* constants (client ID, scope, grant type,
global/CN base URLs, inference URLs, refresh skew)
- Add 'minimax-oauth' ProviderConfig to PROVIDER_REGISTRY (auth_type
oauth_minimax) with global portal + inference base URLs and CN
extras in the extra dict
- Add provider aliases: minimax-portal, minimax-global, minimax_oauth
- Implement _minimax_pkce_pair(), _minimax_request_user_code(),
_minimax_poll_token(), _minimax_save_auth_state(),
_minimax_oauth_login(), _refresh_minimax_oauth_state(),
resolve_minimax_oauth_runtime_credentials(),
get_minimax_oauth_auth_status(), _login_minimax_oauth()
- Token refresh uses standard OAuth2 refresh_token grant; triggers
relogin_required on invalid_grant / refresh_token_reused
- hermes_cli/runtime_provider.py:
- Add minimax-oauth branch (after qwen-oauth) that calls
resolve_minimax_oauth_runtime_credentials() and returns
api_mode='anthropic_messages' with the OAuth Bearer token
- hermes_cli/auth_commands.py:
- Add 'minimax-oauth' to _OAUTH_CAPABLE_PROVIDERS
- Add auth_type auto-detection for oauth_minimax
- Add provider == 'minimax-oauth' branch in auth_add_command
- hermes_cli/doctor.py:
- Import get_minimax_oauth_auth_status
- Add MiniMax OAuth status check in the Auth Providers section
Wire MiniMax-M2.7 and MiniMax-M2.7-highspeed into the model catalog,
CLI model picker, and agent auxiliary/metadata subsystems.
Changes:
- hermes_cli/models.py:
- Add 'minimax-oauth' to _PROVIDER_MODELS with MiniMax-M2.7 and
MiniMax-M2.7-highspeed
- Add ProviderEntry('minimax-oauth', 'MiniMax (OAuth)', ...) to
CANONICAL_PROVIDERS near existing minimax entries
- Add aliases: minimax-portal, minimax-global, minimax_oauth in
_PROVIDER_ALIASES
- hermes_cli/main.py:
- Add 'minimax-oauth' to provider_labels dict
- Insert 'minimax-oauth' into providers list in
select_provider_and_model() near the other minimax entries
- Add 'minimax-oauth' to --provider argparse choices
- Add _model_flow_minimax_oauth() function: ensures login via
_login_minimax_oauth(), resolves runtime credentials, prompts for
model selection, saves model choice and config
- Add dispatch elif branch for selected_provider == 'minimax-oauth'
- agent/auxiliary_client.py:
- Add 'minimax-oauth': 'MiniMax-M2.7-highspeed' to
_API_KEY_PROVIDER_AUX_MODELS
- Add 'minimax-oauth' to _ANTHROPIC_COMPAT_PROVIDERS set
- agent/model_metadata.py:
- Add 'minimax-oauth' to _PROVIDER_PREFIXES frozenset
- MiniMax-M2.7 context length (200_000) already covered by the
existing 'minimax' substring match in DEFAULT_CONTEXT_LENGTHS
Add and extend tests for the minimax-oauth provider across three test
modules.
New file: tests/test_minimax_oauth.py (15 tests)
- test_pkce_pair_produces_valid_s256: verifies PKCE verifier/challenge
pair produces a valid S256 hash and correct lengths
- test_request_user_code_happy_path: mocks httpx, verifies correct
POST parameters and response parsing
- test_request_user_code_state_mismatch_raises: verifies CSRF guard
- test_request_user_code_non_200_raises: verifies HTTP error handling
- test_poll_token_pending_then_success: verifies polling loop retries
on 'pending' and returns on 'success'
- test_poll_token_error_raises: verifies 'error' status raises AuthError
- test_poll_token_timeout_raises: verifies deadline expiry raises
- test_refresh_skip_when_not_expired: verifies no HTTP call when token
is fresh
- test_refresh_updates_access_token: verifies new access/refresh tokens
stored on successful refresh
- test_refresh_reuse_triggers_relogin_required: verifies
relogin_required=True on invalid_grant/refresh_token_reused
- test_resolve_credentials_requires_login: verifies AuthError when no
stored state
- test_provider_registry_contains_minimax_oauth: PROVIDER_REGISTRY key
- test_minimax_oauth_alias_resolves: portal/global/underscore aliases
- test_get_minimax_oauth_auth_status_not_logged_in
- test_get_minimax_oauth_auth_status_logged_in
Extended: tests/hermes_cli/test_runtime_provider_resolution.py
- test_minimax_oauth_runtime_returns_anthropic_messages_mode
- test_minimax_oauth_runtime_uses_inference_base_url
Extended: tests/hermes_cli/test_api_key_providers.py
- TestMinimaxOAuthProvider class (8 tests) covering registry keys,
auth_type, endpoints, client_id, aliases, CANONICAL_PROVIDERS
listing, _PROVIDER_MODELS entries, and aux model
Add comprehensive documentation for the minimax-oauth provider.
New file: website/docs/guides/minimax-oauth.md
- Overview table (provider ID, auth type, models, endpoints)
- Quick start via 'hermes model'
- Manual login via 'hermes auth add minimax-oauth'
- --region global|cn flag reference
- The PKCE OAuth flow explained step-by-step
- hermes doctor output example
- Configuration reference (config.yaml shape, region table, aliases)
- Environment variables note: MINIMAX_API_KEY is NOT used by
minimax-oauth (OAuth path uses browser login)
- Models table with context length note
- Troubleshooting section: expired token, timeout, state mismatch,
headless/remote sessions, not logged in
- Logout command
Updated: website/docs/getting-started/quickstart.md
- Add MiniMax (OAuth) to provider picker table as the recommended
path for users who want MiniMax models without an API key
Updated: website/docs/user-guide/configuration.md
- Add 'minimax-oauth' to the auxiliary providers list
- Add MiniMax OAuth tip callout in the providers section
- Add minimax-oauth row to the provider table (auxiliary tasks)
- Add MiniMax OAuth config.yaml example in Common Setups
Updated: website/docs/reference/environment-variables.md
- Annotate MINIMAX_API_KEY, MINIMAX_BASE_URL, MINIMAX_CN_API_KEY,
MINIMAX_CN_BASE_URL as NOT used by minimax-oauth
- Add minimax-oauth to HERMES_INFERENCE_PROVIDER allowed values
Close integration gaps discovered by auditing qwen-oauth's file coverage. These are surfaces the original salvage missed — they all existed on main and were added in the 747 commits since PR #15203 was opened. Coverage added: - agent/credential_pool.py: seed pool from auth.json providers.minimax-oauth so `hermes auth list` reflects logged-in state and `hermes auth remove minimax-oauth <N>` works through the standard flow. - agent/credential_sources.py: register RemovalStep for minimax-oauth with suppression-aware `_clear_auth_store_provider`. - agent/models_dev.py: PROVIDER_TO_MODELS_DEV mapping (-> 'minimax' family). - hermes_cli/providers.py: HermesOverlay entry (anthropic_messages transport, oauth_external auth_type, api.minimax.io/anthropic base). - hermes_cli/model_normalize.py: add to _MATCHING_PREFIX_STRIP_PROVIDERS so `minimax-oauth/MiniMax-M2.7` in config.yaml gets correctly repaired. - hermes_cli/status.py: render MiniMax OAuth block in `hermes doctor` (logged-in / region / expires_at / error). - hermes_cli/web_server.py: register in OAUTH_PROVIDER_REGISTRY + dispatch branch in _resolve_provider_status so the dashboard auth page shows it. - website/docs/integrations/providers.md: full 'MiniMax (OAuth)' section. - website/docs/reference/cli-commands.md: --provider enum. - website/docs/user-guide/features/fallback-providers.md: fallback table row. - scripts/release.py AUTHOR_MAP: amanning3390 mapping (CI gate).
| if minimax_exp: | ||
| print(f" Access exp: {minimax_exp}") | ||
| if minimax_status.get("error") and not minimax_logged_in: | ||
| print(f" Error: {minimax_status.get('error')}") |
12 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Salvages #15203 onto current main (747 commits behind at time of open) and closes integration gaps against peer OAuth providers.
Adds
minimax-oauthas a first-class provider with a PKCE browser OAuth flow against MiniMax's portal (api.minimax.io/oauth/code+/oauth/token). Reuses the existinganthropic_messagesapi_mode against/anthropic— no new adapter, no new api_mode — sinceagent/anthropic_adapter.pyalready supports Bearer-token auth for MiniMax endpoints.Changes (vs. #15203)
hermes_cli/main.py(argparse choices → runtime validation),tests/hermes_cli/test_runtime_provider_resolution.py(Azure Foundry / tencent-tokenhub additions), and 3 docs files (GMI Cloud entry, custom provider enum, azure-foundry auxiliary entry)feat(minimax-oauth): full integration with peer OAuth providers— closes 10 integration gaps the original PR didn't know about (they were added to main after feat(cli): add minimax-oauth provider with PKCE browser flow #15203 was opened):agent/credential_pool.pyauth.json providers.minimax-oauthsohermes auth listreflects logged-in state andhermes auth remove minimax-oauth <N>works via the standard flowagent/credential_sources.pyRemovalStepfor minimax-oauth (suppression-aware)agent/models_dev.pyPROVIDER_TO_MODELS_DEVmapping →minimaxfamilyhermes_cli/providers.pyHermesOverlay(anthropic_messages / oauth_external / api.minimax.io/anthropic)hermes_cli/model_normalize.py_MATCHING_PREFIX_STRIP_PROVIDERS— repairsminimax-oauth/MiniMax-M2.7→MiniMax-M2.7hermes_cli/status.pyhermes doctorrenders MiniMax OAuth block (logged-in / region / expires / error)hermes_cli/web_server.py_OAUTH_PROVIDER_CATALOGregistration +_resolve_provider_statusdispatchwebsite/docs/integrations/providers.mdwebsite/docs/reference/cli-commands.md--providerenumwebsite/docs/user-guide/features/fallback-providers.mdscripts/release.pyamanning3390mapping (CI gate)Validation
Targeted tests: 278/279 passed in 6.32s (1 pre-existing copilot/GITHUB_TOKEN unrelated failure — verified against clean
origin/main, not introduced by this PR).tests/test_minimax_oauth.py— 15 OAuth flow / refresh / token store teststests/hermes_cli/test_api_key_providers.py— provider registry + aliasestests/hermes_cli/test_runtime_provider_resolution.py— runtime branches (incl. 2 new minimax-oauth tests)E2E verified with isolated
HERMES_HOME+ mock auth state:resolve_runtime_provider(requested="minimax-oauth")→api_mode=anthropic_messages,base_url=https://api.minimax.io/anthropic,source=oauthminimax-portal,minimax-global,minimax_oauth) route tominimax-oauthcredential_pool.load_pool("minimax-oauth")reflects logged-in token from auth.jsonAuthErrorwith guidance:Run \hermes model` and select MiniMax (OAuth).`hermes doctorblock:MiniMax OAuth ✗ not logged in (run: hermes auth add minimax-oauth)/api/providers/oauthexposes{id: "minimax-oauth", flow: "pkce", source_label: "MiniMax (global)"}credential_sources.find_removal_step("minimax-oauth", "oauth")resolves to registered stepmodel_normalize.normalize_model_for_provider("minimax-oauth/MiniMax-M2.7", "minimax-oauth")→MiniMax-M2.7Attribution
Original PR #15203 by @amanning3390. All 4 original commits cherry-picked onto current
mainwith @amanning3390's authorship preserved via rebase-merge. Follow-up integration commit (feat(minimax-oauth): full integration with peer OAuth providers) by @teknium1.Closes #15203.