diff --git a/.changeset/late-clouds-grow.md b/.changeset/late-clouds-grow.md new file mode 100644 index 000000000..557bf3fc7 --- /dev/null +++ b/.changeset/late-clouds-grow.md @@ -0,0 +1,5 @@ +--- +"@slack/types": minor +--- + +feat: add the `app_context_changed` event type for the agent DM experience diff --git a/packages/types/src/events/app.ts b/packages/types/src/events/app.ts index a929e0d54..cbfb53ded 100644 --- a/packages/types/src/events/app.ts +++ b/packages/types/src/events/app.ts @@ -217,6 +217,40 @@ export interface AppRateLimitedEvent { // export interface AppRateLimitedEvent { // } +export interface AppContextChangedEvent { + type: 'app_context_changed'; + channel: string; + user: string; + context: { + entities?: (( + | { + type: 'slack#/types/channel_id'; + value: string; + } + | { + type: 'slack#/types/canvas_id'; + value: string; + } + | { + type: 'slack#/types/list_id'; + value: string; + } + | { + type: 'slack#/types/message_context'; + value: { + message_ts: string; + channel_id: string; + }; + } + ) & { + score?: number; + team_id?: string; + enterprise_id?: string; + })[]; + }; + event_ts: string; +} + export interface AppUninstalledEvent { type: 'app_uninstalled'; } diff --git a/packages/types/src/events/index.ts b/packages/types/src/events/index.ts index bb4de42c0..6d7c97301 100644 --- a/packages/types/src/events/index.ts +++ b/packages/types/src/events/index.ts @@ -1,4 +1,5 @@ import type { + AppContextChangedEvent, AppDeletedEvent, AppHomeOpenedEvent, AppInstalledEvent, @@ -120,6 +121,7 @@ export * from './user'; * This is a discriminated union. The discriminant is the `type` property. */ export type SlackEvent = + | AppContextChangedEvent | AppDeletedEvent | AppHomeOpenedEvent | AppInstalledEvent diff --git a/packages/types/src/events/message.ts b/packages/types/src/events/message.ts index 060e8cf29..ddb09df4d 100644 --- a/packages/types/src/events/message.ts +++ b/packages/types/src/events/message.ts @@ -1,6 +1,7 @@ import type { Block, KnownBlock } from '../block-kit/blocks'; import type { BotProfile } from '../common/bot-profile'; import type { MessageAttachment } from '../message-attachments'; +import type { AppContextChangedEvent } from './app'; type ChannelTypes = 'channel' | 'group' | 'im' | 'mpim' | 'app_home'; @@ -60,6 +61,8 @@ export interface GenericMessageEvent { // TODO: add properties to this field once it's publicly released assistant_thread?: Record; + + app_context?: AppContextChangedEvent['context']; } export interface BotMessageEvent { diff --git a/packages/types/test/events/app.test-d.ts b/packages/types/test/events/app.test-d.ts new file mode 100644 index 000000000..e07b94357 --- /dev/null +++ b/packages/types/test/events/app.test-d.ts @@ -0,0 +1,75 @@ +import { expectAssignable, expectError } from 'tsd'; +import type { AppContextChangedEvent, SlackEvent } from '../../src/index'; + +// a channel_id context entity +const channelContextChangedEvent: AppContextChangedEvent = { + type: 'app_context_changed', + channel: 'D0123456789', + user: 'U0123456789', + context: { + entities: [ + { + type: 'slack#/types/channel_id', + value: 'C0123456789', + team_id: 'T0123456789', + score: 75, + enterprise_id: 'E0123456789', + }, + ], + }, + event_ts: '1234567890.123456', +}; +expectAssignable(channelContextChangedEvent); + +// canvas_id and list_id entities share the string `value` shape +expectAssignable({ + type: 'app_context_changed', + channel: 'D0123456789', + user: 'U0123456789', + context: { + entities: [ + { type: 'slack#/types/canvas_id', value: 'F0123456789' }, + { type: 'slack#/types/list_id', value: 'F0123456780' }, + ], + }, + event_ts: '1234567890.123456', +}); + +// a message_context entity carries an object `value` with message_ts and channel_id +expectAssignable({ + type: 'app_context_changed', + channel: 'D0123456789', + user: 'U0123456789', + context: { + entities: [ + { + type: 'slack#/types/message_context', + value: { message_ts: '1234567890.123456', channel_id: 'C0123456789' }, + team_id: 'T0123456789', + score: 75, + enterprise_id: 'E0123456789', + }, + ], + }, + event_ts: '1234567890.123456', +}); + +// `entities` is optional — the context can be empty +expectAssignable({ + type: 'app_context_changed', + channel: 'D0123456789', + user: 'U0123456789', + context: {}, + event_ts: '1234567890.123456', +}); + +// a message_context entity requires channel_id alongside message_ts +expectError({ + type: 'app_context_changed', + channel: 'D0123456789', + user: 'U0123456789', + context: { + entities: [{ type: 'slack#/types/message_context', value: { message_ts: '1234567890.123456' } }], + }, + event_ts: '1234567890.123456', +}); diff --git a/packages/types/test/events/message.test-d.ts b/packages/types/test/events/message.test-d.ts index a215379f3..0cb5df8c6 100644 --- a/packages/types/test/events/message.test-d.ts +++ b/packages/types/test/events/message.test-d.ts @@ -23,3 +23,27 @@ const messageDeletedEvent: MessageDeletedEvent = { previous_message: anyMessageEvent, }; expectAssignable(messageDeletedEvent.previous_message); + +// the agent DM context is delivered inline on messages via the `app_context` field +const messageWithAppContext: GenericMessageEvent = { + type: 'message', + subtype: undefined, + channel_type: 'im', + channel: 'D0123456789', + user: 'U0123456789', + ts: '1234567890.123456', + event_ts: '1234567890.123456', + text: 'hi', + app_context: { + entities: [ + { + type: 'slack#/types/channel_id', + value: 'C0123456789', + team_id: 'T0123456789', + score: 75, + enterprise_id: 'E0123456789', + }, + ], + }, +}; +expectAssignable(messageWithAppContext);