chat 4.13.0 → 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,225 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Microsoft Teams
|
|
3
|
+
description: Configure the Microsoft Teams adapter with Azure Bot Service.
|
|
4
|
+
type: integration
|
|
5
|
+
prerequisites:
|
|
6
|
+
- /docs/getting-started
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```sh title="Terminal"
|
|
12
|
+
pnpm add @chat-adapter/teams
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```typescript title="lib/bot.ts" lineNumbers
|
|
18
|
+
import { Chat } from "chat";
|
|
19
|
+
import { createTeamsAdapter } from "@chat-adapter/teams";
|
|
20
|
+
|
|
21
|
+
const bot = new Chat({
|
|
22
|
+
userName: "mybot",
|
|
23
|
+
adapters: {
|
|
24
|
+
teams: createTeamsAdapter({
|
|
25
|
+
appId: process.env.TEAMS_APP_ID!,
|
|
26
|
+
appPassword: process.env.TEAMS_APP_PASSWORD!,
|
|
27
|
+
appType: "SingleTenant",
|
|
28
|
+
appTenantId: process.env.TEAMS_APP_TENANT_ID!,
|
|
29
|
+
}),
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
bot.onNewMention(async (thread, message) => {
|
|
34
|
+
await thread.post("Hello from Teams!");
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Azure Bot setup
|
|
39
|
+
|
|
40
|
+
### 1. Create Azure Bot resource
|
|
41
|
+
|
|
42
|
+
1. Go to [portal.azure.com](https://portal.azure.com)
|
|
43
|
+
2. Click **Create a resource**
|
|
44
|
+
3. Search for **Azure Bot** and select it
|
|
45
|
+
4. Click **Create** and fill in:
|
|
46
|
+
- **Bot handle**: Unique identifier for your bot
|
|
47
|
+
- **Subscription**: Your Azure subscription
|
|
48
|
+
- **Resource group**: Create new or use existing
|
|
49
|
+
- **Pricing tier**: F0 (free) for testing
|
|
50
|
+
- **Type of App**: **Single Tenant** (recommended for enterprise)
|
|
51
|
+
- **Creation type**: **Create new Microsoft App ID**
|
|
52
|
+
5. Click **Review + create** then **Create**
|
|
53
|
+
|
|
54
|
+
### 2. Get app credentials
|
|
55
|
+
|
|
56
|
+
1. Go to your Bot resource then **Configuration**
|
|
57
|
+
2. Copy **Microsoft App ID** as `TEAMS_APP_ID`
|
|
58
|
+
3. Click **Manage Password** (next to Microsoft App ID)
|
|
59
|
+
4. In the App Registration page, go to **Certificates & secrets**
|
|
60
|
+
5. Click **New client secret**, add description, select expiry, click **Add**
|
|
61
|
+
6. Copy the **Value** immediately (shown only once) as `TEAMS_APP_PASSWORD`
|
|
62
|
+
7. Go to **Overview** and copy **Directory (tenant) ID** as `TEAMS_APP_TENANT_ID`
|
|
63
|
+
|
|
64
|
+
### 3. Configure messaging endpoint
|
|
65
|
+
|
|
66
|
+
1. In your Azure Bot resource, go to **Configuration**
|
|
67
|
+
2. Set **Messaging endpoint** to `https://your-domain.com/api/webhooks/teams`
|
|
68
|
+
3. Click **Apply**
|
|
69
|
+
|
|
70
|
+
### 4. Enable Teams channel
|
|
71
|
+
|
|
72
|
+
1. In your Azure Bot resource, go to **Channels**
|
|
73
|
+
2. Click **Microsoft Teams**
|
|
74
|
+
3. Accept the terms of service
|
|
75
|
+
4. Click **Apply**
|
|
76
|
+
|
|
77
|
+
### 5. Create Teams app package
|
|
78
|
+
|
|
79
|
+
Create a `manifest.json` file:
|
|
80
|
+
|
|
81
|
+
```json title="manifest.json" lineNumbers
|
|
82
|
+
{
|
|
83
|
+
"$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.16/MicrosoftTeams.schema.json",
|
|
84
|
+
"manifestVersion": "1.16",
|
|
85
|
+
"version": "1.0.0",
|
|
86
|
+
"id": "your_app_id_here",
|
|
87
|
+
"packageName": "com.yourcompany.chatbot",
|
|
88
|
+
"developer": {
|
|
89
|
+
"name": "Your Company",
|
|
90
|
+
"websiteUrl": "https://your-domain.com",
|
|
91
|
+
"privacyUrl": "https://your-domain.com/privacy",
|
|
92
|
+
"termsOfUseUrl": "https://your-domain.com/terms"
|
|
93
|
+
},
|
|
94
|
+
"name": {
|
|
95
|
+
"short": "Chat Bot",
|
|
96
|
+
"full": "Chat SDK Demo Bot"
|
|
97
|
+
},
|
|
98
|
+
"description": {
|
|
99
|
+
"short": "A chat bot powered by Chat SDK",
|
|
100
|
+
"full": "A chat bot powered by Chat SDK that responds to messages and commands."
|
|
101
|
+
},
|
|
102
|
+
"icons": {
|
|
103
|
+
"outline": "outline.png",
|
|
104
|
+
"color": "color.png"
|
|
105
|
+
},
|
|
106
|
+
"accentColor": "#FFFFFF",
|
|
107
|
+
"bots": [
|
|
108
|
+
{
|
|
109
|
+
"botId": "your_app_id_here",
|
|
110
|
+
"scopes": ["personal", "team", "groupchat"],
|
|
111
|
+
"supportsFiles": false,
|
|
112
|
+
"isNotificationOnly": false
|
|
113
|
+
}
|
|
114
|
+
],
|
|
115
|
+
"permissions": ["identity", "messageTeamMembers"],
|
|
116
|
+
"validDomains": ["your-domain.com"]
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Create icon files (32x32 `outline.png` and 192x192 `color.png`), then zip all three files together.
|
|
121
|
+
|
|
122
|
+
### 6. Upload app to Teams
|
|
123
|
+
|
|
124
|
+
**For testing (sideloading):**
|
|
125
|
+
|
|
126
|
+
1. In Teams, click **Apps** in the sidebar
|
|
127
|
+
2. Click **Manage your apps** then **Upload an app**
|
|
128
|
+
3. Click **Upload a custom app** and select your zip file
|
|
129
|
+
|
|
130
|
+
**For organization-wide deployment:**
|
|
131
|
+
|
|
132
|
+
1. Go to [Teams Admin Center](https://admin.teams.microsoft.com)
|
|
133
|
+
2. Go to **Teams apps** then **Manage apps**
|
|
134
|
+
3. Click **Upload new app** and select your zip file
|
|
135
|
+
4. Go to **Setup policies** to control who can use the app
|
|
136
|
+
|
|
137
|
+
## Configuration
|
|
138
|
+
|
|
139
|
+
| Option | Required | Description |
|
|
140
|
+
|--------|----------|-------------|
|
|
141
|
+
| `appId` | Yes | Azure Bot App ID |
|
|
142
|
+
| `appPassword` | Yes | Azure Bot App Password |
|
|
143
|
+
| `appType` | No | `"MultiTenant"` or `"SingleTenant"` (default: `"MultiTenant"`) |
|
|
144
|
+
| `appTenantId` | For SingleTenant | Azure AD Tenant ID |
|
|
145
|
+
|
|
146
|
+
## Environment variables
|
|
147
|
+
|
|
148
|
+
```bash title=".env.local"
|
|
149
|
+
TEAMS_APP_ID=...
|
|
150
|
+
TEAMS_APP_PASSWORD=...
|
|
151
|
+
TEAMS_APP_TENANT_ID=... # Required for SingleTenant
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Features
|
|
155
|
+
|
|
156
|
+
| Feature | Supported |
|
|
157
|
+
|---------|-----------|
|
|
158
|
+
| Mentions | Yes |
|
|
159
|
+
| Reactions (add/remove) | Read-only |
|
|
160
|
+
| Cards (Adaptive Cards) | Yes |
|
|
161
|
+
| Modals | No |
|
|
162
|
+
| Streaming | Post+Edit fallback |
|
|
163
|
+
| DMs | Yes |
|
|
164
|
+
| Ephemeral messages | No (DM fallback) |
|
|
165
|
+
| File uploads | Yes |
|
|
166
|
+
| Typing indicator | No |
|
|
167
|
+
| Message history | No |
|
|
168
|
+
|
|
169
|
+
## Limitations
|
|
170
|
+
|
|
171
|
+
- **Adding reactions**: Teams Bot Framework doesn't support bots adding reactions. Calling `addReaction()` or `removeReaction()` throws a `NotImplementedError`. The bot can still receive reaction events via `onReaction()`.
|
|
172
|
+
- **Typing indicators**: Not available via Bot Framework. `startTyping()` is a no-op.
|
|
173
|
+
|
|
174
|
+
### Message history (`fetchMessages`)
|
|
175
|
+
|
|
176
|
+
Fetching message history requires the Microsoft Graph API with client credentials flow. To enable it:
|
|
177
|
+
|
|
178
|
+
1. Set `appTenantId` in the adapter config
|
|
179
|
+
2. Grant one of these Azure AD app permissions:
|
|
180
|
+
- `ChatMessage.Read.Chat`
|
|
181
|
+
- `Chat.Read.All`
|
|
182
|
+
- `Chat.Read.WhereInstalled`
|
|
183
|
+
|
|
184
|
+
Without these permissions, `fetchMessages` will not be able to retrieve channel history.
|
|
185
|
+
|
|
186
|
+
### Receiving all messages
|
|
187
|
+
|
|
188
|
+
By default, Teams bots only receive messages when directly @-mentioned. To receive all messages in a channel or group chat, add Resource-Specific Consent (RSC) permissions to your Teams app manifest:
|
|
189
|
+
|
|
190
|
+
```json title="manifest.json"
|
|
191
|
+
{
|
|
192
|
+
"authorization": {
|
|
193
|
+
"permissions": {
|
|
194
|
+
"resourceSpecific": [
|
|
195
|
+
{
|
|
196
|
+
"name": "ChannelMessage.Read.Group",
|
|
197
|
+
"type": "Application"
|
|
198
|
+
}
|
|
199
|
+
]
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Alternatively, configure the bot in Azure to receive all messages.
|
|
206
|
+
|
|
207
|
+
## Troubleshooting
|
|
208
|
+
|
|
209
|
+
### "Unauthorized" error
|
|
210
|
+
|
|
211
|
+
- Verify `TEAMS_APP_ID` and `TEAMS_APP_PASSWORD` are correct
|
|
212
|
+
- For SingleTenant apps, ensure `TEAMS_APP_TENANT_ID` is set
|
|
213
|
+
- Check that the messaging endpoint URL is correct in Azure
|
|
214
|
+
|
|
215
|
+
### Bot not appearing in Teams
|
|
216
|
+
|
|
217
|
+
- Verify the Teams channel is enabled in Azure Bot
|
|
218
|
+
- Check that the app manifest is correctly configured
|
|
219
|
+
- Ensure the app is installed in the workspace/team
|
|
220
|
+
|
|
221
|
+
### Messages not received
|
|
222
|
+
|
|
223
|
+
- Verify the messaging endpoint URL is correct
|
|
224
|
+
- Check that your server is accessible from the internet
|
|
225
|
+
- Review Azure Bot logs for errors
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Cards
|
|
3
|
+
description: Rich card components for cross-platform interactive messages.
|
|
4
|
+
type: reference
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Card components render natively on each platform — Block Kit on Slack, Adaptive Cards on Teams, Embeds on Discord, and Google Chat Cards.
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { Card, Text, Button, Actions, Section, Fields, Field, Divider, Image, LinkButton } from "chat";
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
All components support both function-call and JSX syntax. Function-call syntax is recommended for better type inference.
|
|
14
|
+
|
|
15
|
+
## Card
|
|
16
|
+
|
|
17
|
+
Top-level container for a rich message.
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
Card({
|
|
21
|
+
title: "Order #1234",
|
|
22
|
+
subtitle: "Pending approval",
|
|
23
|
+
children: [Text("Total: $50.00")],
|
|
24
|
+
})
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
<TypeTable
|
|
28
|
+
type={{
|
|
29
|
+
title: {
|
|
30
|
+
description: 'Card title.',
|
|
31
|
+
type: 'string',
|
|
32
|
+
},
|
|
33
|
+
subtitle: {
|
|
34
|
+
description: 'Card subtitle.',
|
|
35
|
+
type: 'string',
|
|
36
|
+
},
|
|
37
|
+
imageUrl: {
|
|
38
|
+
description: 'Header image URL.',
|
|
39
|
+
type: 'string',
|
|
40
|
+
},
|
|
41
|
+
children: {
|
|
42
|
+
description: 'Card content elements.',
|
|
43
|
+
type: 'CardChild[]',
|
|
44
|
+
},
|
|
45
|
+
}}
|
|
46
|
+
/>
|
|
47
|
+
|
|
48
|
+
## Text
|
|
49
|
+
|
|
50
|
+
Text content element. Use `CardText` instead of `Text` in JSX to avoid conflicts with React's built-in types.
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
Text("Hello, world!")
|
|
54
|
+
Text("Important", { style: "bold" })
|
|
55
|
+
Text("Subtle note", { style: "muted" })
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
<TypeTable
|
|
59
|
+
type={{
|
|
60
|
+
content: {
|
|
61
|
+
description: 'Text content (first argument).',
|
|
62
|
+
type: 'string',
|
|
63
|
+
},
|
|
64
|
+
'options.style': {
|
|
65
|
+
description: 'Text style.',
|
|
66
|
+
type: '"plain" | "bold" | "muted"',
|
|
67
|
+
},
|
|
68
|
+
}}
|
|
69
|
+
/>
|
|
70
|
+
|
|
71
|
+
## Button
|
|
72
|
+
|
|
73
|
+
Interactive button that triggers an `onAction` handler.
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
Button({ id: "approve", label: "Approve", style: "primary" })
|
|
77
|
+
Button({ id: "delete", label: "Delete", style: "danger", value: "item-123" })
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
<TypeTable
|
|
81
|
+
type={{
|
|
82
|
+
id: {
|
|
83
|
+
description: 'Unique action ID for callback routing.',
|
|
84
|
+
type: 'string',
|
|
85
|
+
},
|
|
86
|
+
label: {
|
|
87
|
+
description: 'Button label text.',
|
|
88
|
+
type: 'string',
|
|
89
|
+
},
|
|
90
|
+
style: {
|
|
91
|
+
description: 'Visual style.',
|
|
92
|
+
type: '"primary" | "danger" | "default"',
|
|
93
|
+
},
|
|
94
|
+
value: {
|
|
95
|
+
description: 'Optional payload sent with the action callback.',
|
|
96
|
+
type: 'string',
|
|
97
|
+
},
|
|
98
|
+
}}
|
|
99
|
+
/>
|
|
100
|
+
|
|
101
|
+
## LinkButton
|
|
102
|
+
|
|
103
|
+
Button that opens a URL. No `onAction` handler needed.
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
LinkButton({ url: "https://example.com", label: "View Docs" })
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
<TypeTable
|
|
110
|
+
type={{
|
|
111
|
+
url: {
|
|
112
|
+
description: 'URL to open when clicked.',
|
|
113
|
+
type: 'string',
|
|
114
|
+
},
|
|
115
|
+
label: {
|
|
116
|
+
description: 'Button label text.',
|
|
117
|
+
type: 'string',
|
|
118
|
+
},
|
|
119
|
+
style: {
|
|
120
|
+
description: 'Visual style.',
|
|
121
|
+
type: '"primary" | "danger" | "default"',
|
|
122
|
+
},
|
|
123
|
+
}}
|
|
124
|
+
/>
|
|
125
|
+
|
|
126
|
+
## Actions
|
|
127
|
+
|
|
128
|
+
Container for buttons and interactive elements. Required wrapper around `Button`, `LinkButton`, `Select`, and `RadioSelect`.
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
Actions([
|
|
132
|
+
Button({ id: "approve", label: "Approve", style: "primary" }),
|
|
133
|
+
Button({ id: "reject", label: "Reject", style: "danger" }),
|
|
134
|
+
LinkButton({ url: "https://example.com", label: "View" }),
|
|
135
|
+
])
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Section
|
|
139
|
+
|
|
140
|
+
Groups related content together.
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
Section([
|
|
144
|
+
Text("Grouped content"),
|
|
145
|
+
Image({ url: "https://example.com/photo.png" }),
|
|
146
|
+
])
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Fields
|
|
150
|
+
|
|
151
|
+
Renders key-value pairs in a compact, multi-column layout.
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
Fields([
|
|
155
|
+
Field({ label: "Name", value: "Jane Smith" }),
|
|
156
|
+
Field({ label: "Role", value: "Engineer" }),
|
|
157
|
+
])
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Field
|
|
161
|
+
|
|
162
|
+
A single key-value pair. Must be used inside `Fields`.
|
|
163
|
+
|
|
164
|
+
<TypeTable
|
|
165
|
+
type={{
|
|
166
|
+
label: {
|
|
167
|
+
description: 'Field label.',
|
|
168
|
+
type: 'string',
|
|
169
|
+
},
|
|
170
|
+
value: {
|
|
171
|
+
description: 'Field value.',
|
|
172
|
+
type: 'string',
|
|
173
|
+
},
|
|
174
|
+
}}
|
|
175
|
+
/>
|
|
176
|
+
|
|
177
|
+
## Image
|
|
178
|
+
|
|
179
|
+
Embeds an image in the card.
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
Image({ url: "https://example.com/screenshot.png", alt: "Screenshot" })
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
<TypeTable
|
|
186
|
+
type={{
|
|
187
|
+
url: {
|
|
188
|
+
description: 'Image URL.',
|
|
189
|
+
type: 'string',
|
|
190
|
+
},
|
|
191
|
+
alt: {
|
|
192
|
+
description: 'Alt text for accessibility.',
|
|
193
|
+
type: 'string',
|
|
194
|
+
},
|
|
195
|
+
}}
|
|
196
|
+
/>
|
|
197
|
+
|
|
198
|
+
## Divider
|
|
199
|
+
|
|
200
|
+
A visual separator between sections.
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
Divider()
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## CardChild types
|
|
207
|
+
|
|
208
|
+
The `children` array in `Card` and `Section` accepts these element types:
|
|
209
|
+
|
|
210
|
+
| Type | Created by |
|
|
211
|
+
|------|-----------|
|
|
212
|
+
| `TextElement` | `Text()` |
|
|
213
|
+
| `ImageElement` | `Image()` |
|
|
214
|
+
| `DividerElement` | `Divider()` |
|
|
215
|
+
| `ActionsElement` | `Actions()` |
|
|
216
|
+
| `SectionElement` | `Section()` |
|
|
217
|
+
| `FieldsElement` | `Fields()` |
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Channel
|
|
3
|
+
description: Channel container that holds threads, with methods for listing, posting, and iteration.
|
|
4
|
+
type: reference
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
A `Channel` represents a channel or conversation container that holds threads. Both `Thread` and `Channel` extend the shared `Postable` interface, so they share common methods like `post()`, `state`, and `messages`.
|
|
8
|
+
|
|
9
|
+
Get a channel via `thread.channel` or `chat.channel()`:
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
// Navigate from a thread
|
|
13
|
+
const channel = thread.channel;
|
|
14
|
+
|
|
15
|
+
// Get directly by ID
|
|
16
|
+
const channel = chat.channel("slack:C123ABC");
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Properties
|
|
20
|
+
|
|
21
|
+
<TypeTable
|
|
22
|
+
type={{
|
|
23
|
+
id: {
|
|
24
|
+
description: 'Channel ID (e.g., "slack:C123ABC", "gchat:spaces/ABC123").',
|
|
25
|
+
type: 'string',
|
|
26
|
+
},
|
|
27
|
+
name: {
|
|
28
|
+
description: 'Channel name (e.g., "#general"). Null until fetchMetadata() is called.',
|
|
29
|
+
type: 'string | null',
|
|
30
|
+
},
|
|
31
|
+
adapter: {
|
|
32
|
+
description: 'The platform adapter this channel belongs to.',
|
|
33
|
+
type: 'Adapter',
|
|
34
|
+
},
|
|
35
|
+
isDM: {
|
|
36
|
+
description: 'Whether this is a direct message conversation.',
|
|
37
|
+
type: 'boolean',
|
|
38
|
+
},
|
|
39
|
+
}}
|
|
40
|
+
/>
|
|
41
|
+
|
|
42
|
+
## Channel ID format
|
|
43
|
+
|
|
44
|
+
Channel IDs are derived from thread IDs by dropping the thread-specific part. By default, this is the first two colon-separated segments:
|
|
45
|
+
|
|
46
|
+
| Platform | Thread ID | Channel ID |
|
|
47
|
+
|----------|-----------|------------|
|
|
48
|
+
| Slack | `slack:C123ABC:1234567890.123456` | `slack:C123ABC` |
|
|
49
|
+
| Teams | `teams:{base64}:{base64}` | `teams:{base64}` |
|
|
50
|
+
| Google Chat | `gchat:spaces/ABC123:{base64}` | `gchat:spaces/ABC123` |
|
|
51
|
+
| Discord | `discord:{guildId}:{channelId}/{messageId}` | `discord:{guildId}` |
|
|
52
|
+
|
|
53
|
+
## messages
|
|
54
|
+
|
|
55
|
+
Iterate channel-level messages (top-level, not thread replies) newest first. Auto-paginates lazily.
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
for await (const msg of channel.messages) {
|
|
59
|
+
console.log(msg.text);
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## threads
|
|
64
|
+
|
|
65
|
+
Iterate threads in the channel, most recently active first. Returns lightweight `ThreadSummary` objects.
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
for await (const thread of channel.threads()) {
|
|
69
|
+
console.log(thread.rootMessage.text, thread.replyCount);
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### ThreadSummary
|
|
74
|
+
|
|
75
|
+
<TypeTable
|
|
76
|
+
type={{
|
|
77
|
+
id: {
|
|
78
|
+
description: 'Full thread ID.',
|
|
79
|
+
type: 'string',
|
|
80
|
+
},
|
|
81
|
+
rootMessage: {
|
|
82
|
+
description: 'The first message of the thread.',
|
|
83
|
+
type: 'Message',
|
|
84
|
+
},
|
|
85
|
+
replyCount: {
|
|
86
|
+
description: 'Number of replies (if available).',
|
|
87
|
+
type: 'number | undefined',
|
|
88
|
+
},
|
|
89
|
+
lastReplyAt: {
|
|
90
|
+
description: 'Timestamp of most recent reply.',
|
|
91
|
+
type: 'Date | undefined',
|
|
92
|
+
},
|
|
93
|
+
}}
|
|
94
|
+
/>
|
|
95
|
+
|
|
96
|
+
## post
|
|
97
|
+
|
|
98
|
+
Post a message to the channel top-level (not in a thread).
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
await channel.post("Hello channel!");
|
|
102
|
+
await channel.post({ markdown: "**Announcement**: New release!" });
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Accepts the same message formats as `thread.post()` — see [PostableMessage](/docs/api/postable-message).
|
|
106
|
+
|
|
107
|
+
## fetchMetadata
|
|
108
|
+
|
|
109
|
+
Fetch channel metadata from the platform.
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
const info = await channel.fetchMetadata();
|
|
113
|
+
console.log(info.name, info.memberCount);
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### ChannelInfo
|
|
117
|
+
|
|
118
|
+
<TypeTable
|
|
119
|
+
type={{
|
|
120
|
+
id: {
|
|
121
|
+
description: 'Channel ID.',
|
|
122
|
+
type: 'string',
|
|
123
|
+
},
|
|
124
|
+
name: {
|
|
125
|
+
description: 'Channel name.',
|
|
126
|
+
type: 'string | undefined',
|
|
127
|
+
},
|
|
128
|
+
isDM: {
|
|
129
|
+
description: 'Whether this is a direct message.',
|
|
130
|
+
type: 'boolean | undefined',
|
|
131
|
+
},
|
|
132
|
+
memberCount: {
|
|
133
|
+
description: 'Number of members in the channel.',
|
|
134
|
+
type: 'number | undefined',
|
|
135
|
+
},
|
|
136
|
+
metadata: {
|
|
137
|
+
description: 'Platform-specific metadata.',
|
|
138
|
+
type: 'Record<string, unknown>',
|
|
139
|
+
},
|
|
140
|
+
}}
|
|
141
|
+
/>
|
|
142
|
+
|
|
143
|
+
## state
|
|
144
|
+
|
|
145
|
+
Store typed, per-channel state. Works the same as thread state with a 30-day TTL.
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
const state = await channel.state;
|
|
149
|
+
await channel.setState({ lastAnnouncement: new Date().toISOString() });
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## postEphemeral
|
|
153
|
+
|
|
154
|
+
Post a message visible only to a specific user.
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
await channel.postEphemeral(userId, "Only you can see this", {
|
|
158
|
+
fallbackToDM: true,
|
|
159
|
+
});
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## startTyping
|
|
163
|
+
|
|
164
|
+
Show a typing indicator. No-op on platforms that don't support it.
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
await channel.startTyping();
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## mentionUser
|
|
171
|
+
|
|
172
|
+
Get a platform-specific @-mention string.
|
|
173
|
+
|
|
174
|
+
```typescript
|
|
175
|
+
await channel.post(`Hey ${channel.mentionUser(userId)}, check this out!`);
|
|
176
|
+
```
|