fix(slack): chunk section-block content and surface postMessage errors (#18) - #30253
fix(slack): chunk section-block content and surface postMessage errors (#18)#30253idl3 wants to merge 1 commit into
Conversation
NousResearch#18) When Rico sends a structured report via send_slash_confirm, the section block text could exceed Slack's 3000-char-per-text-element limit, causing the API to silently reject the message and post empty-looking replies. - Add MAX_SECTION_TEXT_LENGTH = 2900 constant (3000 hard limit minus margin). - Rewrite send_slash_confirm to split the message body via truncate_message at the section budget; the first chunk goes in the button block, overflow chunks post as threaded plain-text replies with [i/N continued] markers so no content is silently dropped. - Add _safe_post_message helper that wraps every chat_postMessage call: on SlackApiError it logs error_code, text_len, blocks_count, and max_section_len at WARNING level before re-raising so silent failures become visible. - Wire _safe_post_message into send(), send_exec_approval, send_slash_confirm, and the button-action follow-up post. - Add tests/gateway/test_slack_chunking.py: 10 cases covering large/small send() chunks, section-block size ceiling, continuation threading, content preservation, and _safe_post_message error logging. All 285 Slack tests pass.
teknium1
left a comment
There was a problem hiding this comment.
Thanks for addressing the Slack block-limit failure. Current main already prevents the rejected-block symptom, but this PR needs a targeted port and one boundary fix.
Problems
gateway/platforms/slack.pywas moved toplugins/platforms/slack/adapter.pyby1a38066054752d601b71fc655a3ed6bf4228e2da, so the submitted patch no longer targets the active adapter.- The new
title_str = title or "Confirm"atgateway/platforms/slack.py:2390is unbounded. A sufficiently long title makesheaderexceed Slack's 3000-character section limit before body content is considered. Current main caps this input atplugins/platforms/slack/adapter.py:3348.
Suggested changes
- Port the continuation/error-detail work to
plugins/platforms/slack/adapter.pywhile retaining the current 150-character title cap and rendered-size budget. - Add an overlong-title regression test; current main already has the relevant section-limit guard in the active adapter.
Automated hermes-sweeper review.
| value = f"{session_key}|{confirm_id}" | ||
|
|
||
| # Reserve room for the "*{title}*\n\n" wrapper inside the section. | ||
| title_str = title or "Confirm" |
There was a problem hiding this comment.
Please retain a title cap here (current main uses [:150]). Without one, a long title makes header exceed Slack's 3000-character section limit before any body chunk is added.
|
Closing as superseded by #69317 (merged): targeted the pre-plugin-migration file; section chunking already exists on main (_split_text) and error surfacing landed via #56618's retry-fallback. Thanks for digging into this — the consolidated fix stands on the cluster's collective analysis, and your work is credited in #69317's summary. |
Summary
When an agents sends a ~2KB structured report via
send_slash_confirm, Slack silently rejected it because the section blocktextfield exceeded the 3000-char-per-element API limit — producing two empty-looking messages at the same timestamp. The top-leveltextfield was fine (well under 40k), but the block-level limit is separate and was never enforced.Root cause:
send_slash_confirmused a hard truncation at 2900 chars (message[:2900] + "..."), which silently drops content rather than chunking it. More critically, no call site checked the Slack API response for error details, so the rejection was invisible in logs.This PR makes the send path section-block-aware and adds error surfacing across all
chat_postMessagecall sites:MAX_SECTION_TEXT_LENGTH = 2900constant added nearMAX_MESSAGE_LENGTH(Slack's 3000-char hard limit minus 100-char margin).send_slash_confirmrewritten: usesBasePlatformAdapter.truncate_messageto split the message body at the section budget (preserving code-block boundaries). The first chunk goes in the button block; overflow posts as threaded plain-text replies with[i/N continued]markers — no content is ever silently dropped._safe_post_messagehelper wraps everychat_postMessagecall. OnSlackApiErrorit logserror_code,text_len,blocks_count, and longest section-block text length atWARNINGlevel before re-raising. Wired intosend(),send_exec_approval,send_slash_confirm, and the button-action follow-up path.tests/gateway/test_slack_chunking.pycovering: large/smallsend()chunking, section-block size ceiling, continuation threading, full content preservation, and_safe_post_messageerror-code logging. All 285 existing Slack tests continue to pass; ruff clean.new-pattern: yes
what: send_slash_confirm now chunks at section-block level and routes all chat_postMessage calls through a logging wrapper
visualizable: no
why: the change is a linear call-site refactor with no branching flow or state machine; a diagram would add no information over the prose description
decision: skip
Test plan
uv run --extra dev python -m pytest tests/gateway/test_slack_chunking.py -v— 10/10 passuv run --extra dev python -m pytest tests/gateway/test_slack.py tests/gateway/test_slack_approval_buttons.py tests/gateway/test_slack_mention.py tests/gateway/test_slack_channel_skills.py -v— 275/275 passuv run --extra dev ruff check gateway/platforms/slack.py tests/gateway/test_slack_chunking.py— clean/hermesslash command in a real workspace and confirm no empty-message pair appearsCloses #18