mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
feat(slack): added slack full message object in response (#1987)
This commit is contained in:
@@ -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`
|
||||
|
||||
@@ -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 |
|
||||
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
@@ -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,
|
||||
},
|
||||
@@ -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,
|
||||
},
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -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
|
||||
@@ -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' },
|
||||
|
||||
@@ -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)',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
@@ -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' },
|
||||
files: {
|
||||
// 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: {
|
||||
id: { type: 'string' },
|
||||
name: { type: 'string' },
|
||||
mimetype: { type: 'string' },
|
||||
size: { type: 'number' },
|
||||
url_private: { type: 'string' },
|
||||
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', 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' },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -51,8 +51,12 @@ export interface SlackAddReactionParams extends SlackBaseParams {
|
||||
|
||||
export interface SlackMessageResponse extends ToolResponse {
|
||||
output: {
|
||||
// Legacy properties for backward compatibility
|
||||
ts: string
|
||||
channel: string
|
||||
fileCount?: number
|
||||
// New comprehensive message object
|
||||
message: SlackMessage
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,22 +68,96 @@ export interface SlackCanvasResponse extends ToolResponse {
|
||||
}
|
||||
}
|
||||
|
||||
export interface SlackReaction {
|
||||
name: string
|
||||
count: number
|
||||
users: string[]
|
||||
}
|
||||
|
||||
export interface SlackMessageEdited {
|
||||
user: string
|
||||
ts: string
|
||||
}
|
||||
|
||||
export interface SlackAttachment {
|
||||
id?: number
|
||||
fallback?: string
|
||||
text?: string
|
||||
pretext?: string
|
||||
color?: string
|
||||
fields?: Array<{
|
||||
title: string
|
||||
value: string
|
||||
short?: boolean
|
||||
}>
|
||||
author_name?: string
|
||||
author_link?: string
|
||||
author_icon?: string
|
||||
title?: string
|
||||
title_link?: string
|
||||
image_url?: string
|
||||
thumb_url?: string
|
||||
footer?: string
|
||||
footer_icon?: string
|
||||
ts?: string
|
||||
}
|
||||
|
||||
export interface SlackBlock {
|
||||
type: string
|
||||
block_id?: string
|
||||
[key: string]: any // Blocks can have various properties depending on type
|
||||
}
|
||||
|
||||
export interface SlackMessage {
|
||||
// Core properties
|
||||
type: string
|
||||
ts: string
|
||||
text: string
|
||||
user?: string
|
||||
bot_id?: string
|
||||
username?: string
|
||||
channel?: string
|
||||
team?: string
|
||||
|
||||
// Thread properties
|
||||
thread_ts?: string
|
||||
parent_user_id?: string
|
||||
reply_count?: number
|
||||
reply_users_count?: number
|
||||
latest_reply?: string
|
||||
subscribed?: boolean
|
||||
last_read?: string
|
||||
unread_count?: number
|
||||
|
||||
// Message subtype
|
||||
subtype?: string
|
||||
|
||||
// Reactions and interactions
|
||||
reactions?: SlackReaction[]
|
||||
is_starred?: boolean
|
||||
pinned_to?: string[]
|
||||
|
||||
// Content attachments
|
||||
files?: Array<{
|
||||
id: string
|
||||
name: string
|
||||
mimetype: string
|
||||
size: number
|
||||
url_private?: string
|
||||
permalink?: string
|
||||
mode?: string
|
||||
}>
|
||||
attachments?: SlackAttachment[]
|
||||
blocks?: SlackBlock[]
|
||||
|
||||
// Metadata
|
||||
edited?: SlackMessageEdited
|
||||
permalink?: string
|
||||
}
|
||||
|
||||
export interface SlackMessageReaderResponse extends ToolResponse {
|
||||
output: {
|
||||
messages: Array<{
|
||||
ts: string
|
||||
text: string
|
||||
user: string
|
||||
type: string
|
||||
subtype?: string
|
||||
files?: Array<{
|
||||
id: string
|
||||
name: string
|
||||
mimetype: string
|
||||
size: number
|
||||
url_private?: string
|
||||
}>
|
||||
}>
|
||||
messages: SlackMessage[]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,12 +174,15 @@ export interface SlackDownloadResponse extends ToolResponse {
|
||||
|
||||
export interface SlackUpdateMessageResponse extends ToolResponse {
|
||||
output: {
|
||||
// Legacy properties for backward compatibility
|
||||
content: string
|
||||
metadata: {
|
||||
channel: string
|
||||
timestamp: string
|
||||
text: string
|
||||
}
|
||||
// New comprehensive message object
|
||||
message: SlackMessage
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -72,30 +72,21 @@ export const slackUpdateMessageTool: ToolConfig<
|
||||
const data = await response.json()
|
||||
|
||||
if (!data.success) {
|
||||
return {
|
||||
success: false,
|
||||
output: {
|
||||
content: data.error || 'Failed to update message',
|
||||
metadata: {
|
||||
channel: '',
|
||||
timestamp: '',
|
||||
text: '',
|
||||
},
|
||||
},
|
||||
error: data.error,
|
||||
}
|
||||
throw new Error(data.error || 'Failed to update message')
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: {
|
||||
content: data.output.content,
|
||||
metadata: data.output.metadata,
|
||||
},
|
||||
output: data.output,
|
||||
}
|
||||
},
|
||||
|
||||
outputs: {
|
||||
message: {
|
||||
type: 'object',
|
||||
description: 'Complete updated message object with all properties returned by Slack',
|
||||
},
|
||||
// Legacy properties for backward compatibility
|
||||
content: { type: 'string', description: 'Success message' },
|
||||
metadata: {
|
||||
type: 'object',
|
||||
|
||||
Reference in New Issue
Block a user