Skip to content

feat: add MiniMax provider with M3 as default - #185

Open
octo-patch wants to merge 1 commit into
memovai:mainfrom
octo-patch:feature/upgrade-minimax-m3
Open

feat: add MiniMax provider with M3 as default#185
octo-patch wants to merge 1 commit into
memovai:mainfrom
octo-patch:feature/upgrade-minimax-m3

Conversation

@octo-patch

@octo-patch octo-patch commented Jun 2, 2026

Copy link
Copy Markdown

Summary

Add a third LLM provider option — minimax — alongside the existing
anthropic and openai choices, with MiniMax-M3 as the default model.

MimiClaw previously had no MiniMax integration at all. This PR adds one by
treating MiniMax as OpenAI-compatible (it exposes
https://api.minimax.io/v1/chat/completions with the standard Bearer
auth scheme), and routing the request/response through the existing
OpenAI codepaths.

Changes

  • New provider constant MIMI_MINIMAX_API_URL in main/mimi_config.h,
    plus MIMI_MINIMAX_DEFAULT_MODEL (MiniMax-M3),
    MIMI_MINIMAX_MODEL_M27 (MiniMax-M2.7),
    MIMI_MINIMAX_MODEL_M27_HS (MiniMax-M2.7-highspeed).
  • New provider_is_minimax() + provider_is_openai_compat() helpers
    in main/llm/llm_proxy.c. Every existing OpenAI branch in llm_proxy.c
    (auth header, request body field name, message conversion, tool-use
    response parsing) now uses the _compat predicate so MiniMax flows
    through the same code without duplicating it.
  • Web onboarding (main/onboard/onboard_html.h) — adds a
    minimax option to the provider dropdown.
  • Serial CLI (main/cli/serial_cli.c) — updates the
    set_model_provider help text to include minimax.
  • mimi_secrets.h.example — documents the three new model IDs and
    shows how to switch to MiniMax from the serial CLI.
  • EN / CN / JA READMEs — updated so the provider list, secrets block,
    and CLI example all reflect the new minimax option.

The default provider is still anthropic (no behavior change for existing
users); MiniMax is opt-in.

Why MiniMax

  • MiniMax-M3 is the current generation model: 512K context, up to 128K
    output, image input support, OpenAI-compatible API — a natural fit for
    MimiClaw's existing OpenAI codepath with no extra protocol layer.
  • Keeps the previous generation (MiniMax-M2.7 / M2.7-highspeed)
    available as a drop-in alternative.

Testing

  • Verified provider routing with a stand-alone C harness that mocks the
    ESP-IDF dependencies and asserts:
    • provider=anthropicMIMI_LLM_API_URL
    • provider=openaiMIMI_OPENAI_API_URL
    • provider=minimaxMIMI_MINIMAX_API_URL
    • provider_is_openai_compat() is true for openai and minimax,
      false for anthropic.
  • Full idf.py build requires the ESP-IDF v5.5+ toolchain (not available
    in this environment); the project's CI workflow
    (.github/workflows/build.yml) will exercise the real build.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added MiniMax LLM provider support with multiple model options (M3 default, M2.7, M2.7-highspeed) selectable via CLI and configuration.
  • Documentation

    • Updated setup guides and CLI documentation to include MiniMax provider configuration and runtime model switching instructions.

- Add `minimax` as a new LLM provider alongside `anthropic` and `openai`
  (MiniMax is OpenAI-compatible, so the existing OpenAI codepaths now also
  serve it via a new provider_is_openai_compat() helper)
- Default MiniMax model is `MiniMax-M3` (current generation);
  `MiniMax-M2.7` and `MiniMax-M2.7-highspeed` are exposed as alternatives
- New constants in mimi_config.h: MIMI_MINIMAX_API_URL,
  MIMI_MINIMAX_DEFAULT_MODEL, MIMI_MINIMAX_MODEL_M27, MIMI_MINIMAX_MODEL_M27_HS
- Update CLI help, web onboarding provider dropdown, secrets example,
  and EN/CN/JA READMEs
@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds MiniMax as a supported LLM provider by defining its configuration constants, treating it as OpenAI-compatible in the request/response proxy layer, and exposing provider selection through CLI, web UI, and documentation in three languages.

Changes

MiniMax LLM Provider Support

Layer / File(s) Summary
MiniMax configuration and constants
main/mimi_config.h, main/mimi_secrets.h.example
Adds MIMI_MINIMAX_API_URL, MIMI_MINIMAX_DEFAULT_MODEL (M3), and alternative M2.7 model variants. Includes example documentation of configuration parameters and MiniMax API key setup.
LLM proxy OpenAI-compatibility handling
main/llm/llm_proxy.c
Introduces helper functions provider_is_minimax() and provider_is_openai_compat() to detect MiniMax and route it through OpenAI-compatible paths. Updates request building (URL/host/path), authorization header selection (Bearer token), max token parameter naming (max_completion_tokens vs. max_tokens), and response JSON schema parsing across direct HTTP and proxy CONNECT-tunnel modes.
User-facing provider selection and documentation
main/cli/serial_cli.c, main/onboard/onboard_html.h, README.md, README_CN.md, README_JA.md
Extends set_model_provider CLI help text, web UI provider dropdown, and multi-language README setup/configuration/CLI sections to include MiniMax with example models and runtime switching commands.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A rabbit hops through three new doors,
Where MiniMax joins the provider floors,
With OpenAI's compatible dance,
Config, proxy, docs—all in one glance! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly and concisely summarizes the main change: adding MiniMax provider support with M3 as the default model.
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 unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Infer (1.2.0)
main/llm/llm_proxy.c

In file included from main/llm/llm_proxy.c:1:
main/llm/llm_proxy.h:3:10: fatal error: 'esp_err.h' file not found
3 | #include "esp_err.h"
| ^~~~~~~~~~~
1 error generated.
Error: the following clang command did not run successfully:
/opt/infer-linux-x86_64-v1.2.0/lib/infer/facebook-clang-plugins/clang/install/bin/clang-18
@/tmp/coderabbit-infer/9f46eaee4a83ae0ca1fd62e6ee110b9dcfaab9dd-535e704b09b3f33f/tmp/clang_command_.tmp.8203e4.txt
++Contents of '/tmp/coderabbit-infer/9f46eaee4a83ae0ca1fd62e6ee110b9dcfaab9dd-535e704b09b3f33f/tmp/clang_command_.tmp.8203e4.txt':
"-cc1" "-load"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../../facebook-clang-plugins/libtooling/build/FacebookClangPlugin.dylib"
"-add-plugin" "BiniouASTExporter" "-plugin-arg-BiniouASTExporter" "-"
"-plugin-arg-BiniouASTExporter" "PREPEND_CURRENT_DIR=1"
"-plugin-arg-BiniouASTExporter" "MAX_STRING_SIZE=65535" "-cc1" "-triple"
"x86_64-unknown-linux-gnu" "-emit-obj"

... [truncated 729 characters] ...

pt/infer-linux-x86_64-v1.2.0/lib/infer/facebook-clang-plugins/clang/install/lib/clang/18/include"
"-internal-isystem" "/usr/local/include" "-internal-isystem"
"/usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include"
"-internal-externc-isystem" "/usr/include/x86_64-linux-gnu"
"-internal-externc-isystem" "/include" "-internal-externc-isystem"
"/usr/include" "-Wno-ignored-optimization-argument" "-Wno-everything"
"-ferror-limit" "19" "-fgnuc-version=4.2.1" "-fskip-odr-check-in-gmf"
"-D__GCC_HAVE_DWARF2_CFI_ASM=1" "-o"
"/tmp/coderabbit-infer/535e704b09b3f33f/file.o" "-x" "c"
"main/llm/llm_proxy.c" "-O0" "-fno-builtin" "-include"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../lib/clang_wrappers/global_defines.h"
"-Wno-everything"

main/cli/serial_cli.c

In file included from main/cli/serial_cli.c:1:
main/cli/serial_cli.h:3:10: fatal error: 'esp_err.h' file not found
3 | #include "esp_err.h"
| ^~~~~~~~~~~
1 error generated.
Error: the following clang command did not run successfully:
/opt/infer-linux-x86_64-v1.2.0/lib/infer/facebook-clang-plugins/clang/install/bin/clang-18
@/tmp/coderabbit-infer/9f46eaee4a83ae0ca1fd62e6ee110b9dcfaab9dd-5a218abb37b1ffdf/tmp/clang_command_.tmp.7cb867.txt
++Contents of '/tmp/coderabbit-infer/9f46eaee4a83ae0ca1fd62e6ee110b9dcfaab9dd-5a218abb37b1ffdf/tmp/clang_command_.tmp.7cb867.txt':
"-cc1" "-load"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../../facebook-clang-plugins/libtooling/build/FacebookClangPlugin.dylib"
"-add-plugin" "BiniouASTExporter" "-plugin-arg-BiniouASTExporter" "-"
"-plugin-arg-BiniouASTExporter" "PREPEND_CURRENT_DIR=1"
"-plugin-arg-BiniouASTExporter" "MAX_STRING_SIZE=65535" "-cc1" "-triple"
"x86_64-unknown-linux-gnu" "-emit-obj

... [truncated 733 characters] ...

t/infer-linux-x86_64-v1.2.0/lib/infer/facebook-clang-plugins/clang/install/lib/clang/18/include"
"-internal-isystem" "/usr/local/include" "-internal-isystem"
"/usr/lib/gcc/x86_64-linux-gnu/12/../../../../x86_64-linux-gnu/include"
"-internal-externc-isystem" "/usr/include/x86_64-linux-gnu"
"-internal-externc-isystem" "/include" "-internal-externc-isystem"
"/usr/include" "-Wno-ignored-optimization-argument" "-Wno-everything"
"-ferror-limit" "19" "-fgnuc-version=4.2.1" "-fskip-odr-check-in-gmf"
"-D__GCC_HAVE_DWARF2_CFI_ASM=1" "-o"
"/tmp/coderabbit-infer/5a218abb37b1ffdf/file.o" "-x" "c"
"main/cli/serial_cli.c" "-O0" "-fno-builtin" "-include"
"/opt/infer-linux-x86_64-v1.2.0/lib/infer/infer/bin/../lib/clang_wrappers/global_defines.h"
"-Wno-everything"


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 and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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)
main/llm/llm_proxy.c (1)

315-334: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Validate snprintf result before writing proxy headers to avoid OOB read.

Line 316/325 assigns hlen = snprintf(...), but Line 336 writes hlen bytes even when snprintf truncates (hlen >= sizeof(header)). That can read past header bounds.

Proposed fix
-    if (provider_is_openai_compat()) {
-        hlen = snprintf(header, sizeof(header),
+    if (provider_is_openai_compat()) {
+        hlen = snprintf(header, sizeof(header),
             "POST %s HTTP/1.1\r\n"
             "Host: %s\r\n"
             "Content-Type: application/json\r\n"
             "Authorization: Bearer %s\r\n"
             "Content-Length: %d\r\n"
             "Connection: close\r\n\r\n",
             llm_api_path(), llm_api_host(), s_api_key, body_len);
     } else {
         hlen = snprintf(header, sizeof(header),
             "POST %s HTTP/1.1\r\n"
             "Host: %s\r\n"
             "Content-Type: application/json\r\n"
             "x-api-key: %s\r\n"
             "anthropic-version: %s\r\n"
             "Content-Length: %d\r\n"
             "Connection: close\r\n\r\n",
             llm_api_path(), llm_api_host(), s_api_key, MIMI_LLM_API_VERSION, body_len);
     }
+    if (hlen < 0 || hlen >= (int)sizeof(header)) {
+        proxy_conn_close(conn);
+        return ESP_ERR_INVALID_SIZE;
+    }
🤖 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 `@main/llm/llm_proxy.c` around lines 315 - 334, snprintf() return (hlen) must
be validated before using it to write header bytes: check if hlen < 0 or hlen >=
sizeof(header) and handle as an error (or clamp) instead of blindly writing hlen
bytes; update the code around the header construction (the two snprintf calls
that set hlen and the subsequent write that uses hlen) to detect truncation or
failures and either fail gracefully or set hlen = sizeof(header)-1 after
ensuring header is NUL-terminated so you never read/write past the header
buffer.
🤖 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 `@main/llm/llm_proxy.c`:
- Around line 315-334: snprintf() return (hlen) must be validated before using
it to write header bytes: check if hlen < 0 or hlen >= sizeof(header) and handle
as an error (or clamp) instead of blindly writing hlen bytes; update the code
around the header construction (the two snprintf calls that set hlen and the
subsequent write that uses hlen) to detect truncation or failures and either
fail gracefully or set hlen = sizeof(header)-1 after ensuring header is
NUL-terminated so you never read/write past the header buffer.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dad8f194-91d4-4ac1-baf9-ada16d54c63c

📥 Commits

Reviewing files that changed from the base of the PR and between bb10ea0 and 9f46eae.

📒 Files selected for processing (8)
  • README.md
  • README_CN.md
  • README_JA.md
  • main/cli/serial_cli.c
  • main/llm/llm_proxy.c
  • main/mimi_config.h
  • main/mimi_secrets.h.example
  • main/onboard/onboard_html.h

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