From 6b9bd4d5f255453042bf95096802874dea555ccc Mon Sep 17 00:00:00 2001 From: n1majne3 Date: Mon, 4 May 2026 10:49:18 +0800 Subject: [PATCH] Fix MiniMax tool calling (#456) Co-authored-by: n1majne3 <24203125+n1majne3@users.noreply.github.com> --- strix/llm/llm.py | 6 ++++-- strix/llm/utils.py | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/strix/llm/llm.py b/strix/llm/llm.py index e500d80..6fd727d 100644 --- a/strix/llm/llm.py +++ b/strix/llm/llm.py @@ -26,8 +26,10 @@ from strix.utils.resource_paths import get_strix_resource_path litellm.drop_params = True litellm.modify_params = True -_THINKING_BLOCK_RE = re.compile(r"]*>.*?", re.DOTALL) -_THINKING_BLOCK_OR_OPEN_RE = re.compile(r"]*>.*?(?:|\Z)", re.DOTALL) +_THINKING_BLOCK_RE = re.compile(r"]*>.*?", re.DOTALL) +_THINKING_BLOCK_OR_OPEN_RE = re.compile( + r"]*>.*?(?:|\Z)", re.DOTALL +) def _find_end_tag_outside_thinking(content: str, end_tag: str) -> int: diff --git a/strix/llm/utils.py b/strix/llm/utils.py index 0f56bed..8b3e4cd 100644 --- a/strix/llm/utils.py +++ b/strix/llm/utils.py @@ -1,4 +1,5 @@ import html +import json import re from typing import Any @@ -6,6 +7,7 @@ from typing import Any _INVOKE_OPEN = re.compile(r'') _PARAM_NAME_ATTR = re.compile(r'') _FUNCTION_CALLS_TAG = re.compile(r"") +_MINIMAX_TOOL_CALL_TAG = re.compile(r"") _STRIP_TAG_QUOTES = re.compile(r"<(function|parameter)\s*=\s*([^>]*?)>") @@ -13,6 +15,7 @@ def normalize_tool_format(content: str) -> str: """Convert alternative tool-call XML formats to the expected one. Handles: + ... → stripped ... → stripped @@ -20,6 +23,8 @@ def normalize_tool_format(content: str) -> str: """ + content = _MINIMAX_TOOL_CALL_TAG.sub("", content) + if ( " list[dict[str, Any]] | None: param_value = html.unescape(param_value) args[param_name] = param_value + if not args: + body_stripped = html.unescape(fn_body.strip()) + if body_stripped.startswith("{"): + try: + parsed = json.loads(body_stripped) + if isinstance(parsed, dict): + args = { + k: v if isinstance(v, str) else json.dumps(v) + for k, v in parsed.items() + } + except (json.JSONDecodeError, ValueError): + pass + tool_invocations.append({"toolName": fn_name, "args": args}) return tool_invocations if tool_invocations else None