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.
Files changed (50) hide show
  1. package/dist/{chunk-OPV5U4WG.js → chunk-V25FKIIL.js} +44 -1
  2. package/dist/index.d.ts +485 -33
  3. package/dist/index.js +862 -135
  4. package/dist/{jsx-runtime-DxATbnrP.d.ts → jsx-runtime-DxGwoLu2.d.ts} +49 -5
  5. package/dist/jsx-runtime.d.ts +1 -1
  6. package/dist/jsx-runtime.js +1 -1
  7. package/docs/actions.mdx +52 -1
  8. package/docs/adapters.mdx +43 -37
  9. package/docs/api/cards.mdx +4 -0
  10. package/docs/api/chat.mdx +172 -6
  11. package/docs/api/index.mdx +2 -0
  12. package/docs/api/markdown.mdx +28 -5
  13. package/docs/api/message.mdx +58 -1
  14. package/docs/api/meta.json +2 -0
  15. package/docs/api/modals.mdx +50 -0
  16. package/docs/api/postable-message.mdx +55 -1
  17. package/docs/api/thread.mdx +33 -3
  18. package/docs/api/transcripts.mdx +220 -0
  19. package/docs/cards.mdx +6 -0
  20. package/docs/concurrency.mdx +4 -0
  21. package/docs/contributing/building.mdx +73 -1
  22. package/docs/contributing/publishing.mdx +33 -0
  23. package/docs/conversation-history.mdx +137 -0
  24. package/docs/direct-messages.mdx +13 -4
  25. package/docs/ephemeral-messages.mdx +1 -1
  26. package/docs/error-handling.mdx +15 -3
  27. package/docs/files.mdx +2 -1
  28. package/docs/getting-started.mdx +1 -11
  29. package/docs/index.mdx +7 -5
  30. package/docs/meta.json +14 -5
  31. package/docs/modals.mdx +97 -1
  32. package/docs/posting-messages.mdx +7 -3
  33. package/docs/streaming.mdx +74 -18
  34. package/docs/subject.mdx +53 -0
  35. package/docs/threads-messages-channels.mdx +43 -0
  36. package/docs/usage.mdx +11 -2
  37. package/package.json +3 -2
  38. package/resources/guides/create-a-discord-support-bot-with-nuxt-and-redis.md +180 -0
  39. package/resources/guides/how-to-build-a-slack-bot-with-next-js-and-redis.md +134 -0
  40. package/resources/guides/how-to-build-an-ai-agent-for-slack-with-chat-sdk-and-ai-sdk.md +220 -0
  41. package/resources/guides/run-and-track-deploys-from-slack.md +270 -0
  42. package/resources/guides/ship-a-github-code-review-bot-with-hono-and-redis.md +147 -0
  43. package/resources/guides/triage-form-submissions-with-chat-sdk.md +178 -0
  44. package/resources/templates.json +19 -0
  45. package/docs/guides/code-review-hono.mdx +0 -241
  46. package/docs/guides/discord-nuxt.mdx +0 -227
  47. package/docs/guides/durable-chat-sessions-nextjs.mdx +0 -337
  48. package/docs/guides/meta.json +0 -10
  49. package/docs/guides/scheduled-posts-neon.mdx +0 -447
  50. package/docs/guides/slack-nextjs.mdx +0 -234
package/dist/index.d.ts CHANGED
@@ -1,27 +1,30 @@
1
1
  import { WORKFLOW_SERIALIZE, WORKFLOW_DESERIALIZE } from '@workflow/serde';
2
2
  import { Root, List, Content, Blockquote, Code, Emphasis, InlineCode, Delete, Link, ListItem, Paragraph, Strong, TableCell, Table as Table$1, TableRow, Text } from 'mdast';
3
- export { Blockquote, Code, Content, Delete, Emphasis, InlineCode, Link, List, ListItem, Table as MdastTable, Paragraph, Root, Strong, TableCell, TableRow, Text } from 'mdast';
4
- import { C as ChatElement, a as CardElement, M as ModalElement, b as CardChild, A as ActionsComponent, B as ButtonComponent, c as CardComponent, d as cardChildToFallbackText$1, e as CardLinkComponent, T as TextComponent, D as DividerComponent, F as FieldComponent, f as FieldsComponent, g as fromReactElement$1, I as ImageComponent, i as isCardElement$1, h as isJSX$1, L as LinkButtonComponent, S as SectionComponent, j as Table$2, t as toCardElement$1, k as toModalElement$1, l as fromReactModalElement$1, m as isModalElement$1, n as ModalComponent, R as RadioSelectComponent, o as SelectComponent, p as SelectOptionComponent, q as TextInputComponent } from './jsx-runtime-DxATbnrP.js';
5
- export { r as ActionsElement, s as ButtonElement, u as ButtonOptions, V as ButtonProps, v as ButtonStyle, W as CardJSXElement, X as CardJSXProps, Y as CardLinkProps, w as CardOptions, Z as CardProps, _ as ContainerProps, x as DividerElement, $ as DividerProps, y as FieldElement, a0 as FieldProps, z as FieldsElement, E as ImageElement, a1 as ImageProps, G as LinkButtonElement, H as LinkButtonOptions, a2 as LinkButtonProps, J as LinkElement, a8 as ModalChild, a9 as ModalOptions, a3 as ModalProps, aa as RadioSelectElement, ab as RadioSelectOptions, K as SectionElement, ac as SelectElement, ad as SelectOptionElement, a4 as SelectOptionProps, ae as SelectOptions, a5 as SelectProps, N as TableAlignment, O as TableElement, P as TableOptions, Q as TextElement, af as TextInputElement, ag as TextInputOptions, a6 as TextInputProps, a7 as TextProps, U as TextStyle } from './jsx-runtime-DxATbnrP.js';
3
+ export { Blockquote, Code, Content, Delete, Emphasis, InlineCode, Link, List, ListItem, Table as MdastTable, Nodes, Paragraph, Root, Strong, TableCell, TableRow, Text } from 'mdast';
4
+ import { C as ChatElement, a as CardElement, M as ModalElement, S as SelectOptionElement, b as CardChild, A as ActionsComponent, B as ButtonComponent, c as CardComponent, d as cardChildToFallbackText$1, e as CardLinkComponent, T as TextComponent, D as DividerComponent, F as FieldComponent, f as FieldsComponent, g as fromReactElement$1, I as ImageComponent, i as isCardElement$1, h as isJSX$1, L as LinkButtonComponent, j as SectionComponent, k as Table$2, t as toCardElement$1, l as toModalElement$1, m as fromReactModalElement$1, n as isModalElement$1, E as ExternalSelectComponent, o as ModalComponent, R as RadioSelectComponent, p as SelectComponent, q as SelectOptionComponent, r as TextInputComponent } from './jsx-runtime-DxGwoLu2.js';
5
+ export { s as ActionsElement, u as ButtonElement, v as ButtonOptions, X as ButtonProps, w as ButtonStyle, Y as CardJSXElement, Z as CardJSXProps, _ as CardLinkProps, x as CardOptions, $ as CardProps, a0 as ContainerProps, y as DividerElement, a1 as DividerProps, ab as ExternalSelectElement, ac as ExternalSelectOptions, a2 as ExternalSelectProps, z as FieldElement, a3 as FieldProps, G as FieldsElement, H as ImageElement, a4 as ImageProps, J as LinkButtonElement, K as LinkButtonOptions, a5 as LinkButtonProps, N as LinkElement, ad as ModalChild, ae as ModalOptions, a6 as ModalProps, af as RadioSelectElement, ag as RadioSelectOptions, O as SectionElement, ah as SelectElement, a7 as SelectOptionProps, ai as SelectOptions, a8 as SelectProps, P as TableAlignment, Q as TableElement, U as TableOptions, V as TextElement, aj as TextInputElement, ak as TextInputOptions, a9 as TextInputProps, aa as TextProps, W as TextStyle } from './jsx-runtime-DxGwoLu2.js';
6
6
 
7
- interface MessageHistoryConfig {
7
+ interface ThreadHistoryConfig {
8
8
  /** Maximum messages to keep per thread (default: 100) */
9
9
  maxMessages?: number;
10
10
  /** TTL for cached history in milliseconds (default: 7 days) */
11
11
  ttlMs?: number;
12
12
  }
13
13
  /**
14
- * Persistent message history cache backed by the StateAdapter.
14
+ * Persistent per-thread history cache backed by the StateAdapter.
15
15
  *
16
- * Used by adapters that lack server-side message history APIs (e.g., WhatsApp, Telegram).
17
- * Messages are atomically appended via `state.appendToList()`, which is safe
18
- * without holding a thread lock.
16
+ * Used by adapters that lack server-side message history APIs (e.g. WhatsApp,
17
+ * Telegram). Messages are atomically appended via `state.appendToList()`,
18
+ * which is safe without holding a thread lock.
19
+ *
20
+ * Distinct from the cross-platform per-user {@link TranscriptsApi} (see
21
+ * `transcripts.ts`) — this cache is keyed by thread, not user.
19
22
  */
20
- declare class MessageHistoryCache {
23
+ declare class ThreadHistoryCache {
21
24
  private readonly state;
22
25
  private readonly maxMessages;
23
26
  private readonly ttlMs;
24
- constructor(state: StateAdapter, config?: MessageHistoryConfig);
27
+ constructor(state: StateAdapter, config?: ThreadHistoryConfig);
25
28
  /**
26
29
  * Atomically append a message to the history for a thread.
27
30
  * Trims to maxMessages (keeps newest) and refreshes TTL.
@@ -54,8 +57,8 @@ interface ChannelImplConfigWithAdapter {
54
57
  channelVisibility?: ChannelVisibility;
55
58
  id: string;
56
59
  isDM?: boolean;
57
- messageHistory?: MessageHistoryCache;
58
60
  stateAdapter: StateAdapter;
61
+ threadHistory?: ThreadHistoryCache;
59
62
  }
60
63
  /**
61
64
  * Config for creating a ChannelImpl with lazy adapter resolution.
@@ -75,7 +78,7 @@ declare class ChannelImpl<TState = Record<string, unknown>> implements Channel<T
75
78
  private readonly _adapterName?;
76
79
  private _stateAdapterInstance?;
77
80
  private _name;
78
- private readonly _messageHistory?;
81
+ private readonly _threadHistory?;
79
82
  constructor(config: ChannelImplConfig);
80
83
  get adapter(): Adapter;
81
84
  private get _stateAdapter();
@@ -103,6 +106,7 @@ declare class ChannelImpl<TState = Record<string, unknown>> implements Channel<T
103
106
  schedule(message: AdapterPostableMessage | ChatElement, options: {
104
107
  postAt: Date;
105
108
  }): Promise<ScheduledMessage>;
109
+ private processCallbackUrls;
106
110
  startTyping(status?: string): Promise<void>;
107
111
  mentionUser(userId: string): string;
108
112
  toJSON(): SerializedChannel;
@@ -206,9 +210,9 @@ interface ThreadImplConfigWithAdapter {
206
210
  isDM?: boolean;
207
211
  isSubscribedContext?: boolean;
208
212
  logger?: Logger;
209
- messageHistory?: MessageHistoryCache;
210
213
  stateAdapter: StateAdapter;
211
214
  streamingUpdateIntervalMs?: number;
215
+ threadHistory?: ThreadHistoryCache;
212
216
  }
213
217
  /**
214
218
  * Config for creating a ThreadImpl with lazy adapter resolution.
@@ -249,8 +253,8 @@ declare class ThreadImpl<TState = Record<string, unknown>> implements Thread<TSt
249
253
  private readonly _fallbackStreamingPlaceholderText;
250
254
  /** Cached channel instance */
251
255
  private _channel?;
252
- /** Message history cache (set only for adapters with persistMessageHistory) */
253
- private readonly _messageHistory?;
256
+ /** Thread history cache (set only for adapters with persistThreadHistory) */
257
+ private readonly _threadHistory?;
254
258
  private readonly _logger?;
255
259
  constructor(config: ThreadImplConfig);
256
260
  /**
@@ -288,6 +292,7 @@ declare class ThreadImpl<TState = Record<string, unknown>> implements Thread<TSt
288
292
  */
289
293
  get messages(): AsyncIterable<Message>;
290
294
  get allMessages(): AsyncIterable<Message>;
295
+ getParticipants(): Promise<Author[]>;
291
296
  isSubscribed(): Promise<boolean>;
292
297
  subscribe(): Promise<void>;
293
298
  unsubscribe(): Promise<void>;
@@ -295,15 +300,23 @@ declare class ThreadImpl<TState = Record<string, unknown>> implements Thread<TSt
295
300
  post(message: string | AdapterPostableMessage | AsyncIterable<string> | ChatElement): Promise<SentMessage>;
296
301
  private handlePostableObject;
297
302
  postEphemeral(user: string | Author, message: AdapterPostableMessage | ChatElement, options: PostEphemeralOptions): Promise<EphemeralMessage | null>;
303
+ private processCallbackUrls;
298
304
  schedule(message: AdapterPostableMessage | ChatElement, options: {
299
305
  postAt: Date;
300
306
  }): Promise<ScheduledMessage>;
301
307
  /**
302
308
  * Handle streaming from an AsyncIterable.
303
309
  * Normalizes the stream (supports both textStream and fullStream from AI SDK),
304
- * then uses adapter's native streaming if available, otherwise falls back to post+edit.
310
+ * then uses the adapter's stream implementation if available, otherwise falls back to post+edit.
305
311
  */
306
312
  private handleStream;
313
+ /**
314
+ * Slack payloads carry the workspace ID in a few different shapes depending on
315
+ * the webhook type:
316
+ * - Message events: `team_id` or `team` as a string
317
+ * - `block_actions` payloads: `team.id` (object), with `user.team_id` as a fallback
318
+ */
319
+ private extractSlackRecipientTeamId;
307
320
  startTyping(status?: string): Promise<void>;
308
321
  /**
309
322
  * Fallback streaming implementation using post + edit.
@@ -410,6 +423,8 @@ interface AddTaskOptions {
410
423
  title: PlanContent;
411
424
  }
412
425
  type UpdateTaskInput = PlanContent | {
426
+ /** Task ID to update. If omitted, updates the last in_progress task. */
427
+ id?: string;
413
428
  /** Task output/results. */
414
429
  output?: PlanContent;
415
430
  /** Optional status override. */
@@ -502,6 +517,14 @@ interface ChatConfig<TAdapters extends Record<string, Adapter> = Record<string,
502
517
  * wait until some real text has been streamed before creating the message.
503
518
  */
504
519
  fallbackStreamingPlaceholderText?: string | null;
520
+ /**
521
+ * Resolves a stable cross-platform user key from inbound messages.
522
+ *
523
+ * Required when `transcripts` is configured. Called once per inbound
524
+ * message during dispatch; the result is attached to the Message
525
+ * instance as `message.userKey` for handlers to use.
526
+ */
527
+ identity?: IdentityResolver;
505
528
  /**
506
529
  * Lock scope determines which messages contend for the same lock.
507
530
  *
@@ -519,13 +542,12 @@ interface ChatConfig<TAdapters extends Record<string, Adapter> = Record<string,
519
542
  */
520
543
  logger?: Logger | LogLevel;
521
544
  /**
522
- * Configuration for persistent message history.
523
- * Only used by adapters that set `persistMessageHistory: true`.
545
+ * @deprecated Renamed to {@link ChatConfig.threadHistory}. Both fields are
546
+ * read for backwards compatibility; `threadHistory` takes precedence when
547
+ * both are set.
524
548
  */
525
549
  messageHistory?: {
526
- /** Maximum messages to store per thread (default: 100) */
527
550
  maxMessages?: number;
528
- /** TTL for cached history in milliseconds (default: 7 days) */
529
551
  ttlMs?: number;
530
552
  };
531
553
  /**
@@ -549,6 +571,28 @@ interface ChatConfig<TAdapters extends Record<string, Adapter> = Record<string,
549
571
  * Defaults to 500ms. Lower values provide smoother updates but may hit rate limits.
550
572
  */
551
573
  streamingUpdateIntervalMs?: number;
574
+ /**
575
+ * Configuration for persistent per-thread message history backfill.
576
+ *
577
+ * Only used by adapters that set `persistThreadHistory: true` (e.g.
578
+ * Telegram, WhatsApp). Distinct from `transcripts` (the cross-platform
579
+ * per-user Transcripts API).
580
+ */
581
+ threadHistory?: {
582
+ /** Maximum messages to store per thread (default: 100) */
583
+ maxMessages?: number;
584
+ /** TTL for cached history in milliseconds (default: 7 days) */
585
+ ttlMs?: number;
586
+ };
587
+ /**
588
+ * Cross-platform per-user message persistence.
589
+ *
590
+ * When set, `chat.transcripts` is available for append/list/count/delete
591
+ * keyed by a resolved cross-platform user key.
592
+ *
593
+ * Requires `identity` to also be set; the constructor throws otherwise.
594
+ */
595
+ transcripts?: TranscriptsConfig;
552
596
  /** Default bot username across all adapters */
553
597
  userName: string;
554
598
  }
@@ -671,6 +715,7 @@ interface Adapter<TThreadId = unknown, TRawMessage = unknown> {
671
715
  * ```
672
716
  */
673
717
  fetchMessages(threadId: string, options?: FetchOptions): Promise<FetchResult<TRawMessage>>;
718
+ fetchSubject?(raw: TRawMessage): Promise<MessageSubject | null>;
674
719
  /** Fetch thread metadata */
675
720
  fetchThread(threadId: string): Promise<ThreadInfo>;
676
721
  /**
@@ -683,6 +728,14 @@ interface Adapter<TThreadId = unknown, TRawMessage = unknown> {
683
728
  * @returns The channel visibility scope
684
729
  */
685
730
  getChannelVisibility?(threadId: string): ChannelVisibility;
731
+ /**
732
+ * Look up user information by user ID.
733
+ * Optional — not all platforms support this.
734
+ *
735
+ * @param userId - Platform-specific user ID
736
+ * @returns User info, or null if user not found
737
+ */
738
+ getUser?(userId: string): Promise<UserInfo | null>;
686
739
  /** Handle incoming webhook request */
687
740
  handleWebhook(request: Request, options?: WebhookOptions): Promise<Response>;
688
741
  /** Called when Chat instance is created (internal use) */
@@ -741,10 +794,17 @@ interface Adapter<TThreadId = unknown, TRawMessage = unknown> {
741
794
  /** Parse platform message format to normalized format */
742
795
  parseMessage(raw: TRawMessage): Message<TRawMessage>;
743
796
  /**
744
- * When true, the SDK persists message history in the state adapter for this platform.
745
- * Use this for platforms that lack server-side message history APIs (e.g., WhatsApp, Telegram).
797
+ * @deprecated Renamed to {@link Adapter.persistThreadHistory}. Both flags
798
+ * are read for backwards compatibility; either being `true` enables
799
+ * persistence.
746
800
  */
747
801
  readonly persistMessageHistory?: boolean;
802
+ /**
803
+ * When true, the SDK persists per-thread message history in the state
804
+ * adapter for this platform. Use for platforms that lack server-side
805
+ * message history APIs (e.g. WhatsApp, Telegram).
806
+ */
807
+ readonly persistThreadHistory?: boolean;
748
808
  /**
749
809
  * Post a message to channel top-level (not in a thread).
750
810
  */
@@ -772,6 +832,12 @@ interface Adapter<TThreadId = unknown, TRawMessage = unknown> {
772
832
  * @param data - The object data (type depends on kind)
773
833
  */
774
834
  postObject?(threadId: string, kind: string, data: unknown): Promise<RawMessage<TRawMessage>>;
835
+ /**
836
+ * Reconstruct fetchData on an attachment after deserialization.
837
+ * Called during message rehydration for queue/debounce strategies.
838
+ * Uses fetchMetadata and adapter auth context to rebuild the download closure.
839
+ */
840
+ rehydrateAttachment?(attachment: Attachment): Attachment;
775
841
  /** Remove a reaction from a message */
776
842
  removeReaction(threadId: string, messageId: string, emoji: EmojiValue | string): Promise<void>;
777
843
  /** Render formatted content to platform-specific string */
@@ -828,6 +894,7 @@ interface MarkdownTextChunk {
828
894
  type: "markdown_text";
829
895
  }
830
896
  interface TaskUpdateChunk {
897
+ details?: string;
831
898
  id: string;
832
899
  output?: string;
833
900
  status: "pending" | "in_progress" | "complete" | "error";
@@ -891,7 +958,7 @@ interface ChatInstance {
891
958
  * @param message - Either a parsed message, or a factory function for lazy async parsing
892
959
  * @param options - Webhook options including waitUntil
893
960
  */
894
- processMessage(adapter: Adapter, threadId: string, message: Message | (() => Promise<Message>), options?: WebhookOptions): void;
961
+ processMessage(adapter: Adapter, threadId: string, message: Message | (() => Promise<Message>), options?: WebhookOptions): Promise<void>;
895
962
  /**
896
963
  * Process a modal close event from an adapter.
897
964
  *
@@ -908,6 +975,11 @@ interface ChatInstance {
908
975
  * @param options - Webhook options
909
976
  */
910
977
  processModalSubmit(event: Omit<ModalSubmitEvent, "relatedThread" | "relatedMessage" | "relatedChannel">, contextId?: string, options?: WebhookOptions): Promise<ModalResponse | undefined>;
978
+ /**
979
+ * Process an interactive options load event from an adapter.
980
+ * Returns normalized select options for the adapter to render.
981
+ */
982
+ processOptionsLoad(event: OptionsLoadEvent, options?: WebhookOptions): Promise<OptionsLoadResult | undefined>;
911
983
  /**
912
984
  * Process an incoming reaction event from an adapter.
913
985
  * Handles waitUntil registration and error catching internally.
@@ -929,6 +1001,12 @@ interface ChatInstance {
929
1001
  adapter: Adapter;
930
1002
  channelId: string;
931
1003
  }, options: WebhookOptions | undefined): void;
1004
+ /**
1005
+ * Cross-platform per-user transcript store. Throws on access when
1006
+ * `transcripts` is not configured on the Chat instance — callers should
1007
+ * check `ChatConfig.transcripts` if they need a no-throw guard.
1008
+ */
1009
+ readonly transcripts: TranscriptsApi;
932
1010
  }
933
1011
  /** Lock scope determines which messages contend for the same lock. */
934
1012
  type LockScope = "thread" | "channel";
@@ -1190,6 +1268,40 @@ interface Thread<TState = Record<string, unknown>, TRawMessage = unknown> extend
1190
1268
  * Used internally for reconstructing messages from serialized data.
1191
1269
  */
1192
1270
  createSentMessageFromMessage(message: Message<TRawMessage>): SentMessage<TRawMessage>;
1271
+ /**
1272
+ * Get the unique human participants in this thread.
1273
+ *
1274
+ * Scans all messages in the thread and returns deduplicated authors,
1275
+ * excluding the bot itself. Useful for deciding whether to subscribe
1276
+ * based on how many humans are participating — subscribe when it's a
1277
+ * 1:1 conversation, unsubscribe when others join so humans can talk
1278
+ * without the bot replying to every message.
1279
+ *
1280
+ * @returns Array of unique non-bot authors
1281
+ *
1282
+ * @example
1283
+ * ```typescript
1284
+ * // Subscribe only when one person is talking to the bot
1285
+ * bot.onNewMention(async (thread, message) => {
1286
+ * const participants = await thread.getParticipants();
1287
+ * if (participants.length === 1) {
1288
+ * await thread.subscribe();
1289
+ * await thread.post("I'm here to help!");
1290
+ * }
1291
+ * });
1292
+ *
1293
+ * // Unsubscribe when the thread becomes a group conversation
1294
+ * bot.onSubscribedMessage(async (thread, message) => {
1295
+ * const participants = await thread.getParticipants();
1296
+ * if (participants.length > 1) {
1297
+ * await thread.unsubscribe();
1298
+ * return;
1299
+ * }
1300
+ * await thread.post("Still here to help!");
1301
+ * });
1302
+ * ```
1303
+ */
1304
+ getParticipants(): Promise<Author[]>;
1193
1305
  /**
1194
1306
  * Check if this thread is currently subscribed.
1195
1307
  *
@@ -1238,6 +1350,13 @@ interface Thread<TState = Record<string, unknown>, TRawMessage = unknown> extend
1238
1350
  * const result = await agent.stream({ prompt: message.text });
1239
1351
  * await thread.post(result.textStream);
1240
1352
  *
1353
+ * // Stream with options via StreamingPlan PostableObject
1354
+ * const stream = new StreamingPlan(result.fullStream, {
1355
+ * groupTasks: "plan",
1356
+ * endWith: [feedbackBlocks],
1357
+ * });
1358
+ * await thread.post(stream);
1359
+ *
1241
1360
  * // Plan with live updates
1242
1361
  * const plan = new Plan({ initialMessage: "Working..." });
1243
1362
  * await thread.post(plan);
@@ -1319,6 +1438,24 @@ interface Thread<TState = Record<string, unknown>, TRawMessage = unknown> extend
1319
1438
  unsubscribe(): Promise<void>;
1320
1439
  }
1321
1440
 
1441
+ interface MessageSubject {
1442
+ assignee?: {
1443
+ id: string;
1444
+ name: string;
1445
+ };
1446
+ author?: {
1447
+ id: string;
1448
+ name: string;
1449
+ };
1450
+ description?: string;
1451
+ id: string;
1452
+ labels?: string[];
1453
+ raw: unknown;
1454
+ status?: string;
1455
+ title?: string;
1456
+ type: string;
1457
+ url?: string;
1458
+ }
1322
1459
  interface ThreadInfo {
1323
1460
  channelId: string;
1324
1461
  channelName?: string;
@@ -1425,6 +1562,21 @@ interface Author {
1425
1562
  /** Username/handle for @-mentions */
1426
1563
  userName: string;
1427
1564
  }
1565
+ /** User information returned by adapter.getUser() */
1566
+ interface UserInfo {
1567
+ /** URL to the user's avatar/profile image */
1568
+ avatarUrl?: string;
1569
+ /** User's email address (requires appropriate scopes on some platforms) */
1570
+ email?: string;
1571
+ /** User's display name / full name */
1572
+ fullName: string;
1573
+ /** Whether the user is a bot */
1574
+ isBot: boolean;
1575
+ /** Platform-specific user ID */
1576
+ userId: string;
1577
+ /** Username/handle */
1578
+ userName: string;
1579
+ }
1428
1580
  interface MessageMetadata {
1429
1581
  /** When the message was sent */
1430
1582
  dateSent: Date;
@@ -1433,7 +1585,7 @@ interface MessageMetadata {
1433
1585
  /** When the message was last edited */
1434
1586
  editedAt?: Date;
1435
1587
  }
1436
- interface SentMessage<TRawMessage = unknown> extends Message<TRawMessage> {
1588
+ interface SentMessage<TRawMessage = unknown> extends Omit<Message<TRawMessage>, "subject"> {
1437
1589
  /** Add a reaction to this message */
1438
1590
  addReaction(emoji: EmojiValue | string): Promise<void>;
1439
1591
  /** Delete this message */
@@ -1510,14 +1662,14 @@ type PostableMessage = AdapterPostableMessage | AsyncIterable<string | StreamChu
1510
1662
  /**
1511
1663
  * Duck-typed stream event compatible with AI SDK's `fullStream`.
1512
1664
  * - `text-delta` events are extracted as text output.
1513
- * - `step-finish` events trigger paragraph separators between steps.
1665
+ * - `finish-step` events trigger paragraph separators between steps.
1514
1666
  * - All other event types (tool-call, tool-result, etc.) are silently skipped.
1515
1667
  */
1516
1668
  type StreamEvent = {
1517
1669
  textDelta: string;
1518
1670
  type: "text-delta";
1519
1671
  } | {
1520
- type: "step-finish";
1672
+ type: "finish-step";
1521
1673
  } | {
1522
1674
  type: string;
1523
1675
  };
@@ -1562,6 +1714,12 @@ interface Attachment {
1562
1714
  * this method handles the auth automatically.
1563
1715
  */
1564
1716
  fetchData?: () => Promise<Buffer>;
1717
+ /**
1718
+ * Platform-specific metadata needed to reconstruct fetchData after serialization.
1719
+ * Adapters store IDs here (e.g. WhatsApp mediaId, Telegram fileId) so that
1720
+ * fetchData can be rebuilt when a message is rehydrated from the queue.
1721
+ */
1722
+ fetchMetadata?: Record<string, string>;
1565
1723
  /** Image/video height (if applicable) */
1566
1724
  height?: number;
1567
1725
  /** MIME type */
@@ -1857,6 +2015,27 @@ interface ActionEvent<TRawMessage = unknown> {
1857
2015
  * ```
1858
2016
  */
1859
2017
  type ActionHandler = (event: ActionEvent) => void | Promise<void>;
2018
+ /**
2019
+ * Event emitted when an adapter needs dynamic options for an external select.
2020
+ */
2021
+ interface OptionsLoadEvent {
2022
+ /** The action ID of the select requesting options */
2023
+ actionId: string;
2024
+ /** The adapter that received this event */
2025
+ adapter: Adapter;
2026
+ /** The current user-entered query text */
2027
+ query: string;
2028
+ /** Raw platform-specific payload */
2029
+ raw: unknown;
2030
+ /** The user requesting options */
2031
+ user: Author;
2032
+ }
2033
+ interface OptionsLoadGroup {
2034
+ label: string;
2035
+ options: SelectOptionElement[];
2036
+ }
2037
+ type OptionsLoadResult = SelectOptionElement[] | OptionsLoadGroup[];
2038
+ type OptionsLoadHandler = (event: OptionsLoadEvent) => OptionsLoadResult | Promise<OptionsLoadResult | undefined> | undefined;
1860
2039
  /**
1861
2040
  * Event emitted when a user submits a modal form.
1862
2041
  */
@@ -1946,7 +2125,10 @@ interface ModalPushResponse {
1946
2125
  interface ModalCloseResponse {
1947
2126
  action: "close";
1948
2127
  }
1949
- type ModalResponse = ModalCloseResponse | ModalErrorsResponse | ModalUpdateResponse | ModalPushResponse;
2128
+ interface ModalClearResponse {
2129
+ action: "clear";
2130
+ }
2131
+ type ModalResponse = ModalCloseResponse | ModalClearResponse | ModalErrorsResponse | ModalUpdateResponse | ModalPushResponse;
1950
2132
  type ModalSubmitHandler = (event: ModalSubmitEvent) => void | Promise<ModalResponse | void | undefined>;
1951
2133
  type ModalCloseHandler = (event: ModalCloseEvent) => void | Promise<void>;
1952
2134
  /**
@@ -2073,6 +2255,141 @@ interface MemberJoinedChannelEvent {
2073
2255
  userId: string;
2074
2256
  }
2075
2257
  type MemberJoinedChannelHandler = (event: MemberJoinedChannelEvent) => void | Promise<void>;
2258
+ /**
2259
+ * Resolves a stable, cross-platform user key from an inbound message context.
2260
+ *
2261
+ * Return `null` to skip persistence for this event (unknown user, system
2262
+ * message, or the bot itself). The SDK fails loudly rather than silently
2263
+ * falling back to a platform-specific ID.
2264
+ */
2265
+ type IdentityResolver = (context: IdentityContext) => string | null | Promise<string | null>;
2266
+ interface IdentityContext {
2267
+ /** Adapter name (e.g. "slack", "discord"). */
2268
+ adapter: string;
2269
+ author: Author;
2270
+ message: Message;
2271
+ }
2272
+ /**
2273
+ * Role tag on a stored message.
2274
+ *
2275
+ * - `user`: produced by the resolved end-user
2276
+ * - `assistant`: produced by this bot
2277
+ * - `system`: SDK-injected marker (handoff, summary). Adapters never produce it.
2278
+ */
2279
+ type TranscriptRole = "user" | "assistant" | "system";
2280
+ interface TranscriptEntry {
2281
+ /** mdast AST. Only present when `transcripts.storeFormatted` is true. */
2282
+ formatted?: FormattedContent;
2283
+ /**
2284
+ * UUID assigned by the SDK at append time. Opaque — not lexicographically
2285
+ * sortable. Entries are returned by `list()` in append order (the underlying
2286
+ * list semantics of `state.appendToList`); use `timestamp` to reason about
2287
+ * ordering across stores.
2288
+ */
2289
+ id: string;
2290
+ /** Originating adapter name. */
2291
+ platform: string;
2292
+ /** Platform-native message ID, when known. */
2293
+ platformMessageId?: string;
2294
+ role: TranscriptRole;
2295
+ /** Plain-text body — canonical field for prompt building. */
2296
+ text: string;
2297
+ /** Originating thread ID. */
2298
+ threadId: string;
2299
+ /** ms-since-epoch, set at append time on the SDK side. */
2300
+ timestamp: number;
2301
+ /** Cross-platform user key from the IdentityResolver. */
2302
+ userKey: string;
2303
+ }
2304
+ /** Duration shorthand: e.g. `"7d"`, `"30m"`, `"2h"`, `"45s"`. */
2305
+ type DurationString = `${number}${"s" | "m" | "h" | "d"}`;
2306
+ interface TranscriptsConfig {
2307
+ /** Hard cap; older messages evicted on append. Default 200. */
2308
+ maxPerUser?: number;
2309
+ /**
2310
+ * Default retention applied as the list TTL. Refreshed on every append
2311
+ * (matches `appendToList` semantics). Omit for no expiry.
2312
+ */
2313
+ retention?: number | DurationString;
2314
+ /** Persist `formatted` (mdast). Default false to keep storage small. */
2315
+ storeFormatted?: boolean;
2316
+ }
2317
+ /**
2318
+ * Input shape for appending a non-Message (e.g. an assistant reply you
2319
+ * just posted via `thread.post()`).
2320
+ */
2321
+ interface AppendInput {
2322
+ formatted?: FormattedContent;
2323
+ platformMessageId?: string;
2324
+ role: TranscriptRole;
2325
+ text: string;
2326
+ }
2327
+ interface AppendOptions {
2328
+ /**
2329
+ * Required when appending an `AppendInput` (assistant/system role) — the
2330
+ * SDK has no Message instance from which to read the resolved key.
2331
+ *
2332
+ * Ignored when appending a Message; the Message's own `userKey` is used.
2333
+ */
2334
+ userKey?: string;
2335
+ }
2336
+ interface ListQuery {
2337
+ /** Newest N kept (still returned in chronological order). Default 50. */
2338
+ limit?: number;
2339
+ /** Filter to a subset of adapter names. */
2340
+ platforms?: string[];
2341
+ /** Filter to specific roles. Default: all. */
2342
+ roles?: TranscriptRole[];
2343
+ /** Filter to a single thread. */
2344
+ threadId?: string;
2345
+ userKey: string;
2346
+ }
2347
+ /**
2348
+ * Target for {@link TranscriptsApi.delete}. Wipes every stored message under
2349
+ * the given user key.
2350
+ */
2351
+ interface DeleteTarget {
2352
+ userKey: string;
2353
+ }
2354
+ /** Query shape for {@link TranscriptsApi.count}. */
2355
+ interface CountQuery {
2356
+ userKey: string;
2357
+ }
2358
+ /**
2359
+ * Cross-platform per-user message store.
2360
+ *
2361
+ * Distinct from the existing per-thread `threadHistory` config (which exists
2362
+ * to backfill thread context for adapters that lack server-side history APIs).
2363
+ * The Transcripts API is keyed by a resolved cross-platform user key and is
2364
+ * intended for transcript-style use cases (LLM context building, audit).
2365
+ */
2366
+ interface TranscriptsApi {
2367
+ /**
2368
+ * Persist a Message (or AppendInput) under the user key.
2369
+ *
2370
+ * - For Message: `userKey` is read from the Message instance (set by the
2371
+ * SDK during inbound dispatch via the configured IdentityResolver).
2372
+ * No-op if the Message has no `userKey` (resolver returned null).
2373
+ * - For AppendInput: `options.userKey` is required.
2374
+ */
2375
+ append<TState = Record<string, unknown>, TRawMessage = unknown>(thread: Postable<TState, TRawMessage>, message: Message | AppendInput, options?: AppendOptions): Promise<TranscriptEntry | null>;
2376
+ /** Total stored count for a user key. */
2377
+ count(query: CountQuery): Promise<number>;
2378
+ /** GDPR / DSR delete — wipes every stored message under the user key. */
2379
+ delete(target: DeleteTarget): Promise<{
2380
+ deleted: number;
2381
+ }>;
2382
+ /**
2383
+ * Returns the most recent entries in chronological order (oldest first),
2384
+ * capped at `query.limit` (default 50).
2385
+ *
2386
+ * Pagination is intentionally not supported — the store keeps at most
2387
+ * `transcripts.maxPerUser` entries per user. To widen the window, raise
2388
+ * `maxPerUser`; to fetch a different slice, narrow with `threadId` /
2389
+ * `platforms` / `roles`.
2390
+ */
2391
+ list(query: ListQuery): Promise<TranscriptEntry[]>;
2392
+ }
2076
2393
 
2077
2394
  /**
2078
2395
  * Message class with serialization support for workflow engines.
@@ -2118,6 +2435,7 @@ interface SerializedMessage {
2118
2435
  size?: number;
2119
2436
  width?: number;
2120
2437
  height?: number;
2438
+ fetchMetadata?: Record<string, string>;
2121
2439
  }>;
2122
2440
  author: {
2123
2441
  userId: string;
@@ -2204,8 +2522,20 @@ declare class Message<TRawMessage = unknown> {
2204
2522
  * ```
2205
2523
  */
2206
2524
  isMention?: boolean;
2525
+ /**
2526
+ * Cross-platform user key for this message's author.
2527
+ *
2528
+ * Set by the Chat SDK before passing the message to handlers, when
2529
+ * `ChatConfig.identity` is configured. `undefined` if no resolver is
2530
+ * configured; `undefined` (i.e. absent) when the resolver returned null.
2531
+ *
2532
+ * Used by the Transcripts API to look up / append per-user transcripts.
2533
+ */
2534
+ userKey?: string;
2207
2535
  /** Links found in the message */
2208
2536
  links: LinkPreview[];
2537
+ private _subjectPromise?;
2538
+ get subject(): Promise<MessageSubject | null>;
2209
2539
  constructor(data: MessageData<TRawMessage>);
2210
2540
  /**
2211
2541
  * Serialize the message to a plain JSON object.
@@ -2369,6 +2699,14 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
2369
2699
  * ```
2370
2700
  */
2371
2701
  registerSingleton(): this;
2702
+ /**
2703
+ * Cross-platform per-user transcript store.
2704
+ *
2705
+ * Available only when `transcripts` is configured on the Chat instance
2706
+ * (and an `identity` resolver is set). Throws on access otherwise so
2707
+ * callers fail loudly rather than silently no-op'ing.
2708
+ */
2709
+ get transcripts(): TranscriptsApi;
2372
2710
  /**
2373
2711
  * Get the registered singleton Chat instance.
2374
2712
  * Throws if no singleton has been registered.
@@ -2386,9 +2724,12 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
2386
2724
  private readonly _fallbackStreamingPlaceholderText;
2387
2725
  private readonly _dedupeTtlMs;
2388
2726
  private readonly _onLockConflict;
2389
- private readonly _messageHistory;
2727
+ private readonly _threadHistory;
2728
+ private readonly _identity;
2729
+ private readonly _transcripts;
2390
2730
  private readonly _concurrencyStrategy;
2391
2731
  private readonly _concurrencyConfig;
2732
+ private readonly _concurrentSlots;
2392
2733
  private readonly _lockScope;
2393
2734
  private readonly mentionHandlers;
2394
2735
  private readonly directMessageHandlers;
@@ -2396,6 +2737,7 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
2396
2737
  private readonly subscribedMessageHandlers;
2397
2738
  private readonly reactionHandlers;
2398
2739
  private readonly actionHandlers;
2740
+ private readonly optionsLoadHandlers;
2399
2741
  private readonly modalSubmitHandlers;
2400
2742
  private readonly modalCloseHandlers;
2401
2743
  private readonly slashCommandHandlers;
@@ -2571,6 +2913,12 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
2571
2913
  */
2572
2914
  onAction(handler: ActionHandler): void;
2573
2915
  onAction(actionIds: string[] | string, handler: ActionHandler): void;
2916
+ /**
2917
+ * Register a handler for loading dynamic options for external selects.
2918
+ * Specific action IDs run before catch-all handlers.
2919
+ */
2920
+ onOptionsLoad(handler: OptionsLoadHandler): void;
2921
+ onOptionsLoad(actionIds: string[] | string, handler: OptionsLoadHandler): void;
2574
2922
  /**
2575
2923
  * Register a handler for modal form submissions.
2576
2924
  *
@@ -2686,7 +3034,7 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
2686
3034
  * Handles waitUntil registration and error catching internally.
2687
3035
  * Adapters should call this instead of handleIncomingMessage directly.
2688
3036
  */
2689
- processMessage(adapter: Adapter, threadId: string, messageOrFactory: Message | (() => Promise<Message>), options?: WebhookOptions): void;
3037
+ processMessage(adapter: Adapter, threadId: string, messageOrFactory: Message | (() => Promise<Message>), options?: WebhookOptions): Promise<void>;
2690
3038
  /**
2691
3039
  * Process an incoming reaction event from an adapter.
2692
3040
  * Handles waitUntil registration and error catching internally.
@@ -2701,7 +3049,8 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
2701
3049
  processAction(event: Omit<ActionEvent, "thread" | "openModal"> & {
2702
3050
  adapter: Adapter;
2703
3051
  }, options: WebhookOptions | undefined): Promise<void>;
2704
- processModalSubmit(event: Omit<ModalSubmitEvent, "relatedThread" | "relatedMessage" | "relatedChannel">, contextId?: string, _options?: WebhookOptions): Promise<ModalResponse | undefined>;
3052
+ processOptionsLoad(event: OptionsLoadEvent, _options?: WebhookOptions): Promise<OptionsLoadResult | undefined>;
3053
+ processModalSubmit(event: Omit<ModalSubmitEvent, "relatedThread" | "relatedMessage" | "relatedChannel">, contextId?: string, options?: WebhookOptions): Promise<ModalResponse | undefined>;
2705
3054
  processModalClose(event: Omit<ModalCloseEvent, "relatedThread" | "relatedMessage" | "relatedChannel">, contextId?: string, options?: WebhookOptions): void;
2706
3055
  /**
2707
3056
  * Process an incoming slash command from an adapter.
@@ -2768,6 +3117,23 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
2768
3117
  * ```
2769
3118
  */
2770
3119
  openDM(user: string | Author): Promise<Thread<TState>>;
3120
+ /**
3121
+ * Look up user information by user ID.
3122
+ *
3123
+ * The adapter is automatically inferred from the user ID format.
3124
+ * Returns user details including email (where available — requires
3125
+ * appropriate scopes on some platforms, e.g. `users:read.email` on Slack).
3126
+ *
3127
+ * @param user - Platform-specific user ID string, or an Author object
3128
+ * @returns User info, or null if user not found
3129
+ *
3130
+ * @example
3131
+ * ```typescript
3132
+ * const user = await chat.getUser("U123456");
3133
+ * console.log(user?.email); // "alice@company.com"
3134
+ * ```
3135
+ */
3136
+ getUser(user: string | Author): Promise<UserInfo | null>;
2771
3137
  /**
2772
3138
  * Get a Channel by its channel ID.
2773
3139
  *
@@ -2795,6 +3161,21 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
2795
3161
  * ```
2796
3162
  */
2797
3163
  channel(channelId: string): Channel<TState>;
3164
+ /**
3165
+ * Get a Thread handle by its thread ID.
3166
+ *
3167
+ * The adapter is automatically inferred from the thread ID prefix.
3168
+ *
3169
+ * @param threadId - Full thread ID (e.g., "slack:C123ABC:1234567890.123456")
3170
+ * @returns A Thread that can be used to post messages, subscribe, etc.
3171
+ *
3172
+ * @example
3173
+ * ```typescript
3174
+ * const thread = chat.thread("slack:C123ABC:1234567890.123456");
3175
+ * await thread.post("Hello from outside a webhook!");
3176
+ * ```
3177
+ */
3178
+ thread(threadId: string): Thread<TState>;
2798
3179
  /**
2799
3180
  * Infer which adapter to use based on the userId format.
2800
3181
  */
@@ -2835,9 +3216,12 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
2835
3216
  */
2836
3217
  private drainQueue;
2837
3218
  /**
2838
- * Concurrent strategy: no locking, process immediately.
3219
+ * Concurrent strategy: no locking, process immediately — but cap
3220
+ * simultaneous handlers per thread at `maxConcurrent` (default Infinity).
2839
3221
  */
2840
3222
  private handleConcurrent;
3223
+ private acquireConcurrentSlot;
3224
+ private releaseConcurrentSlot;
2841
3225
  /**
2842
3226
  * Dispatch a message to the appropriate handler chain based on
2843
3227
  * subscription status, mention detection, and pattern matching.
@@ -2881,6 +3265,21 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
2881
3265
  */
2882
3266
  declare function fromFullStream(stream: AsyncIterable<unknown>): AsyncIterable<string | StreamChunk>;
2883
3267
 
3268
+ /**
3269
+ * @deprecated Renamed — import from `./thread-history` instead.
3270
+ *
3271
+ * This module is preserved for backwards compatibility and re-exports the
3272
+ * new names under the old identifiers. New code should use `ThreadHistoryCache`
3273
+ * and `ThreadHistoryConfig` directly.
3274
+ */
3275
+
3276
+ /** @deprecated Use `ThreadHistoryConfig` from `./thread-history` instead. */
3277
+ type MessageHistoryConfig = ThreadHistoryConfig;
3278
+ /** @deprecated Use `ThreadHistoryCache` from `./thread-history` instead. */
3279
+ declare const MessageHistoryCache: typeof ThreadHistoryCache;
3280
+ /** @deprecated Use `ThreadHistoryCache` from `./thread-history` instead. */
3281
+ type MessageHistoryCache = ThreadHistoryCache;
3282
+
2884
3283
  /**
2885
3284
  * Standalone JSON reviver for Chat SDK objects.
2886
3285
  *
@@ -2953,6 +3352,58 @@ declare class StreamingMarkdownRenderer {
2953
3352
  private formatAppendOnlyText;
2954
3353
  }
2955
3354
 
3355
+ interface StreamingPlanOptions {
3356
+ /**
3357
+ * Block Kit elements to attach when the stream stops (Slack only).
3358
+ * Useful for adding feedback buttons after a streamed response.
3359
+ */
3360
+ endWith?: unknown[];
3361
+ /**
3362
+ * Controls how task_update chunks are displayed (Slack only).
3363
+ * - `"plan"` - all tasks grouped into a single plan block
3364
+ * - `"timeline"` - individual task cards shown inline with text (default)
3365
+ */
3366
+ groupTasks?: "plan" | "timeline";
3367
+ /**
3368
+ * Minimum interval between updates in ms (default: 500).
3369
+ * Used by post+edit streaming paths.
3370
+ */
3371
+ updateIntervalMs?: number;
3372
+ }
3373
+ interface StreamingPlanData {
3374
+ options: StreamingPlanOptions;
3375
+ stream: AsyncIterable<string | StreamChunk | StreamEvent>;
3376
+ }
3377
+ /**
3378
+ * A StreamingPlan wraps an async iterable with platform-specific streaming options.
3379
+ *
3380
+ * Use this when you need to pass options like task grouping or stop blocks
3381
+ * to the streaming API. For simple streaming without options, pass the
3382
+ * async iterable directly to `thread.post()`.
3383
+ *
3384
+ * @example
3385
+ * ```typescript
3386
+ * const stream = new StreamingPlan(result.fullStream, {
3387
+ * groupTasks: "plan",
3388
+ * endWith: [feedbackBlock],
3389
+ * });
3390
+ * await thread.post(stream);
3391
+ * ```
3392
+ */
3393
+ declare class StreamingPlan implements PostableObject<StreamingPlanData> {
3394
+ readonly $$typeof: symbol;
3395
+ readonly kind = "stream";
3396
+ private readonly _stream;
3397
+ private readonly _options;
3398
+ constructor(stream: AsyncIterable<string | StreamChunk | StreamEvent>, options?: StreamingPlanOptions);
3399
+ get stream(): AsyncIterable<string | StreamChunk | StreamEvent>;
3400
+ get options(): StreamingPlanOptions;
3401
+ getFallbackText(): string;
3402
+ getPostData(): StreamingPlanData;
3403
+ isSupported(_adapter: Adapter): boolean;
3404
+ onPosted(_context: PostableObjectContext): void;
3405
+ }
3406
+
2956
3407
  /**
2957
3408
  * Get or create an immutable singleton EmojiValue.
2958
3409
  *
@@ -3037,7 +3488,7 @@ declare const defaultEmojiResolver: EmojiResolver;
3037
3488
  * // Returns: "Thanks! 👍"
3038
3489
  * ```
3039
3490
  */
3040
- declare function convertEmojiPlaceholders(text: string, platform: "slack" | "gchat" | "teams" | "discord" | "github" | "linear" | "whatsapp", resolver?: EmojiResolver): string;
3491
+ declare function convertEmojiPlaceholders(text: string, platform: "slack" | "gchat" | "teams" | "discord" | "messenger" | "github" | "linear" | "whatsapp", resolver?: EmojiResolver): string;
3041
3492
  /** Base emoji object with well-known emoji as EmojiValue singletons */
3042
3493
  type BaseEmojiHelper = {
3043
3494
  [K in WellKnownEmoji]: EmojiValue;
@@ -3390,10 +3841,11 @@ declare const toModalElement: typeof toModalElement$1;
3390
3841
 
3391
3842
  declare const fromReactModalElement: typeof fromReactModalElement$1;
3392
3843
  declare const isModalElement: typeof isModalElement$1;
3844
+ declare const ExternalSelect: ExternalSelectComponent;
3393
3845
  declare const Modal: ModalComponent;
3394
3846
  declare const RadioSelect: RadioSelectComponent;
3395
3847
  declare const Select: SelectComponent;
3396
3848
  declare const SelectOption: SelectOptionComponent;
3397
3849
  declare const TextInput: TextInputComponent;
3398
3850
 
3399
- export { type ActionEvent, type ActionHandler, Actions, ActionsComponent, type Adapter, type AdapterPostableMessage, type AddTaskOptions, type AiAssistantMessage, type AiFilePart, type AiImagePart, type AiMessage, type AiMessagePart, type AiTextPart, type AiUserMessage, type AppHomeOpenedEvent, type AppHomeOpenedHandler, type AssistantContextChangedEvent, type AssistantContextChangedHandler, type AssistantThreadStartedEvent, type AssistantThreadStartedHandler, type Attachment, type Author, BaseFormatConverter, Button, ButtonComponent, Card, CardChild, CardComponent, CardElement, CardLink, CardLinkComponent, CardText, type Channel, ChannelImpl, type ChannelInfo, type ChannelVisibility, Chat, type ChatConfig, ChatElement, ChatError, type ChatInstance, type CompletePlanOptions, type ConcurrencyConfig, type ConcurrencyStrategy, ConsoleLogger, type CustomEmojiMap, DEFAULT_EMOJI_MAP, type DirectMessageHandler, Divider, DividerComponent, type Emoji, type EmojiFormats, type EmojiMapConfig, EmojiResolver, type EmojiValue, type EphemeralMessage, type FetchDirection, type FetchOptions, type FetchResult, Field, FieldComponent, Fields, FieldsComponent, type FileUpload, type FormatConverter, type FormattedContent, Image, ImageComponent, LinkButton, LinkButtonComponent, type LinkPreview, type ListThreadsOptions, type ListThreadsResult, type Lock, LockError, type LockScope, type LockScopeContext, type LogLevel, type Logger, type MarkdownConverter, type MarkdownTextChunk, type MemberJoinedChannelEvent, type MemberJoinedChannelHandler, type MentionHandler, Message, type MessageContext, type MessageData, type MessageHandler, MessageHistoryCache, type MessageHistoryConfig, type MessageMetadata, Modal, type ModalCloseEvent, type ModalCloseHandler, type ModalCloseResponse, ModalComponent, ModalElement, type ModalErrorsResponse, type ModalPushResponse, type ModalResponse, type ModalSubmitEvent, type ModalSubmitHandler, type ModalUpdateResponse, NotImplementedError, Plan, type PlanContent, type PlanModel, type PlanModelTask, type PlanTask, type PlanTaskStatus, type PlanUpdateChunk, type PostEphemeralOptions, type Postable, type PostableAst, type PostableCard, type PostableMarkdown, type PostableMessage, type PostableObject, type PostableObjectContext, type PostableRaw, type QueueEntry, RadioSelect, RadioSelectComponent, RateLimitError, type RawMessage, type ReactionEvent, type ReactionHandler, type ScheduledMessage, Section, SectionComponent, Select, SelectComponent, SelectOption, SelectOptionComponent, type SentMessage, type SerializedChannel, type SerializedMessage, type SerializedThread, type SlashCommandEvent, type SlashCommandHandler, type StartPlanOptions, type StateAdapter, type StreamChunk, type StreamEvent, type StreamOptions, StreamingMarkdownRenderer, type SubscribedMessageHandler, THREAD_STATE_TTL_MS, Table, type TaskUpdateChunk, TextComponent, TextInput, TextInputComponent, type Thread, ThreadImpl, type ThreadInfo, type ThreadSummary, type UpdateTaskInput, type WebhookOptions, type WellKnownEmoji, blockquote, cardChildToFallbackText, codeBlock, convertEmojiPlaceholders, createEmoji, defaultEmojiResolver, deriveChannelId, emoji, emphasis, fromFullStream, fromReactElement, fromReactModalElement, getEmoji, getNodeChildren, getNodeValue, inlineCode, isBlockquoteNode, isCardElement, isCodeNode, isDeleteNode, isEmphasisNode, isInlineCodeNode, isJSX, isLinkNode, isListItemNode, isListNode, isModalElement, isParagraphNode, isPostableObject, isStrongNode, isTableCellNode, isTableNode, isTableRowNode, isTextNode, link, markdownToPlainText, paragraph, parseMarkdown, reviver, root, strikethrough, stringifyMarkdown, strong, tableElementToAscii, tableToAscii, text, toAiMessages, toCardElement, toModalElement, toPlainText, walkAst };
3851
+ export { type ActionEvent, type ActionHandler, Actions, ActionsComponent, type Adapter, type AdapterPostableMessage, type AddTaskOptions, type AiAssistantMessage, type AiFilePart, type AiImagePart, type AiMessage, type AiMessagePart, type AiTextPart, type AiUserMessage, type AppHomeOpenedEvent, type AppHomeOpenedHandler, type AppendInput, type AppendOptions, type AssistantContextChangedEvent, type AssistantContextChangedHandler, type AssistantThreadStartedEvent, type AssistantThreadStartedHandler, type Attachment, type Author, BaseFormatConverter, Button, ButtonComponent, Card, CardChild, CardComponent, CardElement, CardLink, CardLinkComponent, CardText, type Channel, ChannelImpl, type ChannelInfo, type ChannelVisibility, Chat, type ChatConfig, ChatElement, ChatError, type ChatInstance, type CompletePlanOptions, type ConcurrencyConfig, type ConcurrencyStrategy, ConsoleLogger, type CountQuery, type CustomEmojiMap, DEFAULT_EMOJI_MAP, type DeleteTarget, type DirectMessageHandler, Divider, DividerComponent, type DurationString, type Emoji, type EmojiFormats, type EmojiMapConfig, EmojiResolver, type EmojiValue, type EphemeralMessage, ExternalSelect, ExternalSelectComponent, type FetchDirection, type FetchOptions, type FetchResult, Field, FieldComponent, Fields, FieldsComponent, type FileUpload, type FormatConverter, type FormattedContent, type IdentityContext, type IdentityResolver, Image, ImageComponent, LinkButton, LinkButtonComponent, type LinkPreview, type ListQuery, type ListThreadsOptions, type ListThreadsResult, type Lock, LockError, type LockScope, type LockScopeContext, type LogLevel, type Logger, type MarkdownConverter, type MarkdownTextChunk, type MemberJoinedChannelEvent, type MemberJoinedChannelHandler, type MentionHandler, Message, type MessageContext, type MessageData, type MessageHandler, MessageHistoryCache, type MessageHistoryConfig, type MessageMetadata, type MessageSubject, Modal, type ModalClearResponse, type ModalCloseEvent, type ModalCloseHandler, type ModalCloseResponse, ModalComponent, ModalElement, type ModalErrorsResponse, type ModalPushResponse, type ModalResponse, type ModalSubmitEvent, type ModalSubmitHandler, type ModalUpdateResponse, NotImplementedError, type OptionsLoadEvent, type OptionsLoadGroup, type OptionsLoadHandler, type OptionsLoadResult, Plan, type PlanContent, type PlanModel, type PlanModelTask, type PlanTask, type PlanTaskStatus, type PlanUpdateChunk, type PostEphemeralOptions, type Postable, type PostableAst, type PostableCard, type PostableMarkdown, type PostableMessage, type PostableObject, type PostableObjectContext, type PostableRaw, type QueueEntry, RadioSelect, RadioSelectComponent, RateLimitError, type RawMessage, type ReactionEvent, type ReactionHandler, type ScheduledMessage, Section, SectionComponent, Select, SelectComponent, SelectOption, SelectOptionComponent, SelectOptionElement, type SentMessage, type SerializedChannel, type SerializedMessage, type SerializedThread, type SlashCommandEvent, type SlashCommandHandler, type StartPlanOptions, type StateAdapter, type StreamChunk, type StreamEvent, type StreamOptions, StreamingMarkdownRenderer, StreamingPlan, type StreamingPlanData, type StreamingPlanOptions, type SubscribedMessageHandler, THREAD_STATE_TTL_MS, Table, type TaskUpdateChunk, TextComponent, TextInput, TextInputComponent, type Thread, ThreadHistoryCache, type ThreadHistoryConfig, ThreadImpl, type ThreadInfo, type ThreadSummary, type TranscriptEntry, type TranscriptRole, type TranscriptsApi, type TranscriptsConfig, type UpdateTaskInput, type UserInfo, type WebhookOptions, type WellKnownEmoji, blockquote, cardChildToFallbackText, codeBlock, convertEmojiPlaceholders, createEmoji, defaultEmojiResolver, deriveChannelId, emoji, emphasis, fromFullStream, fromReactElement, fromReactModalElement, getEmoji, getNodeChildren, getNodeValue, inlineCode, isBlockquoteNode, isCardElement, isCodeNode, isDeleteNode, isEmphasisNode, isInlineCodeNode, isJSX, isLinkNode, isListItemNode, isListNode, isModalElement, isParagraphNode, isPostableObject, isStrongNode, isTableCellNode, isTableNode, isTableRowNode, isTextNode, link, markdownToPlainText, paragraph, parseMarkdown, reviver, root, strikethrough, stringifyMarkdown, strong, tableElementToAscii, tableToAscii, text, toAiMessages, toCardElement, toModalElement, toPlainText, walkAst };