feat(text_tasks): add MiniMax to external LM provider registry - #1279
feat(text_tasks): add MiniMax to external LM provider registry#1279octo-patch wants to merge 1 commit into
Conversation
Register MiniMax as an external LM provider with both OpenAI Chat and Anthropic Messages protocol options, MiniMax-M3 model defaults, and global plus Mainland China endpoint presets. Enable OpenAI-compatible JSON output for the chat option and document the credential in .env.example.
📝 WalkthroughWalkthroughMiniMax is added as OpenAI-compatible and Anthropic external LM providers, with configuration, URL presets, picker entries, default model handling, and tests. MiniMax OpenAI-compatible requests now support JSON-object response formatting. ChangesMiniMax external LM integration
Estimated code review effort: 2 (Simple) | ~10 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
acestep/text_tasks/external_lm_providers_test.py (1)
67-74: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winAssert the picker ordering contract, not only membership.
The production change inserts MiniMax between OpenAI and Claude, but this test only checks that both entries exist. Assert the full sequence or relative indexes so a later reorder cannot pass unnoticed.
🤖 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 `@acestep/text_tasks/external_lm_providers_test.py` around lines 67 - 74, Update test_get_external_provider_choices_includes_minimax to validate the picker ordering contract, asserting the MiniMax entries appear between OpenAI and Claude in the expected sequence rather than only checking membership. Preserve verification of both MiniMax labels and provider keys.
🤖 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 `@acestep/text_tasks/external_ai_request_helpers.py`:
- Around line 137-139: Update the JSON-output payload branch in the request
helper to add MiniMax’s disabled-thinking setting when provider is "minimax",
using thinking {"type": "disabled"} while preserving the existing
response_format and stop fields. In
acestep/text_tasks/external_ai_request_helpers_test.py lines 130-146, update the
MiniMax assertion to require this thinking payload rather than asserting the
field is absent.
In `@acestep/text_tasks/external_lm_providers.py`:
- Around line 71-85: Update the authentication handling used by the
minimax_anthropic ExternalProviderProfile so requests to its
Anthropic-compatible endpoints send Authorization: Bearer with the API key
instead of relying on the shared x-api-key behavior. Add provider-specific
handling keyed to minimax_anthropic, and add coverage verifying the generated
headers use the required Bearer authorization.
---
Nitpick comments:
In `@acestep/text_tasks/external_lm_providers_test.py`:
- Around line 67-74: Update test_get_external_provider_choices_includes_minimax
to validate the picker ordering contract, asserting the MiniMax entries appear
between OpenAI and Claude in the expected sequence rather than only checking
membership. Preserve verification of both MiniMax labels and provider keys.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 7929d558-7b3c-4dd0-9dc0-c47dd6f569ca
📒 Files selected for processing (5)
.env.exampleacestep/text_tasks/external_ai_request_helpers.pyacestep/text_tasks/external_ai_request_helpers_test.pyacestep/text_tasks/external_lm_providers.pyacestep/text_tasks/external_lm_providers_test.py
| if require_json_output and provider in {"minimax", "openai", "zai"}: | ||
| payload["response_format"] = {"type": "json_object"} | ||
| payload["stop"] = ["```"] |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== locate files =="
fd -a 'external_ai_request_helpers(_test)?\.py$' . | sed 's#^\./##'
echo "== helper outline =="
helper="$(fd 'external_ai_request_helpers\.py$' . | head -n1)"
if [ -n "$helper" ]; then
ast-grep outline "$helper" --view compact || true
wc -l "$helper"
sed -n '1,220p' "$helper"
fi
echo "== test relevant lines =="
if [ -n "${test:-}" ]; then
test="${test:-$(fd 'external_ai_request_helpers_test\.py$' . | head -n1)}"
fi
test="$(fd 'external_ai_request_helpers_test\.py$' . | head -n1 || true)"
if [ -n "$test" ]; then
wc -l "$test"
sed -n '80,170p' "$test"
fi
echo "== search minimax/thinking params =="
rg -n "minimax|thinking|response_format|json_object|stop" .Repository: ace-step/ACE-Step-1.5
Length of output: 50379
🌐 Web query:
MiniMax text-chat OpenAI thinking field disabled adaptive thinking response_format json_object documentation
💡 Result:
To control MiniMax model thinking and output formatting via the OpenAI-compatible Chat Completions API, use the following guidelines based on official documentation: Thinking Control For models that support it (e.g., MiniMax-M3), you can control the generation of thinking content by passing a thinking parameter within the extra_body of your API request [1][2]. - To disable thinking: Set extra_body={"thinking": {"type": "disabled"}} [1][3]. Note that for M2.x models, thinking cannot be disabled; the parameter may be accepted, but thinking will remain active [1][2][3]. - To enable thinking: Set extra_body={"thinking": {"type": "adaptive"}} [1][2]. This is generally the default behavior for M3 on the OpenAI-compatible route [3]. When handling interleaved thinking, you can use the extra_body parameter "reasoning_split": True to receive thinking content in a separate reasoning_details field rather than embedded in the content field [4][5][6]. If reasoning_split is false or omitted, the thinking content is wrapped in tags within the standard content field [4][5]. Response Format (JSON) Support for the response_format parameter, including {"type": "json_object"}, varies by model and endpoint [7][8][9]. While some documentation or third-party implementations suggest support for structured output via JSON mode [9][10], the native API specification notes that certain models (such as MiniMax-Text-01) have specific support for response_format [7]. For many standard MiniMax models (like M2.5) on the OpenAI-compatible endpoint, response_format may be ignored or limited, necessitating alternative methods for ensuring structured output [7]. Always verify specific model capabilities in the official MiniMax platform documentation for the most current information [11][1].
Citations:
- 1: https://platform.minimax.io/docs/api-reference/text-openai-api
- 2: https://platform.minimax.io/docs/api-reference/text-anthropic-api
- 3: https://minimax-ai.chat/docs/api/
- 4: https://platform.minimax.io/docs/guides/text-m2-function-call
- 5: https://platform.minimax.io/docs/guides/text-m3-function-call
- 6: https://www.minimax.io/news/why-is-interleaved-thinking-important-for-m2
- 7: Feature request:
response_formatsupport for MiniMax M2.5 via OpenAI-compatible API MiniMax-AI/MiniMax-M2.5#4 - 8: https://huggingface.co/MiniMaxAI/MiniMax-Text-01/discussions/7
- 9: https://docs.cloudsway.net/maasapi/api-reference/text/MiniMax-M2.52.7/
- 10: https://docs.agno.com/models/providers/native/minimax/usage/structured-output
- 11: https://platform.minimax.io/docs/api-reference/text-chat-openai
🌐 Web query:
site:platform.minimax.io/docs/guides/text-openai-api MiniMax-M3 response_format json_object thinking disabled
💡 Result:
MiniMax’s OpenAI-compatible text API supports the M2.x reasoning models (MiniMax-M2.7, MiniMax-M2.5, MiniMax-M2.1, MiniMax-M2) and reasoning_split=True to separate thinking into reasoning_details. The docs also say response_format is only supported by MiniMax-Text-01, so response_format: {"type":"json_object"} is not documented for MiniMax-M2.x. I also found no documented thinking=disabled option for the OpenAI-compatible M2.x endpoint. (platform.minimax.io)
If you need JSON output with M2.x, the docs suggest using prompt instructions (e.g. “Return a JSON array only”) rather than response_format. (platform.minimax.io)
Citations:
- 1: https://platform.minimax.io/docs/api-reference/text-openai-api?utm_source=openai
- 2: https://platform.minimax.io/docs/token-plan/prompting-best-practices?utm_source=openai
🌐 Web query:
site:platform.minimax.io "MiniMax-M3" "thinking" "adaptive" "disabled"
💡 Result:
For the MiniMax-M3 model, the thinking (or reasoning) capability can be controlled via the API to be enabled or disabled. Documentation from different integration paths (OpenAI SDK vs. Anthropic SDK) provides slightly different phrasing regarding defaults and parameter names, but the underlying functionality is consistent [1][2]. Thinking/Reasoning Control for MiniMax-M3: - To disable thinking: Set the parameter thinking: {"type": "disabled"} in the extra_body (for OpenAI SDK) [1] or the thinking field (for Anthropic SDK) [2]. When disabled, the model skips thinking and provides a direct response [1][2]. - To enable thinking: Set thinking: {"type": "adaptive"} [1][2]. - Defaults: Depending on the specific API documentation page, the default behavior for MiniMax-M3 is stated as either "on by default" [1] or "off by default" [2]. Given this, it is recommended to explicitly set the thinking parameter to your desired state to ensure consistent behavior [1][2]. - Alternative Reasoning Parameter: In some contexts, particularly the Responses API, the capability is controlled via a reasoning field [3]. Setting reasoning: {"effort": "none"} disables reasoning output [3]. Values such as minimal, low, medium, or high enable it [3]. Important Considerations: - M2.x models: Thinking cannot be disabled for M2.x models; even if thinking: {"type": "disabled"} is passed, thinking remains active [1][2][3]. - Message History: When using Interleaved Thinking, it is critical to preserve the entire response message—including reasoning_content or reasoning_details—in the message history for subsequent turns to ensure the model maintains optimal performance [4]. For developers, it is highly recommended to review the specific API documentation relevant to your SDK (e.g., OpenAI vs. Anthropic vs. Responses API) as parameter keys can vary slightly between these implementations [1][2][3].
Citations:
- 1: https://platform.minimax.io/docs/api-reference/text-openai-api
- 2: https://platform.minimax.io/docs/api-reference/text-anthropic-api
- 3: https://platform.minimax.io/docs/api-reference/responses-create
- 4: https://platform.minimax.io/docs/guides/text-m3-function-call
🌐 Web query:
site:platform.minimax.io docs/api-reference/text-chat-openai "extra_body" "thinking" "MiniMax-M3"
💡 Result:
When using the MiniMax-M3 model via the OpenAI-compatible Chat Completions API, you can control the model's thinking behavior and output format using the extra_body parameter in your API request [1][2]. Thinking Control The thinking parameter within extra_body allows you to manage whether the model emits thinking content [1]: - {"type": "adaptive"}: Explicitly enables thinking (the default behavior for MiniMax-M3 if the parameter is omitted) [1][3]. - {"type": "disabled"}: Disables thinking content, causing the model to answer directly [1][3]. Output Formatting (reasoning_split) You can use the reasoning_split parameter within extra_body to determine how thinking content is returned [1][4]: - reasoning_split=True: Separates thinking content into distinct fields (reasoning_content and reasoning_details) [1][4]. This is the recommended "Interleaved Thinking" compatible format, which provides a more developer-friendly output [4][5]. - reasoning_split=False: Embeds the model's thinking within the content field, enclosed in tags [4][5]. This format requires manual parsing if you wish to separate the reasoning from the final answer [4]. Important Usage Note If you are implementing multi-turn conversations, it is essential that you preserve the entire response object (including reasoning content or details) and pass it back in the message history for subsequent turns [4][5]. Modifying or removing the thinking content from the history can negatively impact the model's performance and chain-of-thought capabilities [4][5]. Example Usage python client.chat.completions.create( model="MiniMax-M3", messages=[{"role": "user", "content": "Hi, how are you?"}], extra_body={ "thinking": {"type": "adaptive"}, "reasoning_split": True, },)
Citations:
- 1: https://platform.minimax.io/docs/api-reference/text-openai-api
- 2: https://platform.minimax.io/docs/api-reference/text-chat-openai
- 3: https://platform.minimax.io/docs/api-reference/text-anthropic-api
- 4: https://platform.minimax.io/docs/guides/text-m2-function-call
- 5: https://platform.minimax.io/docs/guides/text-m3-function-call
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== callers of build_request_for_protocol =="
rg -n "build_request_for_protocol\s*\(" . --glob '!**/*.pyc' --glob '!docs/**/*' --glob '!**/node_modules/**' | head -n 120
echo "== relevant external_ai_request_helpers_test lines =="
test="$(fd 'external_ai_request_helpers_test\.py$' . | head -n1)"
sed -n '110,155p' "$test"
echo "== behavioral probe: current helper payload for MiniMax JSON request =="
python3 - <<'PY'
import sys
sys.path.insert(0, '.')
from acestep.text_tasks.external_ai_request_helpers import build_request_for_protocol
payload, headers = build_request_for_protocol(
protocol="openai_chat",
provider="minimax",
api_key="test-key",
model="MiniMax-M3",
messages=[{"role": "system", "content": "s"}, {"role": "user", "content": "u"}],
base_url="https://api.minimax.io/v1/chat/completions",
max_tokens=768,
require_json_output=True,
)
def report(k):
print(f"{k}: {k in payload!r} {payload.get(k)!r}")
report("thinking")
report("response_format")
report("stop")
PYRepository: ace-step/ACE-Step-1.5
Length of output: 3354
Disable MiniMax M3 thinking for format JSON requests.
For MiniMax-M3, omitting thinking on the MiniMax endpoint enables adaptive thinking by default. When require_json_output=True for MiniMax, emit thinking: {"type": "disabled" and assert that payload in the MiniMax test as well, not field absence.
📍 Affects 2 files
acestep/text_tasks/external_ai_request_helpers.py#L137-L139(this comment)acestep/text_tasks/external_ai_request_helpers_test.py#L130-L146
🤖 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 `@acestep/text_tasks/external_ai_request_helpers.py` around lines 137 - 139,
Update the JSON-output payload branch in the request helper to add MiniMax’s
disabled-thinking setting when provider is "minimax", using thinking {"type":
"disabled"} while preserving the existing response_format and stop fields. In
acestep/text_tasks/external_ai_request_helpers_test.py lines 130-146, update the
MiniMax assertion to require this thinking payload rather than asserting the
field is absent.
Source: MCP tools
| "minimax_anthropic": ExternalProviderProfile( | ||
| provider_id="minimax_anthropic", | ||
| label="MiniMax (Anthropic API)", | ||
| protocol="anthropic_messages", | ||
| default_model="MiniMax-M3", | ||
| default_base_url="https://api.minimax.io/anthropic/v1/messages", | ||
| api_key_env="ACESTEP_MINIMAX_API_KEY", | ||
| api_key_required=True, | ||
| secret_path_env="ACESTEP_MINIMAX_SECRET_PATH", | ||
| secret_file_name="minimax_api_key.enc", | ||
| base_url_presets=( | ||
| ("Global Anthropic messages", "https://api.minimax.io/anthropic/v1/messages"), | ||
| ("Mainland China Anthropic messages", "https://api.minimaxi.com/anthropic/v1/messages"), | ||
| ), | ||
| ), |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== locate files =="
git ls-files | rg 'acestep/text_tasks/(external_lm_providers|external_ai_request_helpers)\.py$|external_lm_providers\.py|external_ai_request_helpers\.py' || true
echo "== file line counts =="
wc -l acestep/text_tasks/external_lm_providers.py acestep/text_tasks/external_ai_request_helpers.py
echo "== relevant provider lines =="
sed -n '1,130p' acestep/text_tasks/external_lm_providers.py
echo "== relevant helper lines =="
sed -n '1,220p' acestep/text_tasks/external_ai_request_helpers.py
echo "== search provider/auth references =="
rg -n "minimax_anthropic|anthropic_messages|x-api-key|Authorization: Bearer|ACESTEP_MINIMAX_MINIMAX|secret_path_env|ExternalProviderProfile" acestep/text_tasks acestep || trueRepository: ace-step/ACE-Step-1.5
Length of output: 20967
🌐 Web query:
MiniMax Anthropic API authorization header x-api-key Authorization Bearer platform.minimax.io
💡 Result:
To authenticate with the MiniMax API—including its Anthropic-compatible endpoints—you must use the HTTP Authorization header with the Bearer authentication scheme [1][2][3]. The correct header format is: Authorization: Bearer YOUR_API_KEY While some services and SDKs (such as those designed for Anthropic's native API) default to the x-api-key header, MiniMax endpoints explicitly require the Authorization header [4][5][6]. Using x-api-key may result in authentication errors (such as HTTP 401 or system error 1033) even when accessing Anthropic-compatible routes [4][5][6]. If both headers are provided, the Authorization header takes precedence [3]. Key implementation details: - Base URL: For Anthropic-compatible requests, the base URL is typically https://api.minimax.io/anthropic/v1 [4][7]. - Header requirement: Always use Authorization: Bearer <API_KEY> [8][3][5]. Ensure there is a single space between the word Bearer and your API key [7][9]. - Account Keys: Ensure you are using the correct key (Pay-as-you-go API key or Subscription Key) as obtained from your MiniMax account management portal [7][10][11]. These keys are not always interchangeable depending on the billing model [11].
Citations:
- 1: https://platform.minimax.io/docs/api-reference/text-post
- 2: https://platform.minimax.io/docs/api-reference/text-chat-openai
- 3: https://platform.minimax.io/docs/api-reference/text-chat-anthropic
- 4: MiniMax providers: @ai-sdk/anthropic sends x-api-key but MiniMax requires Authorization: Bearer anomalyco/models.dev#1398
- 5: CN auth header incompatibility: mmx text chat fails with 1033 via x-api-key, succeeds with Authorization Bearer MiniMax-AI/cli#59
- 6: MiniMax provider 401 error: requires Authorization header for Anthropic-compatible endpoint gsd-build/gsd-2#3783
- 7: https://platform.minimax.io/docs/token-plan/other-tools
- 8: https://api.treerouter.ai/en/blog/minimax-api-auth-sdk-troubleshooting
- 9: Provider Auth: MiniMax/XAI require Bearer prefix in Authorization header openclaw/openclaw#29095
- 10: https://platform.minimax.io/docs/api-reference/api-overview
- 11: https://platform.minimax.io/docs/token-plan/faq
🌐 Web query:
site:platform.minimax.io/docs/api-reference/text-post HTTP authorization header x-api-key
💡 Result:
The x-api-key header is a commonly used custom HTTP header for transmitting API keys, but it is not a formal or IANA-registered standard. While many web services implement it as a mechanism for authentication or authorization, it is considered a non-standard practice. In contrast, the official HTTP Authorization header is the standard mechanism for providing authentication credentials, typically using schemes like Bearer or Basic. Using the Authorization header with a custom scheme or standard token format is generally preferred for interoperability and adherence to HTTP specifications over custom headers like x-api-key. Developers often choose x-api-key for its simplicity in implementation or to bypass specific intermediary requirements, but it lacks the universal support and security semantics defined for the Authorization header.
Citations:
Use MiniMax’s documented Authorization: Bearer header for the MiniMax Anthropic profile.
minimax_anthropic uses the anthropic_messages protocol, but the shared Anthropic request builder only sends x-api-key, while MiniMax Anthropic-compatible endpoints require Authorization: Bearer <API_KEY>. Add provider-specific auth handling for this profile and test that the generated headers match MiniMax’s requirement.
🧰 Tools
🪛 Ruff (0.16.0)
[error] 79-79: Possible hardcoded password assigned to argument: "secret_path_env"
(S106)
[error] 80-80: Possible hardcoded password assigned to argument: "secret_file_name"
(S106)
🤖 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 `@acestep/text_tasks/external_lm_providers.py` around lines 71 - 85, Update the
authentication handling used by the minimax_anthropic ExternalProviderProfile so
requests to its Anthropic-compatible endpoints send Authorization: Bearer with
the API key instead of relying on the shared x-api-key behavior. Add
provider-specific handling keyed to minimax_anthropic, and add coverage
verifying the generated headers use the required Bearer authorization.
Source: MCP tools
Reason: The external LM provider registry did not include MiniMax, so users could not select it for captioning, lyrics, or planning tasks.
What changed
Adds MiniMax to the external LM provider registry (
acestep/text_tasks/external_lm_providers.py), following the existing provider-profile pattern:minimax) — OpenAI Chat protocol, default modelMiniMax-M3, default endpointhttps://api.minimax.io/v1/chat/completions.minimax_anthropic) — Anthropic Messages protocol, default modelMiniMax-M3, default endpointhttps://api.minimax.io/anthropic/v1/messages.Both options are exposed in the provider picker via
get_external_provider_choices()and share theACESTEP_MINIMAX_API_KEYcredential. Each profile ships base-URL presets for both the global (api.minimax.io) and Mainland China (api.minimaxi.com) hosts, so users can switch regions from the picker.The OpenAI-compatible MiniMax option is added to the JSON-output allowlist in
build_request_for_protocolso format-mode planning requests receiveresponse_format: {"type": "json_object"}, matching the other OpenAI-compatible providers..env.exampledocuments the newACESTEP_MINIMAX_API_KEYvariable and the regional base URLs.Tests
New unit tests cover the two provider profiles, the regional base-URL presets, picker exposure, the model-choice default, and the OpenAI-compatible JSON-output request path.
Checks
ruff checkon the changed source and test files — passed.python -m unittest acestep.text_tasks.external_lm_providers_test acestep.text_tasks.external_ai_request_helpers_test acestep.text_tasks.external_lm_runtime_store_test acestep.text_tasks.external_lm_model_discovery_test— 29 tests passed.Summary by CodeRabbit