@shipfox/api-integration-slack 10.2.0 → 12.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,127 +1,376 @@
1
- const channelSchema = stringSchema('Slack channel ID');
2
- const cursorSchema = stringSchema('Next page cursor');
3
- const limitSchema = numberSchema('Maximum number of results to return');
1
+ const whitespacePattern = /\s+/;
2
+ // Slack caps the cumulative text across all Markdown blocks in one payload at 12,000 characters;
3
+ // content over that limit is rejected with invalid_blocks rather than truncated. Each tool here
4
+ // sends exactly one Markdown block, so the cap applies to that single block's text.
5
+ const SLACK_MARKDOWN_BLOCK_MAX_LENGTH = 12_000;
6
+ // Only the chat.* methods resolve a user ID into a direct message; conversations.* and reactions.*
7
+ // need the conversation ID itself, so the two targets are described separately.
8
+ const conversationIdSchema = stringSchema('Channel, private group, or direct message conversation ID, such as C0ABC12345 or D0ABC12345. A user ID is not accepted here');
9
+ const messageTargetSchema = stringSchema('Channel, private group, or direct message conversation ID. Pass a user ID to open a direct message with that user');
10
+ const cursorSchema = stringSchema('Pagination cursor from a previous request');
11
+ const messageSchema = {
12
+ ...stringSchema('Message content, written as standard Markdown'),
13
+ maxLength: SLACK_MARKDOWN_BLOCK_MAX_LENGTH
14
+ };
15
+ const threadTsSchema = stringSchema('Timestamp of the parent message to reply in its thread');
16
+ const replyBroadcastSchema = booleanSchema('Also send the thread reply to the channel');
4
17
  export const slackAgentToolCatalog = [
5
18
  tool({
6
- id: 'conversations_history',
7
- description: 'List messages in a Slack channel or direct message.',
19
+ id: 'read_channel',
20
+ description: 'Read messages from a Slack channel in reverse chronological order (newest first). Reading direct message history needs the ID of that conversation, not the ID of the user on the other side.',
21
+ sensitivity: 'read',
22
+ sensitive: false,
23
+ requiredScope: 'read',
24
+ inputSchema: objectSchema({
25
+ channel_id: conversationIdSchema,
26
+ oldest: stringSchema('Start of the time range, as a Slack timestamp'),
27
+ latest: stringSchema('End of the time range, as a Slack timestamp'),
28
+ limit: integerSchema('Messages to return, 1 to 100 (default 100)'),
29
+ cursor: cursorSchema
30
+ }, [
31
+ 'channel_id'
32
+ ])
33
+ }),
34
+ tool({
35
+ id: 'read_thread',
36
+ description: 'Read a Slack thread: the parent message and all of its replies. Requires the channel ID and the timestamp of the parent message.',
8
37
  sensitivity: 'read',
9
38
  sensitive: false,
10
39
  requiredScope: 'read',
11
40
  inputSchema: objectSchema({
12
- channel: channelSchema,
13
- cursor: cursorSchema,
14
- limit: limitSchema,
15
- oldest: stringSchema('Only messages after this Slack timestamp'),
16
- latest: stringSchema('Only messages before this Slack timestamp'),
17
- inclusive: booleanSchema('Include messages at the oldest or latest timestamp')
41
+ channel_id: conversationIdSchema,
42
+ message_ts: stringSchema('Timestamp of the parent message, such as 1234567890.123456'),
43
+ oldest: stringSchema('Start of the time range, as a Slack timestamp'),
44
+ latest: stringSchema('End of the time range, as a Slack timestamp'),
45
+ limit: integerSchema('Messages to return, 1 to 1000 (default 100)'),
46
+ cursor: cursorSchema
18
47
  }, [
19
- 'channel'
48
+ 'channel_id',
49
+ 'message_ts'
20
50
  ])
21
51
  }),
22
52
  tool({
23
- id: 'conversations_replies',
24
- description: 'List replies in a Slack message thread.',
53
+ id: 'read_channel_info',
54
+ description: 'Retrieve metadata for a single Slack channel by ID: name, topic, purpose, privacy, and archive status. Use this to learn what a channel is for before reading or posting. To read its messages, use read_channel instead.',
25
55
  sensitivity: 'read',
26
56
  sensitive: false,
27
57
  requiredScope: 'read',
28
58
  inputSchema: objectSchema({
29
- channel: channelSchema,
30
- ts: stringSchema('Slack timestamp of the parent message'),
31
- cursor: cursorSchema,
32
- limit: limitSchema
59
+ channel_id: conversationIdSchema,
60
+ include_num_members: booleanSchema('Include the channel member count (default false)')
33
61
  }, [
34
- 'channel',
35
- 'ts'
62
+ 'channel_id'
36
63
  ])
37
64
  }),
38
65
  tool({
39
- id: 'conversations_list',
40
- description: 'List Slack channels visible to the bot.',
66
+ id: 'read_channel_members',
67
+ description: 'List the user IDs of the members of a Slack channel. Pair it with read_user_profile to resolve a member to a name.',
41
68
  sensitivity: 'read',
42
69
  sensitive: false,
43
70
  requiredScope: 'read',
44
71
  inputSchema: objectSchema({
45
- cursor: cursorSchema,
46
- limit: limitSchema,
47
- types: stringSchema('Comma-separated channel types, such as public_channel,private_channel'),
48
- exclude_archived: booleanSchema('Exclude archived channels')
49
- })
72
+ channel_id: conversationIdSchema,
73
+ limit: integerSchema('Members to return per page (default 100)'),
74
+ cursor: cursorSchema
75
+ }, [
76
+ 'channel_id'
77
+ ])
50
78
  }),
51
79
  tool({
52
- id: 'users_info',
53
- description: 'Look up a Slack user and profile by user ID.',
80
+ id: 'read_user_profile',
81
+ description: 'Retrieve profile information for a Slack user, including contact details, status, timezone, and role.',
54
82
  sensitivity: 'read',
55
83
  sensitive: false,
56
84
  requiredScope: 'read',
57
85
  inputSchema: objectSchema({
58
- user: stringSchema('Slack user ID')
86
+ user_id: stringSchema('Slack user ID, such as U0ABC12345'),
87
+ include_locale: booleanSchema("Include the user's locale information (default false)")
59
88
  }, [
60
- 'user'
89
+ 'user_id'
61
90
  ])
62
91
  }),
63
92
  tool({
64
- id: 'chat_postMessage',
65
- description: 'Post a Slack message to a channel or thread. Provide text, blocks, or both.',
93
+ id: 'search_channels',
94
+ description: 'Search the channels this integration can see, by name, topic, or purpose. Returns channel names, IDs, topics, purposes, and archive status. Names are typically lowercase with hyphens. Space-separated terms all have to match. Only the requested page is searched, so page through with the returned cursor when a channel is missing.',
95
+ sensitivity: 'read',
96
+ sensitive: false,
97
+ requiredScope: 'read',
98
+ inputSchema: objectSchema({
99
+ query: stringSchema('Search query for finding channels'),
100
+ channel_types: stringSchema('Comma-separated channel types: public_channel, private_channel. Defaults to public_channel'),
101
+ include_archived: booleanSchema('Include archived channels in the results'),
102
+ limit: integerSchema('Channels to scan per page (default 100)'),
103
+ cursor: cursorSchema
104
+ }, [
105
+ 'query'
106
+ ])
107
+ }),
108
+ tool({
109
+ id: 'send_message',
110
+ description: 'Send a message to a Slack channel or user. To send a direct message, pass the user ID as the channel ID. Supports standard Markdown: bold, italic, strikethrough, links, lists, blockquotes, inline code, and code blocks. Returns the posted message timestamp.',
66
111
  sensitivity: 'write',
67
112
  sensitive: false,
68
113
  requiredScope: 'write',
69
114
  inputSchema: objectSchema({
70
- channel: channelSchema,
71
- text: stringSchema('Message text'),
72
- thread_ts: stringSchema('Slack timestamp of the parent message when replying in a thread'),
73
- blocks: arraySchema({
74
- type: 'object'
75
- })
115
+ channel_id: messageTargetSchema,
116
+ message: messageSchema,
117
+ thread_ts: threadTsSchema,
118
+ reply_broadcast: replyBroadcastSchema
76
119
  }, [
77
- 'channel'
120
+ 'channel_id',
121
+ 'message'
78
122
  ])
79
123
  }),
80
124
  tool({
81
- id: 'chat_update',
82
- description: 'Update a Slack message with text, blocks, or both.',
125
+ id: 'schedule_message',
126
+ description: 'Schedule a message for future delivery to a Slack channel. Does not send immediately. post_at has to be at least 2 minutes in the future and at most 120 days out. Once scheduled, the message cannot be edited.',
83
127
  sensitivity: 'write',
84
128
  sensitive: false,
85
129
  requiredScope: 'write',
86
130
  inputSchema: objectSchema({
87
- channel: channelSchema,
88
- ts: stringSchema('Slack timestamp of the message to update'),
89
- text: stringSchema('Updated message text'),
90
- blocks: arraySchema({
91
- type: 'object'
92
- })
131
+ channel_id: messageTargetSchema,
132
+ message: messageSchema,
133
+ post_at: integerSchema('Unix timestamp at which to send the message'),
134
+ thread_ts: threadTsSchema,
135
+ reply_broadcast: replyBroadcastSchema
93
136
  }, [
94
- 'channel',
95
- 'ts'
137
+ 'channel_id',
138
+ 'message',
139
+ 'post_at'
96
140
  ])
97
141
  }),
98
142
  tool({
99
- id: 'reactions_add',
143
+ id: 'update_message',
144
+ description: 'Update an already posted Slack message, replacing its content. Supports the same standard Markdown as send_message.',
145
+ sensitivity: 'write',
146
+ sensitive: false,
147
+ requiredScope: 'write',
148
+ inputSchema: objectSchema({
149
+ channel_id: conversationIdSchema,
150
+ message_ts: stringSchema('Timestamp of the message to update'),
151
+ message: messageSchema
152
+ }, [
153
+ 'channel_id',
154
+ 'message_ts',
155
+ 'message'
156
+ ])
157
+ }),
158
+ tool({
159
+ id: 'add_reaction',
100
160
  description: 'Add an emoji reaction to a Slack message.',
101
161
  sensitivity: 'write',
102
162
  sensitive: false,
103
163
  requiredScope: 'write',
104
164
  inputSchema: objectSchema({
105
- channel: channelSchema,
106
- timestamp: stringSchema('Slack timestamp of the message'),
107
- name: stringSchema('Emoji name without surrounding colons')
165
+ channel_id: conversationIdSchema,
166
+ message_ts: stringSchema('Timestamp of the message to react to'),
167
+ emoji: stringSchema('Emoji name without the surrounding colons, such as white_check_mark')
108
168
  }, [
109
- 'channel',
110
- 'timestamp',
111
- 'name'
169
+ 'channel_id',
170
+ 'message_ts',
171
+ 'emoji'
172
+ ])
173
+ }),
174
+ tool({
175
+ id: 'create_canvas',
176
+ description: 'Create a standalone Slack canvas from Markdown and return its ID. Not available on free teams.',
177
+ sensitivity: 'write',
178
+ sensitive: false,
179
+ requiredScope: 'write',
180
+ inputSchema: objectSchema({
181
+ title: stringSchema('Concise, descriptive canvas name. Do not repeat it in the content'),
182
+ content: stringSchema('Canvas body, written as standard Markdown')
183
+ }, [
184
+ 'title',
185
+ 'content'
112
186
  ])
113
187
  })
114
188
  ];
115
- export const SLACK_TOOL_METHODS = {
116
- conversations_history: 'conversations.history',
117
- conversations_replies: 'conversations.replies',
118
- conversations_list: 'conversations.list',
119
- users_info: 'users.info',
120
- chat_postMessage: 'chat.postMessage',
121
- chat_update: 'chat.update',
122
- reactions_add: 'reactions.add'
189
+ // Tool inputs follow the Slack MCP server's naming so agent prompts port across both, which means
190
+ // every call is translated to the Web API's own parameter names before it is sent.
191
+ export const SLACK_TOOL_OPERATIONS = {
192
+ read_channel: {
193
+ method: 'conversations.history',
194
+ mapArguments: ({ channel_id, oldest, latest, limit, cursor })=>({
195
+ channel: channel_id,
196
+ oldest,
197
+ latest,
198
+ limit,
199
+ cursor
200
+ })
201
+ },
202
+ read_thread: {
203
+ method: 'conversations.replies',
204
+ mapArguments: ({ channel_id, message_ts, oldest, latest, limit, cursor })=>({
205
+ channel: channel_id,
206
+ ts: message_ts,
207
+ oldest,
208
+ latest,
209
+ limit,
210
+ cursor
211
+ })
212
+ },
213
+ read_channel_info: {
214
+ method: 'conversations.info',
215
+ mapArguments: ({ channel_id, include_num_members })=>({
216
+ channel: channel_id,
217
+ include_num_members
218
+ })
219
+ },
220
+ read_channel_members: {
221
+ method: 'conversations.members',
222
+ mapArguments: ({ channel_id, limit, cursor })=>({
223
+ channel: channel_id,
224
+ limit,
225
+ cursor
226
+ })
227
+ },
228
+ read_user_profile: {
229
+ method: 'users.info',
230
+ mapArguments: ({ user_id, include_locale })=>({
231
+ user: user_id,
232
+ include_locale
233
+ })
234
+ },
235
+ search_channels: {
236
+ method: 'conversations.list',
237
+ mapArguments: ({ channel_types, include_archived, limit, cursor })=>({
238
+ types: channel_types,
239
+ exclude_archived: include_archived !== true,
240
+ limit,
241
+ cursor
242
+ }),
243
+ mapOutput: matchingChannels
244
+ },
245
+ send_message: {
246
+ method: 'chat.postMessage',
247
+ mapArguments: ({ channel_id, message, thread_ts, reply_broadcast })=>({
248
+ channel: channel_id,
249
+ ...markdownMessage(message),
250
+ thread_ts,
251
+ reply_broadcast
252
+ }),
253
+ validate: validateMessageLength
254
+ },
255
+ schedule_message: {
256
+ method: 'chat.scheduleMessage',
257
+ mapArguments: ({ channel_id, message, post_at, thread_ts, reply_broadcast })=>({
258
+ channel: channel_id,
259
+ ...markdownMessage(message),
260
+ post_at,
261
+ thread_ts,
262
+ reply_broadcast
263
+ }),
264
+ validate: validateMessageLength
265
+ },
266
+ update_message: {
267
+ method: 'chat.update',
268
+ mapArguments: ({ channel_id, message_ts, message })=>({
269
+ channel: channel_id,
270
+ ts: message_ts,
271
+ ...markdownMessage(message)
272
+ }),
273
+ validate: validateMessageLength
274
+ },
275
+ add_reaction: {
276
+ method: 'reactions.add',
277
+ mapArguments: ({ channel_id, message_ts, emoji })=>({
278
+ channel: channel_id,
279
+ timestamp: message_ts,
280
+ name: emoji
281
+ })
282
+ },
283
+ create_canvas: {
284
+ method: 'canvases.create',
285
+ mapArguments: ({ title, content })=>({
286
+ title,
287
+ document_content: {
288
+ type: 'markdown',
289
+ markdown: content
290
+ }
291
+ })
292
+ }
123
293
  };
124
294
  export const slackAgentToolSelectionCatalog = buildSlackAgentToolSelectionCatalog(slackAgentToolCatalog);
295
+ // A Markdown block renders standard Markdown, which the plain text field does not; text is kept as
296
+ // the notification fallback, so its Markdown syntax is stripped rather than shown literally.
297
+ function markdownMessage(message) {
298
+ if (typeof message !== 'string') return {};
299
+ return {
300
+ text: stripMarkdownForFallback(message),
301
+ blocks: [
302
+ {
303
+ type: 'markdown',
304
+ text: message
305
+ }
306
+ ]
307
+ };
308
+ }
309
+ const codeBlockPattern = /```[^\n]*\n?([\s\S]*?)\n?```/g;
310
+ const inlineCodePattern = /`([^`]+)`/g;
311
+ const linkPattern = /\[([^\]]+)\]\(([^)]+)\)/g;
312
+ const boldPattern = /\*\*([^*]+)\*\*|__([^_]+)__/g;
313
+ const strikethroughPattern = /~~([^~]+)~~/g;
314
+ const italicPattern = /\*([^*]+)\*|_([^_]+)_/g;
315
+ const blockquotePattern = /^>\s?/gm;
316
+ // Reserved code spans are wrapped in a delimiter built at runtime (String.fromCharCode) rather than
317
+ // a literal escape in source. A real chat message is vanishingly unlikely to contain a NUL byte, but
318
+ // isn't guaranteed not to, so any that do appear are stripped from the input first. After that, the
319
+ // only NUL bytes left are the ones this function inserts, so restoration can't misfire on user text.
320
+ const codePlaceholderDelimiter = String.fromCharCode(0);
321
+ const codePlaceholderPattern = new RegExp(`${codePlaceholderDelimiter}(\\d+)${codePlaceholderDelimiter}`, 'g');
322
+ // Best-effort plain-text rendering of the Markdown syntax the tool description promises (bold,
323
+ // italic, strikethrough, links, lists, blockquotes, inline code, code blocks); lists are left as-is
324
+ // since "- item" and "1. item" already read fine as plain text. Code spans are pulled out behind a
325
+ // placeholder first so their own *, _, ~, and [] characters survive the other replacements intact.
326
+ function stripMarkdownForFallback(message) {
327
+ const codeSpans = [];
328
+ const reserveCodeSpan = (_match, code)=>`${codePlaceholderDelimiter}${codeSpans.push(code) - 1}${codePlaceholderDelimiter}`;
329
+ return message.replaceAll(codePlaceholderDelimiter, '').replace(codeBlockPattern, reserveCodeSpan).replace(inlineCodePattern, reserveCodeSpan).replace(linkPattern, (_match, text, url)=>`${text} (${url})`).replace(boldPattern, (_match, asterisk, underscore)=>asterisk ?? underscore ?? '').replace(strikethroughPattern, (_match, text)=>text).replace(italicPattern, (_match, asterisk, underscore)=>asterisk ?? underscore ?? '').replace(blockquotePattern, '').replace(codePlaceholderPattern, (_match, index)=>codeSpans[Number(index)] ?? '');
330
+ }
331
+ function validateMessageLength(args) {
332
+ const { message } = args;
333
+ if (typeof message !== 'string') return undefined;
334
+ // .length counts UTF-16 code units, so astral-plane characters (most emoji) count twice and
335
+ // would reject messages the 12,000-character schema limit still allows; the spread operator
336
+ // iterates by Unicode code point instead.
337
+ const length = [
338
+ ...message
339
+ ].length;
340
+ if (length > SLACK_MARKDOWN_BLOCK_MAX_LENGTH) {
341
+ return {
342
+ message: `Message is ${length.toLocaleString('en-US')} characters, which exceeds Slack's ${SLACK_MARKDOWN_BLOCK_MAX_LENGTH.toLocaleString('en-US')}-character Markdown block limit. Shorten it or split it into multiple messages.`,
343
+ code: 'content-too-large'
344
+ };
345
+ }
346
+ return undefined;
347
+ }
348
+ // Slack has no channel search method for bot tokens, so the requested page is matched locally.
349
+ function matchingChannels(body, args) {
350
+ const { query } = args;
351
+ const { channels } = body;
352
+ if (typeof query !== 'string' || !Array.isArray(channels)) return body;
353
+ const terms = query.toLowerCase().split(whitespacePattern).filter(Boolean);
354
+ if (terms.length === 0) return body;
355
+ return {
356
+ ...body,
357
+ channels: channels.filter((channel)=>matchesTerms(channel, terms))
358
+ };
359
+ }
360
+ function matchesTerms(channel, terms) {
361
+ if (typeof channel !== 'object' || channel === null) return false;
362
+ const { name, topic, purpose } = channel;
363
+ const haystack = [
364
+ name,
365
+ textValue(topic),
366
+ textValue(purpose)
367
+ ].filter((value)=>typeof value === 'string').join(' ').toLowerCase();
368
+ return terms.every((term)=>haystack.includes(term));
369
+ }
370
+ function textValue(field) {
371
+ if (typeof field !== 'object' || field === null) return undefined;
372
+ return field.value;
373
+ }
125
374
  function buildSlackAgentToolSelectionCatalog(catalog) {
126
375
  return {
127
376
  selectors: catalog.map((entry)=>({
@@ -153,12 +402,10 @@ function stringSchema(description) {
153
402
  } : {}
154
403
  };
155
404
  }
156
- function numberSchema(description) {
405
+ function integerSchema(description) {
157
406
  return {
158
- type: 'number',
159
- ...description ? {
160
- description
161
- } : {}
407
+ type: 'integer',
408
+ description
162
409
  };
163
410
  }
164
411
  function booleanSchema(description) {
@@ -167,11 +414,5 @@ function booleanSchema(description) {
167
414
  description
168
415
  };
169
416
  }
170
- function arraySchema(items) {
171
- return {
172
- type: 'array',
173
- items
174
- };
175
- }
176
417
 
177
418
  //# sourceMappingURL=agent-tools.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/agent-tools.ts"],"sourcesContent":["import type {\n AgentToolCatalogEntry,\n AgentToolJsonSchema,\n AgentToolSelectionCatalog,\n AgentToolSelector,\n} from '@shipfox/api-integration-spi';\n\nexport type SlackAgentToolRequiredScope = 'read' | 'write';\nexport type SlackAgentToolCatalogEntry = AgentToolCatalogEntry<SlackAgentToolRequiredScope>;\n\ninterface SlackAgentToolCatalogInput {\n id: string;\n description: string;\n sensitivity: 'read' | 'write';\n sensitive: boolean;\n requiredScope: SlackAgentToolRequiredScope;\n inputSchema: AgentToolJsonSchema;\n}\n\nconst channelSchema = stringSchema('Slack channel ID');\nconst cursorSchema = stringSchema('Next page cursor');\nconst limitSchema = numberSchema('Maximum number of results to return');\n\nexport const slackAgentToolCatalog = [\n tool({\n id: 'conversations_history',\n description: 'List messages in a Slack channel or direct message.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n channel: channelSchema,\n cursor: cursorSchema,\n limit: limitSchema,\n oldest: stringSchema('Only messages after this Slack timestamp'),\n latest: stringSchema('Only messages before this Slack timestamp'),\n inclusive: booleanSchema('Include messages at the oldest or latest timestamp'),\n },\n ['channel'],\n ),\n }),\n tool({\n id: 'conversations_replies',\n description: 'List replies in a Slack message thread.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n channel: channelSchema,\n ts: stringSchema('Slack timestamp of the parent message'),\n cursor: cursorSchema,\n limit: limitSchema,\n },\n ['channel', 'ts'],\n ),\n }),\n tool({\n id: 'conversations_list',\n description: 'List Slack channels visible to the bot.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({\n cursor: cursorSchema,\n limit: limitSchema,\n types: stringSchema('Comma-separated channel types, such as public_channel,private_channel'),\n exclude_archived: booleanSchema('Exclude archived channels'),\n }),\n }),\n tool({\n id: 'users_info',\n description: 'Look up a Slack user and profile by user ID.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema({user: stringSchema('Slack user ID')}, ['user']),\n }),\n tool({\n id: 'chat_postMessage',\n description: 'Post a Slack message to a channel or thread. Provide text, blocks, or both.',\n sensitivity: 'write',\n sensitive: false,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n channel: channelSchema,\n text: stringSchema('Message text'),\n thread_ts: stringSchema('Slack timestamp of the parent message when replying in a thread'),\n blocks: arraySchema({type: 'object'}),\n },\n ['channel'],\n ),\n }),\n tool({\n id: 'chat_update',\n description: 'Update a Slack message with text, blocks, or both.',\n sensitivity: 'write',\n sensitive: false,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n channel: channelSchema,\n ts: stringSchema('Slack timestamp of the message to update'),\n text: stringSchema('Updated message text'),\n blocks: arraySchema({type: 'object'}),\n },\n ['channel', 'ts'],\n ),\n }),\n tool({\n id: 'reactions_add',\n description: 'Add an emoji reaction to a Slack message.',\n sensitivity: 'write',\n sensitive: false,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n channel: channelSchema,\n timestamp: stringSchema('Slack timestamp of the message'),\n name: stringSchema('Emoji name without surrounding colons'),\n },\n ['channel', 'timestamp', 'name'],\n ),\n }),\n] as const satisfies readonly SlackAgentToolCatalogEntry[];\n\nexport type SlackAgentToolId = (typeof slackAgentToolCatalog)[number]['id'];\n\nexport const SLACK_TOOL_METHODS = {\n conversations_history: 'conversations.history',\n conversations_replies: 'conversations.replies',\n conversations_list: 'conversations.list',\n users_info: 'users.info',\n chat_postMessage: 'chat.postMessage',\n chat_update: 'chat.update',\n reactions_add: 'reactions.add',\n} as const satisfies Record<SlackAgentToolId, string>;\n\nexport const slackAgentToolSelectionCatalog =\n buildSlackAgentToolSelectionCatalog(slackAgentToolCatalog);\n\nfunction buildSlackAgentToolSelectionCatalog(\n catalog: readonly SlackAgentToolCatalogEntry[],\n): AgentToolSelectionCatalog {\n return {\n selectors: catalog.map(\n (entry): AgentToolSelector => ({\n token: entry.id,\n kind: 'standalone',\n sensitivity: entry.sensitivity,\n sensitive: entry.sensitive,\n }),\n ),\n };\n}\n\nfunction tool<const Entry extends SlackAgentToolCatalogInput>(input: Entry): Entry {\n return input;\n}\n\nfunction objectSchema(\n properties: Record<string, AgentToolJsonSchema>,\n required: string[] = [],\n): AgentToolJsonSchema {\n return {\n type: 'object',\n additionalProperties: false,\n properties,\n ...(required.length > 0 ? {required} : {}),\n };\n}\n\nfunction stringSchema(description?: string): AgentToolJsonSchema {\n return {type: 'string', ...(description ? {description} : {})};\n}\n\nfunction numberSchema(description?: string): AgentToolJsonSchema {\n return {type: 'number', ...(description ? {description} : {})};\n}\n\nfunction booleanSchema(description: string): AgentToolJsonSchema {\n return {type: 'boolean', description};\n}\n\nfunction arraySchema(items: AgentToolJsonSchema): AgentToolJsonSchema {\n return {type: 'array', items};\n}\n"],"names":["channelSchema","stringSchema","cursorSchema","limitSchema","numberSchema","slackAgentToolCatalog","tool","id","description","sensitivity","sensitive","requiredScope","inputSchema","objectSchema","channel","cursor","limit","oldest","latest","inclusive","booleanSchema","ts","types","exclude_archived","user","text","thread_ts","blocks","arraySchema","type","timestamp","name","SLACK_TOOL_METHODS","conversations_history","conversations_replies","conversations_list","users_info","chat_postMessage","chat_update","reactions_add","slackAgentToolSelectionCatalog","buildSlackAgentToolSelectionCatalog","catalog","selectors","map","entry","token","kind","input","properties","required","additionalProperties","length","items"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/core/agent-tools.ts"],"sourcesContent":["import type {\n AgentToolCatalogEntry,\n AgentToolJsonSchema,\n AgentToolSelectionCatalog,\n AgentToolSelector,\n} from '@shipfox/api-integration-spi';\nimport type {SlackWebApiResponse} from '#api/client.js';\n\nexport type SlackAgentToolRequiredScope = 'read' | 'write';\nexport type SlackAgentToolCatalogEntry = AgentToolCatalogEntry<SlackAgentToolRequiredScope>;\n\ninterface SlackAgentToolCatalogInput {\n id: string;\n description: string;\n sensitivity: 'read' | 'write';\n sensitive: boolean;\n requiredScope: SlackAgentToolRequiredScope;\n inputSchema: AgentToolJsonSchema;\n}\n\nconst whitespacePattern = /\\s+/;\n\n// Slack caps the cumulative text across all Markdown blocks in one payload at 12,000 characters;\n// content over that limit is rejected with invalid_blocks rather than truncated. Each tool here\n// sends exactly one Markdown block, so the cap applies to that single block's text.\nconst SLACK_MARKDOWN_BLOCK_MAX_LENGTH = 12_000;\n\n// Only the chat.* methods resolve a user ID into a direct message; conversations.* and reactions.*\n// need the conversation ID itself, so the two targets are described separately.\nconst conversationIdSchema = stringSchema(\n 'Channel, private group, or direct message conversation ID, such as C0ABC12345 or D0ABC12345. A user ID is not accepted here',\n);\nconst messageTargetSchema = stringSchema(\n 'Channel, private group, or direct message conversation ID. Pass a user ID to open a direct message with that user',\n);\nconst cursorSchema = stringSchema('Pagination cursor from a previous request');\nconst messageSchema = {\n ...stringSchema('Message content, written as standard Markdown'),\n maxLength: SLACK_MARKDOWN_BLOCK_MAX_LENGTH,\n};\nconst threadTsSchema = stringSchema('Timestamp of the parent message to reply in its thread');\nconst replyBroadcastSchema = booleanSchema('Also send the thread reply to the channel');\n\nexport const slackAgentToolCatalog = [\n tool({\n id: 'read_channel',\n description:\n 'Read messages from a Slack channel in reverse chronological order (newest first). Reading direct message history needs the ID of that conversation, not the ID of the user on the other side.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n channel_id: conversationIdSchema,\n oldest: stringSchema('Start of the time range, as a Slack timestamp'),\n latest: stringSchema('End of the time range, as a Slack timestamp'),\n limit: integerSchema('Messages to return, 1 to 100 (default 100)'),\n cursor: cursorSchema,\n },\n ['channel_id'],\n ),\n }),\n tool({\n id: 'read_thread',\n description:\n 'Read a Slack thread: the parent message and all of its replies. Requires the channel ID and the timestamp of the parent message.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n channel_id: conversationIdSchema,\n message_ts: stringSchema('Timestamp of the parent message, such as 1234567890.123456'),\n oldest: stringSchema('Start of the time range, as a Slack timestamp'),\n latest: stringSchema('End of the time range, as a Slack timestamp'),\n limit: integerSchema('Messages to return, 1 to 1000 (default 100)'),\n cursor: cursorSchema,\n },\n ['channel_id', 'message_ts'],\n ),\n }),\n tool({\n id: 'read_channel_info',\n description:\n 'Retrieve metadata for a single Slack channel by ID: name, topic, purpose, privacy, and archive status. Use this to learn what a channel is for before reading or posting. To read its messages, use read_channel instead.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n channel_id: conversationIdSchema,\n include_num_members: booleanSchema('Include the channel member count (default false)'),\n },\n ['channel_id'],\n ),\n }),\n tool({\n id: 'read_channel_members',\n description:\n 'List the user IDs of the members of a Slack channel. Pair it with read_user_profile to resolve a member to a name.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n channel_id: conversationIdSchema,\n limit: integerSchema('Members to return per page (default 100)'),\n cursor: cursorSchema,\n },\n ['channel_id'],\n ),\n }),\n tool({\n id: 'read_user_profile',\n description:\n 'Retrieve profile information for a Slack user, including contact details, status, timezone, and role.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n user_id: stringSchema('Slack user ID, such as U0ABC12345'),\n include_locale: booleanSchema(\"Include the user's locale information (default false)\"),\n },\n ['user_id'],\n ),\n }),\n tool({\n id: 'search_channels',\n description:\n 'Search the channels this integration can see, by name, topic, or purpose. Returns channel names, IDs, topics, purposes, and archive status. Names are typically lowercase with hyphens. Space-separated terms all have to match. Only the requested page is searched, so page through with the returned cursor when a channel is missing.',\n sensitivity: 'read',\n sensitive: false,\n requiredScope: 'read',\n inputSchema: objectSchema(\n {\n query: stringSchema('Search query for finding channels'),\n channel_types: stringSchema(\n 'Comma-separated channel types: public_channel, private_channel. Defaults to public_channel',\n ),\n include_archived: booleanSchema('Include archived channels in the results'),\n limit: integerSchema('Channels to scan per page (default 100)'),\n cursor: cursorSchema,\n },\n ['query'],\n ),\n }),\n tool({\n id: 'send_message',\n description:\n 'Send a message to a Slack channel or user. To send a direct message, pass the user ID as the channel ID. Supports standard Markdown: bold, italic, strikethrough, links, lists, blockquotes, inline code, and code blocks. Returns the posted message timestamp.',\n sensitivity: 'write',\n sensitive: false,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n channel_id: messageTargetSchema,\n message: messageSchema,\n thread_ts: threadTsSchema,\n reply_broadcast: replyBroadcastSchema,\n },\n ['channel_id', 'message'],\n ),\n }),\n tool({\n id: 'schedule_message',\n description:\n 'Schedule a message for future delivery to a Slack channel. Does not send immediately. post_at has to be at least 2 minutes in the future and at most 120 days out. Once scheduled, the message cannot be edited.',\n sensitivity: 'write',\n sensitive: false,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n channel_id: messageTargetSchema,\n message: messageSchema,\n post_at: integerSchema('Unix timestamp at which to send the message'),\n thread_ts: threadTsSchema,\n reply_broadcast: replyBroadcastSchema,\n },\n ['channel_id', 'message', 'post_at'],\n ),\n }),\n tool({\n id: 'update_message',\n description:\n 'Update an already posted Slack message, replacing its content. Supports the same standard Markdown as send_message.',\n sensitivity: 'write',\n sensitive: false,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n channel_id: conversationIdSchema,\n message_ts: stringSchema('Timestamp of the message to update'),\n message: messageSchema,\n },\n ['channel_id', 'message_ts', 'message'],\n ),\n }),\n tool({\n id: 'add_reaction',\n description: 'Add an emoji reaction to a Slack message.',\n sensitivity: 'write',\n sensitive: false,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n channel_id: conversationIdSchema,\n message_ts: stringSchema('Timestamp of the message to react to'),\n emoji: stringSchema('Emoji name without the surrounding colons, such as white_check_mark'),\n },\n ['channel_id', 'message_ts', 'emoji'],\n ),\n }),\n tool({\n id: 'create_canvas',\n description:\n 'Create a standalone Slack canvas from Markdown and return its ID. Not available on free teams.',\n sensitivity: 'write',\n sensitive: false,\n requiredScope: 'write',\n inputSchema: objectSchema(\n {\n title: stringSchema('Concise, descriptive canvas name. Do not repeat it in the content'),\n content: stringSchema('Canvas body, written as standard Markdown'),\n },\n ['title', 'content'],\n ),\n }),\n] as const satisfies readonly SlackAgentToolCatalogEntry[];\n\nexport type SlackAgentToolId = (typeof slackAgentToolCatalog)[number]['id'];\n\nexport interface SlackToolOperation {\n method: string;\n mapArguments: (args: Record<string, unknown>) => Record<string, unknown>;\n mapOutput?: (body: SlackWebApiResponse, args: Record<string, unknown>) => SlackWebApiResponse;\n validate?: (args: Record<string, unknown>) => SlackToolValidationError | undefined;\n}\n\nexport interface SlackToolValidationError {\n message: string;\n code?: string | undefined;\n}\n\n// Tool inputs follow the Slack MCP server's naming so agent prompts port across both, which means\n// every call is translated to the Web API's own parameter names before it is sent.\nexport const SLACK_TOOL_OPERATIONS = {\n read_channel: {\n method: 'conversations.history',\n mapArguments: ({channel_id, oldest, latest, limit, cursor}) => ({\n channel: channel_id,\n oldest,\n latest,\n limit,\n cursor,\n }),\n },\n read_thread: {\n method: 'conversations.replies',\n mapArguments: ({channel_id, message_ts, oldest, latest, limit, cursor}) => ({\n channel: channel_id,\n ts: message_ts,\n oldest,\n latest,\n limit,\n cursor,\n }),\n },\n read_channel_info: {\n method: 'conversations.info',\n mapArguments: ({channel_id, include_num_members}) => ({\n channel: channel_id,\n include_num_members,\n }),\n },\n read_channel_members: {\n method: 'conversations.members',\n mapArguments: ({channel_id, limit, cursor}) => ({channel: channel_id, limit, cursor}),\n },\n read_user_profile: {\n method: 'users.info',\n mapArguments: ({user_id, include_locale}) => ({user: user_id, include_locale}),\n },\n search_channels: {\n method: 'conversations.list',\n mapArguments: ({channel_types, include_archived, limit, cursor}) => ({\n types: channel_types,\n exclude_archived: include_archived !== true,\n limit,\n cursor,\n }),\n mapOutput: matchingChannels,\n },\n send_message: {\n method: 'chat.postMessage',\n mapArguments: ({channel_id, message, thread_ts, reply_broadcast}) => ({\n channel: channel_id,\n ...markdownMessage(message),\n thread_ts,\n reply_broadcast,\n }),\n validate: validateMessageLength,\n },\n schedule_message: {\n method: 'chat.scheduleMessage',\n mapArguments: ({channel_id, message, post_at, thread_ts, reply_broadcast}) => ({\n channel: channel_id,\n ...markdownMessage(message),\n post_at,\n thread_ts,\n reply_broadcast,\n }),\n validate: validateMessageLength,\n },\n update_message: {\n method: 'chat.update',\n mapArguments: ({channel_id, message_ts, message}) => ({\n channel: channel_id,\n ts: message_ts,\n ...markdownMessage(message),\n }),\n validate: validateMessageLength,\n },\n add_reaction: {\n method: 'reactions.add',\n mapArguments: ({channel_id, message_ts, emoji}) => ({\n channel: channel_id,\n timestamp: message_ts,\n name: emoji,\n }),\n },\n create_canvas: {\n method: 'canvases.create',\n mapArguments: ({title, content}) => ({\n title,\n document_content: {type: 'markdown', markdown: content},\n }),\n },\n} as const satisfies Record<SlackAgentToolId, SlackToolOperation>;\n\nexport const slackAgentToolSelectionCatalog =\n buildSlackAgentToolSelectionCatalog(slackAgentToolCatalog);\n\n// A Markdown block renders standard Markdown, which the plain text field does not; text is kept as\n// the notification fallback, so its Markdown syntax is stripped rather than shown literally.\nfunction markdownMessage(message: unknown): Record<string, unknown> {\n if (typeof message !== 'string') return {};\n return {text: stripMarkdownForFallback(message), blocks: [{type: 'markdown', text: message}]};\n}\n\nconst codeBlockPattern = /```[^\\n]*\\n?([\\s\\S]*?)\\n?```/g;\nconst inlineCodePattern = /`([^`]+)`/g;\nconst linkPattern = /\\[([^\\]]+)\\]\\(([^)]+)\\)/g;\nconst boldPattern = /\\*\\*([^*]+)\\*\\*|__([^_]+)__/g;\nconst strikethroughPattern = /~~([^~]+)~~/g;\nconst italicPattern = /\\*([^*]+)\\*|_([^_]+)_/g;\nconst blockquotePattern = /^>\\s?/gm;\n// Reserved code spans are wrapped in a delimiter built at runtime (String.fromCharCode) rather than\n// a literal escape in source. A real chat message is vanishingly unlikely to contain a NUL byte, but\n// isn't guaranteed not to, so any that do appear are stripped from the input first. After that, the\n// only NUL bytes left are the ones this function inserts, so restoration can't misfire on user text.\nconst codePlaceholderDelimiter = String.fromCharCode(0);\nconst codePlaceholderPattern = new RegExp(\n `${codePlaceholderDelimiter}(\\\\d+)${codePlaceholderDelimiter}`,\n 'g',\n);\n\n// Best-effort plain-text rendering of the Markdown syntax the tool description promises (bold,\n// italic, strikethrough, links, lists, blockquotes, inline code, code blocks); lists are left as-is\n// since \"- item\" and \"1. item\" already read fine as plain text. Code spans are pulled out behind a\n// placeholder first so their own *, _, ~, and [] characters survive the other replacements intact.\nfunction stripMarkdownForFallback(message: string): string {\n const codeSpans: string[] = [];\n const reserveCodeSpan = (_match: string, code: string): string =>\n `${codePlaceholderDelimiter}${codeSpans.push(code) - 1}${codePlaceholderDelimiter}`;\n\n return message\n .replaceAll(codePlaceholderDelimiter, '')\n .replace(codeBlockPattern, reserveCodeSpan)\n .replace(inlineCodePattern, reserveCodeSpan)\n .replace(linkPattern, (_match, text: string, url: string) => `${text} (${url})`)\n .replace(\n boldPattern,\n (_match, asterisk?: string, underscore?: string) => asterisk ?? underscore ?? '',\n )\n .replace(strikethroughPattern, (_match, text: string) => text)\n .replace(\n italicPattern,\n (_match, asterisk?: string, underscore?: string) => asterisk ?? underscore ?? '',\n )\n .replace(blockquotePattern, '')\n .replace(codePlaceholderPattern, (_match, index: string) => codeSpans[Number(index)] ?? '');\n}\n\nfunction validateMessageLength(\n args: Record<string, unknown>,\n): SlackToolValidationError | undefined {\n const {message} = args;\n if (typeof message !== 'string') return undefined;\n // .length counts UTF-16 code units, so astral-plane characters (most emoji) count twice and\n // would reject messages the 12,000-character schema limit still allows; the spread operator\n // iterates by Unicode code point instead.\n const length = [...message].length;\n if (length > SLACK_MARKDOWN_BLOCK_MAX_LENGTH) {\n return {\n message: `Message is ${length.toLocaleString('en-US')} characters, which exceeds Slack's ${SLACK_MARKDOWN_BLOCK_MAX_LENGTH.toLocaleString('en-US')}-character Markdown block limit. Shorten it or split it into multiple messages.`,\n code: 'content-too-large',\n };\n }\n return undefined;\n}\n\n// Slack has no channel search method for bot tokens, so the requested page is matched locally.\nfunction matchingChannels(\n body: SlackWebApiResponse,\n args: Record<string, unknown>,\n): SlackWebApiResponse {\n const {query} = args;\n const {channels} = body;\n if (typeof query !== 'string' || !Array.isArray(channels)) return body;\n const terms = query.toLowerCase().split(whitespacePattern).filter(Boolean);\n if (terms.length === 0) return body;\n return {...body, channels: channels.filter((channel) => matchesTerms(channel, terms))};\n}\n\nfunction matchesTerms(channel: unknown, terms: string[]): boolean {\n if (typeof channel !== 'object' || channel === null) return false;\n const {name, topic, purpose} = channel as Record<string, unknown>;\n const haystack = [name, textValue(topic), textValue(purpose)]\n .filter((value): value is string => typeof value === 'string')\n .join(' ')\n .toLowerCase();\n return terms.every((term) => haystack.includes(term));\n}\n\nfunction textValue(field: unknown): unknown {\n if (typeof field !== 'object' || field === null) return undefined;\n return (field as Record<string, unknown>).value;\n}\n\nfunction buildSlackAgentToolSelectionCatalog(\n catalog: readonly SlackAgentToolCatalogEntry[],\n): AgentToolSelectionCatalog {\n return {\n selectors: catalog.map(\n (entry): AgentToolSelector => ({\n token: entry.id,\n kind: 'standalone',\n sensitivity: entry.sensitivity,\n sensitive: entry.sensitive,\n }),\n ),\n };\n}\n\nfunction tool<const Entry extends SlackAgentToolCatalogInput>(input: Entry): Entry {\n return input;\n}\n\nfunction objectSchema(\n properties: Record<string, AgentToolJsonSchema>,\n required: string[] = [],\n): AgentToolJsonSchema {\n return {\n type: 'object',\n additionalProperties: false,\n properties,\n ...(required.length > 0 ? {required} : {}),\n };\n}\n\nfunction stringSchema(description?: string): AgentToolJsonSchema {\n return {type: 'string', ...(description ? {description} : {})};\n}\n\nfunction integerSchema(description: string): AgentToolJsonSchema {\n return {type: 'integer', description};\n}\n\nfunction booleanSchema(description: string): AgentToolJsonSchema {\n return {type: 'boolean', description};\n}\n"],"names":["whitespacePattern","SLACK_MARKDOWN_BLOCK_MAX_LENGTH","conversationIdSchema","stringSchema","messageTargetSchema","cursorSchema","messageSchema","maxLength","threadTsSchema","replyBroadcastSchema","booleanSchema","slackAgentToolCatalog","tool","id","description","sensitivity","sensitive","requiredScope","inputSchema","objectSchema","channel_id","oldest","latest","limit","integerSchema","cursor","message_ts","include_num_members","user_id","include_locale","query","channel_types","include_archived","message","thread_ts","reply_broadcast","post_at","emoji","title","content","SLACK_TOOL_OPERATIONS","read_channel","method","mapArguments","channel","read_thread","ts","read_channel_info","read_channel_members","read_user_profile","user","search_channels","types","exclude_archived","mapOutput","matchingChannels","send_message","markdownMessage","validate","validateMessageLength","schedule_message","update_message","add_reaction","timestamp","name","create_canvas","document_content","type","markdown","slackAgentToolSelectionCatalog","buildSlackAgentToolSelectionCatalog","text","stripMarkdownForFallback","blocks","codeBlockPattern","inlineCodePattern","linkPattern","boldPattern","strikethroughPattern","italicPattern","blockquotePattern","codePlaceholderDelimiter","String","fromCharCode","codePlaceholderPattern","RegExp","codeSpans","reserveCodeSpan","_match","code","push","replaceAll","replace","url","asterisk","underscore","index","Number","args","undefined","length","toLocaleString","body","channels","Array","isArray","terms","toLowerCase","split","filter","Boolean","matchesTerms","topic","purpose","haystack","textValue","value","join","every","term","includes","field","catalog","selectors","map","entry","token","kind","input","properties","required","additionalProperties"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"scopes.d.ts","sourceRoot":"","sources":["../../src/core/scopes.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,gBAAgB,mBAY3B,CAAC;AAEH,wBAAgB,oBAAoB,CAAC,MAAM,oBAAmB,GAAG,MAAM,CAEtE;AAED,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAIrE"}
1
+ {"version":3,"file":"scopes.d.ts","sourceRoot":"","sources":["../../src/core/scopes.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,gBAAgB,mBAgB3B,CAAC;AAEH,wBAAgB,oBAAoB,CAAC,MAAM,oBAAmB,GAAG,MAAM,CAEtE;AAED,wBAAgB,8BAA8B,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAIrE"}
@@ -2,6 +2,9 @@ import { SlackAuthorizationScopeMismatchError } from './errors.js';
2
2
  export const SLACK_BOT_SCOPES = Object.freeze([
3
3
  'app_mentions:read',
4
4
  'im:history',
5
+ 'im:read',
6
+ 'mpim:history',
7
+ 'mpim:read',
5
8
  'chat:write',
6
9
  'channels:history',
7
10
  'groups:history',
@@ -10,6 +13,7 @@ export const SLACK_BOT_SCOPES = Object.freeze([
10
13
  'users:read',
11
14
  'reactions:read',
12
15
  'reactions:write',
16
+ 'canvases:write',
13
17
  'commands'
14
18
  ]);
15
19
  export function formatSlackBotScopes(scopes = SLACK_BOT_SCOPES) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/core/scopes.ts"],"sourcesContent":["import {SlackAuthorizationScopeMismatchError} from './errors.js';\n\nexport const SLACK_BOT_SCOPES = Object.freeze([\n 'app_mentions:read',\n 'im:history',\n 'chat:write',\n 'channels:history',\n 'groups:history',\n 'channels:read',\n 'groups:read',\n 'users:read',\n 'reactions:read',\n 'reactions:write',\n 'commands',\n]);\n\nexport function formatSlackBotScopes(scopes = SLACK_BOT_SCOPES): string {\n return scopes.join(',');\n}\n\nexport function assertSlackAuthorizationScopes(scopes: string[]): void {\n const grantedScopes = new Set(scopes);\n const missingScopes = SLACK_BOT_SCOPES.filter((scope) => !grantedScopes.has(scope));\n if (missingScopes.length > 0) throw new SlackAuthorizationScopeMismatchError(missingScopes);\n}\n"],"names":["SlackAuthorizationScopeMismatchError","SLACK_BOT_SCOPES","Object","freeze","formatSlackBotScopes","scopes","join","assertSlackAuthorizationScopes","grantedScopes","Set","missingScopes","filter","scope","has","length"],"mappings":"AAAA,SAAQA,oCAAoC,QAAO,cAAc;AAEjE,OAAO,MAAMC,mBAAmBC,OAAOC,MAAM,CAAC;IAC5C;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD,EAAE;AAEH,OAAO,SAASC,qBAAqBC,SAASJ,gBAAgB;IAC5D,OAAOI,OAAOC,IAAI,CAAC;AACrB;AAEA,OAAO,SAASC,+BAA+BF,MAAgB;IAC7D,MAAMG,gBAAgB,IAAIC,IAAIJ;IAC9B,MAAMK,gBAAgBT,iBAAiBU,MAAM,CAAC,CAACC,QAAU,CAACJ,cAAcK,GAAG,CAACD;IAC5E,IAAIF,cAAcI,MAAM,GAAG,GAAG,MAAM,IAAId,qCAAqCU;AAC/E"}
1
+ {"version":3,"sources":["../../src/core/scopes.ts"],"sourcesContent":["import {SlackAuthorizationScopeMismatchError} from './errors.js';\n\nexport const SLACK_BOT_SCOPES = Object.freeze([\n 'app_mentions:read',\n 'im:history',\n 'im:read',\n 'mpim:history',\n 'mpim:read',\n 'chat:write',\n 'channels:history',\n 'groups:history',\n 'channels:read',\n 'groups:read',\n 'users:read',\n 'reactions:read',\n 'reactions:write',\n 'canvases:write',\n 'commands',\n]);\n\nexport function formatSlackBotScopes(scopes = SLACK_BOT_SCOPES): string {\n return scopes.join(',');\n}\n\nexport function assertSlackAuthorizationScopes(scopes: string[]): void {\n const grantedScopes = new Set(scopes);\n const missingScopes = SLACK_BOT_SCOPES.filter((scope) => !grantedScopes.has(scope));\n if (missingScopes.length > 0) throw new SlackAuthorizationScopeMismatchError(missingScopes);\n}\n"],"names":["SlackAuthorizationScopeMismatchError","SLACK_BOT_SCOPES","Object","freeze","formatSlackBotScopes","scopes","join","assertSlackAuthorizationScopes","grantedScopes","Set","missingScopes","filter","scope","has","length"],"mappings":"AAAA,SAAQA,oCAAoC,QAAO,cAAc;AAEjE,OAAO,MAAMC,mBAAmBC,OAAOC,MAAM,CAAC;IAC5C;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD,EAAE;AAEH,OAAO,SAASC,qBAAqBC,SAASJ,gBAAgB;IAC5D,OAAOI,OAAOC,IAAI,CAAC;AACrB;AAEA,OAAO,SAASC,+BAA+BF,MAAgB;IAC7D,MAAMG,gBAAgB,IAAIC,IAAIJ;IAC9B,MAAMK,gBAAgBT,iBAAiBU,MAAM,CAAC,CAACC,QAAU,CAACJ,cAAcK,GAAG,CAACD;IAC5E,IAAIF,cAAcI,MAAM,GAAG,GAAG,MAAM,IAAId,qCAAqCU;AAC/E"}
package/dist/index.d.ts CHANGED
@@ -14,7 +14,7 @@ export type { SlackProvider } from '@shipfox/api-integration-slack-dto';
14
14
  export type { SlackApiClient, SlackAuthorization, SlackWebApiResponse } from '#api/client.js';
15
15
  export { createSlackApiClient } from '#api/client.js';
16
16
  export type { SlackAgentToolCatalogEntry, SlackAgentToolId, SlackAgentToolRequiredScope, } from '#core/agent-tools.js';
17
- export { SLACK_TOOL_METHODS, slackAgentToolCatalog, slackAgentToolSelectionCatalog, } from '#core/agent-tools.js';
17
+ export { slackAgentToolCatalog, slackAgentToolSelectionCatalog } from '#core/agent-tools.js';
18
18
  export type { SlackAgentToolsProviderOptions, SlackToolCallResult, } from '#core/agent-tools-provider.js';
19
19
  export { SlackAgentToolsProvider } from '#core/agent-tools-provider.js';
20
20
  export { type DisconnectSlackInstallationParams, disconnectSlackInstallation, } from '#core/disconnect.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ import { migrationsPath } from '#db/migrations.js';
9
9
  import { createSlackIntegrationRoutes } from '#presentation/routes/install.js';
10
10
  import { createSlackWebhookRoutes } from '#presentation/routes/webhooks.js';
11
11
  export { createSlackApiClient } from '#api/client.js';
12
- export { SLACK_TOOL_METHODS, slackAgentToolCatalog, slackAgentToolSelectionCatalog } from '#core/agent-tools.js';
12
+ export { slackAgentToolCatalog, slackAgentToolSelectionCatalog } from '#core/agent-tools.js';
13
13
  export { SlackAgentToolsProvider } from '#core/agent-tools-provider.js';
14
14
  export { disconnectSlackInstallation } from '#core/disconnect.js';
15
15
  export { SlackAccessTokenUnavailableError, SlackAuthorizationScopeMismatchError, SlackBotTokenMissingError, SlackConnectionAlreadyLinkedError, SlackConnectionNotFoundError, SlackEnterpriseInstallUnsupportedError, SlackInstallationAlreadyLinkedError, SlackInstallStateActorMismatchError, SlackInstallStateError, SlackIntegrationProviderError, SlackOAuthCallbackError } from '#core/errors.js';