chat 4.29.0 → 4.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,10 @@
1
- import { r as Chat, R as ChannelVisibility } from '../chat-D9UYaaNO.js';
2
- export { g as AiAssistantMessage, h as AiFilePart, i as AiImagePart, j as AiMessage, k as AiMessagePart, l as AiTextPart, m as AiUserMessage, n as ToAiMessagesOptions, t as toAiMessages } from '../chat-D9UYaaNO.js';
1
+ import { x as Chat, w as ChannelVisibility } from '../chat-BPjXsoIl.js';
2
+ export { d as AiAssistantMessage, e as AiFilePart, f as AiImagePart, g as AiMessage, h as AiMessagePart, i as AiTextPart, j as AiUserMessage, aZ as ToAiMessagesOptions, b7 as toAiMessages } from '../chat-BPjXsoIl.js';
3
3
  import * as ai from 'ai';
4
4
  import { Tool } from 'ai';
5
5
  import '@workflow/serde';
6
6
  import 'mdast';
7
- import '../jsx-runtime-CFq1K_Ve.js';
7
+ import '../jsx-runtime-CnDs8rPr.js';
8
8
 
9
9
  /**
10
10
  * The Chat instance used by all tools to dispatch operations.
@@ -1,6 +1,6 @@
1
1
  import { WORKFLOW_SERIALIZE, WORKFLOW_DESERIALIZE } from '@workflow/serde';
2
2
  import { Root } from 'mdast';
3
- import { Z as ChatElement, C as CardElement, ac as ModalElement, ah as SelectOptionElement } from './jsx-runtime-CFq1K_Ve.js';
3
+ import { n as ChatElement, g as CardElement, Q as ModalElement, $ as SelectOptionElement } from './jsx-runtime-CnDs8rPr.js';
4
4
 
5
5
  interface ThreadHistoryConfig {
6
6
  /** Maximum messages to keep per thread (default: 100) */
@@ -761,7 +761,9 @@ interface Adapter<TThreadId = unknown, TRawMessage = unknown> {
761
761
  * Stream a message using platform-native streaming APIs.
762
762
  *
763
763
  * The adapter consumes the async iterable and handles the entire streaming lifecycle.
764
- * Only available on platforms with native streaming support (e.g., Slack).
764
+ * Available on platforms with native streaming or preview APIs.
765
+ * Adapters may return `null` before consuming any chunks to delegate back to
766
+ * Chat SDK's built-in post+edit fallback for the current thread.
765
767
  *
766
768
  * The stream can yield plain strings (text chunks) or {@link StreamChunk} objects
767
769
  * for rich content like task progress cards. Adapters that don't support structured
@@ -770,9 +772,9 @@ interface Adapter<TThreadId = unknown, TRawMessage = unknown> {
770
772
  * @param threadId - The thread to stream to
771
773
  * @param textStream - Async iterable of text chunks or structured StreamChunk objects
772
774
  * @param options - Platform-specific streaming options
773
- * @returns The raw message after streaming completes
775
+ * @returns The raw message after streaming completes, or `null` to use core fallback
774
776
  */
775
- stream?(threadId: string, textStream: AsyncIterable<string | StreamChunk>, options?: StreamOptions): Promise<RawMessage<TRawMessage>>;
777
+ stream?(threadId: string, textStream: AsyncIterable<string | StreamChunk>, options?: StreamOptions): Promise<RawMessage<TRawMessage> | null>;
776
778
  /** Bot username (can override global userName) */
777
779
  readonly userName: string;
778
780
  }
@@ -1221,8 +1223,8 @@ interface Thread<TState = Record<string, unknown>, TRawMessage = unknown> extend
1221
1223
  * Post a message to this thread.
1222
1224
  *
1223
1225
  * Supports text, markdown, cards, and streaming from async iterables.
1224
- * When posting a stream (e.g., from AI SDK), uses platform-native streaming
1225
- * APIs when available (Slack), or falls back to post + edit with throttling.
1226
+ * When posting a stream (e.g., from AI SDK), uses adapter-native streaming
1227
+ * when available, or falls back to post + edit with throttling.
1226
1228
  *
1227
1229
  * @param message - String, PostableMessage, JSX Card, or AsyncIterable<string>
1228
1230
  * @returns A SentMessage with methods to edit, delete, or add reactions
@@ -3153,4 +3155,4 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
3153
3155
  private runHandlers;
3154
3156
  }
3155
3157
 
3156
- export { type DirectMessageHandler as $, type Adapter as A, type AppendInput as B, type CustomEmojiMap as C, type AppendOptions as D, type EmojiMapConfig as E, type AppHomeOpenedEvent as F, type AppHomeOpenedHandler as G, type AssistantContextChangedEvent as H, type AssistantContextChangedHandler as I, type AssistantThreadStartedEvent as J, type AssistantThreadStartedHandler as K, type Attachment as L, Message as M, type Author as N, type Channel as O, type PostableObject as P, type ChannelInfo as Q, type ChannelVisibility as R, type StreamChunk as S, ThreadHistoryCache as T, type ChatConfig as U, type ChatInstance as V, type WellKnownEmoji as W, type ConcurrencyConfig as X, type ConcurrencyStrategy as Y, type CountQuery as Z, type DeleteTarget as _, type PostableObjectContext as a, type ThreadSummary as a$, type DurationString as a0, type Emoji as a1, type EphemeralMessage as a2, type FetchDirection as a3, type FetchOptions as a4, type FetchResult as a5, type FileUpload as a6, type FormattedContent as a7, type IdentityContext as a8, type IdentityResolver as a9, type ModalUpdateResponse as aA, type OptionsLoadEvent as aB, type OptionsLoadGroup as aC, type OptionsLoadHandler as aD, type OptionsLoadResult as aE, type PlanUpdateChunk as aF, type Postable as aG, type PostableAst as aH, type PostableCard as aI, type PostableMarkdown as aJ, type PostableMessage as aK, type PostableRaw as aL, type PostEphemeralOptions as aM, type QueueEntry as aN, type RawMessage as aO, type ReactionEvent as aP, type ReactionHandler as aQ, type ScheduledMessage as aR, type SentMessage as aS, type SlashCommandEvent as aT, type SlashCommandHandler as aU, type StateAdapter as aV, type StreamOptions as aW, type SubscribedMessageHandler as aX, type TaskUpdateChunk as aY, type Thread as aZ, type ThreadInfo as a_, type LinkPreview as aa, type ListQuery as ab, type ListThreadsOptions as ac, type ListThreadsResult as ad, type Lock as ae, type LockScope as af, type LockScopeContext as ag, type Logger as ah, type LogLevel as ai, type MarkdownTextChunk as aj, type MemberJoinedChannelEvent as ak, type MemberJoinedChannelHandler as al, type MentionHandler as am, type MessageContext as an, type MessageHandler as ao, type MessageMetadata as ap, type MessageSubject as aq, type ModalClearResponse as ar, type ModalCloseEvent as as, type ModalCloseHandler as at, type ModalCloseResponse as au, type ModalErrorsResponse as av, type ModalPushResponse as aw, type ModalResponse as ax, type ModalSubmitEvent as ay, type ModalSubmitHandler as az, type ThreadHistoryConfig as b, type TranscriptEntry as b0, type TranscriptRole as b1, type TranscriptsApi as b2, type TranscriptsConfig as b3, type UserInfo as b4, type WebhookOptions as b5, ConsoleLogger as b6, THREAD_STATE_TTL_MS as b7, type StreamEvent as c, type EmojiValue as d, type EmojiFormats as e, type AdapterPostableMessage as f, type AiAssistantMessage as g, type AiFilePart as h, type AiImagePart as i, type AiMessage as j, type AiMessagePart as k, type AiTextPart as l, type AiUserMessage as m, type ToAiMessagesOptions as n, ChannelImpl as o, deriveChannelId as p, type SerializedChannel as q, Chat as r, type MessageData as s, toAiMessages as t, type SerializedMessage as u, isPostableObject as v, type SerializedThread as w, ThreadImpl as x, type ActionEvent as y, type ActionHandler as z };
3158
+ export { type LockScope as $, type ActionEvent as A, type ConcurrencyConfig as B, type Channel as C, type ConcurrencyStrategy as D, ConsoleLogger as E, type CountQuery as F, type CustomEmojiMap as G, type DeleteTarget as H, type DirectMessageHandler as I, type DurationString as J, type Emoji as K, type EmojiFormats as L, type EmojiMapConfig as M, type EmojiValue as N, type EphemeralMessage as O, type FetchDirection as P, type FetchOptions as Q, type FetchResult as R, type FileUpload as S, type FormattedContent as T, type IdentityContext as U, type IdentityResolver as V, type LinkPreview as W, type ListQuery as X, type ListThreadsOptions as Y, type ListThreadsResult as Z, type Lock as _, type ActionHandler as a, type TranscriptRole as a$, type LockScopeContext as a0, type LogLevel as a1, type Logger as a2, type MarkdownTextChunk as a3, type MemberJoinedChannelEvent as a4, type MemberJoinedChannelHandler as a5, type MentionHandler as a6, Message as a7, type MessageContext as a8, type MessageData as a9, type PostableRaw as aA, type QueueEntry as aB, type RawMessage as aC, type ReactionEvent as aD, type ReactionHandler as aE, type ScheduledMessage as aF, type SentMessage as aG, type SerializedChannel as aH, type SerializedMessage as aI, type SerializedThread as aJ, type SlashCommandEvent as aK, type SlashCommandHandler as aL, type StateAdapter as aM, type StreamChunk as aN, type StreamEvent as aO, type StreamOptions as aP, type SubscribedMessageHandler as aQ, THREAD_STATE_TTL_MS as aR, type TaskUpdateChunk as aS, type Thread as aT, ThreadHistoryCache as aU, type ThreadHistoryConfig as aV, ThreadImpl as aW, type ThreadInfo as aX, type ThreadSummary as aY, type ToAiMessagesOptions as aZ, type TranscriptEntry as a_, type MessageHandler as aa, type MessageMetadata as ab, type MessageSubject as ac, type ModalClearResponse as ad, type ModalCloseEvent as ae, type ModalCloseHandler as af, type ModalCloseResponse as ag, type ModalErrorsResponse as ah, type ModalPushResponse as ai, type ModalResponse as aj, type ModalSubmitEvent as ak, type ModalSubmitHandler as al, type ModalUpdateResponse as am, type OptionsLoadEvent as an, type OptionsLoadGroup as ao, type OptionsLoadHandler as ap, type OptionsLoadResult as aq, type PlanUpdateChunk as ar, type PostEphemeralOptions as as, type Postable as at, type PostableAst as au, type PostableCard as av, type PostableMarkdown as aw, type PostableMessage as ax, type PostableObject as ay, type PostableObjectContext as az, type Adapter as b, type TranscriptsApi as b0, type TranscriptsConfig as b1, type UserInfo as b2, type WebhookOptions as b3, type WellKnownEmoji as b4, deriveChannelId as b5, isPostableObject as b6, toAiMessages as b7, type AdapterPostableMessage as c, type AiAssistantMessage as d, type AiFilePart as e, type AiImagePart as f, type AiMessage as g, type AiMessagePart as h, type AiTextPart as i, type AiUserMessage as j, type AppHomeOpenedEvent as k, type AppHomeOpenedHandler as l, type AppendInput as m, type AppendOptions as n, type AssistantContextChangedEvent as o, type AssistantContextChangedHandler as p, type AssistantThreadStartedEvent as q, type AssistantThreadStartedHandler as r, type Attachment as s, type Author as t, ChannelImpl as u, type ChannelInfo as v, type ChannelVisibility as w, Chat as x, type ChatConfig as y, type ChatInstance as z };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { P as PostableObject, A as Adapter, a as PostableObjectContext, S as StreamChunk, T as ThreadHistoryCache, b as ThreadHistoryConfig, c as StreamEvent, E as EmojiMapConfig, d as EmojiValue, W as WellKnownEmoji, e as EmojiFormats, C as CustomEmojiMap, f as AdapterPostableMessage } from './chat-D9UYaaNO.js';
2
- export { y as ActionEvent, z as ActionHandler, g as AiAssistantMessage, h as AiFilePart, i as AiImagePart, j as AiMessage, k as AiMessagePart, l as AiTextPart, m as AiUserMessage, F as AppHomeOpenedEvent, G as AppHomeOpenedHandler, B as AppendInput, D as AppendOptions, H as AssistantContextChangedEvent, I as AssistantContextChangedHandler, J as AssistantThreadStartedEvent, K as AssistantThreadStartedHandler, L as Attachment, N as Author, O as Channel, o as ChannelImpl, Q as ChannelInfo, R as ChannelVisibility, r as Chat, U as ChatConfig, V as ChatInstance, X as ConcurrencyConfig, Y as ConcurrencyStrategy, b6 as ConsoleLogger, Z as CountQuery, _ as DeleteTarget, $ as DirectMessageHandler, a0 as DurationString, a1 as Emoji, a2 as EphemeralMessage, a3 as FetchDirection, a4 as FetchOptions, a5 as FetchResult, a6 as FileUpload, a7 as FormattedContent, a8 as IdentityContext, a9 as IdentityResolver, aa as LinkPreview, ab as ListQuery, ac as ListThreadsOptions, ad as ListThreadsResult, ae as Lock, af as LockScope, ag as LockScopeContext, ai as LogLevel, ah as Logger, aj as MarkdownTextChunk, ak as MemberJoinedChannelEvent, al as MemberJoinedChannelHandler, am as MentionHandler, M as Message, an as MessageContext, s as MessageData, ao as MessageHandler, ap as MessageMetadata, aq as MessageSubject, ar as ModalClearResponse, as as ModalCloseEvent, at as ModalCloseHandler, au as ModalCloseResponse, av as ModalErrorsResponse, aw as ModalPushResponse, ax as ModalResponse, ay as ModalSubmitEvent, az as ModalSubmitHandler, aA as ModalUpdateResponse, aB as OptionsLoadEvent, aC as OptionsLoadGroup, aD as OptionsLoadHandler, aE as OptionsLoadResult, aF as PlanUpdateChunk, aM as PostEphemeralOptions, aG as Postable, aH as PostableAst, aI as PostableCard, aJ as PostableMarkdown, aK as PostableMessage, aL as PostableRaw, aN as QueueEntry, aO as RawMessage, aP as ReactionEvent, aQ as ReactionHandler, aR as ScheduledMessage, aS as SentMessage, q as SerializedChannel, u as SerializedMessage, w as SerializedThread, aT as SlashCommandEvent, aU as SlashCommandHandler, aV as StateAdapter, aW as StreamOptions, aX as SubscribedMessageHandler, b7 as THREAD_STATE_TTL_MS, aY as TaskUpdateChunk, aZ as Thread, x as ThreadImpl, a_ as ThreadInfo, a$ as ThreadSummary, n as ToAiMessagesOptions, b0 as TranscriptEntry, b1 as TranscriptRole, b2 as TranscriptsApi, b3 as TranscriptsConfig, b4 as UserInfo, b5 as WebhookOptions, p as deriveChannelId, v as isPostableObject, t as toAiMessages } from './chat-D9UYaaNO.js';
1
+ import { ay as PostableObject, b as Adapter, az as PostableObjectContext, aN as StreamChunk, aU as ThreadHistoryCache, aV as ThreadHistoryConfig, aO as StreamEvent, L as EmojiFormats, M as EmojiMapConfig, N as EmojiValue, b4 as WellKnownEmoji, G as CustomEmojiMap, c as AdapterPostableMessage } from './chat-BPjXsoIl.js';
2
+ export { A as ActionEvent, a as ActionHandler, d as AiAssistantMessage, e as AiFilePart, f as AiImagePart, g as AiMessage, h as AiMessagePart, i as AiTextPart, j as AiUserMessage, k as AppHomeOpenedEvent, l as AppHomeOpenedHandler, m as AppendInput, n as AppendOptions, o as AssistantContextChangedEvent, p as AssistantContextChangedHandler, q as AssistantThreadStartedEvent, r as AssistantThreadStartedHandler, s as Attachment, t as Author, C as Channel, u as ChannelImpl, v as ChannelInfo, w as ChannelVisibility, x as Chat, y as ChatConfig, z as ChatInstance, B as ConcurrencyConfig, D as ConcurrencyStrategy, E as ConsoleLogger, F as CountQuery, H as DeleteTarget, I as DirectMessageHandler, J as DurationString, K as Emoji, O as EphemeralMessage, P as FetchDirection, Q as FetchOptions, R as FetchResult, S as FileUpload, T as FormattedContent, U as IdentityContext, V as IdentityResolver, W as LinkPreview, X as ListQuery, Y as ListThreadsOptions, Z as ListThreadsResult, _ as Lock, $ as LockScope, a0 as LockScopeContext, a1 as LogLevel, a2 as Logger, a3 as MarkdownTextChunk, a4 as MemberJoinedChannelEvent, a5 as MemberJoinedChannelHandler, a6 as MentionHandler, a7 as Message, a8 as MessageContext, a9 as MessageData, aa as MessageHandler, ab as MessageMetadata, ac as MessageSubject, ad as ModalClearResponse, ae as ModalCloseEvent, af as ModalCloseHandler, ag as ModalCloseResponse, ah as ModalErrorsResponse, ai as ModalPushResponse, aj as ModalResponse, ak as ModalSubmitEvent, al as ModalSubmitHandler, am as ModalUpdateResponse, an as OptionsLoadEvent, ao as OptionsLoadGroup, ap as OptionsLoadHandler, aq as OptionsLoadResult, ar as PlanUpdateChunk, as as PostEphemeralOptions, at as Postable, au as PostableAst, av as PostableCard, aw as PostableMarkdown, ax as PostableMessage, aA as PostableRaw, aB as QueueEntry, aC as RawMessage, aD as ReactionEvent, aE as ReactionHandler, aF as ScheduledMessage, aG as SentMessage, aH as SerializedChannel, aI as SerializedMessage, aJ as SerializedThread, aK as SlashCommandEvent, aL as SlashCommandHandler, aM as StateAdapter, aP as StreamOptions, aQ as SubscribedMessageHandler, aR as THREAD_STATE_TTL_MS, aS as TaskUpdateChunk, aT as Thread, aW as ThreadImpl, aX as ThreadInfo, aY as ThreadSummary, aZ as ToAiMessagesOptions, a_ as TranscriptEntry, a$ as TranscriptRole, b0 as TranscriptsApi, b1 as TranscriptsConfig, b2 as UserInfo, b3 as WebhookOptions, b5 as deriveChannelId, b6 as isPostableObject, b7 as toAiMessages } from './chat-BPjXsoIl.js';
3
3
  import { Root, List, Content, Blockquote, Code, Emphasis, InlineCode, Delete, Link, ListItem, Paragraph, Strong, TableCell, Table as Table$1, TableRow, Text } from 'mdast';
4
4
  export { Blockquote, Code, Content, Delete, Emphasis, InlineCode, Link, List, ListItem, Table as MdastTable, Nodes, Paragraph, Root, Strong, TableCell, TableRow, Text } from 'mdast';
5
- import { C as CardElement, a as CardChild, A as ActionsComponent, B as ButtonComponent, b as CardComponent, c as cardChildToFallbackText$1, d as CardLinkComponent, T as TextComponent, D as DividerComponent, F as FieldComponent, e as FieldsComponent, f as fromReactElement$1, I as ImageComponent, i as isCardElement$1, g as isJSX$1, L as LinkButtonComponent, S as SectionComponent, h as Table$2, t as toCardElement$1, j as toModalElement$1, k as fromReactModalElement$1, l as isModalElement$1, E as ExternalSelectComponent, M as ModalComponent, R as RadioSelectComponent, m as SelectComponent, n as SelectOptionComponent, o as TextInputComponent } from './jsx-runtime-CFq1K_Ve.js';
6
- export { p as ActionsElement, q as ButtonElement, r as ButtonOptions, U as ButtonProps, s as ButtonStyle, V as CardJSXElement, W as CardJSXProps, X as CardLinkProps, u as CardOptions, Y as CardProps, Z as ChatElement, _ as ContainerProps, v as DividerElement, $ as DividerProps, a9 as ExternalSelectElement, aa as ExternalSelectOptions, a0 as ExternalSelectProps, w as FieldElement, a1 as FieldProps, x as FieldsElement, y as ImageElement, a2 as ImageProps, z as LinkButtonElement, G as LinkButtonOptions, a3 as LinkButtonProps, H as LinkElement, ab as ModalChild, ac as ModalElement, ad as ModalOptions, a4 as ModalProps, ae as RadioSelectElement, af as RadioSelectOptions, J as SectionElement, ag as SelectElement, ah as SelectOptionElement, a5 as SelectOptionProps, ai as SelectOptions, a6 as SelectProps, K as TableAlignment, N as TableElement, O as TableOptions, P as TextElement, aj as TextInputElement, ak as TextInputOptions, a7 as TextInputProps, a8 as TextProps, Q as TextStyle } from './jsx-runtime-CFq1K_Ve.js';
5
+ import { g as CardElement, C as CardChild, A as ActionsComponent, B as ButtonComponent, f as CardComponent, j as CardLinkComponent, a9 as TextComponent, D as DividerComponent, E as ExternalSelectComponent, F as FieldComponent, w as FieldsComponent, I as ImageComponent, L as LinkButtonComponent, P as ModalComponent, T as RadioSelectComponent, W as SectionComponent, Y as SelectComponent, _ as SelectOptionComponent, a3 as Table$2, ab as TextInputComponent, ah as cardChildToFallbackText$1, ai as fromReactElement$1, aj as fromReactModalElement$1, ak as isCardElement$1, am as isJSX$1, an as isModalElement$1, ar as toCardElement$1, as as toModalElement$1 } from './jsx-runtime-CnDs8rPr.js';
6
+ export { a as ActionsElement, b as ButtonElement, c as ButtonOptions, d as ButtonProps, e as ButtonStyle, h as CardJSXElement, i as CardJSXProps, k as CardLinkProps, l as CardOptions, m as CardProps, n as ChatElement, o as ContainerProps, p as DividerElement, q as DividerProps, r as ExternalSelectElement, s as ExternalSelectOptions, t as ExternalSelectProps, u as FieldElement, v as FieldProps, x as FieldsElement, z as ImageElement, G as ImageProps, H as LinkButtonElement, K as LinkButtonOptions, M as LinkButtonProps, N as LinkElement, O as ModalChild, Q as ModalElement, R as ModalOptions, S as ModalProps, U as RadioSelectElement, V as RadioSelectOptions, X as SectionElement, Z as SelectElement, $ as SelectOptionElement, a0 as SelectOptionProps, a1 as SelectOptions, a2 as SelectProps, a4 as TableAlignment, a6 as TableElement, a7 as TableOptions, aa as TextElement, ac as TextInputElement, ad as TextInputOptions, ae as TextInputProps, af as TextProps, ag as TextStyle } from './jsx-runtime-CnDs8rPr.js';
7
7
  import '@workflow/serde';
8
8
 
9
9
  /**
package/dist/index.js CHANGED
@@ -1504,7 +1504,10 @@ var ThreadImpl = class _ThreadImpl {
1504
1504
  */
1505
1505
  async handleStream(rawStream, callerOptions) {
1506
1506
  const textStream = fromFullStream(rawStream);
1507
- const options = { ...callerOptions };
1507
+ const options = {
1508
+ updateIntervalMs: this._streamingUpdateIntervalMs,
1509
+ ...callerOptions
1510
+ };
1508
1511
  if (this._currentMessage) {
1509
1512
  options.recipientUserId = this._currentMessage.author.userId;
1510
1513
  options.recipientTeamId = this.extractSlackRecipientTeamId(
@@ -1533,15 +1536,17 @@ var ThreadImpl = class _ThreadImpl {
1533
1536
  }
1534
1537
  };
1535
1538
  const raw = await this.adapter.stream(this.id, wrappedStream, options);
1536
- const sent = this.createSentMessage(
1537
- raw.id,
1538
- { markdown: accumulated },
1539
- raw.threadId
1540
- );
1541
- if (this._threadHistory) {
1542
- await this._threadHistory.append(this.id, new Message(sent));
1539
+ if (raw) {
1540
+ const sent = this.createSentMessage(
1541
+ raw.id,
1542
+ { markdown: accumulated },
1543
+ raw.threadId
1544
+ );
1545
+ if (this._threadHistory) {
1546
+ await this._threadHistory.append(this.id, new Message(sent));
1547
+ }
1548
+ return sent;
1543
1549
  }
1544
- return sent;
1545
1550
  }
1546
1551
  const textOnlyStream = {
1547
1552
  [Symbol.asyncIterator]: () => {
@@ -779,4 +779,4 @@ declare namespace JSX {
779
779
  }
780
780
  }
781
781
 
782
- export { type DividerProps as $, type ActionsComponent as A, type ButtonComponent as B, type CardElement as C, type DividerComponent as D, type ExternalSelectComponent as E, type FieldComponent as F, type LinkButtonOptions as G, type LinkElement as H, type ImageComponent as I, type SectionElement as J, type TableAlignment as K, type LinkButtonComponent as L, type ModalComponent as M, type TableElement as N, type TableOptions as O, type TextElement as P, type TextStyle as Q, type RadioSelectComponent as R, type SectionComponent as S, type TextComponent as T, type ButtonProps as U, type CardJSXElement as V, type CardJSXProps as W, type CardLinkProps as X, type CardProps as Y, type ChatElement as Z, type ContainerProps as _, type CardChild as a, type ExternalSelectProps as a0, type FieldProps as a1, type ImageProps as a2, type LinkButtonProps as a3, type ModalProps as a4, type SelectOptionProps as a5, type SelectProps as a6, type TextInputProps as a7, type TextProps as a8, type ExternalSelectElement as a9, type ExternalSelectOptions as aa, type ModalChild as ab, type ModalElement as ac, type ModalOptions as ad, type RadioSelectElement as ae, type RadioSelectOptions as af, type SelectElement as ag, type SelectOptionElement 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 CardComponent as b, cardChildToFallbackText as c, type CardLinkComponent as d, type FieldsComponent as e, fromReactElement as f, isJSX as g, Table as h, isCardElement as i, toModalElement as j, fromReactModalElement as k, isModalElement as l, type SelectComponent as m, type SelectOptionComponent as n, type TextInputComponent as o, type ActionsElement as p, type ButtonElement as q, type ButtonOptions as r, type ButtonStyle as s, toCardElement as t, type CardOptions as u, type DividerElement as v, type FieldElement as w, type FieldsElement as x, type ImageElement as y, type LinkButtonElement as z };
782
+ export { type SelectOptionElement as $, type ActionsComponent as A, type ButtonComponent as B, type CardChild as C, type DividerComponent as D, type ExternalSelectComponent as E, type FieldComponent as F, type ImageProps as G, type LinkButtonElement as H, type ImageComponent as I, JSX as J, type LinkButtonOptions as K, type LinkButtonComponent as L, type LinkButtonProps as M, type LinkElement as N, type ModalChild as O, type ModalComponent as P, type ModalElement as Q, type ModalOptions as R, type ModalProps as S, type RadioSelectComponent as T, type RadioSelectElement as U, type RadioSelectOptions as V, type SectionComponent as W, type SectionElement as X, type SelectComponent as Y, type SelectElement as Z, type SelectOptionComponent as _, type ActionsElement as a, type SelectOptionProps as a0, type SelectOptions as a1, type SelectProps as a2, Table as a3, type TableAlignment as a4, type TableComponent as a5, type TableElement as a6, type TableOptions as a7, type TableProps as a8, type TextComponent as a9, type TextElement as aa, type TextInputComponent as ab, type TextInputElement as ac, type TextInputOptions as ad, type TextInputProps as ae, type TextProps as af, type TextStyle as ag, cardChildToFallbackText as ah, fromReactElement as ai, fromReactModalElement as aj, isCardElement as ak, isCardLinkProps as al, isJSX as am, isModalElement as an, jsx as ao, jsxDEV as ap, jsxs as aq, toCardElement as ar, toModalElement as as, type ButtonElement as b, type ButtonOptions as c, type ButtonProps as d, type ButtonStyle as e, type CardComponent as f, type CardElement as g, type CardJSXElement as h, type CardJSXProps as i, type CardLinkComponent as j, type CardLinkProps as k, type CardOptions as l, type CardProps as m, type ChatElement as n, type ContainerProps as o, type DividerElement as p, type DividerProps as q, type ExternalSelectElement as r, type ExternalSelectOptions as s, type ExternalSelectProps as t, type FieldElement as u, type FieldProps as v, type FieldsComponent as w, type FieldsElement as x, Fragment as y, type ImageElement as z };
@@ -1 +1 @@
1
- export { A as ActionsComponent, B as ButtonComponent, U as ButtonProps, b as CardComponent, V as CardJSXElement, W as CardJSXProps, d as CardLinkComponent, X as CardLinkProps, Y as CardProps, Z as ChatElement, _ as ContainerProps, D as DividerComponent, $ as DividerProps, E as ExternalSelectComponent, a0 as ExternalSelectProps, F as FieldComponent, a1 as FieldProps, e as FieldsComponent, ar as Fragment, I as ImageComponent, a2 as ImageProps, as as JSX, L as LinkButtonComponent, a3 as LinkButtonProps, M as ModalComponent, a4 as ModalProps, R as RadioSelectComponent, S as SectionComponent, m as SelectComponent, n as SelectOptionComponent, a5 as SelectOptionProps, a6 as SelectProps, am as TableComponent, al as TableProps, T as TextComponent, o as TextInputComponent, a7 as TextInputProps, a8 as TextProps, an as isCardLinkProps, g as isJSX, ao as jsx, aq as jsxDEV, ap as jsxs, t as toCardElement, j as toModalElement } from './jsx-runtime-CFq1K_Ve.js';
1
+ export { A as ActionsComponent, B as ButtonComponent, d as ButtonProps, f as CardComponent, h as CardJSXElement, i as CardJSXProps, j as CardLinkComponent, k as CardLinkProps, m as CardProps, n as ChatElement, o as ContainerProps, D as DividerComponent, q as DividerProps, E as ExternalSelectComponent, t as ExternalSelectProps, F as FieldComponent, v as FieldProps, w as FieldsComponent, y as Fragment, I as ImageComponent, G as ImageProps, J as JSX, L as LinkButtonComponent, M as LinkButtonProps, P as ModalComponent, S as ModalProps, T as RadioSelectComponent, W as SectionComponent, Y as SelectComponent, _ as SelectOptionComponent, a0 as SelectOptionProps, a2 as SelectProps, a5 as TableComponent, a8 as TableProps, a9 as TextComponent, ab as TextInputComponent, ae as TextInputProps, af as TextProps, al as isCardLinkProps, am as isJSX, ao as jsx, ap as jsxDEV, aq as jsxs, ar as toCardElement, as as toModalElement } from './jsx-runtime-CnDs8rPr.js';
package/docs/adapters.mdx CHANGED
@@ -23,7 +23,7 @@ Ready to build your own? Follow the [building](/docs/contributing/building) guid
23
23
  | Edit message | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Warn /> Partial | <Cross /> | <Cross /> |
24
24
  | Delete message | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Warn /> Partial | <Cross /> | <Cross /> |
25
25
  | File uploads | <Check /> | <Check /> | <Cross /> | <Check /> | <Warn /> Single file/media | <Cross /> | <Cross /> | <Check /> Images, audio, docs | <Cross /> |
26
- | 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
+ | Streaming | <Check /> Native | <Warn /> Native (DMs) / Buffered | <Warn /> Post+Edit | <Warn /> Post+Edit | <Warn /> Private chat drafts / Post+Edit | <Warn /> Buffered | <Warn /> Agent sessions / Post+Edit | <Warn /> Buffered | <Warn /> Buffered |
27
27
  | Scheduled messages | <Check /> Native | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> |
28
28
 
29
29
  ### Rich content
@@ -47,7 +47,7 @@ Ready to build your own? Follow the [building](/docs/contributing/building) guid
47
47
  | Mentions | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Cross /> | <Check /> |
48
48
  | Add reactions | <Check /> | <Cross /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Cross /> |
49
49
  | Remove reactions | <Check /> | <Cross /> | <Check /> | <Check /> | <Check /> | <Warn /> | <Warn /> | <Check /> | <Cross /> |
50
- | Typing indicator | <Check /> | <Check /> | <Cross /> | <Check /> | <Check /> | <Cross /> | <Warn /> Agent sessions | <Cross /> | <Check /> |
50
+ | Typing indicator | <Check /> | <Check /> | <Cross /> | <Check /> | <Check /> | <Cross /> | <Warn /> Agent sessions | <Warn /> | <Check /> |
51
51
  | DMs | <Check /> | <Check /> | <Check /> | <Check /> | <Check /> | <Cross /> | <Cross /> | <Check /> | <Check /> |
52
52
  | Ephemeral messages | <Check /> Native | <Cross /> | <Check /> Native | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> | <Cross /> |
53
53
  | User lookup ([`getUser`](/docs/api/chat#getuser)) | <Check /> | <Warn /> Cached | <Warn /> Cached | <Check /> | <Warn /> Seen users | <Check /> | <Check /> | <Cross /> | <Cross /> |
package/docs/ai/index.mdx CHANGED
@@ -61,3 +61,9 @@ bot.onSubscribedMessage(async (thread) => {
61
61
  - import { toAiMessages } from "chat";
62
62
  + import { toAiMessages } from "chat/ai";
63
63
  ```
64
+
65
+ ## Resources
66
+
67
+ - [Human-in-the-Loop with Chat SDK and Workflow SDK](https://vercel.com/kb/guide/human-in-the-loop-with-chat-sdk-and-workflow-sdk) — Pause durable workflows on Slack approval cards using Chat SDK and Workflow SDK. Uses `createWebhook` to suspend workflows until a button click, with patterns for multi-stage approvals, timeouts via durable sleep, and approver validation.
68
+
69
+ See all guides and templates on the [resources](/resources) page.
@@ -25,4 +25,8 @@ Connect your bot to chat platforms and persist state across restarts.
25
25
 
26
26
  Browse all official and community adapters on the [Adapters](/adapters) page.
27
27
 
28
- Step-by-step guides and starter templates are available on the [Resources](/resources) page.
28
+ ## Resources
29
+
30
+ - [The Complete Guide to Chat SDK](https://vercel.com/kb/guide/the-complete-guide-to-chat-sdk) — End-to-end walkthrough that takes you from zero to a deployed multi-platform bot, covering adapters, state, handlers, cards, and streaming.
31
+
32
+ See all guides and templates on the [resources](/resources) page.
package/docs/index.mdx CHANGED
@@ -55,10 +55,11 @@ Each adapter factory auto-detects credentials from environment variables (`SLACK
55
55
  | Microsoft Teams | `@chat-adapter/teams` | Yes | Read-only | Yes | Yes | Native (DMs) / Buffered | Yes |
56
56
  | Google Chat | `@chat-adapter/gchat` | Yes | Yes | Yes | No | Post+Edit | Yes |
57
57
  | Discord | `@chat-adapter/discord` | Yes | Yes | Yes | No | Post+Edit | Yes |
58
- | Telegram | `@chat-adapter/telegram` | Yes | Yes | Partial | No | Post+Edit | Yes |
58
+ | Telegram | `@chat-adapter/telegram` | Yes | Yes | Partial | No | Private chat drafts / Post+Edit | Yes |
59
59
  | GitHub | `@chat-adapter/github` | Yes | Yes | No | No | Buffered | No |
60
60
  | Linear | `@chat-adapter/linear` | Yes | Yes | No | No | Agent sessions / Post+Edit | No |
61
61
  | WhatsApp | `@chat-adapter/whatsapp` | N/A | Yes | Partial | No | Buffered | Yes |
62
+ | Twilio | `@chat-adapter/twilio` | N/A | No | Fallback | No | Buffered | Yes |
62
63
  | Messenger | `@chat-adapter/messenger` | Yes | Receive-only | Partial | No | Buffered | Yes |
63
64
 
64
65
  ## AI coding agent support
@@ -87,6 +88,7 @@ The SDK is distributed as a set of packages you install based on your needs:
87
88
  | `@chat-adapter/github` | GitHub Issues adapter |
88
89
  | `@chat-adapter/linear` | Linear Issues adapter |
89
90
  | `@chat-adapter/whatsapp` | WhatsApp Business adapter |
91
+ | `@chat-adapter/twilio` | Twilio SMS and MMS adapter |
90
92
  | `@chat-adapter/messenger` | Facebook Messenger adapter |
91
93
  | `@chat-adapter/state-redis` | Redis state adapter (production) |
92
94
  | `@chat-adapter/state-ioredis` | ioredis state adapter (alternative) |
package/docs/meta.json CHANGED
@@ -14,6 +14,7 @@
14
14
  "...ai",
15
15
  "---Adapters---",
16
16
  "adapters",
17
+ "slack-primitives",
17
18
  "state",
18
19
  "---Messaging---",
19
20
  "streaming",
@@ -0,0 +1,320 @@
1
+ ---
2
+ title: Slack Low-Level APIs
3
+ description: Use Slack request verification, formatting, Web API, and Block Kit helpers without the full Chat runtime.
4
+ type: guide
5
+ prerequisites:
6
+ - /adapters/official/slack
7
+ related:
8
+ - /docs/handling-events
9
+ - /docs/cards
10
+ - /docs/slash-commands
11
+ ---
12
+
13
+ The Slack adapter is the right default for most bots. It verifies requests, resolves tokens, parses Slack payloads, stores thread state, and routes events through `Chat`.
14
+
15
+ Use the low-level Slack subpaths when your app already owns routing, state, sessions, or workflow execution and only needs the Slack-specific primitives.
16
+
17
+ | Subpath | Use for |
18
+ |---------|---------|
19
+ | `@chat-adapter/slack/webhook` | Request verification, body parsing, Events API payloads, slash commands, interactions, and continuation data |
20
+ | `@chat-adapter/slack/format` | Slack mrkdwn tokens, text objects, dates, links, mentions, and simple mrkdwn to Markdown conversion |
21
+ | `@chat-adapter/slack/api` | Fetch-based Slack Web API calls, thread replies, views, and files without `@slack/web-api` |
22
+ | `@chat-adapter/slack/blocks` | Runtime-free conversion from simple card objects and input requests to Slack Block Kit |
23
+
24
+ <Callout type="info">
25
+ These subpaths are for custom runtimes. If you want Chat SDK to handle webhook routing, state, subscriptions, and platform normalization, use `createSlackAdapter` from `@chat-adapter/slack`.
26
+ </Callout>
27
+
28
+ ## Webhooks
29
+
30
+ [Slack signs incoming HTTP requests](https://docs.slack.dev/authentication/verifying-requests-from-slack/) with `x-slack-signature` and `x-slack-request-timestamp`. `verifySlackRequest` reads the request body, verifies the signature with your signing secret, and returns the raw body so you can parse it once.
31
+
32
+ ```typescript title="app/api/slack/route.ts" lineNumbers
33
+ import {
34
+ parseSlackWebhookBody,
35
+ verifySlackRequest,
36
+ } from "@chat-adapter/slack/webhook";
37
+ import { postSlackMessage } from "@chat-adapter/slack/api";
38
+
39
+ export async function POST(request: Request) {
40
+ const body = await verifySlackRequest(request, {
41
+ signingSecret: process.env.SLACK_SIGNING_SECRET!,
42
+ });
43
+
44
+ const payload = parseSlackWebhookBody(body, {
45
+ contentType: request.headers.get("content-type"),
46
+ headers: request.headers,
47
+ });
48
+
49
+ if (payload.kind === "url_verification") {
50
+ return Response.json({ challenge: payload.challenge });
51
+ }
52
+
53
+ if (payload.kind === "app_mention") {
54
+ await postSlackMessage({
55
+ channel: payload.continuation.channelId,
56
+ markdownText: `received: ${payload.text}`,
57
+ threadTs: payload.continuation.threadTs,
58
+ token: process.env.SLACK_BOT_TOKEN!,
59
+ });
60
+ }
61
+
62
+ return new Response(null, { status: 200 });
63
+ }
64
+ ```
65
+
66
+ [Slack slash commands](https://docs.slack.dev/interactivity/implementing-slash-commands/) and interactions should be acknowledged quickly. Slack documents a 3000 ms acknowledgement window for slash commands, so do slow work in your queue or workflow runtime after returning a 2xx response.
67
+
68
+ If you do not need direct access to the verified raw body, `readSlackWebhook` combines verification and parsing:
69
+
70
+ ```typescript
71
+ import { readSlackWebhook } from "@chat-adapter/slack/webhook";
72
+
73
+ const payload = await readSlackWebhook(request, {
74
+ signingSecret: process.env.SLACK_SIGNING_SECRET!,
75
+ });
76
+ ```
77
+
78
+ If your framework already buffered the request body, use `verifySlackSignature` with the raw body and headers, then pass that same body to `parseSlackWebhookBody`.
79
+
80
+ ### Payloads
81
+
82
+ `parseSlackWebhookBody` returns typed payloads:
83
+
84
+ | Kind | Slack surface |
85
+ |------|---------------|
86
+ | `url_verification` | Events API URL verification |
87
+ | `app_mention` | App mention events |
88
+ | `direct_message` | Direct message events |
89
+ | `slash_command` | Slash command form posts |
90
+ | `block_actions` | Button, select, and Block Kit action payloads |
91
+ | `block_suggestion` | External select suggestion payloads |
92
+ | `view_submission` | Modal submissions |
93
+ | `view_closed` | Modal close events |
94
+ | `unsupported` | Valid Slack payloads not normalized by this helper yet |
95
+
96
+ Message-like payloads include `continuation`, which contains provider-native reply context:
97
+
98
+ ```typescript
99
+ type SlackContinuation = {
100
+ channelId: string;
101
+ enterpriseId?: string;
102
+ teamId?: string;
103
+ threadTs: string;
104
+ };
105
+ ```
106
+
107
+ This is not a Chat SDK `Thread`. It is the durable Slack data you need to reply later with `@chat-adapter/slack/api`.
108
+
109
+ App mention and direct message payloads also include typed `files` parsed from Slack file objects. Each file keeps the raw Slack object plus common fields like `id`, `name`, `mimeType`, `size`, `url`, and `downloadUrl`.
110
+
111
+ Interaction payloads expose convenience fields from Slack's raw payload:
112
+
113
+ - `block_actions` includes `actions`, `messageBlocks`, `messagePromptBlock`, `messagePromptText`, `messageTs`, `triggerId`, `responseUrl`, `user`, and `continuation`
114
+ - `view_submission` includes `callbackId`, `privateMetadata`, `values`, `responseUrls`, and `user`
115
+
116
+ ## Formatting
117
+
118
+ Slack uses mrkdwn and special tokens for mentions, channels, dates, and links. The format subpath gives you small helpers for those strings.
119
+
120
+ The helper surface includes `escapeSlackText`, `unescapeSlackText`, `createSlackPlainText`, `createSlackMrkdwn`, `formatSlackUser`, `formatSlackChannel`, `formatSlackUserGroup`, `formatSlackSpecialMention`, `formatSlackLink`, `formatSlackDate`, and simple mrkdwn to Markdown normalization.
121
+
122
+ ```typescript title="format.ts" lineNumbers
123
+ import {
124
+ createSlackMrkdwn,
125
+ formatSlackDate,
126
+ formatSlackLink,
127
+ formatSlackUser,
128
+ slackMrkdwnToMarkdown,
129
+ } from "@chat-adapter/slack/format";
130
+
131
+ const text = createSlackMrkdwn(
132
+ `${formatSlackUser("U123")} approved ${formatSlackLink("https://example.com", "the deploy")}`
133
+ );
134
+
135
+ const when = formatSlackDate(
136
+ new Date("2026-05-27T12:00:00Z"),
137
+ "{date_short_pretty} at {time}",
138
+ "May 27 at 12:00"
139
+ );
140
+
141
+ const markdown = slackMrkdwnToMarkdown("hello <@U123|jane>, see <https://example.com|this>");
142
+ ```
143
+
144
+ `linkBareSlackMentions` only links Slack user IDs like `@U123`. It does not resolve display names, because Slack mentions are ID-based.
145
+
146
+ ## Web API
147
+
148
+ The API subpath calls [Slack Web API](https://docs.slack.dev/apis/web-api/) methods with `fetch`. It does not import `@slack/web-api`.
149
+
150
+ ```typescript title="slack.ts" lineNumbers
151
+ import {
152
+ postSlackMessage,
153
+ sendSlackResponseUrl,
154
+ updateSlackMessage,
155
+ } from "@chat-adapter/slack/api";
156
+
157
+ const posted = await postSlackMessage({
158
+ channel: "C123",
159
+ markdownText: "**hello**",
160
+ token: process.env.SLACK_BOT_TOKEN!,
161
+ });
162
+
163
+ await updateSlackMessage({
164
+ channel: "C123",
165
+ text: "updated",
166
+ token: process.env.SLACK_BOT_TOKEN!,
167
+ ts: posted.id,
168
+ });
169
+
170
+ await sendSlackResponseUrl("https://hooks.slack.com/actions/T/1/abc", {
171
+ replaceOriginal: true,
172
+ text: "done",
173
+ });
174
+ ```
175
+
176
+ Use `callSlackApi` when you need a Slack method that does not have a helper yet:
177
+
178
+ ```typescript
179
+ import { callSlackApi } from "@chat-adapter/slack/api";
180
+
181
+ const result = await callSlackApi(
182
+ "reactions.add",
183
+ { channel: "C123", name: "white_check_mark", timestamp: "1710000000.000001" },
184
+ { token: process.env.SLACK_BOT_TOKEN! }
185
+ );
186
+ ```
187
+
188
+ `markdownText` maps to the `markdown_text` field on [`chat.postMessage`](https://docs.slack.dev/reference/methods/chat.postMessage/) and cannot be combined with `text` or `blocks`. Use `text` with `blocks` when you need fallback text.
189
+
190
+ The subpath also includes `postSlackEphemeral`, `deleteSlackMessage`, `resolveSlackBotToken`, `encodeSlackApiBody`, and `assertSlackOk`.
191
+
192
+ Use `fetchSlackThreadReplies` when a custom runtime needs to refresh a thread with [`conversations.replies`](https://docs.slack.dev/reference/methods/conversations.replies/):
193
+
194
+ ```typescript
195
+ import { fetchSlackThreadReplies } from "@chat-adapter/slack/api";
196
+
197
+ const replies = await fetchSlackThreadReplies({
198
+ channel: payload.continuation.channelId,
199
+ limit: 50,
200
+ token: process.env.SLACK_BOT_TOKEN!,
201
+ ts: payload.continuation.threadTs,
202
+ });
203
+ ```
204
+
205
+ Use `openSlackView` to open a modal from an interaction `trigger_id`:
206
+
207
+ ```typescript
208
+ import { openSlackView } from "@chat-adapter/slack/api";
209
+
210
+ await openSlackView({
211
+ token: process.env.SLACK_BOT_TOKEN!,
212
+ triggerId: payload.triggerId,
213
+ view: {
214
+ type: "modal",
215
+ title: { type: "plain_text", text: "Answer" },
216
+ blocks: [],
217
+ },
218
+ });
219
+ ```
220
+
221
+ ### Files
222
+
223
+ [Slack's current external upload flow](https://docs.slack.dev/changelog/2024-04-a-better-way-to-upload-files-is-here-to-stay) uses `files.getUploadURLExternal`, then uploads bytes to the returned URL, then calls `files.completeUploadExternal`.
224
+
225
+ ```typescript
226
+ import { uploadSlackFiles } from "@chat-adapter/slack/api";
227
+
228
+ await uploadSlackFiles(
229
+ [{ data: new Uint8Array([1, 2, 3]), filename: "report.txt" }],
230
+ {
231
+ channelId: "C123",
232
+ initialComment: "report attached",
233
+ token: process.env.SLACK_BOT_TOKEN!,
234
+ }
235
+ );
236
+ ```
237
+
238
+ Use `fetchSlackFile` for private Slack file URLs that require bearer token authorization.
239
+
240
+ ## Blocks
241
+
242
+ The blocks subpath converts simple card objects into Slack Block Kit without importing the full `chat` JSX runtime.
243
+
244
+ It exports `cardToSlackBlocks`, `cardToBlockKit`, `cardToSlackFallbackText`, `cardToFallbackText`, and `convertSlackEmojiPlaceholders`.
245
+
246
+ ```typescript title="blocks.ts" lineNumbers
247
+ import {
248
+ cardToSlackBlocks,
249
+ cardToSlackFallbackText,
250
+ } from "@chat-adapter/slack/blocks";
251
+ import { postSlackMessage } from "@chat-adapter/slack/api";
252
+
253
+ const card = {
254
+ children: [
255
+ { content: "deploy v2.4.1?", type: "text" },
256
+ {
257
+ children: [
258
+ { id: "approve", label: "Approve", style: "primary", type: "button" },
259
+ { id: "deny", label: "Deny", style: "danger", type: "button" },
260
+ ],
261
+ type: "actions",
262
+ },
263
+ ],
264
+ title: "Deployment",
265
+ type: "card",
266
+ } as const;
267
+
268
+ await postSlackMessage({
269
+ blocks: cardToSlackBlocks(card),
270
+ channel: "C123",
271
+ text: cardToSlackFallbackText(card),
272
+ token: process.env.SLACK_BOT_TOKEN!,
273
+ });
274
+ ```
275
+
276
+ Use the full Chat SDK card JSX when you want cross-platform rendering. Use `@chat-adapter/slack/blocks` when you are building a Slack-only runtime and want Block Kit output directly.
277
+
278
+ The blocks subpath also includes small input request helpers for Slack-only runtimes:
279
+
280
+ ```typescript
281
+ import {
282
+ inputRequestToSlackBlocks,
283
+ parseSlackInputResponse,
284
+ } from "@chat-adapter/slack/blocks";
285
+ import { postSlackMessage } from "@chat-adapter/slack/api";
286
+
287
+ await postSlackMessage({
288
+ blocks: inputRequestToSlackBlocks({
289
+ options: [
290
+ { id: "approve", label: "Approve", style: "primary" },
291
+ { id: "deny", label: "Deny", style: "danger" },
292
+ ],
293
+ prompt: "Approve deploy?",
294
+ requestId: "deploy-1",
295
+ }),
296
+ channel: "C123",
297
+ text: "Approve deploy?",
298
+ token: process.env.SLACK_BOT_TOKEN!,
299
+ });
300
+
301
+ if (payload.kind === "block_actions") {
302
+ const action = payload.actions[0];
303
+ const response = action ? parseSlackInputResponse(action) : null;
304
+ }
305
+ ```
306
+
307
+ Set `display: "radio"` for radio buttons, or `display: "select"` for a static select menu. Set `allowFreeform: true` to add a "Type your answer" button next to the provided options.
308
+
309
+ For freeform answers, use `buildSlackFreeformView` with `openSlackView`, then read the submitted value from `payload.values` with `parseSlackFreeformValue`.
310
+
311
+ ## Import boundaries
312
+
313
+ The low-level Slack subpaths are designed to avoid the full runtime import graph:
314
+
315
+ - no `chat` import
316
+ - no `@chat-adapter/shared` import
317
+ - no `@slack/web-api` import
318
+ - no `@slack/socket-mode` import
319
+
320
+ The package still installs the full Slack adapter dependencies. The subpaths keep your source and bundle imports clean, but they are not a package-size split.
@@ -59,10 +59,10 @@ await thread.post(stream);
59
59
  | Platform | Method | Description |
60
60
  |----------|--------|-------------|
61
61
  | Slack | Native streaming API | Uses Slack's `chatStream` for smooth, real-time updates |
62
+ | Telegram | Private chat draft previews | Uses Telegram's `sendMessageDraft` in private chats and falls back to post + edit elsewhere |
62
63
  | Teams | Native (DMs) / Buffered (group chats) | Uses the Teams SDK's native `stream.emit()` for direct messages; accumulates chunks and posts one final message when no native streamer is active |
63
64
  | Google Chat | Post + Edit | Posts a message then edits it as chunks arrive |
64
65
  | Discord | Post + Edit | Posts a message then edits it as chunks arrive |
65
- | Telegram | Post + Edit | Posts a message then edits it as chunks arrive |
66
66
  | GitHub | Buffered | Accumulates chunks and posts one final comment |
67
67
  | Linear | Agent sessions / Post + Edit | Uses agent session activities in agent-session threads; falls back to post+edit comments in issue threads |
68
68
  | WhatsApp | Buffered | Accumulates chunks and sends one final message |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chat",
3
- "version": "4.29.0",
3
+ "version": "4.30.0",
4
4
  "description": "Unified chat abstraction for Slack, Teams, Google Chat, and Discord",
5
5
  "type": "module",
6
6
  "engines": {
@@ -39,7 +39,7 @@ Create a new Nuxt app and add the Chat SDK, AI SDK, and adapter packages:
39
39
 
40
40
  `npx nuxi@latest init my-discord-bot cd my-discord-bot pnpm add chat @chat-adapter/discord @chat-adapter/state-redis ai @ai-sdk/anthropic`
41
41
 
42
- The `chat` package is the Chat SDK core. The `@chat-adapter/discord` and `@chat-adapter/state-redis` packages are the [Discord platform adapter](https://chat-sdk.dev/adapters/discord) and [Redis state adapter](https://chat-sdk.dev/adapters/redis). The `ai` and `@ai-sdk/anthropic` packages are used to generate responses with Claude.
42
+ The `chat` package is the Chat SDK core. The `@chat-adapter/discord` and `@chat-adapter/state-redis` packages are the [Discord platform adapter](https://chat-sdk.dev/adapters/official/discord) and [Redis state adapter](https://chat-sdk.dev/adapters/official/redis). The `ai` and `@ai-sdk/anthropic` packages are used to generate responses with Claude.
43
43
 
44
44
  ### 2\. Create a Discord app
45
45
 
@@ -175,6 +175,10 @@ The listener runs for a fixed duration (10 minutes in this guide) and must be re
175
175
 
176
176
  Verify that `REDIS_URL` is reachable from your deployment environment. The state adapter uses Redis for distributed locking, so the bot won't process messages without a working connection.
177
177
 
178
+ * * *
179
+
180
+ ## Build with a template or read more.
181
+
178
182
  ---
179
183
 
180
184
  [View full KB sitemap](/kb/sitemap.md)