Skip to content

Commit 1404e65

Browse files
fix(slack): restore assistant operation compatibility (#7339)
* fix(slack): restore assistant operation compatibility * fix(slack): split assistant and agent prompts
1 parent 694c34b commit 1404e65

4 files changed

Lines changed: 179 additions & 32 deletions

File tree

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

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -816,6 +816,51 @@ Get a stable permalink URL to a specific Slack message.
816816
| `channel` | string | Channel ID containing the message |
817817
| `permalink` | string | The permalink URL to the message |
818818

819+
### Slack Set Assistant Status
820+
821+
Set or clear the assistant thread status indicator (the loading shimmer) on a Slack AI app thread. Pass an empty status to clear it.
822+
823+
#### Input
824+
825+
| Parameter | Type | Required | Description |
826+
| --------- | ---- | -------- | ----------- |
827+
| `authMethod` | string | No | Authentication method: oauth or bot_token |
828+
| `botToken` | string | No | Bot token for Custom Bot |
829+
| `channel` | string | Yes | Channel ID containing the assistant thread \(e.g., C1234567890 or D1234567890\) |
830+
| `threadTs` | string | Yes | Thread timestamp \(thread_ts\) of the assistant thread \(e.g., 1405894322.002768\) |
831+
| `status` | string | No | Status text to display, e.g. 'Working on it…'. Omit or pass an empty string to clear the status. |
832+
| `loadingMessages` | json | No | Optional list of messages to rotate through as an animated loading indicator \(max 10\). |
833+
834+
#### Output
835+
836+
| Parameter | Type | Description |
837+
| --------- | ---- | ----------- |
838+
| `ok` | boolean | Whether the status was set successfully |
839+
| `channel` | string | Channel ID the status was set on |
840+
| `threadTs` | string | Thread timestamp the status was set on |
841+
842+
### Slack Set Assistant Title
843+
844+
Set the title of a Slack assistant thread (shown in the AI app thread header).
845+
846+
#### Input
847+
848+
| Parameter | Type | Required | Description |
849+
| --------- | ---- | -------- | ----------- |
850+
| `authMethod` | string | No | Authentication method: oauth or bot_token |
851+
| `botToken` | string | No | Bot token for Custom Bot |
852+
| `channel` | string | Yes | Channel ID containing the assistant thread \(e.g., C1234567890 or D1234567890\) |
853+
| `threadTs` | string | Yes | Thread timestamp \(thread_ts\) of the assistant thread \(e.g., 1405894322.002768\) |
854+
| `title` | string | Yes | The title to display for the assistant thread |
855+
856+
#### Output
857+
858+
| Parameter | Type | Description |
859+
| --------- | ---- | ----------- |
860+
| `ok` | boolean | Whether the title was set successfully |
861+
| `channel` | string | Channel ID the title was set on |
862+
| `threadTs` | string | Thread timestamp the title was set on |
863+
819864
### Slack Set Suggested Prompts
820865

821866
Set the clickable suggested prompts shown in a Slack assistant thread (the prompt chips in an AI app).

apps/sim/blocks/blocks/slack.test.ts

Lines changed: 85 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* @vitest-environment node
33
*/
44
import { describe, expect, it } from 'vitest'
5+
import { evaluateSubBlockCondition } from '@/lib/workflows/subblocks/visibility'
56
import {
67
getSlackV2ActionSubBlocks,
78
getSlackV2OperationSentences,
@@ -11,7 +12,7 @@ import {
1112
} from '@/blocks/blocks/slack'
1213

1314
const AGENT_OPERATION_IDS = [
14-
'set_suggested_prompts',
15+
'set_agent_suggested_prompts',
1516
'set_agent_session_status',
1617
'rename_agent_session',
1718
]
@@ -20,6 +21,8 @@ const AGENT_TOOL_IDS = [
2021
'slack_set_agent_session_status_v2',
2122
'slack_rename_agent_session_v2',
2223
]
24+
const ASSISTANT_OPERATION_IDS = ['set_status', 'set_title', 'set_suggested_prompts']
25+
const ASSISTANT_TOOL_IDS = ['slack_set_status', 'slack_set_title']
2326

2427
function operationIds(): string[] {
2528
const operation = SlackV2Block.subBlocks.find((subBlock) => subBlock.id === 'operation')
@@ -32,6 +35,12 @@ function mapSlackV2Params(params: Record<string, unknown>): Record<string, unkno
3235
return mapParams(params)
3336
}
3437

38+
function isSlackV2SubBlockVisible(subBlockId: string, values: Record<string, unknown>): boolean {
39+
const subBlock = SlackV2Block.subBlocks.find((candidate) => candidate.id === subBlockId)
40+
if (!subBlock) throw new Error(`Slack v2 subblock not found: ${subBlockId}`)
41+
return evaluateSubBlockCondition(subBlock.condition, values)
42+
}
43+
3544
describe('Slack block release', () => {
3645
it('releases slack_v2 and keeps the legacy block executable but hidden', () => {
3746
expect(SlackBlock.hideFromToolbar).toBe(true)
@@ -41,21 +50,27 @@ describe('Slack block release', () => {
4150
expect(SlackV2Block.sunset).toBeUndefined()
4251
})
4352

44-
it('replaces legacy assistant operations with custom-bot Agent Sessions operations', () => {
45-
expect(operationIds()).toEqual(expect.arrayContaining(AGENT_OPERATION_IDS))
46-
for (const id of ['set_status', 'set_title']) {
47-
expect(operationIds()).not.toContain(id)
48-
}
49-
expect(getSlackV2ToolAccess()).toEqual(expect.arrayContaining(AGENT_TOOL_IDS))
53+
it('adds custom-bot Agent Sessions operations without removing assistant operations', () => {
54+
expect(operationIds()).toEqual(
55+
expect.arrayContaining([...ASSISTANT_OPERATION_IDS, ...AGENT_OPERATION_IDS])
56+
)
57+
expect(getSlackV2ToolAccess()).toEqual(
58+
expect.arrayContaining([...ASSISTANT_TOOL_IDS, ...AGENT_TOOL_IDS])
59+
)
5060
expect(getSlackV2ToolAccess()).toContain('slack_set_suggested_prompts')
51-
for (const id of ['slack_set_status', 'slack_set_title']) {
52-
expect(getSlackV2ToolAccess()).not.toContain(id)
53-
}
5461
expect(Object.keys(getSlackV2OperationSentences())).toEqual(
55-
expect.arrayContaining(AGENT_OPERATION_IDS)
62+
expect.arrayContaining([...ASSISTANT_OPERATION_IDS, ...AGENT_OPERATION_IDS])
5663
)
5764
})
5865

66+
it('keeps assistant operations routed to their original tools', () => {
67+
const selectTool = SlackV2Block.tools.config?.tool
68+
if (!selectTool) throw new Error('Slack v2 tool selector is required')
69+
70+
expect(selectTool({ operation: 'set_status' })).toBe('slack_set_status')
71+
expect(selectTool({ operation: 'set_title' })).toBe('slack_set_title')
72+
})
73+
5974
it('uses a service-account-only picker for Agent Sessions operations', () => {
6075
const credential = getSlackV2ActionSubBlocks().find(
6176
(subBlock) => subBlock.id === 'agentBotCredential'
@@ -67,7 +82,7 @@ describe('Slack block release', () => {
6782
})
6883
})
6984

70-
it('keeps persisted OAuth suggested prompts on the compatibility tool', () => {
85+
it('keeps assistant suggested prompts on the original fields and tool', () => {
7186
const selectTool = SlackV2Block.tools.config?.tool
7287
if (!selectTool) throw new Error('Slack v2 tool selector is required')
7388

@@ -90,14 +105,28 @@ describe('Slack block release', () => {
90105
prompts: '[{"title":"Summarize","message":"Summarize this thread"}]',
91106
promptsTitle: 'Try asking',
92107
})
108+
109+
const assistantValues = {
110+
operation: 'set_suggested_prompts',
111+
credential: 'oauth-credential',
112+
channel: 'C123',
113+
getThreadTimestamp: '1700000000.000001',
114+
}
115+
expect(isSlackV2SubBlockVisible('credential', assistantValues)).toBe(true)
116+
expect(isSlackV2SubBlockVisible('channel', assistantValues)).toBe(true)
117+
expect(isSlackV2SubBlockVisible('getThreadTimestamp', assistantValues)).toBe(true)
118+
expect(isSlackV2SubBlockVisible('suggestedPrompts', assistantValues)).toBe(true)
119+
expect(isSlackV2SubBlockVisible('agentBotCredential', assistantValues)).toBe(false)
120+
expect(isSlackV2SubBlockVisible('agentChannel', assistantValues)).toBe(false)
121+
expect(isSlackV2SubBlockVisible('agentThreadTs', assistantValues)).toBe(false)
93122
})
94123

95124
it('uses service-account tools for new agent operations', () => {
96125
const selectTool = SlackV2Block.tools.config?.tool
97126
if (!selectTool) throw new Error('Slack v2 tool selector is required')
98127

99128
expect(
100-
selectTool({ operation: 'set_suggested_prompts', agentCredentialId: 'custom-bot' })
129+
selectTool({ operation: 'set_agent_suggested_prompts', agentCredentialId: 'custom-bot' })
101130
).toBe('slack_set_suggested_prompts_v2')
102131
expect(selectTool({ operation: 'set_agent_session_status' })).toBe(
103132
'slack_set_agent_session_status_v2'
@@ -116,5 +145,48 @@ describe('Slack block release', () => {
116145
threadTs: '1700000000.000001',
117146
status: 'processing',
118147
})
148+
149+
const agentPromptValues = {
150+
operation: 'set_agent_suggested_prompts',
151+
agentBotCredential: 'custom-bot',
152+
agentChannel: 'D123',
153+
agentThreadTs: '1700000000.000001',
154+
}
155+
expect(isSlackV2SubBlockVisible('credential', agentPromptValues)).toBe(false)
156+
expect(isSlackV2SubBlockVisible('channel', agentPromptValues)).toBe(false)
157+
expect(isSlackV2SubBlockVisible('getThreadTimestamp', agentPromptValues)).toBe(false)
158+
expect(isSlackV2SubBlockVisible('suggestedPrompts', agentPromptValues)).toBe(true)
159+
expect(isSlackV2SubBlockVisible('agentBotCredential', agentPromptValues)).toBe(true)
160+
expect(isSlackV2SubBlockVisible('agentChannel', agentPromptValues)).toBe(true)
161+
expect(isSlackV2SubBlockVisible('agentThreadTs', agentPromptValues)).toBe(true)
162+
163+
expect(
164+
mapSlackV2Params({
165+
operation: 'set_agent_suggested_prompts',
166+
agentCredentialId: 'custom-bot',
167+
agentChannelId: 'D123',
168+
agentThreadTs: '1700000000.000001',
169+
suggestedPrompts: '[{"title":"Summarize","message":"Summarize this thread"}]',
170+
promptsTitle: 'Try asking',
171+
})
172+
).toMatchObject({
173+
credential: 'custom-bot',
174+
channel: 'D123',
175+
threadTs: '1700000000.000001',
176+
prompts: '[{"title":"Summarize","message":"Summarize this thread"}]',
177+
promptsTitle: 'Try asking',
178+
})
179+
180+
const repurposedValues = {
181+
operation: 'set_agent_suggested_prompts',
182+
credential: 'stale-credential',
183+
channel: 'C123',
184+
suggestedPrompts: '[{"title":"Summarize","message":"Summarize this thread"}]',
185+
}
186+
expect(isSlackV2SubBlockVisible('credential', repurposedValues)).toBe(false)
187+
expect(isSlackV2SubBlockVisible('channel', repurposedValues)).toBe(false)
188+
expect(isSlackV2SubBlockVisible('agentBotCredential', repurposedValues)).toBe(true)
189+
expect(isSlackV2SubBlockVisible('agentChannel', repurposedValues)).toBe(true)
190+
expect(selectTool(repurposedValues)).toBe('slack_set_suggested_prompts_v2')
119191
})
120192
})

apps/sim/blocks/blocks/slack.ts

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ import { getTrigger } from '@/triggers'
1616
const DESTINATION_SWITCH_OPERATIONS = ['send', 'read', 'schedule_message'] as const
1717

1818
const SLACK_V2_AGENT_OPERATIONS = [
19-
'set_suggested_prompts',
19+
'set_agent_suggested_prompts',
2020
'set_agent_session_status',
2121
'rename_agent_session',
2222
] as const
2323

24+
const SLACK_V2_SESSION_OPERATIONS = ['set_agent_session_status', 'rename_agent_session'] as const
25+
2426
const CHANNEL_FIELD = ['channel', 'manualChannel'] as const
2527

2628
/**
@@ -2981,10 +2983,28 @@ function adaptSubBlockForV2(sb: SubBlockConfig): SubBlockConfig {
29812983
if (sb.id === 'getThreadTimestamp') {
29822984
return {
29832985
...sb,
2984-
condition: { field: 'operation', value: ['get_thread', 'get_thread_replies'] },
2986+
condition: {
2987+
field: 'operation',
2988+
value: [
2989+
'get_thread',
2990+
'get_thread_replies',
2991+
'set_status',
2992+
'set_title',
2993+
'set_suggested_prompts',
2994+
],
2995+
},
29852996
required: true,
29862997
}
29872998
}
2999+
if (sb.id === 'suggestedPrompts' || sb.id === 'promptsTitle') {
3000+
return {
3001+
...sb,
3002+
condition: {
3003+
field: 'operation',
3004+
value: ['set_suggested_prompts', 'set_agent_suggested_prompts'],
3005+
},
3006+
}
3007+
}
29883008
if (dependsOn && !Array.isArray(dependsOn) && dependsOn.all?.includes('authMethod')) {
29893009
return { ...sb, dependsOn: ['credential'] }
29903010
}
@@ -3048,10 +3068,7 @@ function getSlackV2AgentSubBlocks(): SubBlockConfig[] {
30483068
title: 'Thread Timestamp',
30493069
type: 'short-input',
30503070
placeholder: 'Thread timestamp (thread_ts)',
3051-
condition: {
3052-
field: 'operation',
3053-
value: ['set_suggested_prompts', 'set_agent_session_status', 'rename_agent_session'],
3054-
},
3071+
condition: { field: 'operation', value: [...SLACK_V2_AGENT_OPERATIONS] },
30553072
required: {
30563073
field: 'operation',
30573074
value: ['set_agent_session_status', 'rename_agent_session'],
@@ -3153,12 +3170,11 @@ export function getSlackV2OperationSentences() {
31533170
if (!operationSentences) {
31543171
throw new Error('Slack action sentences must be defined before building slack_v2')
31553172
}
3156-
const { set_status: _setStatus, set_title: _setTitle, ...v2Sentences } = operationSentences
31573173
return {
3158-
...v2Sentences,
3159-
set_suggested_prompts: [
3174+
...operationSentences,
3175+
set_agent_suggested_prompts: [
31603176
{
3161-
text: 'Set suggested prompts in',
3177+
text: 'Set agent suggested prompts in',
31623178
field: ['agentChannel', 'manualAgentChannel'],
31633179
core: true,
31643180
},
@@ -3239,7 +3255,10 @@ export const SlackV2Block: BlockConfig<SlackResponse> = {
32393255
{ label: 'Get Thread Replies', id: 'get_thread_replies' },
32403256
{ label: 'Get Channel History', id: 'get_channel_history' },
32413257
{ label: 'Get Message Permalink', id: 'get_permalink' },
3242-
{ label: 'Set Suggested Prompts', id: 'set_suggested_prompts' },
3258+
{ label: 'Set Assistant Status', id: 'set_status' },
3259+
{ label: 'Set Assistant Title', id: 'set_title' },
3260+
{ label: 'Set Assistant Suggested Prompts', id: 'set_suggested_prompts' },
3261+
{ label: 'Set Agent Suggested Prompts', id: 'set_agent_suggested_prompts' },
32433262
{ label: 'Set Agent Session Status', id: 'set_agent_session_status' },
32443263
{ label: 'Rename Agent Session', id: 'rename_agent_session' },
32453264
{ label: 'List Channels', id: 'list_channels' },
@@ -3290,6 +3309,8 @@ export const SlackV2Block: BlockConfig<SlackResponse> = {
32903309
'slack_get_thread_replies',
32913310
'slack_get_channel_history',
32923311
'slack_get_permalink',
3312+
'slack_set_status',
3313+
'slack_set_title',
32933314
'slack_set_suggested_prompts',
32943315
'slack_set_suggested_prompts_v2',
32953316
'slack_set_agent_session_status_v2',
@@ -3329,9 +3350,9 @@ export const SlackV2Block: BlockConfig<SlackResponse> = {
33293350
tool: (params) => {
33303351
switch (params.operation) {
33313352
case 'set_suggested_prompts':
3332-
return params.agentCredentialId
3333-
? 'slack_set_suggested_prompts_v2'
3334-
: 'slack_set_suggested_prompts'
3353+
return 'slack_set_suggested_prompts'
3354+
case 'set_agent_suggested_prompts':
3355+
return 'slack_set_suggested_prompts_v2'
33353356
case 'set_agent_session_status':
33363357
return 'slack_set_agent_session_status_v2'
33373358
case 'rename_agent_session':
@@ -3348,9 +3369,6 @@ export const SlackV2Block: BlockConfig<SlackResponse> = {
33483369
if (!mapParams) throw new Error('Slack parameter mapper is required')
33493370
const baseParams = mapParams(params)
33503371
if (!SLACK_V2_AGENT_OPERATIONS.includes(params.operation as never)) return baseParams
3351-
if (params.operation === 'set_suggested_prompts' && !params.agentCredentialId) {
3352-
return baseParams
3353-
}
33543372

33553373
return {
33563374
...baseParams,

packages/deployment-config/src/integrations.json

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21273,9 +21273,21 @@
2127321273
"description": "Get a stable permalink URL to a specific Slack message."
2127421274
},
2127521275
{
21276-
"name": "Set Suggested Prompts",
21276+
"name": "Set Assistant Status",
21277+
"description": "Set or clear the assistant thread status indicator (the loading shimmer) on a Slack AI app thread. Pass an empty status to clear it."
21278+
},
21279+
{
21280+
"name": "Set Assistant Title",
21281+
"description": "Set the title of a Slack assistant thread (shown in the AI app thread header)."
21282+
},
21283+
{
21284+
"name": "Set Assistant Suggested Prompts",
2127721285
"description": "Set the clickable suggested prompts shown in a Slack assistant thread (the prompt chips in an AI app)."
2127821286
},
21287+
{
21288+
"name": "Set Agent Suggested Prompts",
21289+
"description": "Set suggested prompts in Slack Agent View, optionally scoped to a specific thread."
21290+
},
2127921291
{
2128021292
"name": "Set Agent Session Status",
2128121293
"description": "Create or update the state of a Slack agent session associated with a thread."
@@ -21405,7 +21417,7 @@
2140521417
"description": "Set the purpose (description) for a Slack channel (max 250 characters)."
2140621418
}
2140721419
],
21408-
"operationCount": 42,
21420+
"operationCount": 45,
2140921421
"triggers": [
2141021422
{
2141121423
"id": "slack_oauth",

0 commit comments

Comments
 (0)