Added Slack post message tool. Tested, publishes message correctly but proxy needs to be setup

This commit is contained in:
Waleed Latif
2025-02-02 23:43:31 -08:00
parent a040708997
commit 0e99fdd311
5 changed files with 153 additions and 3 deletions

57
blocks/blocks/slack.ts Normal file
View File

@@ -0,0 +1,57 @@
import { SlackIcon } from '@/components/icons'
import { BlockConfig } from '../types'
import { SlackMessageResponse } from '@/tools/slack/message'
export const SlackMessageBlock: BlockConfig<SlackMessageResponse> = {
type: 'slack_message',
toolbar: {
title: 'Slack Message',
description: 'Send a message to Slack',
bgColor: '#611f69',
icon: SlackIcon,
category: 'advanced'
},
tools: {
access: ['slack.message']
},
workflow: {
inputs: {
apiKey: { type: 'string', required: true },
channel: { type: 'string', required: true },
text: { type: 'string', required: true }
},
outputs: {
response: {
type: {
ts: 'string',
channel: 'string'
}
}
},
subBlocks: [
{
id: 'apiKey',
title: 'OAuth Token',
type: 'short-input',
layout: 'full',
placeholder: 'Enter your Slack OAuth token',
password: true,
connectionDroppable: false
},
{
id: 'channel',
title: 'Channel',
type: 'short-input',
layout: 'full',
placeholder: 'Enter Slack channel (e.g., #general)'
},
{
id: 'text',
title: 'Message',
type: 'long-input',
layout: 'full',
placeholder: 'Enter your alert message'
}
]
}
}

View File

@@ -8,6 +8,7 @@ import { CrewAIVisionBlock } from './blocks/crewai'
import { FirecrawlScrapeBlock } from './blocks/firecrawl'
import { JinaBlock } from './blocks/jina'
import { TranslateBlock } from './blocks/translate'
import { SlackMessageBlock } from './blocks/slack'
// Export blocks for ease of use
export {
@@ -17,7 +18,8 @@ export {
CrewAIVisionBlock,
FirecrawlScrapeBlock,
JinaBlock,
TranslateBlock
TranslateBlock,
SlackMessageBlock
}
// Registry of all block configurations
@@ -28,7 +30,8 @@ const blocks: Record<string, BlockConfig> = {
crewai_vision: CrewAIVisionBlock,
firecrawl_scrape: FirecrawlScrapeBlock,
jina_reader: JinaBlock,
translate: TranslateBlock
translate: TranslateBlock,
slack_message: SlackMessageBlock
}
// Build a reverse mapping of tools to block types

View File

@@ -978,3 +978,18 @@ export const TranslateIcon = (props: SVGProps<SVGSVGElement>) => (
<path d="M14 18h6" />
</svg>
)
export const SlackIcon = (props: SVGProps<SVGSVGElement>) => (
<svg
viewBox="0 0 256 256"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<g>
<path d="M53.8412698,161.320635 C53.8412698,176.152381 41.8539683,188.139683 27.0222222,188.139683 C12.1904762,188.139683 0.203174603,176.152381 0.203174603,161.320635 C0.203174603,146.488889 12.1904762,134.501587 27.0222222,134.501587 L53.8412698,134.501587 L53.8412698,161.320635 Z M67.2507937,161.320635 C67.2507937,146.488889 79.2380952,134.501587 94.0698413,134.501587 C108.901587,134.501587 120.888889,146.488889 120.888889,161.320635 L120.888889,228.368254 C120.888889,243.2 108.901587,255.187302 94.0698413,255.187302 C79.2380952,255.187302 67.2507937,243.2 67.2507937,228.368254 L67.2507937,161.320635 Z" fill="#E01E5A" />
<path d="M94.0698413,53.6380952 C79.2380952,53.6380952 67.2507937,41.6507937 67.2507937,26.8190476 C67.2507937,11.9873016 79.2380952,-7.10542736e-15 94.0698413,-7.10542736e-15 C108.901587,-7.10542736e-15 120.888889,11.9873016 120.888889,26.8190476 L120.888889,53.6380952 L94.0698413,53.6380952 Z M94.0698413,67.2507937 C108.901587,67.2507937 120.888889,79.2380952 120.888889,94.0698413 C120.888889,108.901587 108.901587,120.888889 94.0698413,120.888889 L26.8190476,120.888889 C11.9873016,120.888889 0,108.901587 0,94.0698413 C0,79.2380952 11.9873016,67.2507937 26.8190476,67.2507937 L94.0698413,67.2507937 Z" fill="#36C5F0" />
<path d="M201.549206,94.0698413 C201.549206,79.2380952 213.536508,67.2507937 228.368254,67.2507937 C243.2,67.2507937 255.187302,79.2380952 255.187302,94.0698413 C255.187302,108.901587 243.2,120.888889 228.368254,120.888889 L201.549206,120.888889 L201.549206,94.0698413 Z M188.139683,94.0698413 C188.139683,108.901587 176.152381,120.888889 161.320635,120.888889 C146.488889,120.888889 134.501587,108.901587 134.501587,94.0698413 L134.501587,26.8190476 C134.501587,11.9873016 146.488889,-1.42108547e-14 161.320635,-1.42108547e-14 C176.152381,-1.42108547e-14 188.139683,11.9873016 188.139683,26.8190476 L188.139683,94.0698413 Z" fill="#2EB67D" />
<path d="M161.320635,201.549206 C176.152381,201.549206 188.139683,213.536508 188.139683,228.368254 C188.139683,243.2 176.152381,255.187302 161.320635,255.187302 C146.488889,255.187302 134.501587,243.2 134.501587,228.368254 L134.501587,201.549206 L161.320635,201.549206 Z M161.320635,188.139683 C146.488889,188.139683 134.501587,176.152381 134.501587,161.320635 C134.501587,146.488889 146.488889,134.501587 161.320635,134.501587 L228.571429,134.501587 C243.403175,134.501587 255.390476,146.488889 255.390476,161.320635 C255.390476,176.152381 243.403175,188.139683 228.571429,188.139683 L161.320635,188.139683 Z" fill="#ECB22E" />
</g>
</svg>
)

View File

@@ -12,6 +12,8 @@ import { functionExecuteTool as functionExecute } from './function/execute'
import { visionTool as crewAIVision } from './crewai/vision'
import { scrapeTool } from './firecrawl/scrape'
import { readUrlTool } from './jina/reader'
import { slackMessageTool } from './slack/message'
// Registry of all available tools
export const tools: Record<string, ToolConfig> = {
// AI Models
@@ -33,7 +35,9 @@ export const tools: Record<string, ToolConfig> = {
// Firecrawl Tools
'firecrawl.scrape': scrapeTool,
// Jina Tools
'jina.readurl': readUrlTool
'jina.readurl': readUrlTool,
// Slack Tools
'slack.message': slackMessageTool
}
// Get a tool by its ID

71
tools/slack/message.ts Normal file
View File

@@ -0,0 +1,71 @@
import { ToolConfig, ToolResponse } from '../types'
export interface SlackMessageParams {
apiKey: string
channel: string
text: string
}
export interface SlackMessageResponse extends ToolResponse {
output: {
ts: string
channel: string
}
}
export const slackMessageTool: ToolConfig<SlackMessageParams, SlackMessageResponse> = {
id: 'slack.message',
name: 'Slack Message',
description: 'Send a message to a Slack channel',
version: '1.0.0',
params: {
apiKey: {
type: 'string',
required: true,
description: 'Your Slack API token'
},
channel: {
type: 'string',
required: true,
description: 'Target Slack channel (e.g., #general)'
},
text: {
type: 'string',
required: true,
description: 'Message text to send'
}
},
request: {
url: 'https://slack.com/api/chat.postMessage',
method: 'POST',
headers: (params: SlackMessageParams) => ({
'Content-Type': 'application/json',
'Authorization': `Bearer ${params.apiKey}`
}),
body: (params: SlackMessageParams) => ({
channel: params.channel,
text: params.text
})
},
transformResponse: async (response: Response) => {
const data = await response.json()
if (!data.ok) {
throw new Error(data.error || 'Slack API error')
}
return {
success: true,
output: {
ts: data.ts,
channel: data.channel
}
}
},
transformError: (error: any) => {
const message = error.message || 'Slack message failed'
return message
}
}