Skip to content

Commit 395ad91

Browse files
committed
fix: cap slack approval update text
1 parent c4f9cf1 commit 395ad91

3 files changed

Lines changed: 53 additions & 2 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ Docs: https://docs.openclaw.ai
7474
- Slack/interactive replies: drop overlong Block Kit button URLs while preserving valid callback values, so malformed link buttons no longer make Slack reject the whole interactive reply. Thanks @slackapi.
7575
- Slack/commands: truncate native command argument-menu confirmation text to Slack's dialog limit, so long plugin arg names no longer make fallback buttons render invalid Block Kit payloads. Thanks @slackapi.
7676
- Slack/exec approvals: cap native approval metadata context to Slack's element and text limits, so large approval details no longer make Slack reject the approval card. Thanks @slackapi.
77+
- Slack/exec approvals: cap native approval update fallback text to Slack's message limit while preserving the rendered approval blocks, so long commands no longer make resolved or expired approval cards stay stale after `chat.update` rejects `msg_too_long`. Thanks @slackapi.
7778
- Slack/commands: cap native command argument-menu fallback rows to Slack's message block limit, so large plugin choice lists no longer make Slack reject the generated menu. Thanks @slackapi.
7879
- 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.
7980
- 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.

extensions/slack/src/approval-handler.runtime.test.ts

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import { describe, expect, it } from "vitest";
1+
import { describe, expect, it, vi } from "vitest";
22
import { slackApprovalNativeRuntime } from "./approval-handler.runtime.js";
33

44
type SlackPayload = {
55
text: string;
66
blocks?: unknown;
77
};
8+
const SLACK_TEXT_LIMIT = 8000;
89

910
function findSlackActionsBlock(blocks: Array<{ type?: string; elements?: unknown[] }>) {
1011
return blocks.find((block) => block.type === "actions");
@@ -114,6 +115,53 @@ describe("slackApprovalNativeRuntime", () => {
114115
).toBe(false);
115116
});
116117

118+
it("caps resolved update fallback text while preserving approval blocks", async () => {
119+
const blocks = [
120+
{
121+
type: "section",
122+
text: {
123+
type: "mrkdwn",
124+
text: "*Command*\n```short preview```",
125+
},
126+
},
127+
];
128+
const chatUpdate = vi.fn(async (_payload: { text: string; blocks: typeof blocks }) => ({}));
129+
130+
await slackApprovalNativeRuntime.transport.updateEntry?.({
131+
cfg: {} as never,
132+
accountId: "default",
133+
context: {
134+
app: {
135+
client: {
136+
chat: {
137+
update: chatUpdate,
138+
},
139+
},
140+
},
141+
config: {},
142+
} as never,
143+
entry: {
144+
channelId: "C123",
145+
messageTs: "1712345678.999999",
146+
},
147+
payload: {
148+
text: `*Exec approval: Allowed once*\n\n*Command*\n${"a".repeat(9000)}`,
149+
blocks,
150+
},
151+
phase: "resolved",
152+
});
153+
154+
expect(chatUpdate).toHaveBeenCalledWith(
155+
expect.objectContaining({
156+
channel: "C123",
157+
ts: "1712345678.999999",
158+
text: expect.stringMatching(/$/),
159+
blocks,
160+
}),
161+
);
162+
expect(chatUpdate.mock.calls[0]?.[0].text).toHaveLength(SLACK_TEXT_LIMIT);
163+
});
164+
117165
it("keeps pending metadata context within Slack Block Kit limits", async () => {
118166
const payload = (await slackApprovalNativeRuntime.presentation.buildPendingPayload({
119167
cfg: {} as never,

extensions/slack/src/approval-handler.runtime.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ import {
1717
shouldHandleSlackExecApprovalRequest,
1818
normalizeSlackApproverId,
1919
} from "./exec-approvals.js";
20+
import { SLACK_TEXT_LIMIT } from "./limits.js";
2021
import { resolveSlackReplyBlocks } from "./reply-blocks.js";
2122
import { sendMessageSlack } from "./send.js";
23+
import { truncateSlackText } from "./truncate.js";
2224

2325
type SlackBlock = Block | KnownBlock;
2426
type SlackPendingApproval = {
@@ -229,7 +231,7 @@ async function updateMessage(params: {
229231
await params.app.client.chat.update({
230232
channel: params.channelId,
231233
ts: params.messageTs,
232-
text: params.text,
234+
text: truncateSlackText(params.text, SLACK_TEXT_LIMIT),
233235
blocks: params.blocks,
234236
});
235237
} catch (err) {

0 commit comments

Comments
 (0)