Slack: enrich block action context payloads

This commit is contained in:
Colin
2026-02-16 13:12:47 -05:00
committed by Peter Steinberger
parent 7e42408ade
commit 296ba8e934
2 changed files with 77 additions and 2 deletions

View File

@@ -11,7 +11,11 @@ type RegisteredHandler = (args: {
ack: () => Promise<void>;
body: {
user: { id: string };
team?: { id?: string };
trigger_id?: string;
response_url?: string;
channel?: { id?: string };
container?: { channel_id?: string; message_ts?: string; thread_ts?: string };
message?: { ts?: string; text?: string; blocks?: unknown[] };
};
action: Record<string, unknown>;
@@ -100,7 +104,11 @@ describe("registerSlackInteractionEvents", () => {
respond,
body: {
user: { id: "U123" },
team: { id: "T9" },
trigger_id: "123.trigger",
response_url: "https://hooks.slack.test/response",
channel: { id: "C1" },
container: { channel_id: "C1", message_ts: "100.200", thread_ts: "100.100" },
message: {
ts: "100.200",
text: "fallback",
@@ -131,16 +139,24 @@ describe("registerSlackInteractionEvents", () => {
actionType: string;
value: string;
userId: string;
teamId?: string;
triggerId?: string;
responseUrl?: string;
channelId: string;
messageTs: string;
threadTs?: string;
};
expect(payload).toMatchObject({
actionId: "openclaw:verify",
actionType: "button",
value: "approved",
userId: "U123",
teamId: "T9",
triggerId: "123.trigger",
responseUrl: "https://hooks.slack.test/response",
channelId: "C1",
messageTs: "100.200",
threadTs: "100.100",
});
expect(resolveSessionKey).toHaveBeenCalledWith({
channelId: "C1",
@@ -192,6 +208,52 @@ describe("registerSlackInteractionEvents", () => {
expect(app.client.chat.update).not.toHaveBeenCalled();
});
it("falls back to container channel and message timestamps", async () => {
enqueueSystemEventMock.mockReset();
const { ctx, app, getHandler, resolveSessionKey } = createContext();
registerSlackInteractionEvents({ ctx: ctx as never });
const handler = getHandler();
expect(handler).toBeTruthy();
const ack = vi.fn().mockResolvedValue(undefined);
await handler!({
ack,
body: {
user: { id: "U111" },
team: { id: "T111" },
container: { channel_id: "C222", message_ts: "222.333", thread_ts: "222.111" },
},
action: {
type: "button",
action_id: "openclaw:container",
block_id: "container_block",
value: "ok",
text: { type: "plain_text", text: "Container" },
},
});
expect(ack).toHaveBeenCalled();
expect(resolveSessionKey).toHaveBeenCalledWith({
channelId: "C222",
channelType: undefined,
});
expect(enqueueSystemEventMock).toHaveBeenCalledTimes(1);
const [eventText] = enqueueSystemEventMock.mock.calls[0] as [string];
const payload = JSON.parse(eventText.replace("Slack interaction: ", "")) as {
channelId?: string;
messageTs?: string;
threadTs?: string;
teamId?: string;
};
expect(payload).toMatchObject({
channelId: "C222",
messageTs: "222.333",
threadTs: "222.111",
teamId: "T111",
});
expect(app.client.chat.update).not.toHaveBeenCalled();
});
it("captures expanded selection and temporal payload fields", async () => {
enqueueSystemEventMock.mockReset();
const { ctx, getHandler } = createContext();

View File

@@ -31,8 +31,12 @@ type InteractionSummary = {
selectedDateTime?: number;
inputValue?: string;
userId?: string;
teamId?: string;
triggerId?: string;
responseUrl?: string;
channelId?: string;
messageTs?: string;
threadTs?: string;
};
type ModalInputSummary = {
@@ -205,7 +209,11 @@ export function registerSlackInteractionEvents(params: { ctx: SlackMonitorContex
const { ack, body, action, respond } = args;
const typedBody = body as unknown as {
user?: { id?: string };
team?: { id?: string };
trigger_id?: string;
response_url?: string;
channel?: { id?: string };
container?: { channel_id?: string; message_ts?: string; thread_ts?: string };
message?: { ts?: string; text?: string; blocks?: unknown[] };
};
@@ -222,8 +230,9 @@ export function registerSlackInteractionEvents(params: { ctx: SlackMonitorContex
const actionId = typedAction.action_id ?? "unknown";
const blockId = typedAction.block_id;
const userId = typedBody.user?.id ?? "unknown";
const channelId = typedBody.channel?.id;
const messageTs = typedBody.message?.ts;
const channelId = typedBody.channel?.id ?? typedBody.container?.channel_id;
const messageTs = typedBody.message?.ts ?? typedBody.container?.message_ts;
const threadTs = typedBody.container?.thread_ts;
const actionSummary = summarizeAction(typedAction);
const eventPayload: InteractionSummary = {
interactionType: "block_action",
@@ -231,8 +240,12 @@ export function registerSlackInteractionEvents(params: { ctx: SlackMonitorContex
blockId,
...actionSummary,
userId,
teamId: typedBody.team?.id,
triggerId: typedBody.trigger_id,
responseUrl: typedBody.response_url,
channelId,
messageTs,
threadTs,
};
// Log the interaction for debugging