Skip to content

fix(discord): split messages exceeding Discord's 2000 character limit#1001

Merged
xieyxclack merged 1 commit intoagentscope-ai:mainfrom
Atletico1999:fix/discord-message-chunking
Mar 10, 2026
Merged

fix(discord): split messages exceeding Discord's 2000 character limit#1001
xieyxclack merged 1 commit intoagentscope-ai:mainfrom
Atletico1999:fix/discord-message-chunking

Conversation

@Atletico1999
Copy link
Copy Markdown
Contributor

@Atletico1999 Atletico1999 commented Mar 9, 2026

Description

Discord's API rejects messages longer than 2000 characters. When CoPaw generates a long response (e.g. code blocks, detailed explanations), the send() call fails with 400 Bad Request, leaving the user with no reply.

This PR adds automatic message chunking to DiscordChannel:

  • Adds _DISCORD_MAX_LEN class constant (2000 chars)
  • Adds _chunk_text() static method that splits at newline boundaries to preserve markdown formatting.
  • Fence-aware Chunking: Tracks the open/close state of markdown code fences ( ``` and ~~~) via _FENCE_RE. If a chunk splits in the middle of a code block, it automatically appends a closing fence to the current message and prepends an opening fence to the next message. This ensures code syntax highlighting is never broken across messages.
  • Updated send() to iterate over chunks for both channel and DM targets.

Related Issue: N/A (discovered in production)

Security Considerations: None — only affects outbound message formatting.

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • Refactoring

Component(s) Affected

  • Core / Backend (app, agents, config, providers, utils, local_models)
  • Console (frontend web UI)
  • Channels (DingTalk, Feishu, QQ, Discord, iMessage, etc.)
  • Skills
  • CLI
  • Documentation (website)
  • Tests
  • CI/CD
  • Scripts / Deploy

Checklist

  • I ran pre-commit run --all-files locally and it passes
  • If pre-commit auto-fixed files, I committed those changes and reran checks
  • I ran tests locally (pytest or as relevant) and they pass
  • Documentation updated (if needed)
  • Ready for review

Testing

  1. Connect CoPaw to a Discord server
  2. Ask the bot a question that generates a large code block > 2000 chars (e.g. "write a very long python backend script").
  3. Before fix: Bot fails to reply (400 Bad Request on Discord API).
  4. After fix: Bot replies with sequential messages. If the split happens inside a code block, both messages will render as properly formatted code blocks.

Additional Notes

  • All other Discord features, including access control logic, meta passing, and media sending, remain entirely untouched and pure.
  • The file was rewritten from a clean upstream base to guarantee LF endings and no UTF-16/BOM artifacts.

@github-actions github-actions bot added the first-time-contributor PR created by a first time contributor label Mar 9, 2026
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a critical issue where CoPaw's responses exceeding Discord's 2000-character limit would fail to send. By introducing automatic message chunking, the system can now reliably deliver long responses across multiple messages, ensuring users receive complete information. Additionally, the DiscordChannel class has been simplified by removing deprecated access control and media handling logic, making it more focused on core text communication.

Highlights

  • Discord Message Chunking: Implemented automatic message splitting for Discord messages exceeding the 2000-character limit. Messages are now chunked at newline boundaries to preserve markdown formatting, with a hard-split fallback for single lines that are too long.
  • Simplified DiscordChannel Initialization: Removed dm_policy, group_policy, allow_from, and deny_message parameters from the DiscordChannel constructor and related configuration methods, streamlining the channel's setup.
  • Refactored Message Sending Logic: The send method in DiscordChannel was updated to incorporate the new message chunking logic. The _resolve_target, send_content_parts, and send_media methods were removed, indicating a consolidation or removal of media and complex content part handling within this class.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/copaw/app/channels/discord_/channel.py
    • Removed unused imports for tempfile, pathlib, urllib.parse, and OutgoingContentPart.
    • Removed dm_policy, group_policy, allow_from, and deny_message parameters from the __init__ method.
    • Removed is_group and _check_allowlist logic from the on_message handler.
    • Removed allow_from environment variable parsing and related parameters from the from_env method.
    • Removed dm_policy, group_policy, allow_from, and deny_message parameters from the from_config method.
    • Removed the _resolve_target method, consolidating its logic directly into the send method.
    • Added _DISCORD_MAX_LEN class constant to define Discord's message character limit.
    • Implemented the _chunk_text static method to split long messages into Discord-compliant chunks.
    • Refactored the send method to utilize the new _chunk_text method, iterating and sending multiple messages if necessary.
    • Removed the send_content_parts and send_media methods, simplifying the message sending interface.
    • Updated a comment in the _route_from_handle method for clarity.
Activity
  • Atletico1999 created the pull request to fix Discord message length issues.
  • The author has marked the pull request as ready for review.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Generative AI Prohibited Use Policy, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

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 successfully adds message chunking to prevent errors with long messages on Discord. However, it also introduces two critical regressions by removing major features that don't seem related to the main goal of the PR.
Specifically:

  1. Access Control Removed: The allowlist functionality (dm_policy, group_policy, etc.) has been completely removed, which could expose the bot to unintended users.
  2. Media Sending Broken: The ability to send media files (images, videos, etc.) has been removed, as the send_media method implementation is gone.

These changes are not documented in the PR description and should be addressed.

Additionally, I've found an opportunity to simplify the new _chunk_text method by removing some unreachable code, which will improve its readability and maintainability.

Comment thread src/copaw/app/channels/discord_/channel.py
Comment thread src/copaw/app/channels/discord_/channel.py
Comment thread src/copaw/app/channels/discord_/channel.py Outdated
@xieyxclack
Copy link
Copy Markdown
Member

Please run pre-commit run --all-files to reformat the code

@Atletico1999 Atletico1999 force-pushed the fix/discord-message-chunking branch from e25d759 to d2e61be Compare March 9, 2026 07:27
@xieyxclack xieyxclack requested a review from Leirunlin March 9, 2026 07:32
@Atletico1999 Atletico1999 force-pushed the fix/discord-message-chunking branch 2 times, most recently from e45ea01 to bd80359 Compare March 9, 2026 08:26
@Atletico1999
Copy link
Copy Markdown
Contributor Author

Atletico1999 commented Mar 9, 2026

Hi @xieyxclack , I have successfully re-applied the fixes as surgical patches on top of the latest upstream "channel.py" and formatted it. All upstream features (like access control and media sending) are strictly preserved now! Regarding the CI pre-commit failure in #1001, it seems to stem from a Windows CRLF vs LF issue on some unrelated website UI files. Could you please help review the functionality and approve the workflows? Thanks!

@xieyxclack
Copy link
Copy Markdown
Member

@Atletico1999 Of course! Thank you very much for your contribution :)

@Leirunlin
Copy link
Copy Markdown
Collaborator

@Atletico1999 Hi, Thanks for the pr! I reviewed the code and found some tiny issues.

  1. Duplicate BOM line (line 1-2)
    A UTF-8 BOM was prepended, creating a duplicate # -- coding: utf-8 -- line. Please remove it.

  2. Corrupted comment (line 516)
    The Chinese character 或 in _route_from_handle was corrupted to 鎴? — likely a Windows encoding issue. Please fix or replace with English.

  3. Suggestion: code fence awareness
    The current _chunk_text() splits at newline boundaries, which can break markdown code blocks across chunks.
    For example:

Chunk 1: "Here's the code:\n```python\ndef foo():\n    ..."

Chunk 2: "    return bar\n```"   ← missing opening fence, renders as plain text

This is a common long-message scenario (code explanations). Consider tracking fence state during chunking:

  • Detect ```/~~~ open/close lines
  • When flushing a chunk with an open fence, reserve space and append a closing fence
  • Re-emit the opening fence at the start of the next chunk

This would keep code blocks properly formatted across split messages.

If you don't mind, I can help you fix the above issues and check it together. If you have any better suggestions, feel free to discuss.

@Atletico1999
Copy link
Copy Markdown
Contributor Author

Hi @Leirunlin , thanks for the detailed review!

Regarding the three issues:

  1. BOM / duplicate coding line — this was caused by my Windows dev environment (PowerShell UTF-16LE redirection). I've been fighting this across several pushes but the root cause is my local git encoding config. I'll set up core.autocrlf and .gitattributes properly and push a clean version.

  2. Corrupted 或 → 鎴? — same encoding issue. Will fix in the next push.

  3. Code fence awareness — good suggestion. Tracking ``` state during chunking to auto-close/re-open fences across chunks would definitely improve the output for code-heavy responses. Happy to add that.

I also noticed #1073 covers the same problem and brought up some good points (tests, lint). If it makes sense, I can incorporate those improvements (tests + the explicit DISCORD_SEND_CHUNK_SIZE constant) into this PR so everything is in one place, including the code fence handling you suggested. Or if you'd rather go with #1073 as the base, I'm fine with that too — the main thing is getting the fix landed.

Will push the encoding fixes shortly.

Discord's API rejects messages longer than 2000 characters. When CoPaw
generates a long response (code blocks, detailed explanations), the
send() call fails with 400 Bad Request.

Changes:
- Add _DISCORD_MAX_LEN class constant (2000)
- Add _chunk_text() static method that splits at newline boundaries
  with code-fence awareness: tracks open/close of markdown fences
  so split chunks keep code blocks properly formatted
- Modify send() to loop over chunks instead of sending raw text
- Use compiled _FENCE_RE regex for reliable fence detection

All upstream features (access control, media sending, allowlist)
are strictly preserved — no unrelated modifications.
@Atletico1999 Atletico1999 force-pushed the fix/discord-message-chunking branch from bd80359 to cae7724 Compare March 10, 2026 06:56
@Leirunlin
Copy link
Copy Markdown
Collaborator

Hi @Atletico1999, thanks again for the PR and for iterating so quickly.

We’d like to use your implementation as the base, so you can just keep updating this PR.

If either BOM / duplicate coding line or corruption is annoying to fix on your side, you can leave it to me.

Once 3) fence-aware chunking is added, I’m happy to take another review pass.

@Atletico1999
Copy link
Copy Markdown
Contributor Author

Hi @Leirunlin , thanks for making this the base!

I just force-pushed a clean version that includes all three fixes:

  1. BOM / duplicate coding line: Gone. I rewrote the file from a clean upstream base and fixed my local .gitattributes to ensure LF endings.
  2. Corrupted comment: Fixed. The Chinese character was replaced with English or to avoid future Windows encoding issues entirely.
  3. Fence-aware chunking: Implemented via regex (_FENCE_RE). It now tracks the open/close state of ``` and ~~~ fences, auto-closing them at the chunk boundary and re-opening them in the next chunk.

Sorry for the initial encoding mess 😅. It's fully clean and ready for your review whenever you get a chance!

@Leirunlin
Copy link
Copy Markdown
Collaborator

Great! I have tested the new commit locally and it looks good to me.

@xieyxclack xieyxclack merged commit 8e72a39 into agentscope-ai:main Mar 10, 2026
3 checks passed
@github-actions
Copy link
Copy Markdown

Welcome to CoPaw! 🎉

Thank you @Atletico1999 for your first contribution! Your PR has been merged. 🚀

We'd love to give you a shout-out in our release notes! If you're comfortable sharing, please reply to this comment with your social media handles using the format below:

discord: your_discord_handle
x: your_x_handle
xiaohongshu: your_xiaohongshu_id

Note: Only share what you're comfortable with — all fields are optional.

Thanks again for helping make CoPaw better!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

first-time-contributor PR created by a first time contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants