chat 4.20.2 → 4.22.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.
package/dist/index.d.ts CHANGED
@@ -1,8 +1,114 @@
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
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 CardElement, M as ModalElement, a as ChatElement, 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-C2ATKxHQ.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-C2ATKxHQ.js';
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-DraWieqP.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-DraWieqP.js';
6
+
7
+ interface MessageHistoryConfig {
8
+ /** Maximum messages to keep per thread (default: 100) */
9
+ maxMessages?: number;
10
+ /** TTL for cached history in milliseconds (default: 7 days) */
11
+ ttlMs?: number;
12
+ }
13
+ /**
14
+ * Persistent message history cache backed by the StateAdapter.
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.
19
+ */
20
+ declare class MessageHistoryCache {
21
+ private readonly state;
22
+ private readonly maxMessages;
23
+ private readonly ttlMs;
24
+ constructor(state: StateAdapter, config?: MessageHistoryConfig);
25
+ /**
26
+ * Atomically append a message to the history for a thread.
27
+ * Trims to maxMessages (keeps newest) and refreshes TTL.
28
+ */
29
+ append(threadId: string, message: Message): Promise<void>;
30
+ /**
31
+ * Get messages for a thread in chronological order (oldest first).
32
+ *
33
+ * @param threadId - The thread ID
34
+ * @param limit - Optional limit on number of messages to return (returns newest N)
35
+ */
36
+ getMessages(threadId: string, limit?: number): Promise<Message[]>;
37
+ }
38
+
39
+ /**
40
+ * Serialized channel data for passing to external systems (e.g., workflow engines).
41
+ */
42
+ interface SerializedChannel {
43
+ _type: "chat:Channel";
44
+ adapterName: string;
45
+ id: string;
46
+ isDM: boolean;
47
+ }
48
+ /**
49
+ * Config for creating a ChannelImpl with explicit adapter/state instances.
50
+ */
51
+ interface ChannelImplConfigWithAdapter {
52
+ adapter: Adapter;
53
+ id: string;
54
+ isDM?: boolean;
55
+ messageHistory?: MessageHistoryCache;
56
+ stateAdapter: StateAdapter;
57
+ }
58
+ /**
59
+ * Config for creating a ChannelImpl with lazy adapter resolution.
60
+ */
61
+ interface ChannelImplConfigLazy {
62
+ adapterName: string;
63
+ id: string;
64
+ isDM?: boolean;
65
+ }
66
+ type ChannelImplConfig = ChannelImplConfigWithAdapter | ChannelImplConfigLazy;
67
+ declare class ChannelImpl<TState = Record<string, unknown>> implements Channel<TState> {
68
+ readonly id: string;
69
+ readonly isDM: boolean;
70
+ private _adapter?;
71
+ private readonly _adapterName?;
72
+ private _stateAdapterInstance?;
73
+ private _name;
74
+ private readonly _messageHistory?;
75
+ constructor(config: ChannelImplConfig);
76
+ get adapter(): Adapter;
77
+ private get _stateAdapter();
78
+ get name(): string | null;
79
+ get state(): Promise<TState | null>;
80
+ setState(newState: Partial<TState>, options?: {
81
+ replace?: boolean;
82
+ }): Promise<void>;
83
+ /**
84
+ * Iterate messages newest first (backward from most recent).
85
+ * Uses adapter.fetchChannelMessages if available, otherwise falls back
86
+ * to adapter.fetchMessages with the channel ID.
87
+ */
88
+ get messages(): AsyncIterable<Message>;
89
+ /**
90
+ * Iterate threads in this channel, most recently active first.
91
+ */
92
+ threads(): AsyncIterable<ThreadSummary>;
93
+ fetchMetadata(): Promise<ChannelInfo>;
94
+ post(message: string | PostableMessage | ChatElement): Promise<SentMessage>;
95
+ private postSingleMessage;
96
+ postEphemeral(user: string | Author, message: AdapterPostableMessage | ChatElement, options: PostEphemeralOptions): Promise<EphemeralMessage | null>;
97
+ schedule(message: AdapterPostableMessage | ChatElement, options: {
98
+ postAt: Date;
99
+ }): Promise<ScheduledMessage>;
100
+ startTyping(status?: string): Promise<void>;
101
+ mentionUser(userId: string): string;
102
+ toJSON(): SerializedChannel;
103
+ static fromJSON<TState = Record<string, unknown>>(json: SerializedChannel, adapter?: Adapter): ChannelImpl<TState>;
104
+ static [WORKFLOW_SERIALIZE](instance: ChannelImpl): SerializedChannel;
105
+ static [WORKFLOW_DESERIALIZE](data: SerializedChannel): ChannelImpl;
106
+ private createSentMessage;
107
+ }
108
+ /**
109
+ * Derive the channel ID from a thread ID.
110
+ */
111
+ declare function deriveChannelId(adapter: Adapter, threadId: string): string;
6
112
 
7
113
  /**
8
114
  * Logger types and implementations for chat-sdk
@@ -31,6 +137,178 @@ declare class ConsoleLogger implements Logger {
31
137
  error(message: string, ...args: unknown[]): void;
32
138
  }
33
139
 
140
+ /**
141
+ * Serialized thread data for passing to external systems (e.g., workflow engines).
142
+ */
143
+ interface SerializedThread {
144
+ _type: "chat:Thread";
145
+ adapterName: string;
146
+ channelId: string;
147
+ currentMessage?: SerializedMessage;
148
+ id: string;
149
+ isDM: boolean;
150
+ }
151
+ /**
152
+ * Config for creating a ThreadImpl with explicit adapter/state instances.
153
+ */
154
+ interface ThreadImplConfigWithAdapter {
155
+ adapter: Adapter;
156
+ channelId: string;
157
+ currentMessage?: Message;
158
+ fallbackStreamingPlaceholderText?: string | null;
159
+ id: string;
160
+ initialMessage?: Message;
161
+ isDM?: boolean;
162
+ isSubscribedContext?: boolean;
163
+ logger?: Logger;
164
+ messageHistory?: MessageHistoryCache;
165
+ stateAdapter: StateAdapter;
166
+ streamingUpdateIntervalMs?: number;
167
+ }
168
+ /**
169
+ * Config for creating a ThreadImpl with lazy adapter resolution.
170
+ * The adapter will be looked up from the Chat singleton on first access.
171
+ */
172
+ interface ThreadImplConfigLazy {
173
+ adapterName: string;
174
+ channelId: string;
175
+ currentMessage?: Message;
176
+ fallbackStreamingPlaceholderText?: string | null;
177
+ id: string;
178
+ initialMessage?: Message;
179
+ isDM?: boolean;
180
+ isSubscribedContext?: boolean;
181
+ logger?: Logger;
182
+ streamingUpdateIntervalMs?: number;
183
+ }
184
+ type ThreadImplConfig = ThreadImplConfigWithAdapter | ThreadImplConfigLazy;
185
+ declare class ThreadImpl<TState = Record<string, unknown>> implements Thread<TState> {
186
+ readonly id: string;
187
+ readonly channelId: string;
188
+ readonly isDM: boolean;
189
+ /** Direct adapter instance (if provided) */
190
+ private _adapter?;
191
+ /** Adapter name for lazy resolution */
192
+ private readonly _adapterName?;
193
+ /** Direct state adapter instance (if provided) */
194
+ private _stateAdapterInstance?;
195
+ private _recentMessages;
196
+ private readonly _isSubscribedContext;
197
+ /** Current message context for streaming - provides userId/teamId */
198
+ private readonly _currentMessage?;
199
+ /** Update interval for fallback streaming */
200
+ private readonly _streamingUpdateIntervalMs;
201
+ /** Placeholder text for fallback streaming (post + edit) */
202
+ private readonly _fallbackStreamingPlaceholderText;
203
+ /** Cached channel instance */
204
+ private _channel?;
205
+ /** Message history cache (set only for adapters with persistMessageHistory) */
206
+ private readonly _messageHistory?;
207
+ private readonly _logger?;
208
+ constructor(config: ThreadImplConfig);
209
+ /**
210
+ * Get the adapter for this thread.
211
+ * If created with lazy config, resolves from Chat singleton on first access.
212
+ */
213
+ get adapter(): Adapter;
214
+ /**
215
+ * Get the state adapter for this thread.
216
+ * If created with lazy config, resolves from Chat singleton on first access.
217
+ */
218
+ private get _stateAdapter();
219
+ get recentMessages(): Message[];
220
+ set recentMessages(messages: Message[]);
221
+ /**
222
+ * Get the current thread state.
223
+ * Returns null if no state has been set.
224
+ */
225
+ get state(): Promise<TState | null>;
226
+ /**
227
+ * Set the thread state. Merges with existing state by default.
228
+ * State is persisted for 30 days.
229
+ */
230
+ setState(newState: Partial<TState>, options?: {
231
+ replace?: boolean;
232
+ }): Promise<void>;
233
+ /**
234
+ * Get the Channel containing this thread.
235
+ * Lazy-created and cached.
236
+ */
237
+ get channel(): Channel<TState>;
238
+ /**
239
+ * Iterate messages newest first (backward from most recent).
240
+ * Auto-paginates lazily.
241
+ */
242
+ get messages(): AsyncIterable<Message>;
243
+ get allMessages(): AsyncIterable<Message>;
244
+ isSubscribed(): Promise<boolean>;
245
+ subscribe(): Promise<void>;
246
+ unsubscribe(): Promise<void>;
247
+ post(message: string | PostableMessage | ChatElement): Promise<SentMessage>;
248
+ postEphemeral(user: string | Author, message: AdapterPostableMessage | ChatElement, options: PostEphemeralOptions): Promise<EphemeralMessage | null>;
249
+ schedule(message: AdapterPostableMessage | ChatElement, options: {
250
+ postAt: Date;
251
+ }): Promise<ScheduledMessage>;
252
+ /**
253
+ * Handle streaming from an AsyncIterable.
254
+ * Normalizes the stream (supports both textStream and fullStream from AI SDK),
255
+ * then uses adapter's native streaming if available, otherwise falls back to post+edit.
256
+ */
257
+ private handleStream;
258
+ startTyping(status?: string): Promise<void>;
259
+ /**
260
+ * Fallback streaming implementation using post + edit.
261
+ * Used when adapter doesn't support native streaming.
262
+ * Uses recursive setTimeout to send updates every intervalMs (default 500ms).
263
+ * Schedules next update only after current edit completes to avoid overwhelming slow services.
264
+ */
265
+ private fallbackStream;
266
+ refresh(): Promise<void>;
267
+ mentionUser(userId: string): string;
268
+ /**
269
+ * Serialize the thread to a plain JSON object.
270
+ * Use this to pass thread data to external systems like workflow engines.
271
+ *
272
+ * @example
273
+ * ```typescript
274
+ * // Pass to a workflow
275
+ * await workflow.start("my-workflow", {
276
+ * thread: thread.toJSON(),
277
+ * message: serializeMessage(message),
278
+ * });
279
+ * ```
280
+ */
281
+ toJSON(): SerializedThread;
282
+ /**
283
+ * Reconstruct a Thread from serialized JSON data.
284
+ *
285
+ * Reconstructs a ThreadImpl from serialized data.
286
+ * Uses lazy resolution from Chat.getSingleton() for adapter and state.
287
+ *
288
+ * @param json - Serialized thread data
289
+ * @requires Call `chat.registerSingleton()` before deserializing threads
290
+ *
291
+ * @example
292
+ * ```typescript
293
+ * const thread = ThreadImpl.fromJSON(serializedThread);
294
+ * ```
295
+ */
296
+ static fromJSON<TState = Record<string, unknown>>(json: SerializedThread, adapter?: Adapter): ThreadImpl<TState>;
297
+ /**
298
+ * Serialize a ThreadImpl instance for @workflow/serde.
299
+ * This static method is automatically called by workflow serialization.
300
+ */
301
+ static [WORKFLOW_SERIALIZE](instance: ThreadImpl): SerializedThread;
302
+ /**
303
+ * Deserialize a ThreadImpl from @workflow/serde.
304
+ * Uses lazy adapter resolution from Chat.getSingleton().
305
+ * Requires chat.registerSingleton() to have been called.
306
+ */
307
+ static [WORKFLOW_DESERIALIZE](data: SerializedThread): ThreadImpl;
308
+ private createSentMessage;
309
+ createSentMessageFromMessage(message: Message): SentMessage;
310
+ }
311
+
34
312
  /**
35
313
  * Error types for chat-sdk
36
314
  */
@@ -58,6 +336,20 @@ declare class NotImplementedError extends ChatError {
58
336
  interface ChatConfig<TAdapters extends Record<string, Adapter> = Record<string, Adapter>> {
59
337
  /** Map of adapter name to adapter instance */
60
338
  adapters: TAdapters;
339
+ /**
340
+ * How to handle messages that arrive while a handler is already
341
+ * processing on the same thread.
342
+ *
343
+ * - `'drop'` (default) — discard the message (throw `LockError`)
344
+ * - `'queue'` — queue the message; when the current handler finishes,
345
+ * process only the latest queued message with `context.skipped` containing
346
+ * all intermediate messages
347
+ * - `'debounce'` — all messages start/reset a debounce timer; only the
348
+ * final message in a burst is processed
349
+ * - `'concurrent'` — no locking; all messages processed in parallel
350
+ * - `ConcurrencyConfig` — fine-grained control over strategy and parameters
351
+ */
352
+ concurrency?: ConcurrencyStrategy | ConcurrencyConfig;
61
353
  /**
62
354
  * TTL for message deduplication entries in milliseconds.
63
355
  * Defaults to 300000 (5 minutes). Increase if your webhook cold starts
@@ -72,6 +364,17 @@ interface ChatConfig<TAdapters extends Record<string, Adapter> = Record<string,
72
364
  * wait until some real text has been streamed before creating the message.
73
365
  */
74
366
  fallbackStreamingPlaceholderText?: string | null;
367
+ /**
368
+ * Lock scope determines which messages contend for the same lock.
369
+ *
370
+ * - `'thread'`: lock per threadId (default for most adapters)
371
+ * - `'channel'`: lock per channelId (default for WhatsApp, Telegram)
372
+ * - function: resolve scope dynamically per message (async supported)
373
+ *
374
+ * When not set, falls back to the adapter's `lockScope` property,
375
+ * then to `'thread'`.
376
+ */
377
+ lockScope?: LockScope | ((context: LockScopeContext) => LockScope | Promise<LockScope>);
75
378
  /**
76
379
  * Logger instance or log level.
77
380
  * Pass "silent" to disable all logging.
@@ -88,6 +391,8 @@ interface ChatConfig<TAdapters extends Record<string, Adapter> = Record<string,
88
391
  ttlMs?: number;
89
392
  };
90
393
  /**
394
+ * @deprecated Use `concurrency` instead.
395
+ *
91
396
  * Behavior when a thread lock cannot be acquired (another handler is processing).
92
397
  * - `'drop'` (default) — throw `LockError`, preserving current behavior
93
398
  * - `'force'` — force-release the existing lock and re-acquire
@@ -149,6 +454,8 @@ interface Adapter<TThreadId = unknown, TRawMessage = unknown> {
149
454
  decodeThreadId(threadId: string): TThreadId;
150
455
  /** Delete a message */
151
456
  deleteMessage(threadId: string, messageId: string): Promise<void>;
457
+ /** Cleanup hook called when Chat instance is shutdown */
458
+ disconnect?(): Promise<void>;
152
459
  /** Edit an existing message */
153
460
  editMessage(threadId: string, messageId: string, message: AdapterPostableMessage): Promise<RawMessage<TRawMessage>>;
154
461
  /** Encode platform-specific data into a thread ID string */
@@ -221,6 +528,14 @@ interface Adapter<TThreadId = unknown, TRawMessage = unknown> {
221
528
  * List threads in a channel.
222
529
  */
223
530
  listThreads?(channelId: string, options?: ListThreadsOptions): Promise<ListThreadsResult<TRawMessage>>;
531
+ /**
532
+ * Default lock scope for this adapter.
533
+ * - `'thread'` (default): lock per threadId
534
+ * - `'channel'`: lock per channelId (for channel-based platforms like WhatsApp, Telegram)
535
+ *
536
+ * Can be overridden by `ChatConfig.lockScope`.
537
+ */
538
+ readonly lockScope?: LockScope;
224
539
  /** Unique name for this adapter (e.g., "slack", "teams") */
225
540
  readonly name: string;
226
541
  /**
@@ -436,6 +751,57 @@ interface ChatInstance {
436
751
  channelId: string;
437
752
  }, options?: WebhookOptions): void;
438
753
  }
754
+ /** Lock scope determines which messages contend for the same lock. */
755
+ type LockScope = "thread" | "channel";
756
+ /** Context provided to the lockScope resolver function. */
757
+ interface LockScopeContext {
758
+ adapter: Adapter;
759
+ channelId: string;
760
+ isDM: boolean;
761
+ threadId: string;
762
+ }
763
+ /** Concurrency strategy for overlapping messages on the same thread. */
764
+ type ConcurrencyStrategy = "drop" | "queue" | "debounce" | "concurrent";
765
+ /** Fine-grained concurrency configuration. */
766
+ interface ConcurrencyConfig {
767
+ /** Debounce window in milliseconds (debounce strategy). Default: 1500. */
768
+ debounceMs?: number;
769
+ /** Max concurrent handlers per thread (concurrent strategy). Default: Infinity. */
770
+ maxConcurrent?: number;
771
+ /** Max queued messages per thread (queue/debounce strategy). Default: 10. */
772
+ maxQueueSize?: number;
773
+ /** What to do when queue is full. Default: 'drop-oldest'. */
774
+ onQueueFull?: "drop-oldest" | "drop-newest";
775
+ /** TTL for queued entries in milliseconds. Default: 90000 (90s). */
776
+ queueEntryTtlMs?: number;
777
+ /** The concurrency strategy to use. */
778
+ strategy: ConcurrencyStrategy;
779
+ }
780
+ /**
781
+ * An entry in the per-thread message queue.
782
+ * Used by the `queue` and `debounce` concurrency strategies.
783
+ */
784
+ interface QueueEntry {
785
+ /** When this entry was enqueued (Unix ms). */
786
+ enqueuedAt: number;
787
+ /** When this entry expires (Unix ms). Stale entries are discarded on dequeue. */
788
+ expiresAt: number;
789
+ /** The queued message. */
790
+ message: Message;
791
+ }
792
+ /**
793
+ * Context provided to message handlers when messages were queued
794
+ * while a previous handler was running.
795
+ */
796
+ interface MessageContext {
797
+ /**
798
+ * Messages that arrived while the previous handler was running,
799
+ * in chronological order, excluding the current message (which is the latest).
800
+ */
801
+ skipped: Message[];
802
+ /** Total messages received since last handler ran (skipped.length + 1). */
803
+ totalSinceLastHandler: number;
804
+ }
439
805
  interface StateAdapter {
440
806
  /** Acquire a lock on a thread (returns null if already locked) */
441
807
  acquireLock(threadId: string, ttlMs: number): Promise<Lock | null>;
@@ -448,8 +814,12 @@ interface StateAdapter {
448
814
  connect(): Promise<void>;
449
815
  /** Delete a cached value */
450
816
  delete(key: string): Promise<void>;
817
+ /** Pop the next message from the thread's queue. Returns null if empty. */
818
+ dequeue(threadId: string): Promise<QueueEntry | null>;
451
819
  /** Disconnect from the state backend */
452
820
  disconnect(): Promise<void>;
821
+ /** Atomically append a message to the thread's pending queue. Returns new queue depth. */
822
+ enqueue(threadId: string, entry: QueueEntry, maxSize: number): Promise<number>;
453
823
  /** Extend a lock's TTL */
454
824
  extendLock(lock: Lock, ttlMs: number): Promise<boolean>;
455
825
  /**
@@ -464,6 +834,8 @@ interface StateAdapter {
464
834
  getList<T = unknown>(key: string): Promise<T[]>;
465
835
  /** Check if subscribed to a thread */
466
836
  isSubscribed(threadId: string): Promise<boolean>;
837
+ /** Get the current queue depth for a thread. */
838
+ queueDepth(threadId: string): Promise<number>;
467
839
  /** Release a lock */
468
840
  releaseLock(lock: Lock): Promise<void>;
469
841
  /** Set a cached value with optional TTL in milliseconds */
@@ -566,6 +938,11 @@ interface Channel<TState = Record<string, unknown>, TRawMessage = unknown> exten
566
938
  * Empty iterable on threadless platforms.
567
939
  */
568
940
  threads(): AsyncIterable<ThreadSummary<TRawMessage>>;
941
+ /**
942
+ * Serialize the channel to a plain JSON object.
943
+ * Use this to pass channel data to external systems like workflow engines.
944
+ */
945
+ toJSON(): SerializedChannel;
569
946
  }
570
947
  /**
571
948
  * Lightweight summary of a thread within a channel.
@@ -738,6 +1115,11 @@ interface Thread<TState = Record<string, unknown>, TRawMessage = unknown> extend
738
1115
  * ```
739
1116
  */
740
1117
  subscribe(): Promise<void>;
1118
+ /**
1119
+ * Serialize the thread to a plain JSON object.
1120
+ * Use this to pass thread data to external systems like workflow engines.
1121
+ */
1122
+ toJSON(): SerializedThread;
741
1123
  /**
742
1124
  * Unsubscribe from this thread.
743
1125
  *
@@ -1059,7 +1441,7 @@ interface FileUpload {
1059
1441
  * });
1060
1442
  * ```
1061
1443
  */
1062
- type MentionHandler<TState = Record<string, unknown>> = (thread: Thread<TState>, message: Message) => void | Promise<void>;
1444
+ type MentionHandler<TState = Record<string, unknown>> = (thread: Thread<TState>, message: Message, context?: MessageContext) => void | Promise<void>;
1063
1445
  /**
1064
1446
  * Handler for direct messages (1:1 conversations with the bot).
1065
1447
  *
@@ -1068,14 +1450,14 @@ type MentionHandler<TState = Record<string, unknown>> = (thread: Thread<TState>,
1068
1450
  * handlers are registered, DMs fall through to `onNewMention` for backward
1069
1451
  * compatibility.
1070
1452
  */
1071
- type DirectMessageHandler<TState = Record<string, unknown>> = (thread: Thread<TState>, message: Message, channel: Channel<TState>) => void | Promise<void>;
1453
+ type DirectMessageHandler<TState = Record<string, unknown>> = (thread: Thread<TState>, message: Message, channel: Channel<TState>, context?: MessageContext) => void | Promise<void>;
1072
1454
  /**
1073
1455
  * Handler for messages matching a regex pattern.
1074
1456
  *
1075
1457
  * Registered via `chat.onNewMessage(pattern, handler)`. Called when a message
1076
1458
  * matches the pattern in an unsubscribed thread.
1077
1459
  */
1078
- type MessageHandler<TState = Record<string, unknown>> = (thread: Thread<TState>, message: Message) => void | Promise<void>;
1460
+ type MessageHandler<TState = Record<string, unknown>> = (thread: Thread<TState>, message: Message, context?: MessageContext) => void | Promise<void>;
1079
1461
  /**
1080
1462
  * Handler for messages in subscribed threads.
1081
1463
  *
@@ -1099,7 +1481,7 @@ type MessageHandler<TState = Record<string, unknown>> = (thread: Thread<TState>,
1099
1481
  * });
1100
1482
  * ```
1101
1483
  */
1102
- type SubscribedMessageHandler<TState = Record<string, unknown>> = (thread: Thread<TState>, message: Message) => void | Promise<void>;
1484
+ type SubscribedMessageHandler<TState = Record<string, unknown>> = (thread: Thread<TState>, message: Message, context?: MessageContext) => void | Promise<void>;
1103
1485
  /**
1104
1486
  * Well-known emoji that work across platforms (Slack and Google Chat).
1105
1487
  * These are normalized to a common format regardless of platform.
@@ -1684,165 +2066,59 @@ type AiMessagePart = AiTextPart | AiImagePart | AiFilePart;
1684
2066
  *
1685
2067
  * This is a discriminated union matching AI SDK's ModelMessage type:
1686
2068
  * - User messages can have text, image, and file parts
1687
- * - Assistant messages have string content only
1688
- */
1689
- type AiMessage = AiUserMessage | AiAssistantMessage;
1690
- interface AiUserMessage {
1691
- content: string | AiMessagePart[];
1692
- role: "user";
1693
- }
1694
- interface AiAssistantMessage {
1695
- content: string;
1696
- role: "assistant";
1697
- }
1698
- /**
1699
- * Options for converting messages to AI SDK format.
1700
- */
1701
- interface ToAiMessagesOptions {
1702
- /** When true, prefixes user messages with "[username]: " for multi-user context */
1703
- includeNames?: boolean;
1704
- /**
1705
- * Called when an attachment type is not supported (video, audio).
1706
- * Defaults to `console.warn`.
1707
- */
1708
- onUnsupportedAttachment?: (attachment: Attachment, message: Message) => void;
1709
- /**
1710
- * Called for each message after default processing (text, links, attachments).
1711
- * Return the message (modified or as-is) to include it, or `null` to skip it.
1712
- *
1713
- * @param aiMessage - The processed AI message
1714
- * @param source - The original chat Message
1715
- * @returns The message to include, or null to skip
1716
- */
1717
- transformMessage?: (aiMessage: AiMessage, source: Message) => AiMessage | null | Promise<AiMessage | null>;
1718
- }
1719
- /**
1720
- * Convert chat SDK messages to AI SDK conversation format.
1721
- *
1722
- * - Filters out messages with empty/whitespace-only text
1723
- * - Maps `author.isMe === true` to `"assistant"`, otherwise `"user"`
1724
- * - Uses `message.text` for content
1725
- * - Appends link metadata when available
1726
- * - Includes image attachments and text files as `FilePart`
1727
- * - Uses `fetchData()` when available to include attachment data inline (base64)
1728
- * - Warns on unsupported attachment types (video, audio)
1729
- *
1730
- * Works with `FetchResult.messages`, `thread.recentMessages`, or collected iterables.
1731
- *
1732
- * @example
1733
- * ```typescript
1734
- * const result = await thread.adapter.fetchMessages(thread.id, { limit: 20 });
1735
- * const history = await toAiMessages(result.messages);
1736
- * const response = await agent.stream({ prompt: history });
1737
- * ```
1738
- */
1739
- declare function toAiMessages(messages: Message[], options?: ToAiMessagesOptions): Promise<AiMessage[]>;
1740
-
1741
- interface MessageHistoryConfig {
1742
- /** Maximum messages to keep per thread (default: 100) */
1743
- maxMessages?: number;
1744
- /** TTL for cached history in milliseconds (default: 7 days) */
1745
- ttlMs?: number;
1746
- }
1747
- /**
1748
- * Persistent message history cache backed by the StateAdapter.
1749
- *
1750
- * Used by adapters that lack server-side message history APIs (e.g., WhatsApp, Telegram).
1751
- * Messages are atomically appended via `state.appendToList()`, which is safe
1752
- * without holding a thread lock.
1753
- */
1754
- declare class MessageHistoryCache {
1755
- private readonly state;
1756
- private readonly maxMessages;
1757
- private readonly ttlMs;
1758
- constructor(state: StateAdapter, config?: MessageHistoryConfig);
1759
- /**
1760
- * Atomically append a message to the history for a thread.
1761
- * Trims to maxMessages (keeps newest) and refreshes TTL.
1762
- */
1763
- append(threadId: string, message: Message): Promise<void>;
1764
- /**
1765
- * Get messages for a thread in chronological order (oldest first).
1766
- *
1767
- * @param threadId - The thread ID
1768
- * @param limit - Optional limit on number of messages to return (returns newest N)
1769
- */
1770
- getMessages(threadId: string, limit?: number): Promise<Message[]>;
1771
- }
1772
-
1773
- /**
1774
- * Serialized channel data for passing to external systems (e.g., workflow engines).
1775
- */
1776
- interface SerializedChannel {
1777
- _type: "chat:Channel";
1778
- adapterName: string;
1779
- id: string;
1780
- isDM: boolean;
1781
- }
1782
- /**
1783
- * Config for creating a ChannelImpl with explicit adapter/state instances.
1784
- */
1785
- interface ChannelImplConfigWithAdapter {
1786
- adapter: Adapter;
1787
- id: string;
1788
- isDM?: boolean;
1789
- messageHistory?: MessageHistoryCache;
1790
- stateAdapter: StateAdapter;
1791
- }
1792
- /**
1793
- * Config for creating a ChannelImpl with lazy adapter resolution.
1794
- */
1795
- interface ChannelImplConfigLazy {
1796
- adapterName: string;
1797
- id: string;
1798
- isDM?: boolean;
1799
- }
1800
- type ChannelImplConfig = ChannelImplConfigWithAdapter | ChannelImplConfigLazy;
1801
- declare class ChannelImpl<TState = Record<string, unknown>> implements Channel<TState> {
1802
- readonly id: string;
1803
- readonly isDM: boolean;
1804
- private _adapter?;
1805
- private readonly _adapterName?;
1806
- private _stateAdapterInstance?;
1807
- private _name;
1808
- private readonly _messageHistory?;
1809
- constructor(config: ChannelImplConfig);
1810
- get adapter(): Adapter;
1811
- private get _stateAdapter();
1812
- get name(): string | null;
1813
- get state(): Promise<TState | null>;
1814
- setState(newState: Partial<TState>, options?: {
1815
- replace?: boolean;
1816
- }): Promise<void>;
2069
+ * - Assistant messages have string content only
2070
+ */
2071
+ type AiMessage = AiUserMessage | AiAssistantMessage;
2072
+ interface AiUserMessage {
2073
+ content: string | AiMessagePart[];
2074
+ role: "user";
2075
+ }
2076
+ interface AiAssistantMessage {
2077
+ content: string;
2078
+ role: "assistant";
2079
+ }
2080
+ /**
2081
+ * Options for converting messages to AI SDK format.
2082
+ */
2083
+ interface ToAiMessagesOptions {
2084
+ /** When true, prefixes user messages with "[username]: " for multi-user context */
2085
+ includeNames?: boolean;
1817
2086
  /**
1818
- * Iterate messages newest first (backward from most recent).
1819
- * Uses adapter.fetchChannelMessages if available, otherwise falls back
1820
- * to adapter.fetchMessages with the channel ID.
2087
+ * Called when an attachment type is not supported (video, audio).
2088
+ * Defaults to `console.warn`.
1821
2089
  */
1822
- get messages(): AsyncIterable<Message>;
2090
+ onUnsupportedAttachment?: (attachment: Attachment, message: Message) => void;
1823
2091
  /**
1824
- * Iterate threads in this channel, most recently active first.
2092
+ * Called for each message after default processing (text, links, attachments).
2093
+ * Return the message (modified or as-is) to include it, or `null` to skip it.
2094
+ *
2095
+ * @param aiMessage - The processed AI message
2096
+ * @param source - The original chat Message
2097
+ * @returns The message to include, or null to skip
1825
2098
  */
1826
- threads(): AsyncIterable<ThreadSummary>;
1827
- fetchMetadata(): Promise<ChannelInfo>;
1828
- post(message: string | PostableMessage | ChatElement): Promise<SentMessage>;
1829
- private postSingleMessage;
1830
- postEphemeral(user: string | Author, message: AdapterPostableMessage | ChatElement, options: PostEphemeralOptions): Promise<EphemeralMessage | null>;
1831
- schedule(message: AdapterPostableMessage | ChatElement, options: {
1832
- postAt: Date;
1833
- }): Promise<ScheduledMessage>;
1834
- startTyping(status?: string): Promise<void>;
1835
- mentionUser(userId: string): string;
1836
- toJSON(): SerializedChannel;
1837
- static fromJSON<TState = Record<string, unknown>>(json: SerializedChannel, adapter?: Adapter): ChannelImpl<TState>;
1838
- static [WORKFLOW_SERIALIZE](instance: ChannelImpl): SerializedChannel;
1839
- static [WORKFLOW_DESERIALIZE](data: SerializedChannel): ChannelImpl;
1840
- private createSentMessage;
2099
+ transformMessage?: (aiMessage: AiMessage, source: Message) => AiMessage | null | Promise<AiMessage | null>;
1841
2100
  }
1842
2101
  /**
1843
- * Derive the channel ID from a thread ID.
2102
+ * Convert chat SDK messages to AI SDK conversation format.
2103
+ *
2104
+ * - Filters out messages with empty/whitespace-only text
2105
+ * - Maps `author.isMe === true` to `"assistant"`, otherwise `"user"`
2106
+ * - Uses `message.text` for content
2107
+ * - Appends link metadata when available
2108
+ * - Includes image attachments and text files as `FilePart`
2109
+ * - Uses `fetchData()` when available to include attachment data inline (base64)
2110
+ * - Warns on unsupported attachment types (video, audio)
2111
+ *
2112
+ * Works with `FetchResult.messages`, `thread.recentMessages`, or collected iterables.
2113
+ *
2114
+ * @example
2115
+ * ```typescript
2116
+ * const result = await thread.adapter.fetchMessages(thread.id, { limit: 20 });
2117
+ * const history = await toAiMessages(result.messages);
2118
+ * const response = await agent.stream({ prompt: history });
2119
+ * ```
1844
2120
  */
1845
- declare function deriveChannelId(adapter: Adapter, threadId: string): string;
2121
+ declare function toAiMessages(messages: Message[], options?: ToAiMessagesOptions): Promise<AiMessage[]>;
1846
2122
 
1847
2123
  /** Filter can be EmojiValue objects, emoji names, or raw emoji formats */
1848
2124
  type EmojiFilter = EmojiValue | string;
@@ -1917,6 +2193,9 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
1917
2193
  private readonly _dedupeTtlMs;
1918
2194
  private readonly _onLockConflict;
1919
2195
  private readonly _messageHistory;
2196
+ private readonly _concurrencyStrategy;
2197
+ private readonly _concurrencyConfig;
2198
+ private readonly _lockScope;
1920
2199
  private readonly mentionHandlers;
1921
2200
  private readonly directMessageHandlers;
1922
2201
  private readonly messagePatterns;
@@ -2286,6 +2565,12 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
2286
2565
  * Infer which adapter to use based on the userId format.
2287
2566
  */
2288
2567
  private inferAdapterFromUserId;
2568
+ /**
2569
+ * Resolve the lock key for a message based on lock scope.
2570
+ * With 'thread' scope, returns threadId. With 'channel' scope,
2571
+ * returns channelId (derived via adapter.channelIdFromThreadId).
2572
+ */
2573
+ private getLockKey;
2289
2574
  /**
2290
2575
  * Handle an incoming message from an adapter.
2291
2576
  * This is called by adapters when they receive a webhook.
@@ -2294,9 +2579,36 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
2294
2579
  * - Deduplication: Same message may arrive multiple times (e.g., Slack sends
2295
2580
  * both `message` and `app_mention` events, GChat sends direct webhook + Pub/Sub)
2296
2581
  * - Bot filtering: Messages from the bot itself are skipped
2297
- * - Locking: Only one instance processes a thread at a time
2582
+ * - Concurrency: Controlled by `concurrency` config (drop, queue, debounce, concurrent)
2298
2583
  */
2299
2584
  handleIncomingMessage(adapter: Adapter, threadId: string, message: Message): Promise<void>;
2585
+ /**
2586
+ * Drop strategy: acquire lock or fail. Original behavior.
2587
+ */
2588
+ private handleDrop;
2589
+ /**
2590
+ * Queue/Debounce strategy: enqueue if lock is busy, drain after processing.
2591
+ */
2592
+ private handleQueueOrDebounce;
2593
+ /**
2594
+ * Debounce loop: wait for debounceMs, check if newer message arrived,
2595
+ * repeat until no new messages, then process the final message.
2596
+ */
2597
+ private debounceLoop;
2598
+ /**
2599
+ * Drain queue: collect all pending messages, dispatch the latest with
2600
+ * skipped context, then check for more.
2601
+ */
2602
+ private drainQueue;
2603
+ /**
2604
+ * Concurrent strategy: no locking, process immediately.
2605
+ */
2606
+ private handleConcurrent;
2607
+ /**
2608
+ * Dispatch a message to the appropriate handler chain based on
2609
+ * subscription status, mention detection, and pattern matching.
2610
+ */
2611
+ private dispatchToHandlers;
2300
2612
  private createThread;
2301
2613
  /**
2302
2614
  * Detect if the bot was mentioned in the message.
@@ -2304,6 +2616,13 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
2304
2616
  */
2305
2617
  private detectMention;
2306
2618
  private escapeRegex;
2619
+ /**
2620
+ * Reconstruct a proper Message instance from a dequeued entry.
2621
+ * After JSON roundtrip through the state adapter, the message is a plain
2622
+ * object (not a Message instance). This restores class invariants like
2623
+ * `links` defaulting to `[]` and `metadata.dateSent` being a Date.
2624
+ */
2625
+ private rehydrateMessage;
2307
2626
  private runHandlers;
2308
2627
  }
2309
2628
 
@@ -2374,178 +2693,6 @@ declare class StreamingMarkdownRenderer {
2374
2693
  finish(): string;
2375
2694
  }
2376
2695
 
2377
- /**
2378
- * Serialized thread data for passing to external systems (e.g., workflow engines).
2379
- */
2380
- interface SerializedThread {
2381
- _type: "chat:Thread";
2382
- adapterName: string;
2383
- channelId: string;
2384
- currentMessage?: SerializedMessage;
2385
- id: string;
2386
- isDM: boolean;
2387
- }
2388
- /**
2389
- * Config for creating a ThreadImpl with explicit adapter/state instances.
2390
- */
2391
- interface ThreadImplConfigWithAdapter {
2392
- adapter: Adapter;
2393
- channelId: string;
2394
- currentMessage?: Message;
2395
- fallbackStreamingPlaceholderText?: string | null;
2396
- id: string;
2397
- initialMessage?: Message;
2398
- isDM?: boolean;
2399
- isSubscribedContext?: boolean;
2400
- logger?: Logger;
2401
- messageHistory?: MessageHistoryCache;
2402
- stateAdapter: StateAdapter;
2403
- streamingUpdateIntervalMs?: number;
2404
- }
2405
- /**
2406
- * Config for creating a ThreadImpl with lazy adapter resolution.
2407
- * The adapter will be looked up from the Chat singleton on first access.
2408
- */
2409
- interface ThreadImplConfigLazy {
2410
- adapterName: string;
2411
- channelId: string;
2412
- currentMessage?: Message;
2413
- fallbackStreamingPlaceholderText?: string | null;
2414
- id: string;
2415
- initialMessage?: Message;
2416
- isDM?: boolean;
2417
- isSubscribedContext?: boolean;
2418
- logger?: Logger;
2419
- streamingUpdateIntervalMs?: number;
2420
- }
2421
- type ThreadImplConfig = ThreadImplConfigWithAdapter | ThreadImplConfigLazy;
2422
- declare class ThreadImpl<TState = Record<string, unknown>> implements Thread<TState> {
2423
- readonly id: string;
2424
- readonly channelId: string;
2425
- readonly isDM: boolean;
2426
- /** Direct adapter instance (if provided) */
2427
- private _adapter?;
2428
- /** Adapter name for lazy resolution */
2429
- private readonly _adapterName?;
2430
- /** Direct state adapter instance (if provided) */
2431
- private _stateAdapterInstance?;
2432
- private _recentMessages;
2433
- private readonly _isSubscribedContext;
2434
- /** Current message context for streaming - provides userId/teamId */
2435
- private readonly _currentMessage?;
2436
- /** Update interval for fallback streaming */
2437
- private readonly _streamingUpdateIntervalMs;
2438
- /** Placeholder text for fallback streaming (post + edit) */
2439
- private readonly _fallbackStreamingPlaceholderText;
2440
- /** Cached channel instance */
2441
- private _channel?;
2442
- /** Message history cache (set only for adapters with persistMessageHistory) */
2443
- private readonly _messageHistory?;
2444
- private readonly _logger?;
2445
- constructor(config: ThreadImplConfig);
2446
- /**
2447
- * Get the adapter for this thread.
2448
- * If created with lazy config, resolves from Chat singleton on first access.
2449
- */
2450
- get adapter(): Adapter;
2451
- /**
2452
- * Get the state adapter for this thread.
2453
- * If created with lazy config, resolves from Chat singleton on first access.
2454
- */
2455
- private get _stateAdapter();
2456
- get recentMessages(): Message[];
2457
- set recentMessages(messages: Message[]);
2458
- /**
2459
- * Get the current thread state.
2460
- * Returns null if no state has been set.
2461
- */
2462
- get state(): Promise<TState | null>;
2463
- /**
2464
- * Set the thread state. Merges with existing state by default.
2465
- * State is persisted for 30 days.
2466
- */
2467
- setState(newState: Partial<TState>, options?: {
2468
- replace?: boolean;
2469
- }): Promise<void>;
2470
- /**
2471
- * Get the Channel containing this thread.
2472
- * Lazy-created and cached.
2473
- */
2474
- get channel(): Channel<TState>;
2475
- /**
2476
- * Iterate messages newest first (backward from most recent).
2477
- * Auto-paginates lazily.
2478
- */
2479
- get messages(): AsyncIterable<Message>;
2480
- get allMessages(): AsyncIterable<Message>;
2481
- isSubscribed(): Promise<boolean>;
2482
- subscribe(): Promise<void>;
2483
- unsubscribe(): Promise<void>;
2484
- post(message: string | PostableMessage | ChatElement): Promise<SentMessage>;
2485
- postEphemeral(user: string | Author, message: AdapterPostableMessage | ChatElement, options: PostEphemeralOptions): Promise<EphemeralMessage | null>;
2486
- schedule(message: AdapterPostableMessage | ChatElement, options: {
2487
- postAt: Date;
2488
- }): Promise<ScheduledMessage>;
2489
- /**
2490
- * Handle streaming from an AsyncIterable.
2491
- * Normalizes the stream (supports both textStream and fullStream from AI SDK),
2492
- * then uses adapter's native streaming if available, otherwise falls back to post+edit.
2493
- */
2494
- private handleStream;
2495
- startTyping(status?: string): Promise<void>;
2496
- /**
2497
- * Fallback streaming implementation using post + edit.
2498
- * Used when adapter doesn't support native streaming.
2499
- * Uses recursive setTimeout to send updates every intervalMs (default 500ms).
2500
- * Schedules next update only after current edit completes to avoid overwhelming slow services.
2501
- */
2502
- private fallbackStream;
2503
- refresh(): Promise<void>;
2504
- mentionUser(userId: string): string;
2505
- /**
2506
- * Serialize the thread to a plain JSON object.
2507
- * Use this to pass thread data to external systems like workflow engines.
2508
- *
2509
- * @example
2510
- * ```typescript
2511
- * // Pass to a workflow
2512
- * await workflow.start("my-workflow", {
2513
- * thread: thread.toJSON(),
2514
- * message: serializeMessage(message),
2515
- * });
2516
- * ```
2517
- */
2518
- toJSON(): SerializedThread;
2519
- /**
2520
- * Reconstruct a Thread from serialized JSON data.
2521
- *
2522
- * Reconstructs a ThreadImpl from serialized data.
2523
- * Uses lazy resolution from Chat.getSingleton() for adapter and state.
2524
- *
2525
- * @param json - Serialized thread data
2526
- * @requires Call `chat.registerSingleton()` before deserializing threads
2527
- *
2528
- * @example
2529
- * ```typescript
2530
- * const thread = ThreadImpl.fromJSON(serializedThread);
2531
- * ```
2532
- */
2533
- static fromJSON<TState = Record<string, unknown>>(json: SerializedThread, adapter?: Adapter): ThreadImpl<TState>;
2534
- /**
2535
- * Serialize a ThreadImpl instance for @workflow/serde.
2536
- * This static method is automatically called by workflow serialization.
2537
- */
2538
- static [WORKFLOW_SERIALIZE](instance: ThreadImpl): SerializedThread;
2539
- /**
2540
- * Deserialize a ThreadImpl from @workflow/serde.
2541
- * Uses lazy adapter resolution from Chat.getSingleton().
2542
- * Requires chat.registerSingleton() to have been called.
2543
- */
2544
- static [WORKFLOW_DESERIALIZE](data: SerializedThread): ThreadImpl;
2545
- private createSentMessage;
2546
- createSentMessageFromMessage(message: Message): SentMessage;
2547
- }
2548
-
2549
2696
  /**
2550
2697
  * Get or create an immutable singleton EmojiValue.
2551
2698
  *
@@ -2989,4 +3136,4 @@ declare const Select: SelectComponent;
2989
3136
  declare const SelectOption: SelectOptionComponent;
2990
3137
  declare const TextInput: TextInputComponent;
2991
3138
 
2992
- export { type ActionEvent, type ActionHandler, Actions, ActionsComponent, type Adapter, type AdapterPostableMessage, 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, Chat, type ChatConfig, ChatElement, ChatError, type ChatInstance, 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 LogLevel, type Logger, type MarkdownConverter, type MarkdownTextChunk, type MemberJoinedChannelEvent, type MemberJoinedChannelHandler, type MentionHandler, Message, 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, type PlanUpdateChunk, type PostEphemeralOptions, type Postable, type PostableAst, type PostableCard, type PostableMarkdown, type PostableMessage, type PostableRaw, 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 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 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, isStrongNode, isTableCellNode, isTableNode, isTableRowNode, isTextNode, link, markdownToPlainText, paragraph, parseMarkdown, root, strikethrough, stringifyMarkdown, strong, tableElementToAscii, tableToAscii, text, toAiMessages, toCardElement, toModalElement, toPlainText, walkAst };
3139
+ export { type ActionEvent, type ActionHandler, Actions, ActionsComponent, type Adapter, type AdapterPostableMessage, 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, Chat, type ChatConfig, ChatElement, ChatError, type ChatInstance, 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, type PlanUpdateChunk, type PostEphemeralOptions, type Postable, type PostableAst, type PostableCard, type PostableMarkdown, type PostableMessage, 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 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 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, isStrongNode, isTableCellNode, isTableNode, isTableRowNode, isTextNode, link, markdownToPlainText, paragraph, parseMarkdown, root, strikethrough, stringifyMarkdown, strong, tableElementToAscii, tableToAscii, text, toAiMessages, toCardElement, toModalElement, toPlainText, walkAst };