chat 4.26.0 → 4.28.1
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/dist/{chunk-OPV5U4WG.js → chunk-V25FKIIL.js} +44 -1
- package/dist/index.d.ts +485 -33
- package/dist/index.js +862 -135
- package/dist/{jsx-runtime-DxATbnrP.d.ts → jsx-runtime-DxGwoLu2.d.ts} +49 -5
- package/dist/jsx-runtime.d.ts +1 -1
- package/dist/jsx-runtime.js +1 -1
- package/docs/actions.mdx +52 -1
- package/docs/adapters.mdx +43 -37
- package/docs/api/cards.mdx +4 -0
- package/docs/api/chat.mdx +172 -6
- package/docs/api/index.mdx +2 -0
- package/docs/api/markdown.mdx +28 -5
- package/docs/api/message.mdx +58 -1
- package/docs/api/meta.json +2 -0
- package/docs/api/modals.mdx +50 -0
- package/docs/api/postable-message.mdx +55 -1
- package/docs/api/thread.mdx +33 -3
- package/docs/api/transcripts.mdx +220 -0
- package/docs/cards.mdx +6 -0
- package/docs/concurrency.mdx +4 -0
- package/docs/contributing/building.mdx +73 -1
- package/docs/contributing/publishing.mdx +33 -0
- package/docs/conversation-history.mdx +137 -0
- package/docs/direct-messages.mdx +13 -4
- package/docs/ephemeral-messages.mdx +1 -1
- package/docs/error-handling.mdx +15 -3
- package/docs/files.mdx +2 -1
- package/docs/getting-started.mdx +1 -11
- package/docs/index.mdx +7 -5
- package/docs/meta.json +14 -5
- package/docs/modals.mdx +97 -1
- package/docs/posting-messages.mdx +7 -3
- package/docs/streaming.mdx +74 -18
- package/docs/subject.mdx +53 -0
- package/docs/threads-messages-channels.mdx +43 -0
- package/docs/usage.mdx +11 -2
- package/package.json +3 -2
- package/resources/guides/create-a-discord-support-bot-with-nuxt-and-redis.md +180 -0
- package/resources/guides/how-to-build-a-slack-bot-with-next-js-and-redis.md +134 -0
- package/resources/guides/how-to-build-an-ai-agent-for-slack-with-chat-sdk-and-ai-sdk.md +220 -0
- package/resources/guides/run-and-track-deploys-from-slack.md +270 -0
- package/resources/guides/ship-a-github-code-review-bot-with-hono-and-redis.md +147 -0
- package/resources/guides/triage-form-submissions-with-chat-sdk.md +178 -0
- package/resources/templates.json +19 -0
- package/docs/guides/code-review-hono.mdx +0 -241
- package/docs/guides/discord-nuxt.mdx +0 -227
- package/docs/guides/durable-chat-sessions-nextjs.mdx +0 -337
- package/docs/guides/meta.json +0 -10
- package/docs/guides/scheduled-posts-neon.mdx +0 -447
- package/docs/guides/slack-nextjs.mdx +0 -234
|
@@ -52,6 +52,8 @@ type TextStyle = "plain" | "bold" | "muted";
|
|
|
52
52
|
interface ButtonElement {
|
|
53
53
|
/** Whether this button triggers a regular action or opens a modal dialog. Default: "action" */
|
|
54
54
|
actionType?: "action" | "modal";
|
|
55
|
+
/** URL to POST action data to when this button is clicked */
|
|
56
|
+
callbackUrl?: string;
|
|
55
57
|
/** If true, the button is displayed in an inactive state and doesn't respond to user actions */
|
|
56
58
|
disabled?: boolean;
|
|
57
59
|
/** Unique action ID for callback routing */
|
|
@@ -241,6 +243,8 @@ declare function Actions(children: (ButtonElement | LinkButtonElement | SelectEl
|
|
|
241
243
|
interface ButtonOptions {
|
|
242
244
|
/** Whether this button triggers a regular action or opens a modal dialog. Default: "action" */
|
|
243
245
|
actionType?: "action" | "modal";
|
|
246
|
+
/** URL to POST action data to when this button is clicked */
|
|
247
|
+
callbackUrl?: string;
|
|
244
248
|
/** If true, the button is displayed in an inactive state and doesn't respond to user actions */
|
|
245
249
|
disabled?: boolean;
|
|
246
250
|
/** Unique action ID for callback routing */
|
|
@@ -371,9 +375,11 @@ declare function cardChildToFallbackText(child: CardChild): string | null;
|
|
|
371
375
|
* Modal elements for form dialogs.
|
|
372
376
|
*/
|
|
373
377
|
|
|
374
|
-
type ModalChild = TextInputElement | SelectElement | RadioSelectElement | TextElement | FieldsElement;
|
|
378
|
+
type ModalChild = TextInputElement | SelectElement | ExternalSelectElement | RadioSelectElement | TextElement | FieldsElement;
|
|
375
379
|
interface ModalElement {
|
|
376
380
|
callbackId: string;
|
|
381
|
+
/** URL to POST form values to when this modal is submitted */
|
|
382
|
+
callbackUrl?: string;
|
|
377
383
|
children: ModalChild[];
|
|
378
384
|
closeLabel?: string;
|
|
379
385
|
notifyOnClose?: boolean;
|
|
@@ -402,6 +408,15 @@ interface SelectElement {
|
|
|
402
408
|
placeholder?: string;
|
|
403
409
|
type: "select";
|
|
404
410
|
}
|
|
411
|
+
interface ExternalSelectElement {
|
|
412
|
+
id: string;
|
|
413
|
+
initialOption?: SelectOptionElement;
|
|
414
|
+
label: string;
|
|
415
|
+
minQueryLength?: number;
|
|
416
|
+
optional?: boolean;
|
|
417
|
+
placeholder?: string;
|
|
418
|
+
type: "external_select";
|
|
419
|
+
}
|
|
405
420
|
interface SelectOptionElement {
|
|
406
421
|
description?: string;
|
|
407
422
|
label: string;
|
|
@@ -418,6 +433,8 @@ interface RadioSelectElement {
|
|
|
418
433
|
declare function isModalElement(value: unknown): value is ModalElement;
|
|
419
434
|
interface ModalOptions {
|
|
420
435
|
callbackId: string;
|
|
436
|
+
/** URL to POST form values to when this modal is submitted */
|
|
437
|
+
callbackUrl?: string;
|
|
421
438
|
children?: ModalChild[];
|
|
422
439
|
closeLabel?: string;
|
|
423
440
|
notifyOnClose?: boolean;
|
|
@@ -446,6 +463,15 @@ interface SelectOptions {
|
|
|
446
463
|
placeholder?: string;
|
|
447
464
|
}
|
|
448
465
|
declare function Select(options: SelectOptions): SelectElement;
|
|
466
|
+
interface ExternalSelectOptions {
|
|
467
|
+
id: string;
|
|
468
|
+
initialOption?: SelectOptionElement;
|
|
469
|
+
label: string;
|
|
470
|
+
minQueryLength?: number;
|
|
471
|
+
optional?: boolean;
|
|
472
|
+
placeholder?: string;
|
|
473
|
+
}
|
|
474
|
+
declare function ExternalSelect(options: ExternalSelectOptions): ExternalSelectElement;
|
|
449
475
|
declare function SelectOption(options: {
|
|
450
476
|
label: string;
|
|
451
477
|
value: string;
|
|
@@ -509,6 +535,7 @@ interface TextProps {
|
|
|
509
535
|
/** Props for Button component in JSX */
|
|
510
536
|
interface ButtonProps {
|
|
511
537
|
actionType?: "action" | "modal";
|
|
538
|
+
callbackUrl?: string;
|
|
512
539
|
children?: string | number | (string | number | undefined)[];
|
|
513
540
|
disabled?: boolean;
|
|
514
541
|
id: string;
|
|
@@ -548,6 +575,7 @@ type DividerProps = Record<string, never>;
|
|
|
548
575
|
/** Props for Modal component in JSX */
|
|
549
576
|
interface ModalProps {
|
|
550
577
|
callbackId: string;
|
|
578
|
+
callbackUrl?: string;
|
|
551
579
|
children?: unknown;
|
|
552
580
|
closeLabel?: string;
|
|
553
581
|
notifyOnClose?: boolean;
|
|
@@ -574,6 +602,18 @@ interface SelectProps {
|
|
|
574
602
|
optional?: boolean;
|
|
575
603
|
placeholder?: string;
|
|
576
604
|
}
|
|
605
|
+
/** Props for ExternalSelect component in JSX */
|
|
606
|
+
interface ExternalSelectProps {
|
|
607
|
+
id: string;
|
|
608
|
+
initialOption?: {
|
|
609
|
+
label: string;
|
|
610
|
+
value: string;
|
|
611
|
+
};
|
|
612
|
+
label: string;
|
|
613
|
+
minQueryLength?: number;
|
|
614
|
+
optional?: boolean;
|
|
615
|
+
placeholder?: string;
|
|
616
|
+
}
|
|
577
617
|
/** Props for SelectOption component in JSX */
|
|
578
618
|
interface SelectOptionProps {
|
|
579
619
|
description?: string;
|
|
@@ -586,9 +626,9 @@ interface TableProps {
|
|
|
586
626
|
rows: string[][];
|
|
587
627
|
}
|
|
588
628
|
/** Union of all valid JSX props */
|
|
589
|
-
type CardJSXProps = CardProps | TextProps | ButtonProps | LinkButtonProps | CardLinkProps | ImageProps | FieldProps | ContainerProps | DividerProps | ModalProps | TextInputProps | SelectProps | SelectOptionProps | TableProps;
|
|
629
|
+
type CardJSXProps = CardProps | TextProps | ButtonProps | LinkButtonProps | CardLinkProps | ImageProps | FieldProps | ContainerProps | DividerProps | ModalProps | TextInputProps | SelectProps | ExternalSelectProps | SelectOptionProps | TableProps;
|
|
590
630
|
/** Component function type with proper overloads */
|
|
591
|
-
type CardComponentFunction = typeof Card | typeof Text | typeof Button | typeof LinkButton | typeof CardLink | typeof Image | typeof Field | typeof Divider | typeof Section | typeof Actions | typeof Fields | typeof Modal | typeof TextInput | typeof Select | typeof RadioSelect | typeof SelectOption | typeof Table;
|
|
631
|
+
type CardComponentFunction = typeof Card | typeof Text | typeof Button | typeof LinkButton | typeof CardLink | typeof Image | typeof Field | typeof Divider | typeof Section | typeof Actions | typeof Fields | typeof Modal | typeof TextInput | typeof Select | typeof ExternalSelect | typeof RadioSelect | typeof SelectOption | typeof Table;
|
|
592
632
|
/**
|
|
593
633
|
* Represents a JSX element from the chat JSX runtime.
|
|
594
634
|
* This is the type returned when using JSX syntax with chat components.
|
|
@@ -600,7 +640,7 @@ interface CardJSXElement<P extends CardJSXProps = CardJSXProps> {
|
|
|
600
640
|
type: CardComponentFunction;
|
|
601
641
|
}
|
|
602
642
|
/** Union of all element types that can be produced by chat components */
|
|
603
|
-
type ChatElement = CardJSXElement | CardElement | TextElement | ButtonElement | LinkButtonElement | LinkElement | ImageElement | DividerElement | ActionsElement | SectionElement | FieldsElement | FieldElement | ModalElement | TextInputElement | SelectElement | SelectOptionElement | RadioSelectElement | TableElement;
|
|
643
|
+
type ChatElement = CardJSXElement | CardElement | TextElement | ButtonElement | LinkButtonElement | LinkElement | ImageElement | DividerElement | ActionsElement | SectionElement | FieldsElement | FieldElement | ModalElement | TextInputElement | SelectElement | ExternalSelectElement | SelectOptionElement | RadioSelectElement | TableElement;
|
|
604
644
|
interface CardComponent {
|
|
605
645
|
(options?: CardOptions): CardElement;
|
|
606
646
|
(props: CardProps): ChatElement;
|
|
@@ -668,6 +708,10 @@ interface SelectComponent {
|
|
|
668
708
|
(options: SelectOptions): SelectElement;
|
|
669
709
|
(props: SelectProps): ChatElement;
|
|
670
710
|
}
|
|
711
|
+
interface ExternalSelectComponent {
|
|
712
|
+
(options: ExternalSelectOptions): ExternalSelectElement;
|
|
713
|
+
(props: ExternalSelectProps): ChatElement;
|
|
714
|
+
}
|
|
671
715
|
interface SelectOptionComponent {
|
|
672
716
|
(options: {
|
|
673
717
|
label: string;
|
|
@@ -735,4 +779,4 @@ declare namespace JSX {
|
|
|
735
779
|
}
|
|
736
780
|
}
|
|
737
781
|
|
|
738
|
-
export { type
|
|
782
|
+
export { type CardProps as $, type ActionsComponent as A, type ButtonComponent as B, type ChatElement as C, type DividerComponent as D, type ExternalSelectComponent as E, type FieldComponent as F, type FieldsElement as G, type ImageElement as H, type ImageComponent as I, type LinkButtonElement as J, type LinkButtonOptions as K, type LinkButtonComponent as L, type ModalElement as M, type LinkElement as N, type SectionElement as O, type TableAlignment as P, type TableElement as Q, type RadioSelectComponent as R, type SelectOptionElement as S, type TextComponent as T, type TableOptions as U, type TextElement as V, type TextStyle as W, type ButtonProps as X, type CardJSXElement as Y, type CardJSXProps as Z, type CardLinkProps as _, type CardElement as a, type ContainerProps as a0, type DividerProps as a1, type ExternalSelectProps as a2, type FieldProps as a3, type ImageProps as a4, type LinkButtonProps as a5, type ModalProps as a6, type SelectOptionProps as a7, type SelectProps as a8, type TextInputProps as a9, type TextProps as aa, type ExternalSelectElement as ab, type ExternalSelectOptions as ac, type ModalChild as ad, type ModalOptions as ae, type RadioSelectElement as af, type RadioSelectOptions as ag, type SelectElement as ah, type SelectOptions as ai, type TextInputElement as aj, type TextInputOptions as ak, type TableProps as al, type TableComponent as am, isCardLinkProps as an, jsx as ao, jsxs as ap, jsxDEV as aq, Fragment as ar, JSX as as, type CardChild as b, type CardComponent as c, cardChildToFallbackText as d, type CardLinkComponent as e, type FieldsComponent as f, fromReactElement as g, isJSX as h, isCardElement as i, type SectionComponent as j, Table as k, toModalElement as l, fromReactModalElement as m, isModalElement as n, type ModalComponent as o, type SelectComponent as p, type SelectOptionComponent as q, type TextInputComponent as r, type ActionsElement as s, toCardElement as t, type ButtonElement as u, type ButtonOptions as v, type ButtonStyle as w, type CardOptions as x, type DividerElement as y, type FieldElement as z };
|
package/dist/jsx-runtime.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { A as ActionsComponent, B as ButtonComponent,
|
|
1
|
+
export { A as ActionsComponent, B as ButtonComponent, X as ButtonProps, c as CardComponent, Y as CardJSXElement, Z as CardJSXProps, e as CardLinkComponent, _ as CardLinkProps, $ as CardProps, C as ChatElement, a0 as ContainerProps, D as DividerComponent, a1 as DividerProps, E as ExternalSelectComponent, a2 as ExternalSelectProps, F as FieldComponent, a3 as FieldProps, f as FieldsComponent, ar as Fragment, I as ImageComponent, a4 as ImageProps, as as JSX, L as LinkButtonComponent, a5 as LinkButtonProps, o as ModalComponent, a6 as ModalProps, R as RadioSelectComponent, j as SectionComponent, p as SelectComponent, q as SelectOptionComponent, a7 as SelectOptionProps, a8 as SelectProps, am as TableComponent, al as TableProps, T as TextComponent, r as TextInputComponent, a9 as TextInputProps, aa as TextProps, an as isCardLinkProps, h as isJSX, ao as jsx, aq as jsxDEV, ap as jsxs, t as toCardElement, l as toModalElement } from './jsx-runtime-DxGwoLu2.js';
|
package/dist/jsx-runtime.js
CHANGED
package/docs/actions.mdx
CHANGED
|
@@ -94,5 +94,56 @@ bot.onAction("feedback", async (event) => {
|
|
|
94
94
|
```
|
|
95
95
|
|
|
96
96
|
<Callout type="info">
|
|
97
|
-
Modals are currently supported on Slack. Other platforms will receive a no-op
|
|
97
|
+
Modals are currently supported on Slack and Teams. Other platforms will receive a no-op
|
|
98
|
+
or fallback behavior.
|
|
98
99
|
</Callout>
|
|
100
|
+
|
|
101
|
+
## Callback URLs
|
|
102
|
+
|
|
103
|
+
Buttons accept a `callbackUrl` prop. When clicked, the action data is POSTed to that URL in addition to firing any `onAction` handler. This pairs naturally with webhook-based workflow engines to build approval flows without any `onAction` handler at all:
|
|
104
|
+
|
|
105
|
+
```tsx title="lib/bot.tsx" lineNumbers
|
|
106
|
+
bot.onNewMention(async (thread) => {
|
|
107
|
+
const approveUrl = "https://example.com/webhook/approve";
|
|
108
|
+
const denyUrl = "https://example.com/webhook/deny";
|
|
109
|
+
|
|
110
|
+
await thread.post(
|
|
111
|
+
<Card title="Deploy v2.4.1?">
|
|
112
|
+
<Actions>
|
|
113
|
+
<Button callbackUrl={approveUrl} id="approve" style="primary">
|
|
114
|
+
Approve
|
|
115
|
+
</Button>
|
|
116
|
+
<Button callbackUrl={denyUrl} id="deny" style="danger">
|
|
117
|
+
Deny
|
|
118
|
+
</Button>
|
|
119
|
+
</Actions>
|
|
120
|
+
</Card>
|
|
121
|
+
);
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Callback payload
|
|
126
|
+
|
|
127
|
+
The POST body sent to the `callbackUrl`:
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"type": "action",
|
|
132
|
+
"actionId": "approve",
|
|
133
|
+
"user": { "id": "U123", "name": "alice" },
|
|
134
|
+
"threadId": "slack:C123:1234567890.123",
|
|
135
|
+
"messageId": "1234567890.456"
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
If the button also has a `value` prop, it is included in the payload as `"value"`.
|
|
140
|
+
|
|
141
|
+
<Callout type="info">
|
|
142
|
+
Platform limits apply to encoded button data. Discord's `custom_id` has a 100
|
|
143
|
+
character limit - if the action ID plus callback token exceed this, posting
|
|
144
|
+
the card throws a `ValidationError`. Telegram's `callback_data` has a 64 byte
|
|
145
|
+
limit - buttons that exceed this will throw a `ValidationError`. Keep action
|
|
146
|
+
IDs short when using `callbackUrl` on these platforms.
|
|
147
|
+
</Callout>
|
|
148
|
+
|
|
149
|
+
For modals, see [callbackUrl on modals](/docs/modals#callback-urls).
|
package/docs/adapters.mdx
CHANGED
|
@@ -8,60 +8,66 @@ prerequisites:
|
|
|
8
8
|
|
|
9
9
|
Adapters handle webhook verification, message parsing, and API calls for each platform. Install only the adapters you need. Browse all available adapters — including community-built ones — on the [Adapters](/adapters) page.
|
|
10
10
|
|
|
11
|
+
Need a browser chat UI? See the [Web adapter](/adapters/web) — it speaks the AI SDK `useChat` protocol so the same bot serves Slack, Teams, **and** a `<Conversation>` from `ai-elements` out of the box.
|
|
12
|
+
|
|
11
13
|
Ready to build your own? Follow the [building](/docs/contributing/building) guide.
|
|
12
14
|
|
|
13
15
|
## Feature matrix
|
|
14
16
|
|
|
15
17
|
### Messaging
|
|
16
18
|
|
|
17
|
-
| Feature | [Slack](/adapters/slack) | [Teams](/adapters/teams) | [Google Chat](/adapters/google-chat) | [Discord](/adapters/discord) | [Telegram](/adapters/telegram) | [GitHub](/adapters/github) | [Linear](/adapters/linear) | [WhatsApp](/adapters/whatsapp) |
|
|
18
|
-
|
|
19
|
-
| Post message |
|
|
20
|
-
| Edit message |
|
|
21
|
-
| Delete message |
|
|
22
|
-
| File uploads |
|
|
23
|
-
| Streaming |
|
|
24
|
-
| Scheduled messages |
|
|
19
|
+
| Feature | [Slack](/adapters/slack) | [Teams](/adapters/teams) | [Google Chat](/adapters/google-chat) | [Discord](/adapters/discord) | [Telegram](/adapters/telegram) | [GitHub](/adapters/github) | [Linear](/adapters/linear) | [WhatsApp](/adapters/whatsapp) | [Messenger](/adapters/messenger) |
|
|
20
|
+
|---------|-------|-------|-------------|---------|---------|--------|--------|-----------|-----------|
|
|
21
|
+
| Post message | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
22
|
+
| Edit message | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Warn /> Partial | <Cross /> | <Cross /> |
|
|
23
|
+
| Delete message | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Warn /> Partial | <Cross /> | <Cross /> |
|
|
24
|
+
| File uploads | <Check /> | <Check /> | <Cross /> | <Check /> | <Warn /> Single file | <Cross /> | <Cross /> | <Check /> Images, audio, docs | <Cross /> |
|
|
25
|
+
| Streaming | <Check /> Native | <Warn /> Native (DMs) / Buffered | <Warn /> Post+Edit | <Warn /> Post+Edit | <Warn /> Post+Edit | <Warn /> Buffered | <Warn /> Agent sessions / Post+Edit | <Warn /> Buffered | <Warn /> Buffered |
|
|
26
|
+
| Scheduled messages | <Check /> Native | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> |
|
|
25
27
|
|
|
26
28
|
### Rich content
|
|
27
29
|
|
|
28
|
-
| Feature | Slack | Teams | Google Chat | Discord | Telegram | GitHub | Linear | WhatsApp |
|
|
29
|
-
|
|
30
|
-
| Card format | Block Kit | Adaptive Cards | Google Chat Cards | Embeds | Markdown + inline keyboard buttons | GFM Markdown | Markdown | WhatsApp templates |
|
|
31
|
-
| Buttons |
|
|
32
|
-
| Link buttons |
|
|
33
|
-
| Select menus |
|
|
34
|
-
| Tables |
|
|
35
|
-
| Fields |
|
|
36
|
-
| Images in cards |
|
|
37
|
-
| Modals |
|
|
30
|
+
| Feature | Slack | Teams | Google Chat | Discord | Telegram | GitHub | Linear | WhatsApp | Messenger |
|
|
31
|
+
|---------|-------|-------|-------------|---------|----------|--------|--------|-----------|-----------|
|
|
32
|
+
| Card format | Block Kit | Adaptive Cards | Google Chat Cards | Embeds | Markdown + inline keyboard buttons | GFM Markdown | Markdown | WhatsApp templates | Generic/Button Templates |
|
|
33
|
+
| Buttons | <Check /> | <Check /> | <Check /> | <Check /> | <Warn /> Inline keyboard callbacks | <Cross /> | <Cross /> | <Check /> Interactive replies | <Warn /> Max 3, postback |
|
|
34
|
+
| Link buttons | <Check /> | <Check /> | <Check /> | <Check /> | <Warn /> Inline keyboard URLs | <Cross /> | <Cross /> | <Cross /> | <Check /> |
|
|
35
|
+
| Select menus | <Check /> | <Cross /> | <Check /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> |
|
|
36
|
+
| Tables | <Check /> Block Kit | <Check /> GFM | <Warn /> ASCII | <Check /> GFM | <Warn /> ASCII | <Check /> GFM | <Check /> GFM | <Cross /> | <Warn /> ASCII |
|
|
37
|
+
| Fields | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Warn /> Template variables | <Warn /> ASCII |
|
|
38
|
+
| Images in cards | <Check /> | <Check /> | <Check /> | <Check /> | <Cross /> | <Check /> | <Cross /> | <Check /> | <Check /> |
|
|
39
|
+
| Modals | <Check /> | <Check /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> |
|
|
38
40
|
|
|
39
41
|
### Conversations
|
|
40
42
|
|
|
41
|
-
| Feature | Slack | Teams | Google Chat | Discord | Telegram | GitHub | Linear | WhatsApp |
|
|
42
|
-
|
|
43
|
-
| Slash commands |
|
|
44
|
-
| Mentions |
|
|
45
|
-
| Add reactions |
|
|
46
|
-
| Remove reactions |
|
|
47
|
-
| Typing indicator |
|
|
48
|
-
| DMs |
|
|
49
|
-
| Ephemeral messages |
|
|
43
|
+
| Feature | Slack | Teams | Google Chat | Discord | Telegram | GitHub | Linear | WhatsApp | Messenger |
|
|
44
|
+
|---------|-------|-------|-------------|---------|----------|--------|--------|-----------|-----------|
|
|
45
|
+
| Slash commands | <Check /> | <Cross /> | <Cross /> | <Check /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> |
|
|
46
|
+
| Mentions | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Cross /> | <Check /> |
|
|
47
|
+
| Add reactions | <Check /> | <Cross /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Cross /> |
|
|
48
|
+
| Remove reactions | <Check /> | <Cross /> | <Check /> | <Check /> | <Check /> | <Warn /> | <Warn /> | <Check /> | <Cross /> |
|
|
49
|
+
| Typing indicator | <Check /> | <Check /> | <Cross /> | <Check /> | <Check /> | <Cross /> | <Warn /> Agent sessions | <Cross /> | <Check /> |
|
|
50
|
+
| DMs | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Cross /> | <Cross /> | <Check /> | <Check /> |
|
|
51
|
+
| Ephemeral messages | <Check /> Native | <Cross /> | <Check /> Native | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> |
|
|
52
|
+
| User lookup ([`getUser`](/docs/api/chat#getuser)) | <Check /> | <Warn /> Cached | <Warn /> Cached | <Check /> | <Warn /> Seen users | <Check /> | <Check /> | <Cross /> | <Cross /> |
|
|
53
|
+
| Parent subject ([`message.subject`](/docs/subject)) | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Check /> | <Check /> | <Cross /> | <Cross /> |
|
|
54
|
+
| Native client ([`.client`](/docs/api/chat#getadapter)) | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Check /> | <Check /> | <Cross /> | <Cross /> |
|
|
55
|
+
| Custom API endpoint (`apiUrl`) | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
50
56
|
|
|
51
57
|
### Message history
|
|
52
58
|
|
|
53
|
-
| Feature | Slack | Teams | Google Chat | Discord | Telegram | GitHub | Linear | WhatsApp |
|
|
54
|
-
|
|
55
|
-
| Fetch messages |
|
|
56
|
-
| Fetch single message |
|
|
57
|
-
| Fetch thread info |
|
|
58
|
-
| Fetch channel messages |
|
|
59
|
-
| List threads |
|
|
60
|
-
| Fetch channel info |
|
|
61
|
-
| Post channel message |
|
|
59
|
+
| Feature | Slack | Teams | Google Chat | Discord | Telegram | GitHub | Linear | WhatsApp | Messenger |
|
|
60
|
+
|---------|-------|-------|-------------|---------|----------|--------|--------|-----------|-----------|
|
|
61
|
+
| Fetch messages | <Check /> | <Check /> | <Check /> | <Check /> | <Warn /> Cached | <Check /> | <Check /> | <Warn /> Cached sent messages only | <Warn /> Cached sent messages only |
|
|
62
|
+
| Fetch single message | <Check /> | <Cross /> | <Cross /> | <Cross /> | <Warn /> Cached | <Cross /> | <Cross /> | <Cross /> | <Warn /> Cached |
|
|
63
|
+
| Fetch thread info | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> |
|
|
64
|
+
| Fetch channel messages | <Check /> | <Check /> | <Check /> | <Check /> | <Warn /> Cached | <Check /> | <Cross /> | <Cross /> | <Warn /> Cached |
|
|
65
|
+
| List threads | <Check /> | <Check /> | <Check /> | <Check /> | <Cross /> | <Check /> | <Cross /> | <Cross /> | <Cross /> |
|
|
66
|
+
| Fetch channel info | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Cross /> | <Cross /> | <Check /> |
|
|
67
|
+
| Post channel message | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Cross /> | <Cross /> | <Check /> | <Check /> |
|
|
62
68
|
|
|
63
69
|
<Callout type="info">
|
|
64
|
-
|
|
70
|
+
<Warn /> indicates partial support — the feature works with limitations. See individual adapter pages for details.
|
|
65
71
|
</Callout>
|
|
66
72
|
|
|
67
73
|
## How adapters work
|
package/docs/api/cards.mdx
CHANGED
|
@@ -100,6 +100,10 @@ Button({ id: "delete", label: "Delete", style: "danger", value: "item-123" })
|
|
|
100
100
|
type: '"action" | "modal"',
|
|
101
101
|
default: '"action"',
|
|
102
102
|
},
|
|
103
|
+
callbackUrl: {
|
|
104
|
+
description: 'URL to POST action data to when this button is clicked.',
|
|
105
|
+
type: 'string',
|
|
106
|
+
},
|
|
103
107
|
}}
|
|
104
108
|
/>
|
|
105
109
|
|
package/docs/api/chat.mdx
CHANGED
|
@@ -168,7 +168,9 @@ Fires when a user clicks a button or selects an option in a card.
|
|
|
168
168
|
```typescript
|
|
169
169
|
// Single action
|
|
170
170
|
bot.onAction("approve", async (event) => {
|
|
171
|
-
|
|
171
|
+
if (event.thread) {
|
|
172
|
+
await event.thread.post("Approved!");
|
|
173
|
+
}
|
|
172
174
|
});
|
|
173
175
|
|
|
174
176
|
// Multiple actions
|
|
@@ -193,8 +195,8 @@ bot.onAction(async (event) => { /* ... */ });
|
|
|
193
195
|
type: 'Author',
|
|
194
196
|
},
|
|
195
197
|
'event.thread': {
|
|
196
|
-
description: 'The thread containing the card.',
|
|
197
|
-
type: 'Thread',
|
|
198
|
+
description: 'The thread containing the card, or null for view-based actions.',
|
|
199
|
+
type: 'Thread | null',
|
|
198
200
|
},
|
|
199
201
|
'event.triggerId': {
|
|
200
202
|
description: 'Trigger ID for opening modals (platform-specific, may expire quickly).',
|
|
@@ -255,14 +257,53 @@ bot.onModalSubmit("feedback", async (event) => {
|
|
|
255
257
|
|
|
256
258
|
Returns `ModalResponse | undefined` to control the modal after submission:
|
|
257
259
|
|
|
258
|
-
- `{ action: "close" }` — close the
|
|
260
|
+
- `{ action: "close" }` — close the current view (goes back one level in the stack)
|
|
261
|
+
- `{ action: "clear" }` — close all views and dismiss the modal entirely
|
|
259
262
|
- `{ action: "errors", errors: { fieldId: "message" } }` — show validation errors
|
|
260
263
|
- `{ action: "update", modal: ModalElement }` — replace the modal content
|
|
261
264
|
- `{ action: "push", modal: ModalElement }` — push a new modal view onto the stack
|
|
262
265
|
|
|
266
|
+
### onOptionsLoad
|
|
267
|
+
|
|
268
|
+
Fires when an `ExternalSelect` requests options dynamically. The handler is keyed on the select's `id` and must return options synchronously enough for Slack's 3-second budget (the adapter caps the loader at ~2.5s and substitutes an empty result on timeout). Slack-only.
|
|
269
|
+
|
|
270
|
+
```typescript
|
|
271
|
+
bot.onOptionsLoad("assignee", async (event) => {
|
|
272
|
+
const people = await peopleService.search(event.query);
|
|
273
|
+
return people.map((p) => ({ label: p.fullName, value: p.id }));
|
|
274
|
+
});
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Return an array of `OptionsLoadGroup` (`{ label, options }[]`) instead of a flat array to render grouped headers (e.g. "Recent" / "All"). Slack limits: max 100 groups, max 100 options per group.
|
|
278
|
+
|
|
279
|
+
<TypeTable
|
|
280
|
+
type={{
|
|
281
|
+
'event.actionId': {
|
|
282
|
+
description: 'The id of the select requesting options (matches the id passed to bot.onOptionsLoad).',
|
|
283
|
+
type: 'string',
|
|
284
|
+
},
|
|
285
|
+
'event.query': {
|
|
286
|
+
description: 'The text the user has typed so far.',
|
|
287
|
+
type: 'string',
|
|
288
|
+
},
|
|
289
|
+
'event.user': {
|
|
290
|
+
description: 'The user requesting options.',
|
|
291
|
+
type: 'Author',
|
|
292
|
+
},
|
|
293
|
+
'event.adapter': {
|
|
294
|
+
description: 'The adapter that received this event.',
|
|
295
|
+
type: 'Adapter',
|
|
296
|
+
},
|
|
297
|
+
'event.raw': {
|
|
298
|
+
description: 'Raw platform-specific payload.',
|
|
299
|
+
type: 'unknown',
|
|
300
|
+
},
|
|
301
|
+
}}
|
|
302
|
+
/>
|
|
303
|
+
|
|
263
304
|
### onSlashCommand
|
|
264
305
|
|
|
265
|
-
Fires when a user invokes a `/command` in the message composer. Currently supported on Slack.
|
|
306
|
+
Fires when a user invokes a `/command` in the message composer. Currently supported on Slack and Discord.
|
|
266
307
|
|
|
267
308
|
```typescript
|
|
268
309
|
// Specific command
|
|
@@ -425,12 +466,42 @@ bot.webhooks.teams(request, { waitUntil });
|
|
|
425
466
|
|
|
426
467
|
### getAdapter
|
|
427
468
|
|
|
428
|
-
Get
|
|
469
|
+
Get a typed adapter instance by name.
|
|
429
470
|
|
|
430
471
|
```typescript
|
|
431
472
|
const slack = bot.getAdapter("slack");
|
|
432
473
|
```
|
|
433
474
|
|
|
475
|
+
#### Direct client access
|
|
476
|
+
|
|
477
|
+
Use `.client` to access the platform's typed native API client directly — available on Linear and GitHub:
|
|
478
|
+
|
|
479
|
+
```typescript
|
|
480
|
+
// Linear - full LinearClient from @linear/sdk
|
|
481
|
+
const linear = bot.getAdapter("linear").client;
|
|
482
|
+
const issue = await linear.issue("ENG-123");
|
|
483
|
+
const project = await issue.project;
|
|
484
|
+
|
|
485
|
+
// GitHub - full Octokit from @octokit/rest
|
|
486
|
+
const github = bot.getAdapter("github").client;
|
|
487
|
+
const { data: pulls } = await github.rest.pulls.list({
|
|
488
|
+
owner: "vercel",
|
|
489
|
+
repo: "chat",
|
|
490
|
+
state: "open",
|
|
491
|
+
});
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
The client uses the credentials from your adapter config. For multi-tenant adapters (Linear, GitHub), it returns the client for the current webhook request context.
|
|
495
|
+
|
|
496
|
+
<Callout type="warn">
|
|
497
|
+
For multi-tenant adapters (GitHub App without a fixed installation ID, Linear with per-org OAuth), `client` requires webhook handler context to resolve credentials. Calling it outside a handler throws. Single-tenant adapters (PAT, API key) work anywhere.
|
|
498
|
+
</Callout>
|
|
499
|
+
|
|
500
|
+
| Adapter | `client` type |
|
|
501
|
+
|---------|---------------|
|
|
502
|
+
| Linear | `LinearClient` from `@linear/sdk` |
|
|
503
|
+
| GitHub | `Octokit` from `@octokit/rest` |
|
|
504
|
+
|
|
434
505
|
### openDM
|
|
435
506
|
|
|
436
507
|
Open a direct message thread with a user.
|
|
@@ -443,6 +514,101 @@ await dm.post("Hello via DM!");
|
|
|
443
514
|
const dm = await bot.openDM(message.author);
|
|
444
515
|
```
|
|
445
516
|
|
|
517
|
+
### getUser
|
|
518
|
+
|
|
519
|
+
Look up user information by user ID. Returns a `UserInfo` object with name, email, avatar, and bot status, or `null` if the user was not found. Supported on Slack, Microsoft Teams, Discord, Google Chat, GitHub, Linear, and Telegram. Other adapters will throw `NOT_SUPPORTED`.
|
|
520
|
+
|
|
521
|
+
```typescript
|
|
522
|
+
const user = await bot.getUser("U123456");
|
|
523
|
+
console.log(user?.email); // "alice@company.com"
|
|
524
|
+
console.log(user?.fullName); // "Alice Smith"
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
```typescript
|
|
528
|
+
// Or with an Author object from a message handler
|
|
529
|
+
const user = await bot.getUser(message.author);
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
<TypeTable
|
|
533
|
+
type={{
|
|
534
|
+
userId: {
|
|
535
|
+
description: 'Platform-specific user ID.',
|
|
536
|
+
type: 'string',
|
|
537
|
+
},
|
|
538
|
+
userName: {
|
|
539
|
+
description: 'Username/handle.',
|
|
540
|
+
type: 'string',
|
|
541
|
+
},
|
|
542
|
+
fullName: {
|
|
543
|
+
description: 'Display name / full name.',
|
|
544
|
+
type: 'string',
|
|
545
|
+
},
|
|
546
|
+
isBot: {
|
|
547
|
+
description: 'Whether the user is a bot.',
|
|
548
|
+
type: 'boolean',
|
|
549
|
+
},
|
|
550
|
+
email: {
|
|
551
|
+
description: 'Email address (requires scopes on some platforms).',
|
|
552
|
+
type: 'string | undefined',
|
|
553
|
+
},
|
|
554
|
+
avatarUrl: {
|
|
555
|
+
description: 'Profile image URL.',
|
|
556
|
+
type: 'string | undefined',
|
|
557
|
+
},
|
|
558
|
+
}}
|
|
559
|
+
/>
|
|
560
|
+
|
|
561
|
+
<Callout type="info">
|
|
562
|
+
**Per-platform constraints:**
|
|
563
|
+
- **Slack** — requires both `users:read` and `users:read.email` scopes (the email scope must be granted at OAuth install time).
|
|
564
|
+
- **Discord** — bot tokens never see email (the `email` OAuth scope only applies in user-context auth).
|
|
565
|
+
- **Telegram** — bots can only look up users who have previously messaged them.
|
|
566
|
+
- **Microsoft Teams** — only works for users who previously interacted with the bot (cached from webhook activity). `avatarUrl` is not returned (Graph API requires a separate photo call).
|
|
567
|
+
- **Google Chat** — same caching constraint as Teams: only users seen in prior webhooks.
|
|
568
|
+
- **GitHub** — `email` is `null` unless the user made it public, or you authenticated with the `user:email` scope.
|
|
569
|
+
- **Linear** — full profile (incl. email + avatar) for any active workspace member.
|
|
570
|
+
|
|
571
|
+
Fields that aren't available return `undefined`. Numeric user IDs (Discord/Telegram/GitHub) can be ambiguous when multiple of those adapters are registered — `bot.getUser` throws a `ChatError` with code `AMBIGUOUS_USER_ID` in that case. Pass an `Author` from a message handler (which already carries the adapter), or call the adapter directly (`adapter.getUser(userId)`).
|
|
572
|
+
</Callout>
|
|
573
|
+
|
|
574
|
+
`bot.getUser` throws a `ChatError` in three cases. Handle them if your bot runs on multiple platforms:
|
|
575
|
+
|
|
576
|
+
| Code | When |
|
|
577
|
+
|------|------|
|
|
578
|
+
| `NOT_SUPPORTED` | The resolved adapter doesn't implement `getUser` (e.g. WhatsApp) |
|
|
579
|
+
| `AMBIGUOUS_USER_ID` | A numeric user ID could belong to more than one registered adapter (Discord/Telegram/GitHub) |
|
|
580
|
+
| `UNKNOWN_USER_ID_FORMAT` | The `userId` string doesn't match any registered platform's ID format |
|
|
581
|
+
|
|
582
|
+
```typescript
|
|
583
|
+
import { ChatError } from "chat";
|
|
584
|
+
|
|
585
|
+
try {
|
|
586
|
+
const user = await bot.getUser(userId);
|
|
587
|
+
if (!user) {
|
|
588
|
+
// User not found on this platform
|
|
589
|
+
}
|
|
590
|
+
} catch (error) {
|
|
591
|
+
if (error instanceof ChatError) {
|
|
592
|
+
if (error.code === "NOT_SUPPORTED") {
|
|
593
|
+
// This adapter doesn't support user lookups
|
|
594
|
+
} else if (error.code === "AMBIGUOUS_USER_ID") {
|
|
595
|
+
// Pass message.author or call adapter.getUser(userId) directly
|
|
596
|
+
} else if (error.code === "UNKNOWN_USER_ID_FORMAT") {
|
|
597
|
+
// userId doesn't match any known platform format
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
### thread
|
|
604
|
+
|
|
605
|
+
Get a Thread handle by its thread ID. Useful for posting to threads outside of webhook contexts (e.g. cron jobs, external triggers).
|
|
606
|
+
|
|
607
|
+
```typescript
|
|
608
|
+
const thread = bot.thread("slack:C123ABC:1234567890.123456");
|
|
609
|
+
await thread.post("Hello from a cron job!");
|
|
610
|
+
```
|
|
611
|
+
|
|
446
612
|
### channel
|
|
447
613
|
|
|
448
614
|
Get a Channel by its channel ID.
|
package/docs/api/index.mdx
CHANGED
|
@@ -31,6 +31,8 @@ import { Chat, root, paragraph, text, Card, Button, emoji } from "chat";
|
|
|
31
31
|
| Export | Description |
|
|
32
32
|
|--------|-------------|
|
|
33
33
|
| [`PostableMessage`](/docs/api/postable-message) | Union type accepted by `thread.post()` |
|
|
34
|
+
| [`Plan`](/docs/api/postable-message#plan) | Step-by-step task list that mutates after posting |
|
|
35
|
+
| [`StreamingPlan`](/docs/api/postable-message#streamingplan) | Wraps an async iterable with platform-specific streaming options |
|
|
34
36
|
| [`Cards`](/docs/api/cards) | Rich card components — `Card`, `Text`, `Button`, `Actions`, etc. |
|
|
35
37
|
| [`Markdown`](/docs/api/markdown) | AST builder functions — `root`, `paragraph`, `text`, `strong`, etc. |
|
|
36
38
|
| [`Modals`](/docs/api/modals) | Modal form components — `Modal`, `TextInput`, `Select`, etc. |
|