Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions apps/docs/content/docs/en/tools/slack.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,10 @@ Send messages to Slack channels or users through the Slack API. Supports Slack m

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `message` | object | Complete message object with all properties returned by Slack |
| `ts` | string | Message timestamp |
| `channel` | string | Channel ID where message was sent |
| `fileCount` | number | Number of files uploaded \(when files are attached\) |

### `slack_canvas`

Expand Down Expand Up @@ -157,6 +159,7 @@ Update a message previously sent by the bot in Slack

| Parameter | Type | Description |
| --------- | ---- | ----------- |
| `message` | object | Complete updated message object with all properties returned by Slack |
| `content` | string | Success message |
| `metadata` | object | Updated message metadata |

Expand Down
41 changes: 40 additions & 1 deletion apps/sim/app/api/tools/slack/send-message/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,16 @@ export async function POST(request: NextRequest) {
}

logger.info(`[${requestId}] Message sent successfully`)
const messageObj = data.message || {
type: 'message',
ts: data.ts,
text: validatedData.text,
channel: data.channel,
}
return NextResponse.json({
success: true,
output: {
message: messageObj,
ts: data.ts,
channel: data.channel,
},
Expand All @@ -107,9 +114,16 @@ export async function POST(request: NextRequest) {
})

const data = await response.json()
const messageObj = data.message || {
type: 'message',
ts: data.ts,
text: validatedData.text,
channel: data.channel,
}
return NextResponse.json({
success: true,
output: {
message: messageObj,
ts: data.ts,
channel: data.channel,
},
Expand Down Expand Up @@ -174,9 +188,16 @@ export async function POST(request: NextRequest) {
})

const data = await response.json()
const messageObj = data.message || {
type: 'message',
ts: data.ts,
text: validatedData.text,
channel: data.channel,
}
return NextResponse.json({
success: true,
output: {
message: messageObj,
ts: data.ts,
channel: data.channel,
},
Expand Down Expand Up @@ -211,10 +232,28 @@ export async function POST(request: NextRequest) {

logger.info(`[${requestId}] Files uploaded and shared successfully`)

// For file uploads, construct a message object
const fileTs = completeData.files?.[0]?.created?.toString() || (Date.now() / 1000).toString()
const fileMessage = {
type: 'message',
ts: fileTs,
text: validatedData.text,
channel: validatedData.channel,
files: completeData.files?.map((file: any) => ({
id: file?.id,
name: file?.name,
mimetype: file?.mimetype,
size: file?.size,
url_private: file?.url_private,
permalink: file?.permalink,
})),
}

return NextResponse.json({
success: true,
output: {
ts: completeData.files?.[0]?.created || Date.now() / 1000,
message: fileMessage,
ts: fileTs,
channel: validatedData.channel,
fileCount: uploadedFileIds.length,
},
Expand Down
10 changes: 9 additions & 1 deletion apps/sim/app/api/tools/slack/update-message/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,22 @@ export async function POST(request: NextRequest) {
timestamp: data.ts,
})

const messageObj = data.message || {
type: 'message',
ts: data.ts,
text: data.text || validatedData.text,
channel: data.channel,
}

return NextResponse.json({
success: true,
output: {
message: messageObj,
content: 'Message updated successfully',
metadata: {
channel: data.channel,
timestamp: data.ts,
text: data.text,
text: data.text || validatedData.text,
},
},
})
Expand Down
24 changes: 21 additions & 3 deletions apps/sim/blocks/blocks/slack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -464,18 +464,29 @@ export const SlackBlock: BlockConfig<SlackResponse> = {
thread_ts: { type: 'string', description: 'Thread timestamp for reply' },
},
outputs: {
// slack_message outputs
// slack_message outputs (send operation)
message: {
type: 'json',
description:
'Complete message object with all properties: ts, text, user, channel, reactions, threads, files, attachments, blocks, stars, pins, and edit history',
},
// Legacy properties for send operation (backward compatibility)
ts: { type: 'string', description: 'Message timestamp returned by Slack API' },
channel: { type: 'string', description: 'Channel identifier where message was sent' },
fileCount: {
type: 'number',
description: 'Number of files uploaded (when files are attached)',
},

// slack_canvas outputs
canvas_id: { type: 'string', description: 'Canvas identifier for created canvases' },
title: { type: 'string', description: 'Canvas title' },

// slack_message_reader outputs
// slack_message_reader outputs (read operation)
messages: {
type: 'json',
description: 'Array of message objects with text, user, timestamp, and file attachments',
description:
'Array of message objects with comprehensive properties: text, user, timestamp, reactions, threads, files, attachments, blocks, stars, pins, and edit history',
},

// slack_download outputs
Expand All @@ -484,6 +495,13 @@ export const SlackBlock: BlockConfig<SlackResponse> = {
description: 'Downloaded file stored in execution files',
},

// slack_update_message outputs (update operation)
content: { type: 'string', description: 'Success message for update operation' },
metadata: {
type: 'json',
description: 'Updated message metadata (legacy, use message object instead)',
},

// Trigger outputs (when used as webhook trigger)
event_type: { type: 'string', description: 'Type of Slack event that triggered the workflow' },
channel_name: { type: 'string', description: 'Human-readable channel name' },
Expand Down
9 changes: 9 additions & 0 deletions apps/sim/tools/slack/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,16 @@ export const slackMessageTool: ToolConfig<SlackMessageParams, SlackMessageRespon
},

outputs: {
message: {
type: 'object',
description: 'Complete message object with all properties returned by Slack',
},
// Legacy properties for backward compatibility
ts: { type: 'string', description: 'Message timestamp' },
channel: { type: 'string', description: 'Channel ID where message was sent' },
fileCount: {
type: 'number',
description: 'Number of files uploaded (when files are attached)',
},
},
}
132 changes: 120 additions & 12 deletions apps/sim/tools/slack/message_reader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,18 +89,59 @@ export const slackMessageReaderTool: ToolConfig<
const data = await response.json()

const messages = (data.messages || []).map((message: any) => ({
// Core properties
type: message.type || 'message',
ts: message.ts,
text: message.text || '',
user: message.user || message.bot_id || 'unknown',
type: message.type || 'message',
user: message.user,
bot_id: message.bot_id,
username: message.username,
channel: message.channel,
team: message.team,

// Thread properties
thread_ts: message.thread_ts,
parent_user_id: message.parent_user_id,
reply_count: message.reply_count,
reply_users_count: message.reply_users_count,
latest_reply: message.latest_reply,
subscribed: message.subscribed,
last_read: message.last_read,
unread_count: message.unread_count,

// Message subtype
subtype: message.subtype,

// Reactions and interactions
reactions: message.reactions?.map((reaction: any) => ({
name: reaction.name,
count: reaction.count,
users: reaction.users || [],
})),
is_starred: message.is_starred,
pinned_to: message.pinned_to,

// Content attachments
files: message.files?.map((file: any) => ({
id: file.id,
name: file.name,
mimetype: file.mimetype,
size: file.size,
url_private: file.url_private,
permalink: file.permalink,
mode: file.mode,
})),
attachments: message.attachments,
blocks: message.blocks,

// Metadata
edited: message.edited
? {
user: message.edited.user,
ts: message.edited.ts,
}
: undefined,
permalink: message.permalink,
}))

return {
Expand All @@ -118,24 +159,91 @@ export const slackMessageReaderTool: ToolConfig<
items: {
type: 'object',
properties: {
ts: { type: 'string' },
text: { type: 'string' },
user: { type: 'string' },
type: { type: 'string' },
subtype: { type: 'string' },
// Core properties
type: { type: 'string', description: 'Message type' },
ts: { type: 'string', description: 'Message timestamp' },
text: { type: 'string', description: 'Message text content' },
user: { type: 'string', description: 'User ID who sent the message' },
bot_id: { type: 'string', description: 'Bot ID if sent by a bot' },
username: { type: 'string', description: 'Display username' },
channel: { type: 'string', description: 'Channel ID' },
team: { type: 'string', description: 'Team ID' },

// Thread properties
thread_ts: { type: 'string', description: 'Thread parent message timestamp' },
parent_user_id: { type: 'string', description: 'User ID of thread parent' },
reply_count: { type: 'number', description: 'Number of thread replies' },
reply_users_count: { type: 'number', description: 'Number of users who replied' },
latest_reply: { type: 'string', description: 'Timestamp of latest reply' },
subscribed: { type: 'boolean', description: 'Whether user is subscribed to thread' },
last_read: { type: 'string', description: 'Last read timestamp' },
unread_count: { type: 'number', description: 'Number of unread messages' },

// Message subtype
subtype: { type: 'string', description: 'Message subtype' },

// Reactions and interactions
reactions: {
type: 'array',
description: 'Array of reactions on this message',
items: {
type: 'object',
properties: {
name: { type: 'string', description: 'Emoji name' },
count: { type: 'number', description: 'Number of reactions' },
users: {
type: 'array',
description: 'Array of user IDs who reacted',
items: { type: 'string' },
},
},
},
},
is_starred: { type: 'boolean', description: 'Whether message is starred' },
pinned_to: {
type: 'array',
description: 'Array of channel IDs where message is pinned',
items: { type: 'string' },
},

// Content attachments
files: {
type: 'array',
description: 'Array of files attached to message',
items: {
type: 'object',
properties: {
id: { type: 'string' },
name: { type: 'string' },
mimetype: { type: 'string' },
size: { type: 'number' },
url_private: { type: 'string' },
id: { type: 'string', description: 'File ID' },
name: { type: 'string', description: 'File name' },
mimetype: { type: 'string', description: 'MIME type' },
size: { type: 'number', description: 'File size in bytes' },
url_private: { type: 'string', description: 'Private download URL' },
permalink: { type: 'string', description: 'Permanent link to file' },
mode: { type: 'string', description: 'File mode' },
},
},
},
attachments: {
type: 'array',
description: 'Array of legacy attachments',
items: { type: 'object' },
},
blocks: {
type: 'array',
description: 'Array of Block Kit blocks',
items: { type: 'object' },
},

// Metadata
edited: {
type: 'object',
description: 'Edit information if message was edited',
properties: {
user: { type: 'string', description: 'User ID who edited' },
ts: { type: 'string', description: 'Edit timestamp' },
},
},
permalink: { type: 'string', description: 'Permanent link to message' },
},
},
},
Expand Down
Loading