From c4f9cf1a27f18d9fb2a46f95c904dd6a305cc524 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 30 Apr 2026 05:11:53 +0100 Subject: [PATCH] fix: cap slack edit fallback text --- CHANGELOG.md | 1 + extensions/slack/src/actions.blocks.test.ts | 30 +++++++++++++++++++++ extensions/slack/src/actions.ts | 6 ++++- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b680dd8809b..8f43010d716 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -78,6 +78,7 @@ Docs: https://docs.openclaw.ai - Slack/commands: drop fallback command argument buttons whose encoded values exceed Slack's button-value limit, so one oversized plugin choice no longer makes Slack reject the whole menu. Thanks @slackapi. - Slack/messages: merge message-tool presentation and interactive blocks on Slack sends, so buttons and selects are no longer dropped when a structured message body is also present. Thanks @slackapi. - Slack/messages: cap Block Kit fallback text to Slack's send limit while preserving the rendered blocks, so long context fallbacks no longer make rich Slack messages fail with `msg_too_long`. Thanks @slackapi. +- Slack/messages: cap Block Kit fallback text on message edits while preserving the rendered blocks, so long context fallbacks no longer make Slack reject `chat.update` calls with `msg_too_long`. Thanks @slackapi. - Channels/WhatsApp: require Baileys outbound message ids before marking auto-replies delivered, so transcript text and ack reactions no longer make failed group replies look sent. Fixes #49225. Thanks @TinyTb. - CLI/update: scope packaged Node compile caches by OpenClaw version and install metadata, so global installs no longer reuse stale compiled chunks after package updates. Thanks @pashpashpash. - Channels/Voice call: keep pre-auth webhook in-flight limiting active when socket remote address metadata is missing, so slow-body requests from stripped-IP proxy paths still share the fallback bucket. (#74453) Thanks @davidangularme. diff --git a/extensions/slack/src/actions.blocks.test.ts b/extensions/slack/src/actions.blocks.test.ts index 15cda608907..224b8d92e1e 100644 --- a/extensions/slack/src/actions.blocks.test.ts +++ b/extensions/slack/src/actions.blocks.test.ts @@ -3,6 +3,7 @@ import { createSlackEditTestClient, installSlackBlockTestMocks } from "./blocks. installSlackBlockTestMocks(); const { editSlackMessage } = await import("./actions.js"); +const SLACK_TEXT_LIMIT = 8000; describe("editSlackMessage blocks", () => { it("updates with valid blocks", async () => { @@ -80,6 +81,35 @@ describe("editSlackMessage blocks", () => { ); }); + it("caps long block fallback text while preserving edit blocks", async () => { + const client = createSlackEditTestClient(); + const longContextText = "a".repeat(3000); + const blocks = [ + { + type: "context", + elements: [ + { type: "mrkdwn", text: longContextText }, + { type: "mrkdwn", text: longContextText }, + { type: "mrkdwn", text: longContextText }, + ], + }, + ]; + + await editSlackMessage("C123", "171234.567", "", { + token: "xoxb-test", + client, + blocks, + }); + + expect(client.chat.update).toHaveBeenCalledWith( + expect.objectContaining({ + text: expect.stringMatching(/…$/), + blocks, + }), + ); + expect(client.chat.update.mock.calls[0]?.[0].text).toHaveLength(SLACK_TEXT_LIMIT); + }); + it("rejects empty blocks arrays", async () => { const client = createSlackEditTestClient(); diff --git a/extensions/slack/src/actions.ts b/extensions/slack/src/actions.ts index 2bfc4247ec2..f1dbd45b9af 100644 --- a/extensions/slack/src/actions.ts +++ b/extensions/slack/src/actions.ts @@ -6,10 +6,12 @@ import { resolveSlackAccount } from "./accounts.js"; import { buildSlackBlocksFallbackText } from "./blocks-fallback.js"; import { validateSlackBlocksArray } from "./blocks-input.js"; import { createSlackWebClient, getSlackWriteClient } from "./client.js"; +import { SLACK_TEXT_LIMIT } from "./limits.js"; import { resolveSlackMedia } from "./monitor/media.js"; import type { SlackMediaResult } from "./monitor/media.js"; import { sendMessageSlack } from "./send.js"; import { resolveSlackBotToken } from "./token.js"; +import { truncateSlackText } from "./truncate.js"; export type SlackActionClientOpts = { cfg?: OpenClawConfig; @@ -234,7 +236,9 @@ export async function editSlackMessage( await client.chat.update({ channel: channelId, ts: messageId, - text: trimmedContent || (blocks ? buildSlackBlocksFallbackText(blocks) : " "), + text: + trimmedContent || + (blocks ? truncateSlackText(buildSlackBlocksFallbackText(blocks), SLACK_TEXT_LIMIT) : " "), ...(blocks ? { blocks } : {}), }); }