fix(weixin): keep multi-line messages in single bubble by default (#7903)

The Weixin adapter was splitting responses at every top-level newline,
causing notification spam (up to 70 API calls for a single long markdown
response). This salvages the best aspects of six contributor PRs:

Compact mode (new default):
- Messages under the 4000-char limit stay as a single bubble even with
  multiple lines, paragraphs, and code blocks
- Only oversized messages get split at logical markdown boundaries
- Inter-chunk delay (0.3s) between chunks prevents WeChat rate-limit drops

Legacy mode (opt-in):
- Set split_multiline_messages: true in platforms.weixin.extra config
- Or set WEIXIN_SPLIT_MULTILINE_MESSAGES=true env var
- Restores the old per-line splitting behavior

Salvaged from PRs #7797 (guantoubaozi), #7792 (luoxiao6645),
#7838 (qyx596), #7825 (weedge), #7784 (sherunlock03), #7773 (JnyRoad).
Core fix unanimous across all six; config toggle from #7838; inter-chunk
delay from #7825.
This commit is contained in:
Teknium 2026-04-11 12:00:05 -07:00 committed by GitHub
parent 3ec8809b78
commit da9f96bf51
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 97 additions and 28 deletions

View file

@ -66,6 +66,9 @@ WEIXIN_ACCOUNT_ID=your-account-id
WEIXIN_DM_POLICY=open
WEIXIN_ALLOWED_USERS=user_id_1,user_id_2
# Optional: restore legacy multiline splitting behavior
# WEIXIN_SPLIT_MULTILINE_MESSAGES=true
# Optional: home channel for cron/notifications
WEIXIN_HOME_CHANNEL=chat_id
WEIXIN_HOME_CHANNEL_NAME=Home
@ -88,7 +91,7 @@ The adapter will restore saved credentials, connect to the iLink API, and begin
- **AES-128-ECB encrypted CDN** — automatic encryption/decryption for all media transfers
- **Context token persistence** — disk-backed reply continuity across restarts
- **Markdown formatting** — headers, tables, and code blocks are reformatted for WeChat readability
- **Smart message chunking**long messages are split at logical boundaries (paragraphs, code fences)
- **Smart message chunking**messages stay as a single bubble when under the limit; only oversized payloads split at logical boundaries
- **Typing indicators** — shows "typing…" status in the WeChat client while the agent processes
- **SSRF protection** — outbound media URLs are validated before download
- **Message deduplication** — 5-minute sliding window prevents double-processing
@ -108,6 +111,7 @@ Set these in `config.yaml` under `platforms.weixin.extra`:
| `group_policy` | `disabled` | Group access: `open`, `allowlist`, `disabled` |
| `allow_from` | `[]` | User IDs allowed for DMs (when dm_policy=allowlist) |
| `group_allow_from` | `[]` | Group IDs allowed (when group_policy=allowlist) |
| `split_multiline_messages` | `false` | When `true`, split multi-line replies into multiple chat messages (legacy behavior). When `false`, keep multi-line replies as one message unless they exceed the length limit. |
## Access Policies
@ -211,13 +215,14 @@ WeChat's personal chat does not natively render full Markdown. The adapter refor
## Message Chunking
Long messages are split intelligently for chat delivery:
Messages are delivered as a single chat message whenever they fit within the platform limit. Only oversized payloads are split for delivery:
- Maximum message length: **4000 characters**
- Split points prefer paragraph boundaries and blank lines
- Code fences are kept intact (never split mid-block)
- Indented continuation lines (sub-items in reformatted tables/lists) stay with their parent
- Messages under the limit stay intact even when they contain multiple paragraphs or line breaks
- Oversized messages split at logical boundaries (paragraphs, blank lines, code fences)
- Code fences are kept intact whenever possible (never split mid-block unless the fence itself exceeds the limit)
- Oversized individual blocks fall back to the base adapter's truncation logic
- A 0.3 s inter-chunk delay prevents WeChat rate-limit drops when multiple chunks are sent
## Typing Indicators