Skip to content

Commit cccd7ae

Browse files
fix(slack): address workflow API review findings
1 parent 2071b46 commit cccd7ae

22 files changed

Lines changed: 250 additions & 53 deletions

‎apps/docs/content/docs/integrations/slack.mdx‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2251,7 +2251,7 @@ Start an asynchronous CSV or JSON List export. Use the returned job_id with Get
22512251

22522252
### Slack Get List Export
22532253

2254-
Read a List export job status and its download URL when ready. Format and inclusion options must match Start List Export.
2254+
Read a List export job status and its download URL when ready. Format, Include Threads, and Include Attachments must match Start List Export.
22552255

22562256
#### Input
22572257

@@ -2340,7 +2340,7 @@ Join a public Slack channel as the authenticated bot.
23402340
| Parameter | Type | Description |
23412341
| --------- | ---- | ----------- |
23422342
| `ok` | boolean | Ok |
2343-
| `channel` | object | Conversation |
2343+
| `conversation` | object | Conversation |
23442344
| ↳ `id` | string | Id |
23452345
| ↳ `name` | string | Name |
23462346
| ↳ `creator` | string | Creator |
@@ -2462,7 +2462,7 @@ Open a DM or group DM with 1–8 user IDs, or resume a conversation by ID. Suppl
24622462
| Parameter | Type | Description |
24632463
| --------- | ---- | ----------- |
24642464
| `ok` | boolean | Ok |
2465-
| `channel` | object | Conversation |
2465+
| `conversation` | object | Conversation |
24662466
| ↳ `id` | string | Id |
24672467
| ↳ `name` | string | Name |
24682468
| ↳ `creator` | string | Creator |
@@ -2725,7 +2725,7 @@ List one page of Slack files matching user, channel, type, or timestamp filters.
27252725
| Parameter | Type | Description |
27262726
| --------- | ---- | ----------- |
27272727
| `ok` | boolean | Ok |
2728-
| `files` | array | Files |
2728+
| `fileMetadata` | array | Files |
27292729
| ↳ `id` | string | Id |
27302730
| ↳ `name` | string | Name |
27312731
| ↳ `title` | string | Title |
@@ -3261,7 +3261,7 @@ Read the user IDs in a Slack user group.
32613261
| Parameter | Type | Required | Description |
32623262
| --------- | ---- | -------- | ----------- |
32633263
| `usergroup` | string | Yes | User Group ID |
3264-
| `include_disabled` | boolean | No | Include Disabled Groups |
3264+
| `include_disabled` | boolean | No | Include Disabled Users |
32653265
| `team_id` | string | No | Workspace ID |
32663266

32673267
#### Output
@@ -3372,7 +3372,7 @@ Search messages visible to the authorized Slack user. Requires a managed user cr
33723372

33733373
### Slack Search Files
33743374

3375-
Search files visible to the authorized Slack user. Requires a managed user credential with search:read. Continue using files.paging.
3375+
Search files visible to the authorized Slack user. Requires a managed user credential with search:read. Continue using fileSearchResults.paging.
33763376

33773377
#### Input
33783378

@@ -3392,7 +3392,7 @@ Search files visible to the authorized Slack user. Requires a managed user crede
33923392
| --------- | ---- | ----------- |
33933393
| `ok` | boolean | Ok |
33943394
| `query` | string | Query |
3395-
| `files` | object | Filesearch |
3395+
| `fileSearchResults` | object | Filesearch |
33963396
| ↳ `matches` | array | Matches |
33973397
| ↳ `id` | string | Id |
33983398
| ↳ `name` | string | Name |
@@ -3487,7 +3487,7 @@ Search messages and files visible to the authorized Slack user. Requires a manag
34873487
| ↳ `page_count` | number | Page count |
34883488
| ↳ `per_page` | number | Per page |
34893489
| ↳ `total_count` | number | Total count |
3490-
| `files` | object | Filesearch |
3490+
| `fileSearchResults` | object | Filesearch |
34913491
| ↳ `matches` | array | Matches |
34923492
| ↳ `id` | string | Id |
34933493
| ↳ `name` | string | Name |

‎apps/sim/blocks/blocks/slack-workflow-operations.test.ts‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,30 @@ describe('Slack workflow operations in the existing block', () => {
5454
}
5555
)
5656

57+
it('keeps message output types while exposing conversation and file metadata separately', () => {
58+
expect(SlackV2Block.outputs.channel.type).toBe('string')
59+
expect(SlackV2Block.outputs.files.type).toBe('file[]')
60+
for (const key of ['conversation', 'fileMetadata', 'fileSearchResults'])
61+
expect(SlackV2Block.outputs[key].type).toBe('json')
62+
})
63+
64+
it('does not offer Canvas ownership for channels and clears stale access choices', () => {
65+
const field = SlackV2Block.subBlocks.find(({ id }) => id === 'slack_share_canvas_access_level')!
66+
const options = field.options
67+
if (typeof options !== 'function') throw new Error('Expected dynamic access options')
68+
for (const channels of ['["C1"]', ['C1'], '<Block.channels>']) {
69+
expect(
70+
options({ values: { slack_share_canvas_channel_ids: channels } }).map(({ id }) => id)
71+
).toEqual(['read', 'write'])
72+
}
73+
for (const channels of ['', '[]', [], undefined]) {
74+
expect(
75+
options({ values: { slack_share_canvas_channel_ids: channels } }).map(({ id }) => id)
76+
).toContain('owner')
77+
}
78+
expect(field.dependsOn).toEqual(['slack_share_canvas_channel_ids'])
79+
})
80+
5781
it('keeps target alternatives available in basic mode', () => {
5882
for (const [operation, params] of [
5983
['open_conversation', ['users', 'channel']],
@@ -164,6 +188,17 @@ describe('Slack custom-app permissions', () => {
164188
)
165189
})
166190

191+
it('grants conversation reads when only conversation management is enabled', () => {
192+
const manifest = buildSlackManifest(new Set(['action_manage_conversations']), {
193+
appName: 'Test',
194+
webhookUrl: 'https://example.com/slack',
195+
})
196+
const oauth = manifest.oauth_config as { scopes: { bot: string[] } }
197+
expect(oauth.scopes.bot).toEqual(
198+
expect.arrayContaining(['channels:read', 'groups:read', 'im:read', 'mpim:read'])
199+
)
200+
})
201+
167202
it('covers user-only operations through managed user scopes and leaves native Sim scopes unchanged', () => {
168203
for (const operation of SLACK_WORKFLOW_OPERATIONS.filter(({ auth }) => auth === 'user')) {
169204
expect(SLACK_MANAGED_USER_SCOPES).toEqual(

‎apps/sim/blocks/blocks/slack-workflow-operations.ts‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ interface SlackWorkflowField {
1313
type: 'string' | 'boolean' | 'number' | 'json'
1414
required: boolean
1515
enum?: string[]
16+
options?: SubBlockConfig['options']
17+
dependsOn?: string[]
1618
default?: string
1719
allowEmpty?: boolean
1820
basic?: boolean
@@ -192,6 +194,18 @@ export const SLACK_WORKFLOW_OPERATIONS: readonly SlackWorkflowOperation[] = [
192194
type: 'string',
193195
required: true,
194196
enum: ['read', 'write', 'owner'],
197+
dependsOn: ['slack_share_canvas_channel_ids'],
198+
options: ({ values } = { values: {} }) => {
199+
const channels = values.slack_share_canvas_channel_ids
200+
const hasChannels = Array.isArray(channels)
201+
? channels.length > 0
202+
: typeof channels === 'string' && channels.trim() !== '' && channels.trim() !== '[]'
203+
return [
204+
{ id: 'read', label: 'Can view' },
205+
{ id: 'write', label: 'Can edit' },
206+
...(!hasChannels ? [{ id: 'owner', label: 'Owner (users only)' }] : []),
207+
]
208+
},
195209
default: 'read',
196210
},
197211
{
@@ -1175,7 +1189,7 @@ export const SLACK_WORKFLOW_OPERATIONS: readonly SlackWorkflowOperation[] = [
11751189
{
11761190
id: 'slack_list_user_group_members_include_disabled',
11771191
param: 'include_disabled',
1178-
title: 'Include Disabled Groups',
1192+
title: 'Include Disabled Users',
11791193
type: 'boolean',
11801194
required: false,
11811195
},
@@ -1653,7 +1667,8 @@ export function getSlackWorkflowSubBlocks(): SubBlockConfig[] {
16531667
...(field.type === 'json' ? { language: 'json' as const } : {}),
16541668
...(field.enum
16551669
? {
1656-
options: field.enum.map((value) => ({ id: value, label: value })),
1670+
options: field.options ?? field.enum.map((value) => ({ id: value, label: value })),
1671+
...(field.dependsOn ? { dependsOn: field.dependsOn } : {}),
16571672
...(field.default === undefined ? {} : { value: () => field.default! }),
16581673
}
16591674
: {}),

‎apps/sim/blocks/blocks/slack.ts‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3987,13 +3987,17 @@ export const SlackV2Block: BlockConfig<SlackResponse> = {
39873987
type: 'json',
39883988
description: 'Conversation messages, or search results with matches and paging',
39893989
},
3990-
files: {
3990+
fileMetadata: {
39913991
type: 'json',
3992-
description: 'File metadata, or search results with matches and paging',
3992+
description: 'Slack file metadata (id, name, title, mimetype, permalink)',
39933993
},
3994-
channel: {
3994+
fileSearchResults: {
39953995
type: 'json',
3996-
description: 'Conversation ID or opened conversation details, depending on the operation',
3996+
description: 'File search results with matches and paging',
3997+
},
3998+
conversation: {
3999+
type: 'json',
4000+
description: 'Opened or joined conversation details (id, name, is_im, is_mpim)',
39974001
},
39984002

39994003
listId: { type: 'string', description: 'Created List ID' },

‎apps/sim/tools/generated/tool-metadata.ts‎

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

‎apps/sim/tools/generated/tool-outputs.ts‎

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

‎apps/sim/tools/slack/fixtures/workflow-api-responses.json‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,16 @@
12951295
"slack_get_dnd_info": [
12961296
{
12971297
"ok": true
1298+
},
1299+
{
1300+
"ok": true,
1301+
"dnd_enabled": true,
1302+
"next_dnd_start_ts": 1450416600,
1303+
"next_dnd_end_ts": 1450452600,
1304+
"snooze_enabled": true,
1305+
"snooze_endtime": 1450416600,
1306+
"snooze_remaining": 1196,
1307+
"snooze_is_indefinite": false
12981308
}
12991309
],
13001310
"slack_get_team_dnd_info": [

‎apps/sim/tools/slack/join_conversation.ts‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ export const slackJoinConversationTool = createSlackWebApiTool({
2424
},
2525
},
2626
input: z.object({ channel: z.string().trim().min(1) }),
27-
output: z.object({ ok: z.literal(true), channel: conversationSchema }),
28-
outputs: { ok: { type: 'boolean', description: 'Ok' }, channel: { ...conversationOutput } },
27+
output: z
28+
.object({ ok: z.literal(true), channel: conversationSchema })
29+
.transform(({ channel, ...rest }) => ({ ...rest, conversation: channel })),
30+
outputs: { ok: { type: 'boolean', description: 'Ok' }, conversation: { ...conversationOutput } },
2931
})

‎apps/sim/tools/slack/list_files.ts‎

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,16 @@ export const slackListFilesTool = createSlackWebApiTool({
6363
show_files_hidden_by_limit: z.boolean().optional(),
6464
team_id: z.string().trim().min(1).optional(),
6565
}),
66-
output: z.object({
67-
ok: z.literal(true),
68-
files: z.array(fileSchema),
69-
paging: pagingSchema.optional(),
70-
}),
66+
output: z
67+
.object({
68+
ok: z.literal(true),
69+
files: z.array(fileSchema),
70+
paging: pagingSchema.optional(),
71+
})
72+
.transform(({ files, ...rest }) => ({ ...rest, fileMetadata: files })),
7173
outputs: {
7274
ok: { type: 'boolean', description: 'Ok' },
73-
files: { type: 'array', description: 'Files', items: { ...fileOutput } },
75+
fileMetadata: { type: 'array', description: 'Files', items: { ...fileOutput } },
7476
paging: { ...pagingOutput, optional: true },
7577
},
7678
})

‎apps/sim/tools/slack/list_user_group_members.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const slackListUserGroupMembersTool = createSlackWebApiTool({
2525
type: 'boolean',
2626
required: false,
2727
visibility: 'user-or-llm',
28-
description: 'Include Disabled Groups',
28+
description: 'Include Disabled Users',
2929
},
3030
team_id: {
3131
type: 'string',

0 commit comments

Comments
 (0)