Skip to content

fix(tools): accept JSON-encoded messages in send_message_to_user - #10709

Open
rudycelekli wants to merge 2 commits into
AstrBotDevs:masterfrom
rudycelekli:fix/send-message-json-string-messages
Open

rudycelekli wants to merge 2 commits into
AstrBotDevs:masterfrom
rudycelekli:fix/send-message-json-string-messages

Conversation

@rudycelekli

@rudycelekli rudycelekli commented Oct 23, 2026 •

Copy link
Copy Markdown

Fixes #7961

Some models (reported with MiniMax, also seen with other OpenAI-compatible providers) send the messages argument of send_message_to_user as a JSON-encoded string instead of an array, typically when the text is long and multi-line:

{'messages': '[{"type": "plain", "text": "...\\n\\n..."}]'}

SendMessageToUserTool.call() only accepted a list, so it returned error: messages parameter is empty or invalid.. The model then had to retry, and in cron jobs the first delivery attempt failed.

Modifications / 改动点

  • astrbot/core/tools/message_tools.py: when messages is a string, try json.loads before validating. If the string is not valid JSON, the existing error is returned unchanged. The decoded value goes through the same per-item validation as before.

  • tests/unit/test_message_tools.py: one test for a JSON-encoded string containing newlines and escaped quotes, and one test showing that a non-JSON string is still rejected without sending anything.

  • This is NOT a breaking change. / 这不是一个破坏性变更。

Screenshots or Test Results / 运行截图或测试结果

$ uv run pytest tests/unit/test_message_tools.py -q
42 passed

ruff format / ruff check pass.


Checklist / 检查清单

  • 😊 If there are new features added in the PR, I have discussed it with the authors through issues/emails, etc. / 如果 PR 中有新加入的功能,已经通过 Issue / 邮件等方式和作者讨论过。
  • 👀 My changes have been well-tested, and "Verification Steps" and "Screenshots" have been provided above. / 我的更改经过了良好的测试,并已在上方提供了“验证步骤”和“运行截图”。
  • 📚 No WebUI navigation, page structure or labels changed, so no documentation update is needed. / 未改动 WebUI 入口、页面结构或术语,无需更新文档。
  • 🤓 I have ensured that no new dependencies are introduced. / 我确保没有引入新依赖库。
  • 😮 My changes do not introduce malicious code. / 我的更改没有引入恶意代码。

Summary by Sourcery

Accept JSON-encoded message arrays in send_message_to_user while preserving validation for invalid input.

Bug Fixes:

  • Allow send_message_to_user to accept JSON-encoded message arrays from compatible models, including long multi-line content.
  • Continue rejecting malformed, resource-limit-exceeding, and non-JSON message strings without sending a message.

Tests:

  • Add coverage for decoding escaped JSON message content and safely rejecting invalid or resource-intensive inputs.

Review follow-up (2026-10-26)

Fixed decoder boundary handling: catch ValueError (which includes JSONDecodeError) and RecursionError, letting both reach the existing invalid-messages return before component construction or sending. Added actual deeply nested JSON and oversized integer inputs, with assertions that no message send occurs. Before: 2 failed / 42 passed; after: all 44 tests in tests/unit/test_message_tools.py pass. Whole-repository Ruff lint/format checks pass. Local Python 3.13.5 validation; hosted Python 3.12 CI remains separate. No live message delivery.

Co-authored-by: Cursor <cursoragent@cursor.com>

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

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="astrbot/core/tools/message_tools.py" line_range="227-228" />
<code_context>
+            # Some models send the array as a JSON-encoded string, especially
+            # for long multi-line text.
+            try:
+                messages = json.loads(messages)
+            except json.JSONDecodeError:
+                pass
         if not isinstance(messages, list) or not messages:
</code_context>
<issue_to_address>
**Invalid messages raise exceptions**

When the JSON string exceeds Python’s nesting or integer-conversion limits, `json.loads(messages)` raises `RecursionError` or `ValueError`, which the `JSONDecodeError` handler does not catch. `call_local_llm_tool` propagates the exception instead of returning the invalid-messages error.

Catch `RecursionError` and `ValueError` alongside `JSONDecodeError` so these inputs reach the existing invalid-messages check.
</issue_to_address>

Sourcery assessment

Needs a human reviewer. 1 finding to address first, and a JSON-encoded array now reaches the existing send flow, so if it is decoded into the wrong content, a message may be sent to the session and cannot be recalled by reverting. Reverting stops future sends through this path but does not undo messages already delivered.

Blocking findings: astrbot/core/tools/message_tools.py:228


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread astrbot/core/tools/message_tools.py Outdated

This branch has not been deployed

No deployments
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.

[Bug]CronJob 中 send_message_to_user 长文本参数序列化失败

1 participant