Skip to content

feat(text_tasks): add MiniMax to external LM provider registry - #1279

Open
octo-patch wants to merge 1 commit into
ace-step:mainfrom
octo-patch:octo/20260729-provider-add-recvq9lqXzql1G
Open

feat(text_tasks): add MiniMax to external LM provider registry#1279
octo-patch wants to merge 1 commit into
ace-step:mainfrom
octo-patch:octo/20260729-provider-add-recvq9lqXzql1G

Conversation

@octo-patch

@octo-patch octo-patch commented Jul 29, 2026

Copy link
Copy Markdown

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 (minimax) — OpenAI Chat protocol, default model MiniMax-M3, default endpoint https://api.minimax.io/v1/chat/completions.
  • MiniMax (Anthropic API) (minimax_anthropic) — Anthropic Messages protocol, default model MiniMax-M3, default endpoint https://api.minimax.io/anthropic/v1/messages.

Both options are exposed in the provider picker via get_external_provider_choices() and share the ACESTEP_MINIMAX_API_KEY credential. 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_protocol so format-mode planning requests receive response_format: {"type": "json_object"}, matching the other OpenAI-compatible providers.

.env.example documents the new ACESTEP_MINIMAX_API_KEY variable 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 check on 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

  • New Features
    • Added MiniMax as an external language model provider, including OpenAI-compatible and Anthropic-compatible options.
    • Added support for selecting MiniMax models and regional API endpoints.
    • Added configuration guidance for MiniMax API authentication and custom base URLs.
  • Bug Fixes
    • Enabled structured JSON responses when using MiniMax through compatible chat integrations.

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

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

MiniMax 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.

Changes

MiniMax external LM integration

Layer / File(s) Summary
MiniMax provider profiles and configuration
.env.example, acestep/text_tasks/external_lm_providers.py, acestep/text_tasks/external_lm_providers_test.py
Adds MiniMax provider profiles, API key settings, base URL presets, picker ordering, default models, and helper tests.
MiniMax JSON request formatting
acestep/text_tasks/external_ai_request_helpers.py, acestep/text_tasks/external_ai_request_helpers_test.py
Enables JSON-object response formatting and stop-sequence settings for MiniMax OpenAI-compatible requests and tests the generated payload.

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

A rabbit hops through config bright,
MiniMax joins the provider flight.
JSON curls into a tidy square,
With URLs and models neatly there.
Tests thump softly: all is right!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding MiniMax support to the external LM provider registry.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

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

@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: 2

🧹 Nitpick comments (1)
acestep/text_tasks/external_lm_providers_test.py (1)

67-74: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Assert 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

📥 Commits

Reviewing files that changed from the base of the PR and between 6d467e4 and 7e616bf.

📒 Files selected for processing (5)
  • .env.example
  • acestep/text_tasks/external_ai_request_helpers.py
  • acestep/text_tasks/external_ai_request_helpers_test.py
  • acestep/text_tasks/external_lm_providers.py
  • acestep/text_tasks/external_lm_providers_test.py

Comment on lines +137 to 139
if require_json_output and provider in {"minimax", "openai", "zai"}:
payload["response_format"] = {"type": "json_object"}
payload["stop"] = ["```"]

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.

🎯 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:


🌐 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:


🌐 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:


🌐 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:


🏁 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")
PY

Repository: 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

Comment on lines +71 to +85
"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"),
),
),

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.

🗄️ 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 || true

Repository: 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:


🌐 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

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