chat 4.13.1 → 4.13.2
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.
- package/README.md +19 -31
- package/dist/{chunk-WKJEG4FE.js → chunk-THM4ACIE.js} +12 -4
- package/dist/chunk-THM4ACIE.js.map +1 -0
- package/dist/index.d.ts +409 -415
- package/dist/index.js +63 -29
- package/dist/index.js.map +1 -1
- package/dist/{jsx-runtime-COVsDskT.d.ts → jsx-runtime-Bdt1Dwzf.d.ts} +71 -71
- package/dist/jsx-runtime.d.ts +1 -1
- package/dist/jsx-runtime.js +1 -1
- package/docs/actions.mdx +98 -0
- package/docs/adapters/discord.mdx +217 -0
- package/docs/adapters/gchat.mdx +232 -0
- package/docs/adapters/github.mdx +225 -0
- package/docs/adapters/index.mdx +110 -0
- package/docs/adapters/linear.mdx +207 -0
- package/docs/adapters/meta.json +12 -0
- package/docs/adapters/slack.mdx +293 -0
- package/docs/adapters/teams.mdx +225 -0
- package/docs/api/cards.mdx +217 -0
- package/docs/api/channel.mdx +176 -0
- package/docs/api/chat.mdx +469 -0
- package/docs/api/index.mdx +29 -0
- package/docs/api/markdown.mdx +235 -0
- package/docs/api/message.mdx +163 -0
- package/docs/api/meta.json +14 -0
- package/docs/api/modals.mdx +222 -0
- package/docs/api/postable-message.mdx +166 -0
- package/docs/api/thread.mdx +186 -0
- package/docs/cards.mdx +213 -0
- package/docs/direct-messages.mdx +56 -0
- package/docs/emoji.mdx +77 -0
- package/docs/ephemeral-messages.mdx +77 -0
- package/docs/error-handling.mdx +147 -0
- package/docs/files.mdx +77 -0
- package/docs/getting-started.mdx +12 -0
- package/docs/guides/code-review-hono.mdx +248 -0
- package/docs/guides/discord-nuxt.mdx +237 -0
- package/docs/guides/meta.json +4 -0
- package/docs/guides/slack-nextjs.mdx +245 -0
- package/docs/index.mdx +92 -0
- package/docs/meta.json +20 -0
- package/docs/modals.mdx +208 -0
- package/docs/posting-messages.mdx +177 -0
- package/docs/slash-commands.mdx +110 -0
- package/docs/state/index.mdx +31 -0
- package/docs/state/ioredis.mdx +81 -0
- package/docs/state/memory.mdx +52 -0
- package/docs/state/meta.json +9 -0
- package/docs/state/redis.mdx +93 -0
- package/docs/streaming.mdx +99 -0
- package/docs/usage.mdx +338 -0
- package/package.json +10 -10
- package/dist/chunk-WKJEG4FE.js.map +0 -1
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Redis
|
|
3
|
+
description: Production state adapter using the official redis package.
|
|
4
|
+
type: reference
|
|
5
|
+
prerequisites:
|
|
6
|
+
- /docs/getting-started
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
The recommended state adapter for production. Uses the official [redis](https://www.npmjs.com/package/redis) package.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```sh title="Terminal"
|
|
14
|
+
pnpm add @chat-adapter/state-redis
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
20
|
+
import { Chat } from "chat";
|
|
21
|
+
import { createRedisState } from "@chat-adapter/state-redis";
|
|
22
|
+
|
|
23
|
+
const bot = new Chat({
|
|
24
|
+
userName: "mybot",
|
|
25
|
+
adapters: { /* ... */ },
|
|
26
|
+
state: createRedisState({
|
|
27
|
+
url: process.env.REDIS_URL!,
|
|
28
|
+
}),
|
|
29
|
+
});
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Using an existing client
|
|
33
|
+
|
|
34
|
+
If you already have a connected Redis client, pass it directly:
|
|
35
|
+
|
|
36
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
37
|
+
import { createClient } from "redis";
|
|
38
|
+
|
|
39
|
+
const client = createClient({ url: "redis://localhost:6379" });
|
|
40
|
+
await client.connect();
|
|
41
|
+
|
|
42
|
+
const state = createRedisState({ client });
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Key prefix
|
|
46
|
+
|
|
47
|
+
All keys are namespaced under a configurable prefix (default: `"chat-sdk"`):
|
|
48
|
+
|
|
49
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
50
|
+
const state = createRedisState({
|
|
51
|
+
url: process.env.REDIS_URL!,
|
|
52
|
+
keyPrefix: "my-bot",
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Configuration
|
|
57
|
+
|
|
58
|
+
| Option | Required | Description |
|
|
59
|
+
|--------|----------|-------------|
|
|
60
|
+
| `url` | Yes* | Redis connection URL |
|
|
61
|
+
| `client` | No | Existing `redis` client instance |
|
|
62
|
+
| `keyPrefix` | No | Prefix for all keys (default: `"chat-sdk"`) |
|
|
63
|
+
|
|
64
|
+
*Either `url` or `client` is required.
|
|
65
|
+
|
|
66
|
+
## Environment variables
|
|
67
|
+
|
|
68
|
+
```bash title=".env.local"
|
|
69
|
+
REDIS_URL=redis://localhost:6379
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
For serverless deployments (Vercel, AWS Lambda), use a serverless-compatible Redis provider like [Upstash](https://upstash.com).
|
|
73
|
+
|
|
74
|
+
## Key structure
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
{keyPrefix}:subscriptions - SET of subscribed thread IDs
|
|
78
|
+
{keyPrefix}:lock:{threadId} - Lock key with TTL
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Production recommendations
|
|
82
|
+
|
|
83
|
+
- Use Redis 6.0+ for best performance
|
|
84
|
+
- Enable Redis persistence (RDB or AOF)
|
|
85
|
+
- Use Redis Cluster for high availability
|
|
86
|
+
- Set appropriate memory limits
|
|
87
|
+
|
|
88
|
+
## Features
|
|
89
|
+
|
|
90
|
+
- Persistent subscriptions across restarts
|
|
91
|
+
- Distributed locking across multiple instances
|
|
92
|
+
- Automatic reconnection
|
|
93
|
+
- Key prefix namespacing
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Streaming
|
|
3
|
+
description: Stream real-time text responses from AI models and other async sources to chat platforms.
|
|
4
|
+
type: guide
|
|
5
|
+
prerequisites:
|
|
6
|
+
- /docs/usage
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Chat SDK accepts any `AsyncIterable<string>` as a message, enabling real-time streaming of AI responses and other incremental content to chat platforms.
|
|
10
|
+
|
|
11
|
+
## AI SDK integration
|
|
12
|
+
|
|
13
|
+
Pass an AI SDK `textStream` directly to `thread.post()`:
|
|
14
|
+
|
|
15
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
16
|
+
import { ToolLoopAgent } from "ai";
|
|
17
|
+
|
|
18
|
+
const agent = new ToolLoopAgent({
|
|
19
|
+
model: "anthropic/claude-4.5-sonnet",
|
|
20
|
+
instructions: "You are a helpful assistant.",
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
bot.onNewMention(async (thread, message) => {
|
|
24
|
+
const result = await agent.stream({ prompt: message.text });
|
|
25
|
+
await thread.post(result.textStream);
|
|
26
|
+
});
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Custom streams
|
|
30
|
+
|
|
31
|
+
Any async iterable works:
|
|
32
|
+
|
|
33
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
34
|
+
const stream = (async function* () {
|
|
35
|
+
yield "Processing";
|
|
36
|
+
yield "...";
|
|
37
|
+
yield " done!";
|
|
38
|
+
})();
|
|
39
|
+
|
|
40
|
+
await thread.post(stream);
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Platform behavior
|
|
44
|
+
|
|
45
|
+
| Platform | Method | Description |
|
|
46
|
+
|----------|--------|-------------|
|
|
47
|
+
| Slack | Native streaming API | Uses Slack's `chatStream` for smooth, real-time updates |
|
|
48
|
+
| Teams | Post + Edit | Posts a message then edits it as chunks arrive |
|
|
49
|
+
| Google Chat | Post + Edit | Posts a message then edits it as chunks arrive |
|
|
50
|
+
| Discord | Post + Edit | Posts a message then edits it as chunks arrive |
|
|
51
|
+
|
|
52
|
+
The post+edit fallback throttles edits to avoid rate limits. Configure the update interval when creating your `Chat` instance:
|
|
53
|
+
|
|
54
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
55
|
+
const bot = new Chat({
|
|
56
|
+
// ...
|
|
57
|
+
streamingUpdateIntervalMs: 500, // Default: 500ms
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Stop blocks (Slack only)
|
|
62
|
+
|
|
63
|
+
When streaming in Slack, you can attach Block Kit elements to the final message using `stopBlocks`. This is useful for adding action buttons after a streamed response completes:
|
|
64
|
+
|
|
65
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
66
|
+
await thread.stream(textStream, {
|
|
67
|
+
stopBlocks: [
|
|
68
|
+
{
|
|
69
|
+
type: "actions",
|
|
70
|
+
elements: [{
|
|
71
|
+
type: "button",
|
|
72
|
+
text: { type: "plain_text", text: "Retry" },
|
|
73
|
+
action_id: "retry",
|
|
74
|
+
}],
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Streaming with conversation history
|
|
81
|
+
|
|
82
|
+
Combine message history with streaming for multi-turn AI conversations:
|
|
83
|
+
|
|
84
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
85
|
+
bot.onSubscribedMessage(async (thread, message) => {
|
|
86
|
+
// Fetch recent messages for context
|
|
87
|
+
const result = await thread.adapter.fetchMessages(thread.id, { limit: 20 });
|
|
88
|
+
|
|
89
|
+
const history = result.messages
|
|
90
|
+
.filter((msg) => msg.text.trim())
|
|
91
|
+
.map((msg) => ({
|
|
92
|
+
role: msg.author.isMe ? "assistant" as const : "user" as const,
|
|
93
|
+
content: msg.text,
|
|
94
|
+
}));
|
|
95
|
+
|
|
96
|
+
const response = await agent.stream({ prompt: history });
|
|
97
|
+
await thread.post(response.textStream);
|
|
98
|
+
});
|
|
99
|
+
```
|
package/docs/usage.mdx
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Usage
|
|
3
|
+
description: Event handlers, threads, channels, messages, and the core patterns of Chat SDK.
|
|
4
|
+
type: guide
|
|
5
|
+
prerequisites:
|
|
6
|
+
- /docs/getting-started
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Chat SDK uses an event-driven architecture. You register handlers for different event types, and the SDK routes incoming webhooks to the appropriate handler.
|
|
10
|
+
|
|
11
|
+
## Event handlers
|
|
12
|
+
|
|
13
|
+
### Mention handler
|
|
14
|
+
|
|
15
|
+
`onNewMention` fires when your bot is @-mentioned in a thread it hasn't subscribed to yet. This is the primary entry point for new conversations.
|
|
16
|
+
|
|
17
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
18
|
+
bot.onNewMention(async (thread, message) => {
|
|
19
|
+
await thread.subscribe();
|
|
20
|
+
await thread.post("Hello! I'm now listening to this thread.");
|
|
21
|
+
});
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Subscribed message handler
|
|
25
|
+
|
|
26
|
+
`onSubscribedMessage` fires for every new message in a thread your bot has subscribed to. Once subscribed, all messages (including @mentions) route here instead of `onNewMention`.
|
|
27
|
+
|
|
28
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
29
|
+
bot.onSubscribedMessage(async (thread, message) => {
|
|
30
|
+
// Check if the bot was @-mentioned specifically
|
|
31
|
+
if (message.isMention) {
|
|
32
|
+
await thread.post("You mentioned me!");
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
await thread.post(`Got your message: ${message.text}`);
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Pattern handler
|
|
41
|
+
|
|
42
|
+
`onNewMessage` fires for messages matching a regex pattern in threads the bot is **not** subscribed to. Useful for keyword-triggered responses.
|
|
43
|
+
|
|
44
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
45
|
+
bot.onNewMessage(/^help$/i, async (thread, message) => {
|
|
46
|
+
await thread.post("Here's how I can help...");
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Slash command handler
|
|
51
|
+
|
|
52
|
+
`onSlashCommand` fires when a user invokes a `/command` in the message composer. See [Slash Commands](/docs/slash-commands) for the full guide.
|
|
53
|
+
|
|
54
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
55
|
+
bot.onSlashCommand("/status", async (event) => {
|
|
56
|
+
await event.channel.post("All systems operational!");
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Reaction handler
|
|
61
|
+
|
|
62
|
+
`onReaction` fires when users add or remove emoji reactions to messages.
|
|
63
|
+
|
|
64
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
65
|
+
import { emoji } from "chat";
|
|
66
|
+
|
|
67
|
+
bot.onReaction(["thumbs_up", "heart"], async (event) => {
|
|
68
|
+
if (!event.added) return;
|
|
69
|
+
|
|
70
|
+
await event.adapter.addReaction(
|
|
71
|
+
event.threadId,
|
|
72
|
+
event.messageId,
|
|
73
|
+
emoji.raised_hands
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The `event` object includes:
|
|
79
|
+
|
|
80
|
+
| Property | Type | Description |
|
|
81
|
+
|----------|------|-------------|
|
|
82
|
+
| `emoji` | `EmojiValue` | Normalized emoji for comparison |
|
|
83
|
+
| `rawEmoji` | `string` | Platform-specific emoji string |
|
|
84
|
+
| `added` | `boolean` | `true` if added, `false` if removed |
|
|
85
|
+
| `user` | `Author` | The user who reacted |
|
|
86
|
+
| `message` | `Message` (optional) | The message that was reacted to |
|
|
87
|
+
| `thread` | `Thread` | Thread for posting replies |
|
|
88
|
+
| `adapter` | `Adapter` | The platform adapter |
|
|
89
|
+
|
|
90
|
+
### Assistant thread handler
|
|
91
|
+
|
|
92
|
+
`onAssistantThreadStarted` fires when a user opens a new assistant thread in Slack. Use it with the Slack Assistants API to set suggested prompts and status indicators. See [Slack Assistants API](/docs/adapters/slack#slack-assistants-api) for details.
|
|
93
|
+
|
|
94
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
95
|
+
bot.onAssistantThreadStarted(async (event) => {
|
|
96
|
+
const slack = bot.getAdapter("slack") as SlackAdapter;
|
|
97
|
+
await slack.setSuggestedPrompts(event.channelId, event.threadTs, [
|
|
98
|
+
{ title: "Get started", message: "What can you help me with?" },
|
|
99
|
+
]);
|
|
100
|
+
});
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### App Home handler
|
|
104
|
+
|
|
105
|
+
`onAppHomeOpened` fires when a user opens your bot's Home tab in Slack. Use it to publish a dynamic view.
|
|
106
|
+
|
|
107
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
108
|
+
bot.onAppHomeOpened(async (event) => {
|
|
109
|
+
const slack = bot.getAdapter("slack") as SlackAdapter;
|
|
110
|
+
await slack.publishHomeView(event.userId, {
|
|
111
|
+
type: "home",
|
|
112
|
+
blocks: [{ type: "section", text: { type: "mrkdwn", text: "Welcome!" } }],
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Threads
|
|
118
|
+
|
|
119
|
+
A `Thread` represents a conversation thread on any platform. It provides methods for posting messages, managing subscriptions, and accessing message history.
|
|
120
|
+
|
|
121
|
+
### Post a message
|
|
122
|
+
|
|
123
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
124
|
+
// Plain text
|
|
125
|
+
await thread.post("Hello world");
|
|
126
|
+
|
|
127
|
+
// Markdown (converted to each platform's format)
|
|
128
|
+
await thread.post("**Bold** and _italic_ text");
|
|
129
|
+
|
|
130
|
+
// Structured message with attachments
|
|
131
|
+
await thread.post({
|
|
132
|
+
markdown: "Here's a file:",
|
|
133
|
+
files: [{ data: buffer, filename: "report.pdf" }],
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Subscribe and unsubscribe
|
|
138
|
+
|
|
139
|
+
Subscriptions persist across restarts (stored in your state adapter). When a thread is subscribed, all messages route to `onSubscribedMessage`.
|
|
140
|
+
|
|
141
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
142
|
+
await thread.subscribe();
|
|
143
|
+
await thread.unsubscribe();
|
|
144
|
+
|
|
145
|
+
const subscribed = await thread.isSubscribed();
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Typing indicator
|
|
149
|
+
|
|
150
|
+
```typescript title="lib/bot.ts"
|
|
151
|
+
await thread.startTyping();
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
<Callout type="info">
|
|
155
|
+
Not all platforms support typing indicators. The call is a no-op on unsupported platforms. See the [adapter feature matrix](/docs/adapters) for details.
|
|
156
|
+
</Callout>
|
|
157
|
+
|
|
158
|
+
### Message history
|
|
159
|
+
|
|
160
|
+
Access recent messages or iterate through full history:
|
|
161
|
+
|
|
162
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
163
|
+
// Cached messages from the webhook payload
|
|
164
|
+
const recent = thread.recentMessages;
|
|
165
|
+
|
|
166
|
+
// Newest first (auto-paginates)
|
|
167
|
+
for await (const msg of thread.messages) {
|
|
168
|
+
console.log(msg.text);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Oldest first (auto-paginates)
|
|
172
|
+
for await (const msg of thread.allMessages) {
|
|
173
|
+
console.log(msg.text);
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Thread state
|
|
178
|
+
|
|
179
|
+
Store typed, per-thread state that persists across requests:
|
|
180
|
+
|
|
181
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
182
|
+
interface ThreadState {
|
|
183
|
+
aiMode?: boolean;
|
|
184
|
+
context?: string;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const bot = new Chat<typeof adapters, ThreadState>({
|
|
188
|
+
// ...config
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
bot.onNewMention(async (thread) => {
|
|
192
|
+
await thread.setState({ aiMode: true });
|
|
193
|
+
|
|
194
|
+
const state = await thread.state; // ThreadState | null
|
|
195
|
+
if (state?.aiMode) {
|
|
196
|
+
// AI mode is enabled
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
State is stored in your state adapter with a 30-day TTL. Use `{ replace: true }` to replace state entirely instead of merging:
|
|
202
|
+
|
|
203
|
+
```typescript title="lib/bot.ts"
|
|
204
|
+
await thread.setState({ aiMode: false }, { replace: true });
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Messages
|
|
208
|
+
|
|
209
|
+
Incoming messages are normalized across platforms into a consistent format:
|
|
210
|
+
|
|
211
|
+
| Property | Type | Description |
|
|
212
|
+
|----------|------|-------------|
|
|
213
|
+
| `id` | `string` | Platform message ID |
|
|
214
|
+
| `threadId` | `string` | Thread ID in `adapter:channel:thread` format |
|
|
215
|
+
| `text` | `string` | Plain text content |
|
|
216
|
+
| `formatted` | `Root` | mdast AST representation |
|
|
217
|
+
| `raw` | `unknown` | Original platform-specific payload |
|
|
218
|
+
| `author` | `Author` | Message author info |
|
|
219
|
+
| `metadata` | `MessageMetadata` | Timestamps and edit status |
|
|
220
|
+
| `attachments` | `Attachment[]` (optional) | File attachments |
|
|
221
|
+
| `isMention` | `boolean` (optional) | Whether the bot was @-mentioned |
|
|
222
|
+
|
|
223
|
+
### Author
|
|
224
|
+
|
|
225
|
+
```typescript lineNumbers
|
|
226
|
+
interface Author {
|
|
227
|
+
userId: string;
|
|
228
|
+
userName: string;
|
|
229
|
+
fullName: string;
|
|
230
|
+
isBot: boolean | "unknown";
|
|
231
|
+
isMe: boolean; // true if message is from the bot itself
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Sent messages
|
|
236
|
+
|
|
237
|
+
When you post a message, you get back a `SentMessage` with methods to edit, delete, and react:
|
|
238
|
+
|
|
239
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
240
|
+
const sent = await thread.post("Processing...");
|
|
241
|
+
// Do some work...
|
|
242
|
+
await sent.edit("Done!");
|
|
243
|
+
|
|
244
|
+
// Or delete
|
|
245
|
+
await sent.delete();
|
|
246
|
+
|
|
247
|
+
// Add/remove reactions
|
|
248
|
+
await sent.addReaction(emoji.check);
|
|
249
|
+
await sent.removeReaction(emoji.check);
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## Channels
|
|
253
|
+
|
|
254
|
+
A `Channel` represents the container that holds threads (e.g., a Slack channel, a Teams conversation). Navigate to a channel from a thread or get one directly:
|
|
255
|
+
|
|
256
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
257
|
+
// From a thread
|
|
258
|
+
const channel = thread.channel;
|
|
259
|
+
|
|
260
|
+
// Directly by ID
|
|
261
|
+
const channel = bot.channel("slack:C123ABC");
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### List threads
|
|
265
|
+
|
|
266
|
+
Iterate threads in a channel, most recently active first:
|
|
267
|
+
|
|
268
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
269
|
+
for await (const thread of channel.threads()) {
|
|
270
|
+
console.log(thread.rootMessage.text, thread.replyCount);
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Channel messages
|
|
275
|
+
|
|
276
|
+
Iterate top-level messages (not thread replies):
|
|
277
|
+
|
|
278
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
279
|
+
for await (const msg of channel.messages) {
|
|
280
|
+
console.log(msg.text);
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Post to a channel
|
|
285
|
+
|
|
286
|
+
Post a top-level message (not inside a thread):
|
|
287
|
+
|
|
288
|
+
```typescript title="lib/bot.ts"
|
|
289
|
+
await channel.post("Hello channel!");
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Channel metadata
|
|
293
|
+
|
|
294
|
+
```typescript title="lib/bot.ts"
|
|
295
|
+
const info = await channel.fetchMetadata();
|
|
296
|
+
console.log(info.name, info.memberCount);
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
## Thread ID format
|
|
300
|
+
|
|
301
|
+
All thread IDs follow the pattern `{adapter}:{channel}:{thread}`:
|
|
302
|
+
|
|
303
|
+
- **Slack**: `slack:C123ABC:1234567890.123456`
|
|
304
|
+
- **Teams**: `teams:{base64(conversationId)}:{base64(serviceUrl)}`
|
|
305
|
+
- **Google Chat**: `gchat:spaces/ABC123:{base64(threadName)}`
|
|
306
|
+
- **Discord**: `discord:{guildId}:{channelId}/{messageId}`
|
|
307
|
+
|
|
308
|
+
You typically don't need to construct these yourself — they're provided by the SDK in event handlers.
|
|
309
|
+
|
|
310
|
+
## Logging
|
|
311
|
+
|
|
312
|
+
Configure logging when creating the `Chat` instance:
|
|
313
|
+
|
|
314
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
315
|
+
// Use a built-in log level
|
|
316
|
+
const bot = new Chat({
|
|
317
|
+
// ...
|
|
318
|
+
logger: "debug", // "debug" | "info" | "warn" | "error" | "silent"
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// Or use ConsoleLogger for child loggers
|
|
322
|
+
import { ConsoleLogger } from "chat";
|
|
323
|
+
|
|
324
|
+
const logger = new ConsoleLogger("info");
|
|
325
|
+
const bot = new Chat({
|
|
326
|
+
// ...
|
|
327
|
+
logger,
|
|
328
|
+
});
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
Pass child loggers to adapters for prefixed log output:
|
|
332
|
+
|
|
333
|
+
```typescript title="lib/bot.ts"
|
|
334
|
+
createSlackAdapter({
|
|
335
|
+
// ...
|
|
336
|
+
logger: logger.child("slack"),
|
|
337
|
+
});
|
|
338
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chat",
|
|
3
|
-
"version": "4.13.
|
|
3
|
+
"version": "4.13.2",
|
|
4
4
|
"description": "Unified chat abstraction for Slack, Teams, Google Chat, and Discord",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -21,10 +21,11 @@
|
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
23
|
"files": [
|
|
24
|
-
"dist"
|
|
24
|
+
"dist",
|
|
25
|
+
"docs"
|
|
25
26
|
],
|
|
26
27
|
"dependencies": {
|
|
27
|
-
"@workflow/serde": "4.0
|
|
28
|
+
"@workflow/serde": "4.1.0-beta.2",
|
|
28
29
|
"mdast-util-to-string": "^4.0.0",
|
|
29
30
|
"remark-gfm": "^4.0.0",
|
|
30
31
|
"remark-parse": "^11.0.0",
|
|
@@ -40,12 +41,12 @@
|
|
|
40
41
|
},
|
|
41
42
|
"repository": {
|
|
42
43
|
"type": "git",
|
|
43
|
-
"url": "git+https://github.com/vercel
|
|
44
|
+
"url": "git+https://github.com/vercel/chat.git",
|
|
44
45
|
"directory": "packages/chat-sdk"
|
|
45
46
|
},
|
|
46
|
-
"homepage": "https://github.com/vercel
|
|
47
|
+
"homepage": "https://github.com/vercel/chat#readme",
|
|
47
48
|
"bugs": {
|
|
48
|
-
"url": "https://github.com/vercel
|
|
49
|
+
"url": "https://github.com/vercel/chat/issues"
|
|
49
50
|
},
|
|
50
51
|
"publishConfig": {
|
|
51
52
|
"access": "public"
|
|
@@ -60,12 +61,11 @@
|
|
|
60
61
|
],
|
|
61
62
|
"license": "MIT",
|
|
62
63
|
"scripts": {
|
|
63
|
-
"build": "
|
|
64
|
+
"build": "pnpm clean && tsup && cp -r ../../apps/docs/content/docs ./docs",
|
|
64
65
|
"dev": "tsup --watch",
|
|
65
|
-
"test": "vitest run",
|
|
66
|
+
"test": "vitest run --coverage",
|
|
66
67
|
"test:watch": "vitest",
|
|
67
68
|
"typecheck": "tsc --noEmit",
|
|
68
|
-
"
|
|
69
|
-
"clean": "rm -rf dist"
|
|
69
|
+
"clean": "rm -rf dist docs"
|
|
70
70
|
}
|
|
71
71
|
}
|