Skip to content

feat(tool_parser,reasoning_parser): add MiniMax-M3 tool and reasoning parsers#1815

Open
slin1237 wants to merge 1 commit into
mainfrom
feat/minimax-m3-parser
Open

feat(tool_parser,reasoning_parser): add MiniMax-M3 tool and reasoning parsers#1815
slin1237 wants to merge 1 commit into
mainfrom
feat/minimax-m3-parser

Conversation

@slin1237

@slin1237 slin1237 commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Description

Problem

SMG has no parser for MiniMax-M3, so M3 tool calls and <mm:think> reasoning content are not extracted.

Solution

Add MiniMax-M3 tool and reasoning parsers and register them so M3 model IDs route to them — ordered ahead of the broad MiniMax/M2 patterns so M3 IDs aren't captured by the M2 parser.

Changes

  • Tool parser (crates/tool_parser/src/parsers/minimax_m3.rs): M3 namespaced framing (]<]minimax[>[ before each structural tag), recursive parameter elements (nested objects/arrays), schema-type coercion with JSON-type inference fallback, XML entity decoding, mixed-text preservation, and streaming (block-level invoke emission with partial-token hold-back via longest_partial_suffix).
  • Reasoning parser (crates/reasoning_parser/src/parsers/minimax_m3.rs): <mm:think> / </mm:think> delimiters via BaseReasoningParser (always_in_reasoning=false).
  • Registration: both factories register minimax_m3 and route minimax-m3 / MiniMax-M3* / mm-m3 to it, before the broad minimax (M2) match.

Test Plan

  • cargo +nightly fmt --all — clean
  • cargo clippy -p tool-parser -p reasoning-parser --all-targets -- -D warnings — clean (default features)
  • cargo test -p tool-parser -p reasoning-parser — all pass, incl. the new tool_parser_minimax_m3 suite (30 cases: single/multiple/parallel calls, streaming at chunk and char boundaries, nested objects/arrays, schema coercion, XML entities, malformed/incomplete input, reset) and the reasoning-parser unit tests.
Checklist
  • cargo +nightly fmt passes
  • cargo clippy --all-targets -- -D warnings passes (parser crates; default features — workspace --all-features pulls opencv, unrelated)
  • (Optional) Documentation updated

Summary by CodeRabbit

  • New Features

    • Added support for MiniMax M3 model with complete reasoning and tool-call parsing capabilities
    • Automatic intelligent routing for MiniMax M3 model variants (minimax-m3, mm-m3)
  • Tests

    • Added comprehensive test coverage validating MiniMax M3 reasoning and tool parsing across multiple scenarios

… parsers

Tool parser handles M3's namespaced framing (`]<]minimax[>[` prefix before each
structural tag), recursive parameter elements (objects/arrays), schema-type
coercion, XML entity decoding, and streaming. Reasoning parser uses the
`<mm:think>`/`</mm:think>` delimiters. Both register M3 model patterns ahead of
the broad `minimax` (M2) match so M3 IDs are not captured by the M2 parser.

Signed-off-by: Simo Lin <linsimo.mark@gmail.com>
@slin1237 slin1237 requested a review from CatherineSue as a code owner June 22, 2026 12:24
@github-actions github-actions Bot added tests Test changes tool-parser Tool/function call parser changes reasoning-parser Reasoning parser changes labels Jun 22, 2026
@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds MinimaxM3Parser to both the reasoning_parser and tool_parser crates. The reasoning parser uses <mm:think> delimiters with always_in_reasoning = false. The tool parser uses namespace-prefixed <tool_call>/<invoke> XML framing with streaming support, schema-driven type coercion, and XML entity decoding. Both parsers are registered in their respective factories with model-pattern routing for minimax-m3 and mm-m3 IDs.

Changes

MiniMax M3 Parser Support

Layer / File(s) Summary
Reasoning parser: MinimaxM3Parser struct and trait impl
crates/reasoning_parser/src/parsers/minimax_m3.rs
Defines MinimaxM3Parser wrapping BaseReasoningParser with <mm:think> delimiters and always_in_reasoning = false, implements Default and ReasoningParser trait delegation, and adds unit tests for extraction, passthrough, streaming, and reset.
Reasoning parser: module wiring, re-exports, and factory registration
crates/reasoning_parser/src/parsers/mod.rs, crates/reasoning_parser/src/lib.rs, crates/reasoning_parser/src/factory.rs
Declares the minimax_m3 submodule and re-exports MinimaxM3Parser, then registers the parser and model-pattern routes (minimax-m3, mm-m3) in the reasoning ParserFactory with a routing test.
Tool parser: MinimaxM3Parser struct, XML parsing utilities, and complete-parse orchestration
crates/tool_parser/src/parsers/minimax_m3.rs (lines 1–396)
Defines the struct with streaming state and M3 marker constants, implements leaf-value coercion, token-boundary suffix matching, XML entity decoding, recursive parameter element parsing, invoke extraction, and the full non-streaming parse path.
Tool parser: ToolParser trait impl and streaming
crates/tool_parser/src/parsers/minimax_m3.rs (lines 397–512)
Implements ToolParser trait: non-streaming methods delegate to the complete parser; parse_incremental buffers chunks, detects markers, emits text vs. ToolCallItems, and manages per-tool streamed argument storage and reset.
Tool parser: module wiring, re-exports, and factory registration
crates/tool_parser/src/parsers/mod.rs, crates/tool_parser/src/lib.rs, crates/tool_parser/src/factory.rs
Declares the minimax_m3 submodule, re-exports MinimaxM3Parser, registers it in ParserFactory::new, and adds M3-specific model-pattern routes ahead of the general minimax* catch-all.
Tool parser: integration test suite
crates/tool_parser/tests/tool_parser_minimax_m3.rs
Full integration tests covering complete and streaming parse, schema-driven typing, nested structures, XML entity decoding, edge cases (malformed markup, many params, Python-style literals, unicode), and streaming robustness against boundary splits and truncated input.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • lightseekorg/smg#901: Adds ParserFactory::list_parsers() to enumerate registered reasoning parser names, which will now include the newly registered minimax_m3 entry.

Suggested labels

tool-parser, reasoning-parser, tests

Suggested reviewers

  • CatherineSue

Poem

🐇 Hoppity-hop, a new parser's in town,
<mm:think> and <tool_call> without a frown!
M3 tags decoded, XML unspooled,
Streaming chunks buffered, type coercion tooled.
The factory now routes with precise flair —
MiniMax M3 parsed beyond compare! 🌟

🚥 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 accurately describes the main changes: adding MiniMax-M3 parsers for both tool and reasoning parsing functionality.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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 feat/minimax-m3-parser

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

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f02fc04d58

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

registry.map_model("minimax*", "minimax_m2");
registry.map_model("MiniMax*", "minimax_m2");
// M3 IDs route to the M3 parser via longer (more specific) patterns.
registry.map_model("minimax-m3*", "minimax_m3");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add the mm-m3 alias to tool parser routing

When the model ID uses the mm-m3 alias, the tool parser factory has no matching prefix and it also does not start with the broader minimax*/MiniMax* patterns, so auto-detection falls back to passthrough and M3 tool-call blocks are never parsed. The reasoning factory in this same change routes mm-m3 to minimax_m3, so add an mm-m3* mapping alongside these M3 tool mappings.

Useful? React with 👍 / 👎.


let mut map: Map<String, Value> = Map::new();
for (name, child) in children {
let child_json = Self::value_to_json(child, None);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve schema types for nested M3 parameters

For nested object/array parameters, child values are always converted with declared_type set to None here, so nested schema information is discarded. In a tool schema such as shipping.zip declared as a string, <zip>00123</zip> will be inferred as number 123 instead of preserving the string; array item fields have the same issue in the array branch above. Pass the nested child/item schema through the recursion to avoid silently corrupting nested tool arguments.

Useful? React with 👍 / 👎.

// M3 IDs route to the M3 parser via longer (more specific) patterns.
registry.map_model("minimax-m3*", "minimax_m3");
registry.map_model("MiniMax-M3*", "minimax_m3");
registry.map_model("MiniMaxAI/MiniMax-M3*", "minimax_m3");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Nit: The reasoning parser registers mm-m3 as a pattern (line 204 of reasoning_parser/src/factory.rs), but there's no corresponding mm-m3* glob here. A model ID like "mm-m3-chat" would get M3 reasoning parsing but fall through to the default (passthrough) tool parser, since none of minimax-m3* / MiniMax-M3* / MiniMaxAI/MiniMax-M3* match the mm- prefix.

This mirrors an existing gap with M2 (mm-m2 in reasoning, no mm-m2* in tool), but the PR could close it for M3:

Suggested change
registry.map_model("MiniMaxAI/MiniMax-M3*", "minimax_m3");
registry.map_model("MiniMaxAI/MiniMax-M3*", "minimax_m3");
registry.map_model("mm-m3*", "minimax_m3");

Comment on lines +409 to +410
// M3 IDs route to the M3 parser via longer (more specific) patterns.
registry.map_model("minimax-m3*", "minimax_m3");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Nit: The reasoning parser factory has test_minimax_m3_model verifying that M3 model IDs (e.g. "MiniMaxAI/MiniMax-M3", "mm-m3-chat") route to the M3 parser and not the broad M2 one. Consider adding an equivalent test for the tool parser factory — the mechanism is different here (longest-glob-wins vs first-substring-wins), so a test would guard against regressions if the patterns are ever reordered.

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

Clean, well-structured PR with thorough test coverage (30 cases for the tool parser, 7 for reasoning). The critical pattern-ordering concern is handled correctly in both factories — reasoning uses first-substring-match with M3 before M2, tool uses longest-glob-wins. Two minor nits posted inline (missing mm-m3* tool parser glob, no factory routing test for tool parser). No bugs found.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces support for the MiniMax M3 model by implementing specific reasoning and tool parsers. In reasoning_parser, a new MinimaxM3Parser is added to handle reasoning blocks enclosed in <mm:think> tags. In tool_parser, a corresponding MinimaxM3Parser is introduced to parse tool calls framed with the ]<]minimax[>[ namespace marker, supporting nested parameters and multiple invokes. Model routing and factory registrations are updated in both crates to correctly map M3 model IDs, and comprehensive unit and integration tests are added to verify the new parsers. There are no review comments to address, and I have no additional feedback to provide.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

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

Actionable comments posted: 1

🤖 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 `@crates/tool_parser/src/factory.rs`:
- Around line 406-412: The `mm-m3*` model pattern is missing from the model
mappings in the registry, which causes mm-m3 IDs to be misrouted away from the
minimax_m3 parser. Add a new registry.map_model call that maps the "mm-m3*"
pattern to "minimax_m3", placing it alongside the existing minimax-m3,
MiniMax-M3, and MiniMaxAI/MiniMax-M3 mappings that are already routed to the M3
parser.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: d796d76d-17e5-4dbf-ba8f-596e95b108d6

📥 Commits

Reviewing files that changed from the base of the PR and between 6c3ce8e and f02fc04.

📒 Files selected for processing (9)
  • crates/reasoning_parser/src/factory.rs
  • crates/reasoning_parser/src/lib.rs
  • crates/reasoning_parser/src/parsers/minimax_m3.rs
  • crates/reasoning_parser/src/parsers/mod.rs
  • crates/tool_parser/src/factory.rs
  • crates/tool_parser/src/lib.rs
  • crates/tool_parser/src/parsers/minimax_m3.rs
  • crates/tool_parser/src/parsers/mod.rs
  • crates/tool_parser/tests/tool_parser_minimax_m3.rs

Comment on lines +406 to +412
// General MiniMax IDs default to the M2 parser.
registry.map_model("minimax*", "minimax_m2");
registry.map_model("MiniMax*", "minimax_m2");
// M3 IDs route to the M3 parser via longer (more specific) patterns.
registry.map_model("minimax-m3*", "minimax_m3");
registry.map_model("MiniMax-M3*", "minimax_m3");
registry.map_model("MiniMaxAI/MiniMax-M3*", "minimax_m3");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add missing mm-m3* model mapping to minimax_m3.

Line 410-Line 412 add M3 routes, but mm-m3* is still not mapped despite the PR contract. That can misroute mm-m3 IDs away from the M3 parser.

Proposed fix
         // M3 IDs route to the M3 parser via longer (more specific) patterns.
         registry.map_model("minimax-m3*", "minimax_m3");
+        registry.map_model("mm-m3*", "minimax_m3");
         registry.map_model("MiniMax-M3*", "minimax_m3");
         registry.map_model("MiniMaxAI/MiniMax-M3*", "minimax_m3");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// General MiniMax IDs default to the M2 parser.
registry.map_model("minimax*", "minimax_m2");
registry.map_model("MiniMax*", "minimax_m2");
// M3 IDs route to the M3 parser via longer (more specific) patterns.
registry.map_model("minimax-m3*", "minimax_m3");
registry.map_model("MiniMax-M3*", "minimax_m3");
registry.map_model("MiniMaxAI/MiniMax-M3*", "minimax_m3");
// General MiniMax IDs default to the M2 parser.
registry.map_model("minimax*", "minimax_m2");
registry.map_model("MiniMax*", "minimax_m2");
// M3 IDs route to the M3 parser via longer (more specific) patterns.
registry.map_model("minimax-m3*", "minimax_m3");
registry.map_model("mm-m3*", "minimax_m3");
registry.map_model("MiniMax-M3*", "minimax_m3");
registry.map_model("MiniMaxAI/MiniMax-M3*", "minimax_m3");
🤖 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 `@crates/tool_parser/src/factory.rs` around lines 406 - 412, The `mm-m3*` model
pattern is missing from the model mappings in the registry, which causes mm-m3
IDs to be misrouted away from the minimax_m3 parser. Add a new
registry.map_model call that maps the "mm-m3*" pattern to "minimax_m3", placing
it alongside the existing minimax-m3, MiniMax-M3, and MiniMaxAI/MiniMax-M3
mappings that are already routed to the M3 parser.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

This pull request has been automatically marked as stale because it has not had any activity within 14 days. It will be automatically closed if no further activity occurs within 16 days. Leave a comment if you feel this pull request should remain open. Thank you!

@github-actions github-actions Bot added the stale PR has been inactive for 14+ days label Jul 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

reasoning-parser Reasoning parser changes stale PR has been inactive for 14+ days tests Test changes tool-parser Tool/function call parser changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant