chat 4.28.1 → 4.30.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.
Files changed (48) hide show
  1. package/dist/ai/index.d.ts +501 -0
  2. package/dist/ai/index.js +500 -0
  3. package/dist/chat-BPjXsoIl.d.ts +3158 -0
  4. package/dist/chunk-HD375J7S.js +128 -0
  5. package/dist/index.d.ts +6 -3143
  6. package/dist/index.js +45 -139
  7. package/dist/{jsx-runtime-DxGwoLu2.d.ts → jsx-runtime-CnDs8rPr.d.ts} +1 -1
  8. package/dist/jsx-runtime.d.ts +1 -1
  9. package/docs/adapters.mdx +35 -5
  10. package/docs/ai/ai-sdk-tools.mdx +227 -0
  11. package/docs/ai/index.mdx +69 -0
  12. package/docs/ai/meta.json +4 -0
  13. package/docs/{api → ai}/to-ai-messages.mdx +16 -3
  14. package/docs/ai/types.mdx +243 -0
  15. package/docs/api/chat.mdx +50 -10
  16. package/docs/api/index.mdx +4 -6
  17. package/docs/api/message.mdx +1 -1
  18. package/docs/api/meta.json +0 -1
  19. package/docs/api/postable-message.mdx +3 -3
  20. package/docs/api/thread.mdx +1 -1
  21. package/docs/concurrency.mdx +54 -15
  22. package/docs/contributing/building.mdx +1 -1
  23. package/docs/contributing/testing.mdx +4 -0
  24. package/docs/direct-messages.mdx +10 -1
  25. package/docs/files.mdx +20 -0
  26. package/docs/getting-started.mdx +5 -1
  27. package/docs/handling-events.mdx +10 -7
  28. package/docs/index.mdx +4 -1
  29. package/docs/meta.json +4 -0
  30. package/docs/posting-messages.mdx +3 -1
  31. package/docs/slack-primitives.mdx +320 -0
  32. package/docs/slash-commands.mdx +4 -4
  33. package/docs/streaming.mdx +4 -4
  34. package/docs/subject.mdx +1 -1
  35. package/docs/testing.mdx +142 -0
  36. package/docs/threads-messages-channels.mdx +1 -1
  37. package/docs/usage.mdx +8 -4
  38. package/package.json +23 -2
  39. package/resources/guides/create-a-discord-support-bot-with-nuxt-and-redis.md +5 -1
  40. package/resources/guides/how-to-build-a-slack-bot-with-next-js-and-redis.md +5 -1
  41. package/resources/guides/how-to-build-an-ai-agent-for-slack-with-chat-sdk-and-ai-sdk.md +1 -1
  42. package/resources/guides/human-in-the-loop-with-chat-sdk-and-workflow-sdk.md +176 -0
  43. package/resources/guides/liveblocks-chat-sdk-ai-sdk.md +165 -0
  44. package/resources/guides/run-and-track-deploys-from-slack.md +7 -5
  45. package/resources/guides/ship-a-github-code-review-bot-with-hono-and-redis.md +5 -1
  46. package/resources/guides/slack-bot-vercel-blob.md +254 -0
  47. package/resources/guides/triage-form-submissions-with-chat-sdk.md +3 -1
  48. package/resources/templates.json +5 -0
@@ -0,0 +1,500 @@
1
+ import {
2
+ toAiMessages
3
+ } from "../chunk-HD375J7S.js";
4
+
5
+ // src/ai/tools/channels.ts
6
+ import { tool } from "ai";
7
+ import { z } from "zod";
8
+ var getChannelInfo = (chat) => tool({
9
+ description: "Fetch metadata for a channel: name, member count, DM status, visibility, etc. Use to identify a channel before posting.",
10
+ inputSchema: z.object({
11
+ channelId: z.string().describe("Full channel id including adapter prefix")
12
+ }),
13
+ execute: async ({ channelId }) => {
14
+ const channel = chat.channel(channelId);
15
+ const info = await channel.fetchMetadata();
16
+ return {
17
+ id: info.id,
18
+ name: info.name,
19
+ isDM: info.isDM ?? false,
20
+ memberCount: info.memberCount,
21
+ channelVisibility: info.channelVisibility
22
+ };
23
+ }
24
+ });
25
+
26
+ // src/ai/tools/messages.ts
27
+ import { tool as tool2 } from "ai";
28
+ import { z as z2 } from "zod";
29
+ var POSTABLE_INPUT = z2.union([
30
+ z2.string().describe("Plain text body"),
31
+ z2.object({ markdown: z2.string() }).describe("Markdown body, converted to the platform's native format"),
32
+ z2.object({ raw: z2.string() }).describe("Raw body, passed through to the platform untouched")
33
+ ]).describe("Message body");
34
+ var postMessage = (chat, { needsApproval = true } = {}) => tool2({
35
+ description: "Post a message inside an existing thread. Use this to reply within a conversation the bot already has context for. The threadId is the full id (e.g. 'slack:C123:1234567890.123456').",
36
+ needsApproval,
37
+ inputSchema: z2.object({
38
+ threadId: z2.string().describe("Full thread id including adapter prefix"),
39
+ message: POSTABLE_INPUT
40
+ }),
41
+ execute: async ({ threadId, message }) => {
42
+ const thread = chat.thread(threadId);
43
+ const sent = await thread.post(toPostable(message));
44
+ return {
45
+ messageId: sent.id,
46
+ threadId: sent.threadId
47
+ };
48
+ }
49
+ });
50
+ var postChannelMessage = (chat, { needsApproval = true } = {}) => tool2({
51
+ description: "Post a top-level message to a channel (not threaded under an existing message). The channelId is the full id (e.g. 'slack:C123ABC').",
52
+ needsApproval,
53
+ inputSchema: z2.object({
54
+ channelId: z2.string().describe("Full channel id including adapter prefix"),
55
+ message: POSTABLE_INPUT
56
+ }),
57
+ execute: async ({ channelId, message }) => {
58
+ const channel = chat.channel(channelId);
59
+ const sent = await channel.post(toPostable(message));
60
+ return {
61
+ messageId: sent.id,
62
+ threadId: sent.threadId
63
+ };
64
+ }
65
+ });
66
+ var sendDirectMessage = (chat, { needsApproval = true } = {}) => tool2({
67
+ description: "Open (or reuse) a 1:1 direct-message conversation with a user and post a message in it. The userId format is platform-specific (e.g. 'U123456' for Slack, 'users/123' for Google Chat).",
68
+ needsApproval,
69
+ inputSchema: z2.object({
70
+ userId: z2.string().describe("Platform-specific user id; the adapter is auto-detected"),
71
+ message: POSTABLE_INPUT
72
+ }),
73
+ execute: async ({ userId, message }) => {
74
+ const dm = await chat.openDM(userId);
75
+ const sent = await dm.post(toPostable(message));
76
+ return {
77
+ messageId: sent.id,
78
+ threadId: sent.threadId
79
+ };
80
+ }
81
+ });
82
+ var editMessage = (chat, { needsApproval = true } = {}) => tool2({
83
+ description: "Edit a previously posted message in a thread. Replaces the existing message body. Only messages the bot itself authored can be edited on most platforms.",
84
+ needsApproval,
85
+ inputSchema: z2.object({
86
+ threadId: z2.string().describe("Full thread id"),
87
+ messageId: z2.string().describe("Platform-specific message id of the message to edit"),
88
+ message: POSTABLE_INPUT
89
+ }),
90
+ execute: async ({ threadId, messageId, message }) => {
91
+ const thread = chat.thread(threadId);
92
+ const result = await thread.adapter.editMessage(
93
+ threadId,
94
+ messageId,
95
+ toPostable(message)
96
+ );
97
+ return { messageId: result.id, threadId: result.threadId };
98
+ }
99
+ });
100
+ var deleteMessage = (chat, { needsApproval = true } = {}) => tool2({
101
+ description: "Delete a message from a thread. Only messages the bot itself authored can be deleted on most platforms.",
102
+ needsApproval,
103
+ inputSchema: z2.object({
104
+ threadId: z2.string().describe("Full thread id"),
105
+ messageId: z2.string().describe("Platform-specific message id of the message to delete")
106
+ }),
107
+ execute: async ({ threadId, messageId }) => {
108
+ const thread = chat.thread(threadId);
109
+ await thread.adapter.deleteMessage(threadId, messageId);
110
+ return { deleted: true, messageId, threadId };
111
+ }
112
+ });
113
+ function toPostable(input) {
114
+ if (typeof input === "string") {
115
+ return input;
116
+ }
117
+ if ("markdown" in input) {
118
+ return { markdown: input.markdown };
119
+ }
120
+ return { raw: input.raw };
121
+ }
122
+
123
+ // src/ai/tools/reactions.ts
124
+ import { tool as tool3 } from "ai";
125
+ import { z as z3 } from "zod";
126
+ var addReaction = (chat, { needsApproval = true } = {}) => tool3({
127
+ description: "Add an emoji reaction to a specific message. Use a well-known emoji name (e.g. 'thumbs_up', 'heart', 'check') or a platform-native shorthand.",
128
+ needsApproval,
129
+ inputSchema: z3.object({
130
+ threadId: z3.string().describe("Full thread id"),
131
+ messageId: z3.string().describe("Platform-specific message id to react to"),
132
+ emoji: z3.string().describe(
133
+ "Emoji name or platform shortcode (e.g. 'thumbs_up', 'white_check_mark')"
134
+ )
135
+ }),
136
+ execute: async ({ threadId, messageId, emoji }) => {
137
+ const thread = chat.thread(threadId);
138
+ await thread.adapter.addReaction(threadId, messageId, emoji);
139
+ return { added: true, emoji, messageId, threadId };
140
+ }
141
+ });
142
+ var removeReaction = (chat, { needsApproval = true } = {}) => tool3({
143
+ description: "Remove an emoji reaction the bot previously added to a message.",
144
+ needsApproval,
145
+ inputSchema: z3.object({
146
+ threadId: z3.string().describe("Full thread id"),
147
+ messageId: z3.string().describe("Platform-specific message id to remove the reaction from"),
148
+ emoji: z3.string().describe(
149
+ "Emoji name or platform shortcode previously added by the bot"
150
+ )
151
+ }),
152
+ execute: async ({ threadId, messageId, emoji }) => {
153
+ const thread = chat.thread(threadId);
154
+ await thread.adapter.removeReaction(threadId, messageId, emoji);
155
+ return { removed: true, emoji, messageId, threadId };
156
+ }
157
+ });
158
+
159
+ // src/ai/tools/threads.ts
160
+ import { tool as tool4 } from "ai";
161
+ import { z as z4 } from "zod";
162
+ var FETCH_DIRECTION = z4.enum(["forward", "backward"]).optional().default("backward");
163
+ function projectMessage(message) {
164
+ return {
165
+ id: message.id,
166
+ threadId: message.threadId,
167
+ text: message.text,
168
+ author: {
169
+ userId: message.author.userId,
170
+ userName: message.author.userName,
171
+ fullName: message.author.fullName,
172
+ isBot: message.author.isBot,
173
+ isMe: message.author.isMe
174
+ },
175
+ dateSent: message.metadata.dateSent?.toISOString(),
176
+ edited: message.metadata.edited,
177
+ isMention: message.isMention,
178
+ attachments: (message.attachments ?? []).map((att) => ({
179
+ type: att.type,
180
+ name: att.name,
181
+ mimeType: att.mimeType,
182
+ url: att.url
183
+ }))
184
+ };
185
+ }
186
+ var fetchMessages = (chat) => tool4({
187
+ description: "Fetch recent messages from a thread, ordered chronologically (oldest first within the page). Use to read the conversation before responding.",
188
+ inputSchema: z4.object({
189
+ threadId: z4.string().describe("Full thread id"),
190
+ limit: z4.number().int().min(1).max(100).optional().default(20).describe("Maximum number of messages to fetch"),
191
+ cursor: z4.string().optional().describe("Pagination cursor from a previous fetchMessages call"),
192
+ direction: FETCH_DIRECTION.describe(
193
+ "'backward' (default) returns the most recent messages; 'forward' iterates from the oldest"
194
+ )
195
+ }),
196
+ execute: async ({ threadId, limit, cursor, direction }) => {
197
+ const thread = chat.thread(threadId);
198
+ const result = await thread.adapter.fetchMessages(threadId, {
199
+ limit,
200
+ cursor,
201
+ direction
202
+ });
203
+ return {
204
+ messages: result.messages.map(projectMessage),
205
+ nextCursor: result.nextCursor
206
+ };
207
+ }
208
+ });
209
+ var fetchChannelMessages = (chat) => tool4({
210
+ description: "Fetch top-level messages in a channel (not thread replies). Returns messages in chronological order within the page.",
211
+ inputSchema: z4.object({
212
+ channelId: z4.string().describe("Full channel id"),
213
+ limit: z4.number().int().min(1).max(100).optional().default(20),
214
+ cursor: z4.string().optional(),
215
+ direction: FETCH_DIRECTION
216
+ }),
217
+ execute: async ({ channelId, limit, cursor, direction }) => {
218
+ const adapterName = channelId.split(":")[0];
219
+ const adapter = adapterName ? chat.getAdapter(adapterName) : void 0;
220
+ if (!adapter?.fetchChannelMessages) {
221
+ throw new Error(
222
+ `Adapter "${adapterName}" does not support fetching channel messages`
223
+ );
224
+ }
225
+ const result = await adapter.fetchChannelMessages(channelId, {
226
+ limit,
227
+ cursor,
228
+ direction
229
+ });
230
+ return {
231
+ messages: result.messages.map(projectMessage),
232
+ nextCursor: result.nextCursor
233
+ };
234
+ }
235
+ });
236
+ var fetchThread = (chat) => tool4({
237
+ description: "Fetch metadata about a thread (channel id, channel name, visibility, DM status, etc).",
238
+ inputSchema: z4.object({
239
+ threadId: z4.string().describe("Full thread id")
240
+ }),
241
+ execute: async ({ threadId }) => {
242
+ const thread = chat.thread(threadId);
243
+ const info = await thread.adapter.fetchThread(threadId);
244
+ return {
245
+ id: info.id,
246
+ channelId: info.channelId,
247
+ channelName: info.channelName,
248
+ channelVisibility: info.channelVisibility,
249
+ isDM: info.isDM ?? false
250
+ };
251
+ }
252
+ });
253
+ var listThreads = (chat) => tool4({
254
+ description: "List recent threads in a channel. Returns lightweight summaries with the root message of each thread.",
255
+ inputSchema: z4.object({
256
+ channelId: z4.string().describe("Full channel id"),
257
+ limit: z4.number().int().min(1).max(100).optional().default(20),
258
+ cursor: z4.string().optional()
259
+ }),
260
+ execute: async ({ channelId, limit, cursor }) => {
261
+ const adapterName = channelId.split(":")[0];
262
+ const adapter = adapterName ? chat.getAdapter(adapterName) : void 0;
263
+ if (!adapter?.listThreads) {
264
+ throw new Error(
265
+ `Adapter "${adapterName}" does not support listing threads`
266
+ );
267
+ }
268
+ const result = await adapter.listThreads(channelId, { limit, cursor });
269
+ return {
270
+ threads: result.threads.map((t) => ({
271
+ id: t.id,
272
+ replyCount: t.replyCount,
273
+ lastReplyAt: t.lastReplyAt?.toISOString(),
274
+ rootMessage: projectMessage(t.rootMessage)
275
+ })),
276
+ nextCursor: result.nextCursor
277
+ };
278
+ }
279
+ });
280
+ var getThreadParticipants = (chat) => tool4({
281
+ description: "Return the unique non-bot participants in a thread. Useful for deciding whether to subscribe (1:1) or stay quiet (group).",
282
+ inputSchema: z4.object({
283
+ threadId: z4.string().describe("Full thread id")
284
+ }),
285
+ execute: async ({ threadId }) => {
286
+ const thread = chat.thread(threadId);
287
+ const participants = await thread.getParticipants();
288
+ return {
289
+ participants: participants.map((author) => ({
290
+ userId: author.userId,
291
+ userName: author.userName,
292
+ fullName: author.fullName,
293
+ isBot: author.isBot
294
+ }))
295
+ };
296
+ }
297
+ });
298
+ var subscribeThread = (chat, { needsApproval = true } = {}) => tool4({
299
+ description: "Subscribe to all future messages in a thread. After subscribing, the bot will receive every message in this thread (not just @mentions).",
300
+ needsApproval,
301
+ inputSchema: z4.object({
302
+ threadId: z4.string().describe("Full thread id to subscribe to")
303
+ }),
304
+ execute: async ({ threadId }) => {
305
+ const thread = chat.thread(threadId);
306
+ await thread.subscribe();
307
+ return { subscribed: true, threadId };
308
+ }
309
+ });
310
+ var unsubscribeThread = (chat, { needsApproval = true } = {}) => tool4({
311
+ description: "Unsubscribe from a thread. The bot will stop receiving non-mention messages in this thread.",
312
+ needsApproval,
313
+ inputSchema: z4.object({
314
+ threadId: z4.string().describe("Full thread id to unsubscribe from")
315
+ }),
316
+ execute: async ({ threadId }) => {
317
+ const thread = chat.thread(threadId);
318
+ await thread.unsubscribe();
319
+ return { subscribed: false, threadId };
320
+ }
321
+ });
322
+ var startTyping = (chat) => tool4({
323
+ description: "Show a typing indicator in a thread. Use this when starting a long-running operation so users know the bot is working.",
324
+ inputSchema: z4.object({
325
+ threadId: z4.string().describe("Full thread id"),
326
+ status: z4.string().optional().describe(
327
+ "Optional human-readable status (some platforms display this, others ignore it)"
328
+ )
329
+ }),
330
+ execute: async ({ threadId, status }) => {
331
+ const thread = chat.thread(threadId);
332
+ await thread.startTyping(status);
333
+ return { typing: true, threadId };
334
+ }
335
+ });
336
+
337
+ // src/ai/tools/users.ts
338
+ import { tool as tool5 } from "ai";
339
+ import { z as z5 } from "zod";
340
+ var getUser = (chat) => tool5({
341
+ description: "Look up profile information about a user by their platform-specific id (e.g. 'U123456' for Slack, '29:...' for Teams, 'users/123' for Google Chat). Returns null if the user is unknown.",
342
+ inputSchema: z5.object({
343
+ userId: z5.string().describe("Platform-specific user id; the adapter is auto-detected")
344
+ }),
345
+ execute: async ({ userId }) => {
346
+ const user = await chat.getUser(userId);
347
+ if (!user) {
348
+ return null;
349
+ }
350
+ return {
351
+ userId: user.userId,
352
+ userName: user.userName,
353
+ fullName: user.fullName,
354
+ email: user.email,
355
+ isBot: user.isBot,
356
+ avatarUrl: user.avatarUrl
357
+ };
358
+ }
359
+ });
360
+
361
+ // src/ai/index.ts
362
+ var PROTECTED_TOOL_FIELDS = /* @__PURE__ */ new Set([
363
+ "args",
364
+ "execute",
365
+ "id",
366
+ "inputSchema",
367
+ "outputSchema",
368
+ "supportsDeferredResults",
369
+ "type"
370
+ ]);
371
+ var PRESET_TOOLS = {
372
+ reader: [
373
+ "fetchMessages",
374
+ "fetchChannelMessages",
375
+ "fetchThread",
376
+ "listThreads",
377
+ "getThreadParticipants",
378
+ "getChannelInfo",
379
+ "getUser"
380
+ ],
381
+ messenger: [
382
+ "fetchMessages",
383
+ "fetchThread",
384
+ "getChannelInfo",
385
+ "getUser",
386
+ "postMessage",
387
+ "postChannelMessage",
388
+ "sendDirectMessage",
389
+ "addReaction",
390
+ "removeReaction",
391
+ "startTyping"
392
+ ],
393
+ moderator: [
394
+ "fetchMessages",
395
+ "fetchChannelMessages",
396
+ "fetchThread",
397
+ "listThreads",
398
+ "getThreadParticipants",
399
+ "getChannelInfo",
400
+ "getUser",
401
+ "postMessage",
402
+ "postChannelMessage",
403
+ "sendDirectMessage",
404
+ "editMessage",
405
+ "deleteMessage",
406
+ "addReaction",
407
+ "removeReaction",
408
+ "subscribeThread",
409
+ "unsubscribeThread",
410
+ "startTyping"
411
+ ]
412
+ };
413
+ function resolveApproval(toolName, config) {
414
+ if (typeof config === "boolean") {
415
+ return config;
416
+ }
417
+ return config[toolName] ?? true;
418
+ }
419
+ function resolvePresetTools(preset) {
420
+ const presets = Array.isArray(preset) ? preset : [preset];
421
+ const tools = /* @__PURE__ */ new Set();
422
+ for (const p of presets) {
423
+ for (const t of PRESET_TOOLS[p]) {
424
+ tools.add(t);
425
+ }
426
+ }
427
+ return tools;
428
+ }
429
+ function applyOverrides(tool6, overrides) {
430
+ if (!overrides) {
431
+ return tool6;
432
+ }
433
+ const safeOverrides = Object.fromEntries(
434
+ Object.entries(overrides).filter(
435
+ ([key]) => !PROTECTED_TOOL_FIELDS.has(key)
436
+ )
437
+ );
438
+ return { ...tool6, ...safeOverrides };
439
+ }
440
+ function createChatTools({
441
+ chat,
442
+ requireApproval = true,
443
+ preset,
444
+ overrides
445
+ }) {
446
+ if (!chat) {
447
+ throw new Error(
448
+ "createChatTools requires a `chat` instance. Pass your `new Chat({ ... })` instance as the `chat` option."
449
+ );
450
+ }
451
+ const approval = (name) => ({
452
+ needsApproval: resolveApproval(name, requireApproval)
453
+ });
454
+ const allowed = preset ? resolvePresetTools(preset) : null;
455
+ const factories = {
456
+ fetchMessages: () => fetchMessages(chat),
457
+ fetchChannelMessages: () => fetchChannelMessages(chat),
458
+ fetchThread: () => fetchThread(chat),
459
+ listThreads: () => listThreads(chat),
460
+ getThreadParticipants: () => getThreadParticipants(chat),
461
+ getChannelInfo: () => getChannelInfo(chat),
462
+ getUser: () => getUser(chat),
463
+ startTyping: () => startTyping(chat),
464
+ postMessage: () => postMessage(chat, approval("postMessage")),
465
+ postChannelMessage: () => postChannelMessage(chat, approval("postChannelMessage")),
466
+ sendDirectMessage: () => sendDirectMessage(chat, approval("sendDirectMessage")),
467
+ editMessage: () => editMessage(chat, approval("editMessage")),
468
+ deleteMessage: () => deleteMessage(chat, approval("deleteMessage")),
469
+ addReaction: () => addReaction(chat, approval("addReaction")),
470
+ removeReaction: () => removeReaction(chat, approval("removeReaction")),
471
+ subscribeThread: () => subscribeThread(chat, approval("subscribeThread")),
472
+ unsubscribeThread: () => unsubscribeThread(chat, approval("unsubscribeThread"))
473
+ };
474
+ const entries = Object.entries(factories).filter(([name]) => !allowed || allowed.has(name)).map(([name, build]) => {
475
+ const built = build();
476
+ return [name, applyOverrides(built, overrides?.[name])];
477
+ });
478
+ return Object.fromEntries(entries);
479
+ }
480
+ export {
481
+ addReaction,
482
+ createChatTools,
483
+ deleteMessage,
484
+ editMessage,
485
+ fetchChannelMessages,
486
+ fetchMessages,
487
+ fetchThread,
488
+ getChannelInfo,
489
+ getThreadParticipants,
490
+ getUser,
491
+ listThreads,
492
+ postChannelMessage,
493
+ postMessage,
494
+ removeReaction,
495
+ sendDirectMessage,
496
+ startTyping,
497
+ subscribeThread,
498
+ toAiMessages,
499
+ unsubscribeThread
500
+ };