feat(slack): opt-in Block Kit rendering for agent messages (salvage #56090) - #56102
Conversation
Add platforms.slack.extra.rich_blocks (default off). When enabled, the final agent message is sent as Slack Block Kit blocks — section headers, dividers, and true nested lists via rich_text — instead of flat mrkdwn. - New plugins/platforms/slack/block_kit.py: pure markdown->blocks renderer (headers, dividers, nested ordered/bullet lists, blockquotes, fenced code; pipe-tables as aligned monospace since Block Kit has no robust table block). Enforces Slack's 50-block / 3000-char section limits and returns None to fall back to plain text on empty/oversized/unexpected input. Never raises. - adapter.send(): render blocks on the single-chunk primary message; a text= fallback is ALWAYS sent alongside (notifications/accessibility). - adapter.edit_message(): blocks only on finalize=True, so intermediate streaming edits stay plain mrkdwn (no per-flush block re-derivation). - Docs (EN + zh-Hans) + config example. Send-side only: no app reinstall. Tests: pure-renderer unit suite + adapter integration suite (blocks present when on, plain text when off, text fallback always set, finalize gating, multi-chunk fallback). Prove-failed against a stubbed renderer.
Replace the interim monospace table fallback with Slack's native `table` block (rows of rich_text cells). Addresses the core ask in #18918. - _table_block(): builds type:"table" with rich_text cells, so inline formatting (bold, links, code) renders inside cells. - Column alignment parsed from the markdown separator row (:---, :-:, --:) into column_settings (left = default/null-skip, center/right emitted). - Escaped pipes (\\|) are not treated as column separators. - Respects Slack's table limits (100 rows / 20 cols / 10k aggregate chars); oversized or unparseable tables gracefully fall back to aligned monospace (rich_text_preformatted), so a big table never breaks the message. Docs (EN + zh-Hans) updated to describe native tables + the fallback. Tests: native table shape, alignment->column_settings, inline-formatted cells, oversized/too-wide monospace fallback, escaped-pipe cell. Prove- failed against a stubbed _table_block (native-table tests fail, fallback tests stay green). All existing Slack tests still pass.
The renderer now emits native Block Kit table blocks; the module and _rich_blocks_enabled docstrings still described the earlier monospace-only approach.
Related: salvage of #56090 (@benbarclay's original, still open) onto current |
|
Live validation found one Slack API schema issue in the merged native table path. With "column_settings": [null, {"align": "right"}, null]Slack rejects this at send time: The table block docs say missing Focused bug issue: #56615 @teknium1 the PR keeps this PR’s Block Kit renderer approach intact and only hardens the table schema + no-block fallback path. |
Infographic
Summary
Slack agent replies can now render as structured Block Kit — headers, dividers, true nested lists, blockquotes, code, and native
tableblocks — behind an opt-in flag (platforms.slack.extra.rich_blocks: true, default off). Salvage of #56090 by @benbarclay onto currentmain. Closes #18918.Changes
plugins/platforms/slack/block_kit.py(new): purerender_blocks(markdown)— headers, dividers,rich_textnested lists, blockquotes, preformatted code, and nativetableblocks with per-column alignment and inline-formattedrich_textcells. Enforces Slack's 50-block / 3000-char / table (100 rows · 20 cols · 10k chars) limits; over-limit or unparseable tables fall back to aligned monospace. Never raises →Noneon any unexpected input.plugins/platforms/slack/adapter.py:send()renders blocks on the single-chunk primary message;edit_message()renders blocks only onfinalize=True(streaming edits stay plain mrkdwn). Atext=fallback is always sent alongside blocks.website/docs/user-guide/messaging/slack.md+ zh-Hans i18n — config example + key-table row._rich_blocks_enableddocstrings, which still described the earlier monospace-only table approach.Validation
tests/gateway/test_slack_block_kit.py+_adapter.py— 27/27 passtableblock, alignment (left→null, right emitted), in-cell bold + link survivePlugin-only PR (touches
plugins/platforms/slack/,tests/gateway/,website/docs/), contributor authorship preserved via rebase-merge.