fix(gateway): Slack approval UX in threads — block-size overflow + typed-prefix instruction text (#43444)
Two fixes for the reported Slack thread approval UX: 1. Slack Block Kit approval/confirm sends silently overflowed the 3000-char section-block cap (flat 2900-char truncation + header + reason), so long execute_code approvals failed with invalid_blocks and fell back to the plain-text prompt with no buttons. Budget the command preview against the rendered fixed parts so blocks never exceed the cap (send_exec_approval + send_slash_confirm). 2. The text fallbacks told users to reply /approve — which Slack blocks inside threads and Matrix clients reserve client-side. Add a typed_command_prefix capability flag on BasePlatformAdapter (default "/"; Slack and Matrix set "!" to match their existing bang-prefix rewrite) and use it in the shared fallback prompt builders (exec approval, update prompt, destructive slash confirm, expensive-model confirm) plus Matrix's reaction-prompt text. The slash-confirm text-intercept now also accepts bang-prefixed replies (!always, !cancel) since those keywords aren't registered commands and the adapters' rewrite doesn't touch them.
This commit is contained in:
@@ -318,6 +318,11 @@ class SlackAdapter(BasePlatformAdapter):
|
||||
|
||||
MAX_MESSAGE_LENGTH = 39000 # Slack API allows 40,000 chars; leave margin
|
||||
supports_code_blocks = True # Slack mrkdwn renders fenced code blocks
|
||||
# Slack blocks typed native slash commands inside threads ("/approve is
|
||||
# not supported in threads. Sorry!"). The adapter rewrites a leading
|
||||
# "!" to "/" for known commands (see _handle_slack_message), so "!" is
|
||||
# the prefix that works everywhere — instruction text must show it.
|
||||
typed_command_prefix = "!"
|
||||
|
||||
def __init__(self, config: PlatformConfig):
|
||||
super().__init__(config, Platform.SLACK)
|
||||
@@ -2692,19 +2697,26 @@ class SlackAdapter(BasePlatformAdapter):
|
||||
return SendResult(success=False, error="Not connected")
|
||||
|
||||
try:
|
||||
cmd_preview = command[:2900] + "..." if len(command) > 2900 else command
|
||||
thread_ts = self._resolve_thread_ts(None, metadata)
|
||||
|
||||
# Slack hard-caps a section block's text at 3000 chars; an
|
||||
# oversized block fails the whole send with ``invalid_blocks``
|
||||
# and the gateway falls back to the plain-text prompt (no
|
||||
# buttons). execute_code approvals embed the entire script in
|
||||
# ``command``, so budget the preview against the fixed parts
|
||||
# instead of a flat truncation that overflows once the header +
|
||||
# reason are added.
|
||||
header = ":warning: *Command Approval Required*\n"
|
||||
reason = f"Reason: {description[:500]}"
|
||||
budget = 3000 - len(header) - len(reason) - len("``````\n") - len("...")
|
||||
cmd_preview = command[:budget] + "..." if len(command) > budget else command
|
||||
|
||||
blocks = [
|
||||
{
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": (
|
||||
f":warning: *Command Approval Required*\n"
|
||||
f"```{cmd_preview}```\n"
|
||||
f"Reason: {description}"
|
||||
),
|
||||
"text": f"{header}```{cmd_preview}```\n{reason}",
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -2772,8 +2784,13 @@ class SlackAdapter(BasePlatformAdapter):
|
||||
return SendResult(success=False, error="Not connected")
|
||||
|
||||
try:
|
||||
body = message[:2900] + "..." if len(message) > 2900 else message
|
||||
thread_ts = self._resolve_thread_ts(None, metadata)
|
||||
# Same 3000-char section-block cap as send_exec_approval: budget
|
||||
# the body against the rendered title so the wrapper never pushes
|
||||
# the block over the limit (overflow → invalid_blocks → no buttons).
|
||||
_title = (title or "Confirm")[:150]
|
||||
budget = 3000 - len(f"*{_title}*\n\n") - len("...")
|
||||
body = message[:budget] + "..." if len(message) > budget else message
|
||||
# Encode session_key and confirm_id into the button value so the
|
||||
# callback handler can resolve without extra bookkeeping.
|
||||
value = f"{session_key}|{confirm_id}"
|
||||
@@ -2783,7 +2800,7 @@ class SlackAdapter(BasePlatformAdapter):
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": f"*{title or 'Confirm'}*\n\n{body}",
|
||||
"text": f"*{_title}*\n\n{body}",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user