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.
Files changed (53) hide show
  1. package/README.md +19 -31
  2. package/dist/{chunk-WKJEG4FE.js → chunk-THM4ACIE.js} +12 -4
  3. package/dist/chunk-THM4ACIE.js.map +1 -0
  4. package/dist/index.d.ts +409 -415
  5. package/dist/index.js +63 -29
  6. package/dist/index.js.map +1 -1
  7. package/dist/{jsx-runtime-COVsDskT.d.ts → jsx-runtime-Bdt1Dwzf.d.ts} +71 -71
  8. package/dist/jsx-runtime.d.ts +1 -1
  9. package/dist/jsx-runtime.js +1 -1
  10. package/docs/actions.mdx +98 -0
  11. package/docs/adapters/discord.mdx +217 -0
  12. package/docs/adapters/gchat.mdx +232 -0
  13. package/docs/adapters/github.mdx +225 -0
  14. package/docs/adapters/index.mdx +110 -0
  15. package/docs/adapters/linear.mdx +207 -0
  16. package/docs/adapters/meta.json +12 -0
  17. package/docs/adapters/slack.mdx +293 -0
  18. package/docs/adapters/teams.mdx +225 -0
  19. package/docs/api/cards.mdx +217 -0
  20. package/docs/api/channel.mdx +176 -0
  21. package/docs/api/chat.mdx +469 -0
  22. package/docs/api/index.mdx +29 -0
  23. package/docs/api/markdown.mdx +235 -0
  24. package/docs/api/message.mdx +163 -0
  25. package/docs/api/meta.json +14 -0
  26. package/docs/api/modals.mdx +222 -0
  27. package/docs/api/postable-message.mdx +166 -0
  28. package/docs/api/thread.mdx +186 -0
  29. package/docs/cards.mdx +213 -0
  30. package/docs/direct-messages.mdx +56 -0
  31. package/docs/emoji.mdx +77 -0
  32. package/docs/ephemeral-messages.mdx +77 -0
  33. package/docs/error-handling.mdx +147 -0
  34. package/docs/files.mdx +77 -0
  35. package/docs/getting-started.mdx +12 -0
  36. package/docs/guides/code-review-hono.mdx +248 -0
  37. package/docs/guides/discord-nuxt.mdx +237 -0
  38. package/docs/guides/meta.json +4 -0
  39. package/docs/guides/slack-nextjs.mdx +245 -0
  40. package/docs/index.mdx +92 -0
  41. package/docs/meta.json +20 -0
  42. package/docs/modals.mdx +208 -0
  43. package/docs/posting-messages.mdx +177 -0
  44. package/docs/slash-commands.mdx +110 -0
  45. package/docs/state/index.mdx +31 -0
  46. package/docs/state/ioredis.mdx +81 -0
  47. package/docs/state/memory.mdx +52 -0
  48. package/docs/state/meta.json +9 -0
  49. package/docs/state/redis.mdx +93 -0
  50. package/docs/streaming.mdx +99 -0
  51. package/docs/usage.mdx +338 -0
  52. package/package.json +10 -10
  53. 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
+ ```