chat 4.11.0 → 4.13.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
@@ -234,6 +234,29 @@ interface Adapter<TThreadId = unknown, TRawMessage = unknown> {
234
234
  * @returns The raw message after streaming completes
235
235
  */
236
236
  stream?(threadId: string, textStream: AsyncIterable<string>, options?: StreamOptions): Promise<RawMessage<TRawMessage>>;
237
+ /**
238
+ * Derive channel ID from a thread ID.
239
+ * Default fallback: first two colon-separated parts (e.g., "slack:C123").
240
+ * Adapters with different structures should override this.
241
+ */
242
+ channelIdFromThreadId?(threadId: string): string;
243
+ /**
244
+ * Fetch channel-level messages (top-level, not thread replies).
245
+ * For example, Slack's conversations.history vs conversations.replies.
246
+ */
247
+ fetchChannelMessages?(channelId: string, options?: FetchOptions): Promise<FetchResult<TRawMessage>>;
248
+ /**
249
+ * List threads in a channel.
250
+ */
251
+ listThreads?(channelId: string, options?: ListThreadsOptions): Promise<ListThreadsResult<TRawMessage>>;
252
+ /**
253
+ * Fetch channel info/metadata.
254
+ */
255
+ fetchChannelInfo?(channelId: string): Promise<ChannelInfo>;
256
+ /**
257
+ * Post a message to channel top-level (not in a thread).
258
+ */
259
+ postChannelMessage?(channelId: string, message: AdapterPostableMessage): Promise<RawMessage<TRawMessage>>;
237
260
  }
238
261
  /**
239
262
  * Options for streaming messages.
@@ -246,6 +269,8 @@ interface StreamOptions {
246
269
  recipientTeamId?: string;
247
270
  /** Minimum interval between updates in ms (default: 1000). Used for fallback mode (GChat/Teams). */
248
271
  updateIntervalMs?: number;
272
+ /** Block Kit elements to attach when stopping the stream (Slack only, via chat.stopStream) */
273
+ stopBlocks?: unknown[];
249
274
  }
250
275
  /** Internal interface for Chat instance passed to adapters */
251
276
  interface ChatInstance {
@@ -286,19 +311,33 @@ interface ChatInstance {
286
311
  /**
287
312
  * Process a modal submit event from an adapter.
288
313
  *
289
- * @param event - The modal submit event (without relatedThread/relatedMessage)
290
- * @param contextId - Context ID for retrieving stored thread/message context
314
+ * @param event - The modal submit event (without relatedThread/relatedMessage/relatedChannel)
315
+ * @param contextId - Context ID for retrieving stored thread/message/channel context
291
316
  * @param options - Webhook options
292
317
  */
293
- processModalSubmit(event: Omit<ModalSubmitEvent, "relatedThread" | "relatedMessage">, contextId?: string, options?: WebhookOptions): Promise<ModalResponse | undefined>;
318
+ processModalSubmit(event: Omit<ModalSubmitEvent, "relatedThread" | "relatedMessage" | "relatedChannel">, contextId?: string, options?: WebhookOptions): Promise<ModalResponse | undefined>;
294
319
  /**
295
320
  * Process a modal close event from an adapter.
296
321
  *
297
- * @param event - The modal close event (without relatedThread/relatedMessage)
298
- * @param contextId - Context ID for retrieving stored thread/message context
322
+ * @param event - The modal close event (without relatedThread/relatedMessage/relatedChannel)
323
+ * @param contextId - Context ID for retrieving stored thread/message/channel context
299
324
  * @param options - Webhook options
300
325
  */
301
- processModalClose(event: Omit<ModalCloseEvent, "relatedThread" | "relatedMessage">, contextId?: string, options?: WebhookOptions): void;
326
+ processModalClose(event: Omit<ModalCloseEvent, "relatedThread" | "relatedMessage" | "relatedChannel">, contextId?: string, options?: WebhookOptions): void;
327
+ /**
328
+ * Process an incoming slash command from an adapter.
329
+ * Handles waitUntil registration and error catching internally.
330
+ *
331
+ * @param event - The slash command event
332
+ * @param options - Webhook options including waitUntil
333
+ */
334
+ processSlashCommand(event: Omit<SlashCommandEvent, "channel" | "openModal"> & {
335
+ adapter: Adapter;
336
+ channelId: string;
337
+ }, options?: WebhookOptions): void;
338
+ processAssistantThreadStarted(event: AssistantThreadStartedEvent, options?: WebhookOptions): void;
339
+ processAssistantContextChanged(event: AssistantContextChangedEvent, options?: WebhookOptions): void;
340
+ processAppHomeOpened(event: AppHomeOpenedEvent, options?: WebhookOptions): void;
302
341
  getState(): StateAdapter;
303
342
  getUserName(): string;
304
343
  /** Get the configured logger, optionally with a child prefix */
@@ -335,54 +374,121 @@ interface Lock {
335
374
  token: string;
336
375
  expiresAt: number;
337
376
  }
338
- /** Default TTL for thread state (30 days in milliseconds) */
339
- declare const THREAD_STATE_TTL_MS: number;
340
377
  /**
341
- * Thread interface with support for custom state.
342
- * @template TState - Custom state type stored per-thread (default: Record<string, unknown>)
378
+ * Base interface for entities that can receive messages.
379
+ * Both Thread and Channel extend this interface.
380
+ *
381
+ * @template TState - Custom state type stored per entity
343
382
  * @template TRawMessage - Platform-specific raw message type
344
383
  */
345
- interface Thread<TState = Record<string, unknown>, TRawMessage = unknown> {
346
- /** Unique thread ID (format: "adapter:channel:thread") */
384
+ interface Postable<TState = Record<string, unknown>, TRawMessage = unknown> {
385
+ /** Unique ID */
347
386
  readonly id: string;
348
- /** The adapter this thread belongs to */
387
+ /** The adapter this entity belongs to */
349
388
  readonly adapter: Adapter;
350
- /** Channel/conversation ID */
351
- readonly channelId: string;
352
389
  /** Whether this is a direct message conversation */
353
390
  readonly isDM: boolean;
354
391
  /**
355
- * Get the current thread state.
392
+ * Get the current state.
356
393
  * Returns null if no state has been set.
357
- *
358
- * @example
359
- * ```typescript
360
- * const state = await thread.state;
361
- * if (state?.aiMode) {
362
- * // AI mode is enabled
363
- * }
364
- * ```
365
394
  */
366
395
  readonly state: Promise<TState | null>;
367
396
  /**
368
- * Set the thread state. Merges with existing state by default.
369
- * State is persisted for 30 days.
370
- *
371
- * @param state - Partial state to merge, or full state if replace is true
372
- * @param options - Options for setting state
373
- *
374
- * @example
375
- * ```typescript
376
- * // Merge with existing state
377
- * await thread.setState({ aiMode: true });
378
- *
379
- * // Replace entire state
380
- * await thread.setState({ aiMode: true }, { replace: true });
381
- * ```
397
+ * Set the state. Merges with existing state by default.
382
398
  */
383
399
  setState(state: Partial<TState>, options?: {
384
400
  replace?: boolean;
385
401
  }): Promise<void>;
402
+ /**
403
+ * Iterate messages newest first (backward from most recent).
404
+ * Auto-paginates lazily — only fetches pages as consumed.
405
+ */
406
+ readonly messages: AsyncIterable<Message<TRawMessage>>;
407
+ /**
408
+ * Post a message.
409
+ */
410
+ post(message: string | PostableMessage | CardJSXElement): Promise<SentMessage<TRawMessage>>;
411
+ /**
412
+ * Post an ephemeral message visible only to a specific user.
413
+ */
414
+ postEphemeral(user: string | Author, message: AdapterPostableMessage | CardJSXElement, options: PostEphemeralOptions): Promise<EphemeralMessage | null>;
415
+ /** Show typing indicator */
416
+ startTyping(): Promise<void>;
417
+ /**
418
+ * Get a platform-specific mention string for a user.
419
+ */
420
+ mentionUser(userId: string): string;
421
+ }
422
+ /**
423
+ * Represents a channel/conversation container that holds threads.
424
+ * Extends Postable for message posting capabilities.
425
+ *
426
+ * @template TState - Custom state type stored per channel
427
+ * @template TRawMessage - Platform-specific raw message type
428
+ */
429
+ interface Channel<TState = Record<string, unknown>, TRawMessage = unknown> extends Postable<TState, TRawMessage> {
430
+ /** Channel name (e.g., "#general"). Null until fetchInfo() is called. */
431
+ readonly name: string | null;
432
+ /**
433
+ * Iterate threads in this channel, most recently active first.
434
+ * Returns ThreadSummary (lightweight) for efficiency.
435
+ * Empty iterable on threadless platforms.
436
+ */
437
+ threads(): AsyncIterable<ThreadSummary<TRawMessage>>;
438
+ /** Fetch channel metadata from the platform */
439
+ fetchMetadata(): Promise<ChannelInfo>;
440
+ }
441
+ /**
442
+ * Lightweight summary of a thread within a channel.
443
+ */
444
+ interface ThreadSummary<TRawMessage = unknown> {
445
+ /** Full thread ID */
446
+ id: string;
447
+ /** Root/first message of the thread */
448
+ rootMessage: Message<TRawMessage>;
449
+ /** Reply count (if available) */
450
+ replyCount?: number;
451
+ /** Timestamp of most recent reply */
452
+ lastReplyAt?: Date;
453
+ }
454
+ /**
455
+ * Channel metadata returned by fetchInfo().
456
+ */
457
+ interface ChannelInfo {
458
+ id: string;
459
+ name?: string;
460
+ isDM?: boolean;
461
+ memberCount?: number;
462
+ metadata: Record<string, unknown>;
463
+ }
464
+ /**
465
+ * Options for listing threads in a channel.
466
+ */
467
+ interface ListThreadsOptions {
468
+ limit?: number;
469
+ cursor?: string;
470
+ }
471
+ /**
472
+ * Result of listing threads in a channel.
473
+ */
474
+ interface ListThreadsResult<TRawMessage = unknown> {
475
+ threads: ThreadSummary<TRawMessage>[];
476
+ nextCursor?: string;
477
+ }
478
+ /** Default TTL for thread state (30 days in milliseconds) */
479
+ declare const THREAD_STATE_TTL_MS: number;
480
+ /**
481
+ * Thread interface with support for custom state.
482
+ * Extends Postable for shared message posting capabilities.
483
+ *
484
+ * @template TState - Custom state type stored per-thread (default: Record<string, unknown>)
485
+ * @template TRawMessage - Platform-specific raw message type
486
+ */
487
+ interface Thread<TState = Record<string, unknown>, TRawMessage = unknown> extends Postable<TState, TRawMessage> {
488
+ /** Channel/conversation ID */
489
+ readonly channelId: string;
490
+ /** Get the Channel containing this thread */
491
+ readonly channel: Channel<TState, TRawMessage>;
386
492
  /** Recently fetched messages (cached) */
387
493
  recentMessages: Message<TRawMessage>[];
388
494
  /**
@@ -1014,6 +1120,11 @@ interface ModalSubmitEvent<TRawMessage = unknown> {
1014
1120
  * This is a SentMessage with edit/delete capabilities.
1015
1121
  */
1016
1122
  relatedMessage?: SentMessage<TRawMessage>;
1123
+ /**
1124
+ * The channel where the modal was originally triggered from.
1125
+ * Available when the modal was opened via SlashCommandEvent.openModal().
1126
+ */
1127
+ relatedChannel?: Channel<Record<string, unknown>, TRawMessage>;
1017
1128
  }
1018
1129
  /**
1019
1130
  * Event emitted when a user closes/cancels a modal (requires notifyOnClose).
@@ -1045,6 +1156,11 @@ interface ModalCloseEvent<TRawMessage = unknown> {
1045
1156
  * This is a SentMessage with edit/delete capabilities.
1046
1157
  */
1047
1158
  relatedMessage?: SentMessage<TRawMessage>;
1159
+ /**
1160
+ * The channel where the modal was originally triggered from.
1161
+ * Available when the modal was opened via SlashCommandEvent.openModal().
1162
+ */
1163
+ relatedChannel?: Channel<Record<string, unknown>, TRawMessage>;
1048
1164
  }
1049
1165
  type ModalErrorsResponse = {
1050
1166
  action: "errors";
@@ -1064,6 +1180,123 @@ type ModalCloseResponse = {
1064
1180
  type ModalResponse = ModalCloseResponse | ModalErrorsResponse | ModalUpdateResponse | ModalPushResponse;
1065
1181
  type ModalSubmitHandler = (event: ModalSubmitEvent) => Promise<ModalResponse | undefined>;
1066
1182
  type ModalCloseHandler = (event: ModalCloseEvent) => Promise<void>;
1183
+ /**
1184
+ * Event emitted when a user invokes a slash command.
1185
+ *
1186
+ * Slash commands are triggered when a user types `/command` in the message composer.
1187
+ * The event provides access to the channel where the command was invoked, allowing
1188
+ * you to post responses using standard SDK methods.
1189
+ *
1190
+ * @example
1191
+ * ```typescript
1192
+ * chat.onSlashCommand("/help", async (event) => {
1193
+ * // Post visible to everyone in the channel
1194
+ * await event.channel.post("Here are the available commands...");
1195
+ * });
1196
+ *
1197
+ * chat.onSlashCommand("/secret", async (event) => {
1198
+ * // Post ephemeral (only the invoking user sees it)
1199
+ * await event.channel.postEphemeral(
1200
+ * event.user,
1201
+ * "This is just for you!",
1202
+ * { fallbackToDM: false }
1203
+ * );
1204
+ * });
1205
+ *
1206
+ * chat.onSlashCommand("/feedback", async (event) => {
1207
+ * // Open a modal
1208
+ * await event.openModal({
1209
+ * type: "modal",
1210
+ * callbackId: "feedback_modal",
1211
+ * title: "Submit Feedback",
1212
+ * children: [{ type: "text_input", id: "feedback", label: "Your feedback" }],
1213
+ * });
1214
+ * });
1215
+ * ```
1216
+ */
1217
+ interface SlashCommandEvent<TState = Record<string, unknown>> {
1218
+ /** The slash command name (e.g., "/help") */
1219
+ command: string;
1220
+ /** Arguments text after the command (e.g., "topic search" from "/help topic search") */
1221
+ text: string;
1222
+ /** The user who invoked the command */
1223
+ user: Author;
1224
+ /** The channel where the command was invoked */
1225
+ channel: Channel<TState>;
1226
+ /** The adapter that received this event */
1227
+ adapter: Adapter;
1228
+ /** Platform-specific raw payload */
1229
+ raw: unknown;
1230
+ /** Trigger ID for opening modals (time-limited, typically ~3 seconds) */
1231
+ triggerId?: string;
1232
+ /**
1233
+ * Open a modal/dialog form in response to this slash command.
1234
+ *
1235
+ * @param modal - The modal element to display (JSX or ModalElement)
1236
+ * @returns The view/dialog ID, or undefined if modals are not supported
1237
+ */
1238
+ openModal(modal: ModalElement | CardJSXElement): Promise<{
1239
+ viewId: string;
1240
+ } | undefined>;
1241
+ }
1242
+ /**
1243
+ * Handler for slash command events.
1244
+ *
1245
+ * @example
1246
+ * ```typescript
1247
+ * // Handle a specific command
1248
+ * chat.onSlashCommand("/status", async (event) => {
1249
+ * await event.channel.post("All systems operational!");
1250
+ * });
1251
+ *
1252
+ * // Handle multiple commands
1253
+ * chat.onSlashCommand(["/help", "/info"], async (event) => {
1254
+ * await event.channel.post(`You invoked ${event.command}`);
1255
+ * });
1256
+ *
1257
+ * // Catch-all handler
1258
+ * chat.onSlashCommand(async (event) => {
1259
+ * console.log(`Command: ${event.command}, Args: ${event.text}`);
1260
+ * });
1261
+ * ```
1262
+ */
1263
+ type SlashCommandHandler<TState = Record<string, unknown>> = (event: SlashCommandEvent<TState>) => Promise<void>;
1264
+ interface AssistantThreadStartedEvent {
1265
+ threadId: string;
1266
+ userId: string;
1267
+ channelId: string;
1268
+ threadTs: string;
1269
+ context: {
1270
+ channelId?: string;
1271
+ teamId?: string;
1272
+ enterpriseId?: string;
1273
+ threadEntryPoint?: string;
1274
+ forceSearch?: boolean;
1275
+ };
1276
+ adapter: Adapter;
1277
+ }
1278
+ type AssistantThreadStartedHandler = (event: AssistantThreadStartedEvent) => Promise<void>;
1279
+ interface AssistantContextChangedEvent {
1280
+ threadId: string;
1281
+ userId: string;
1282
+ channelId: string;
1283
+ threadTs: string;
1284
+ context: {
1285
+ channelId?: string;
1286
+ teamId?: string;
1287
+ enterpriseId?: string;
1288
+ threadEntryPoint?: string;
1289
+ forceSearch?: boolean;
1290
+ };
1291
+ adapter: Adapter;
1292
+ }
1293
+ type AssistantContextChangedHandler = (event: AssistantContextChangedEvent) => Promise<void>;
1294
+ interface AppHomeOpenedEvent {
1295
+ userId: string;
1296
+ channelId: string;
1297
+ adapter: Adapter;
1298
+ }
1299
+ type AppHomeOpenedHandler = (event: AppHomeOpenedEvent) => Promise<void>;
1067
1300
 
1068
1301
  /**
1069
1302
  * Message class with serialization support for workflow engines.
@@ -1212,6 +1445,77 @@ declare class Message<TRawMessage = unknown> {
1212
1445
  static [WORKFLOW_DESERIALIZE](data: SerializedMessage): Message;
1213
1446
  }
1214
1447
 
1448
+ /**
1449
+ * Serialized channel data for passing to external systems (e.g., workflow engines).
1450
+ */
1451
+ interface SerializedChannel {
1452
+ _type: "chat:Channel";
1453
+ id: string;
1454
+ adapterName: string;
1455
+ isDM: boolean;
1456
+ }
1457
+ /**
1458
+ * Config for creating a ChannelImpl with explicit adapter/state instances.
1459
+ */
1460
+ interface ChannelImplConfigWithAdapter {
1461
+ id: string;
1462
+ adapter: Adapter;
1463
+ stateAdapter: StateAdapter;
1464
+ isDM?: boolean;
1465
+ }
1466
+ /**
1467
+ * Config for creating a ChannelImpl with lazy adapter resolution.
1468
+ */
1469
+ interface ChannelImplConfigLazy {
1470
+ id: string;
1471
+ adapterName: string;
1472
+ isDM?: boolean;
1473
+ }
1474
+ type ChannelImplConfig = ChannelImplConfigWithAdapter | ChannelImplConfigLazy;
1475
+ declare class ChannelImpl<TState = Record<string, unknown>> implements Channel<TState> {
1476
+ readonly id: string;
1477
+ readonly isDM: boolean;
1478
+ private _adapter?;
1479
+ private _adapterName?;
1480
+ private _stateAdapterInstance?;
1481
+ private _name;
1482
+ constructor(config: ChannelImplConfig);
1483
+ get adapter(): Adapter;
1484
+ private get _stateAdapter();
1485
+ get name(): string | null;
1486
+ get state(): Promise<TState | null>;
1487
+ setState(newState: Partial<TState>, options?: {
1488
+ replace?: boolean;
1489
+ }): Promise<void>;
1490
+ /**
1491
+ * Iterate messages newest first (backward from most recent).
1492
+ * Uses adapter.fetchChannelMessages if available, otherwise falls back
1493
+ * to adapter.fetchMessages with the channel ID.
1494
+ */
1495
+ get messages(): AsyncIterable<Message>;
1496
+ /**
1497
+ * Iterate threads in this channel, most recently active first.
1498
+ */
1499
+ threads(): AsyncIterable<ThreadSummary>;
1500
+ fetchMetadata(): Promise<ChannelInfo>;
1501
+ post(message: string | PostableMessage | CardJSXElement): Promise<SentMessage>;
1502
+ private postSingleMessage;
1503
+ postEphemeral(user: string | Author, message: AdapterPostableMessage | CardJSXElement, options: PostEphemeralOptions): Promise<EphemeralMessage | null>;
1504
+ startTyping(): Promise<void>;
1505
+ mentionUser(userId: string): string;
1506
+ toJSON(): SerializedChannel;
1507
+ static fromJSON<TState = Record<string, unknown>>(json: SerializedChannel, adapter?: Adapter): ChannelImpl<TState>;
1508
+ static [WORKFLOW_SERIALIZE](instance: ChannelImpl): SerializedChannel;
1509
+ static [WORKFLOW_DESERIALIZE](data: SerializedChannel): ChannelImpl;
1510
+ private createSentMessage;
1511
+ }
1512
+ /**
1513
+ * Derive the channel ID from a thread ID.
1514
+ * Uses adapter.channelIdFromThreadId if available, otherwise defaults to
1515
+ * first two colon-separated parts.
1516
+ */
1517
+ declare function deriveChannelId(adapter: Adapter, threadId: string): string;
1518
+
1215
1519
  /** Filter can be EmojiValue objects, emoji names, or raw emoji formats */
1216
1520
  type EmojiFilter = EmojiValue | string;
1217
1521
  /**
@@ -1288,6 +1592,10 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
1288
1592
  private actionHandlers;
1289
1593
  private modalSubmitHandlers;
1290
1594
  private modalCloseHandlers;
1595
+ private slashCommandHandlers;
1596
+ private assistantThreadStartedHandlers;
1597
+ private assistantContextChangedHandlers;
1598
+ private appHomeOpenedHandlers;
1291
1599
  /** Initialization state */
1292
1600
  private initPromise;
1293
1601
  private initialized;
@@ -1445,6 +1753,48 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
1445
1753
  onModalClose(handler: ModalCloseHandler): void;
1446
1754
  onModalClose(callbackId: string, handler: ModalCloseHandler): void;
1447
1755
  onModalClose(callbackIds: string[], handler: ModalCloseHandler): void;
1756
+ /**
1757
+ * Register a handler for slash command events.
1758
+ *
1759
+ * Slash commands are triggered when a user types `/command` in the message composer.
1760
+ * Use `event.channel.post()` or `event.channel.postEphemeral()` to respond.
1761
+ *
1762
+ * @example
1763
+ * ```typescript
1764
+ * // Handle a specific command
1765
+ * chat.onSlashCommand("/help", async (event) => {
1766
+ * await event.channel.post("Here are the available commands...");
1767
+ * });
1768
+ *
1769
+ * // Handle multiple commands
1770
+ * chat.onSlashCommand(["/status", "/health"], async (event) => {
1771
+ * await event.channel.post("All systems operational!");
1772
+ * });
1773
+ *
1774
+ * // Handle all commands (catch-all)
1775
+ * chat.onSlashCommand(async (event) => {
1776
+ * console.log(`Received command: ${event.command} ${event.text}`);
1777
+ * });
1778
+ *
1779
+ * // Open a modal from a slash command
1780
+ * chat.onSlashCommand("/feedback", async (event) => {
1781
+ * await event.openModal({
1782
+ * callbackId: "feedback_modal",
1783
+ * title: "Submit Feedback",
1784
+ * inputs: [{ id: "feedback", type: "text_input", label: "Your feedback" }],
1785
+ * });
1786
+ * });
1787
+ * ```
1788
+ *
1789
+ * @param commandOrHandler - Either a command, array of commands, or the handler
1790
+ * @param handler - The handler (if command filter is provided)
1791
+ */
1792
+ onSlashCommand(handler: SlashCommandHandler<TState>): void;
1793
+ onSlashCommand(command: string, handler: SlashCommandHandler<TState>): void;
1794
+ onSlashCommand(commands: string[], handler: SlashCommandHandler<TState>): void;
1795
+ onAssistantThreadStarted(handler: AssistantThreadStartedHandler): void;
1796
+ onAssistantContextChanged(handler: AssistantContextChangedHandler): void;
1797
+ onAppHomeOpened(handler: AppHomeOpenedHandler): void;
1448
1798
  /**
1449
1799
  * Get an adapter by name with type safety.
1450
1800
  */
@@ -1489,16 +1839,31 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
1489
1839
  processAction(event: Omit<ActionEvent, "thread" | "openModal"> & {
1490
1840
  adapter: Adapter;
1491
1841
  }, options?: WebhookOptions): void;
1492
- processModalSubmit(event: Omit<ModalSubmitEvent, "relatedThread" | "relatedMessage">, contextId?: string, _options?: WebhookOptions): Promise<ModalResponse | undefined>;
1493
- processModalClose(event: Omit<ModalCloseEvent, "relatedThread" | "relatedMessage">, contextId?: string, options?: WebhookOptions): void;
1842
+ processModalSubmit(event: Omit<ModalSubmitEvent, "relatedThread" | "relatedMessage" | "relatedChannel">, contextId?: string, _options?: WebhookOptions): Promise<ModalResponse | undefined>;
1843
+ processModalClose(event: Omit<ModalCloseEvent, "relatedThread" | "relatedMessage" | "relatedChannel">, contextId?: string, options?: WebhookOptions): void;
1844
+ /**
1845
+ * Process an incoming slash command from an adapter.
1846
+ * Handles waitUntil registration and error catching internally.
1847
+ */
1848
+ processSlashCommand(event: Omit<SlashCommandEvent, "channel" | "openModal"> & {
1849
+ adapter: Adapter;
1850
+ channelId: string;
1851
+ }, options?: WebhookOptions): void;
1852
+ processAssistantThreadStarted(event: AssistantThreadStartedEvent, options?: WebhookOptions): void;
1853
+ processAssistantContextChanged(event: AssistantContextChangedEvent, options?: WebhookOptions): void;
1854
+ processAppHomeOpened(event: AppHomeOpenedEvent, options?: WebhookOptions): void;
1855
+ /**
1856
+ * Handle a slash command event internally.
1857
+ */
1858
+ private handleSlashCommandEvent;
1494
1859
  /**
1495
1860
  * Store modal context server-side with a context ID.
1496
- * Called when opening a modal to preserve thread/message for the submit handler.
1861
+ * Called when opening a modal to preserve thread/message/channel for the submit handler.
1497
1862
  */
1498
1863
  private storeModalContext;
1499
1864
  /**
1500
1865
  * Retrieve and delete modal context from server-side storage.
1501
- * Called when processing modal submit/close to reconstruct thread/message.
1866
+ * Called when processing modal submit/close to reconstruct thread/message/channel.
1502
1867
  */
1503
1868
  private retrieveModalContext;
1504
1869
  /**
@@ -1540,6 +1905,33 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
1540
1905
  * ```
1541
1906
  */
1542
1907
  openDM(user: string | Author): Promise<Thread<TState>>;
1908
+ /**
1909
+ * Get a Channel by its channel ID.
1910
+ *
1911
+ * The adapter is automatically inferred from the channel ID prefix.
1912
+ *
1913
+ * @param channelId - Channel ID (e.g., "slack:C123ABC", "gchat:spaces/ABC123")
1914
+ * @returns A Channel that can be used to list threads, post messages, iterate messages, etc.
1915
+ *
1916
+ * @example
1917
+ * ```typescript
1918
+ * const channel = chat.channel("slack:C123ABC");
1919
+ *
1920
+ * // Iterate messages newest first
1921
+ * for await (const msg of channel.messages) {
1922
+ * console.log(msg.text);
1923
+ * }
1924
+ *
1925
+ * // List threads
1926
+ * for await (const t of channel.threads()) {
1927
+ * console.log(t.rootMessage.text, t.replyCount);
1928
+ * }
1929
+ *
1930
+ * // Post to channel
1931
+ * await channel.post("Hello channel!");
1932
+ * ```
1933
+ */
1934
+ channel(channelId: string): Channel<TState>;
1543
1935
  /**
1544
1936
  * Infer which adapter to use based on the userId format.
1545
1937
  */
@@ -1620,6 +2012,8 @@ declare class ThreadImpl<TState = Record<string, unknown>> implements Thread<TSt
1620
2012
  private _currentMessage?;
1621
2013
  /** Update interval for fallback streaming */
1622
2014
  private _streamingUpdateIntervalMs;
2015
+ /** Cached channel instance */
2016
+ private _channel?;
1623
2017
  constructor(config: ThreadImplConfig);
1624
2018
  /**
1625
2019
  * Get the adapter for this thread.
@@ -1645,6 +2039,16 @@ declare class ThreadImpl<TState = Record<string, unknown>> implements Thread<TSt
1645
2039
  setState(newState: Partial<TState>, options?: {
1646
2040
  replace?: boolean;
1647
2041
  }): Promise<void>;
2042
+ /**
2043
+ * Get the Channel containing this thread.
2044
+ * Lazy-created and cached.
2045
+ */
2046
+ get channel(): Channel<TState>;
2047
+ /**
2048
+ * Iterate messages newest first (backward from most recent).
2049
+ * Auto-paginates lazily.
2050
+ */
2051
+ get messages(): AsyncIterable<Message>;
1648
2052
  get allMessages(): AsyncIterable<Message>;
1649
2053
  isSubscribed(): Promise<boolean>;
1650
2054
  subscribe(): Promise<void>;
@@ -2103,4 +2507,4 @@ declare const Select: typeof Select$1;
2103
2507
  declare const SelectOption: typeof SelectOption$1;
2104
2508
  declare const TextInput: typeof TextInput$1;
2105
2509
 
2106
- export { type ActionEvent, type ActionHandler, Actions, type Adapter, type AdapterPostableMessage, type Attachment, type Author, BaseFormatConverter, Button, Card, CardChild, CardElement, CardJSXElement, CardText, Chat, type ChatConfig, ChatError, type ChatInstance, ConsoleLogger, type CustomEmojiMap, DEFAULT_EMOJI_MAP, Divider, type Emoji, type EmojiFormats, type EmojiMapConfig, EmojiResolver, type EmojiValue, type EphemeralMessage, type FetchDirection, type FetchOptions, type FetchResult, Field, Fields, type FileUpload, type FormatConverter, type FormattedContent, Image, LinkButton, type Lock, LockError, type LogLevel, type Logger, type MarkdownConverter, type MentionHandler, Message, type MessageData, type MessageHandler, type MessageMetadata, Modal, type ModalCloseEvent, type ModalCloseHandler, type ModalCloseResponse, ModalElement, type ModalErrorsResponse, type ModalPushResponse, type ModalResponse, type ModalSubmitEvent, type ModalSubmitHandler, type ModalUpdateResponse, NotImplementedError, type PostEphemeralOptions, type PostableAst, type PostableCard, type PostableMarkdown, type PostableMessage, type PostableRaw, RadioSelect, RateLimitError, type RawMessage, type ReactionEvent, type ReactionHandler, Section, Select, SelectOption, type SentMessage, type SerializedMessage, type SerializedThread, type StateAdapter, type StreamOptions, type SubscribedMessageHandler, THREAD_STATE_TTL_MS, TextInput, type Thread, ThreadImpl, type ThreadInfo, type WebhookOptions, type WellKnownEmoji, blockquote, codeBlock, convertEmojiPlaceholders, createEmoji, defaultEmojiResolver, emoji, emphasis, fromReactElement, fromReactModalElement, getEmoji, getNodeChildren, getNodeValue, inlineCode, isBlockquoteNode, isCardElement, isCodeNode, isDeleteNode, isEmphasisNode, isInlineCodeNode, isJSX, isLinkNode, isListItemNode, isListNode, isModalElement, isParagraphNode, isStrongNode, isTextNode, link, markdownToPlainText, paragraph, parseMarkdown, root, strikethrough, stringifyMarkdown, strong, text, toCardElement, toModalElement, toPlainText, walkAst };
2510
+ export { type ActionEvent, type ActionHandler, Actions, type Adapter, type AdapterPostableMessage, type AppHomeOpenedEvent, type AppHomeOpenedHandler, type AssistantContextChangedEvent, type AssistantContextChangedHandler, type AssistantThreadStartedEvent, type AssistantThreadStartedHandler, type Attachment, type Author, BaseFormatConverter, Button, Card, CardChild, CardElement, CardJSXElement, CardText, type Channel, ChannelImpl, type ChannelInfo, Chat, type ChatConfig, ChatError, type ChatInstance, ConsoleLogger, type CustomEmojiMap, DEFAULT_EMOJI_MAP, Divider, type Emoji, type EmojiFormats, type EmojiMapConfig, EmojiResolver, type EmojiValue, type EphemeralMessage, type FetchDirection, type FetchOptions, type FetchResult, Field, Fields, type FileUpload, type FormatConverter, type FormattedContent, Image, LinkButton, type ListThreadsOptions, type ListThreadsResult, type Lock, LockError, type LogLevel, type Logger, type MarkdownConverter, type MentionHandler, Message, type MessageData, type MessageHandler, type MessageMetadata, Modal, type ModalCloseEvent, type ModalCloseHandler, type ModalCloseResponse, ModalElement, type ModalErrorsResponse, type ModalPushResponse, type ModalResponse, type ModalSubmitEvent, type ModalSubmitHandler, type ModalUpdateResponse, NotImplementedError, type PostEphemeralOptions, type Postable, type PostableAst, type PostableCard, type PostableMarkdown, type PostableMessage, type PostableRaw, RadioSelect, RateLimitError, type RawMessage, type ReactionEvent, type ReactionHandler, Section, Select, SelectOption, type SentMessage, type SerializedChannel, type SerializedMessage, type SerializedThread, type SlashCommandEvent, type SlashCommandHandler, type StateAdapter, type StreamOptions, type SubscribedMessageHandler, THREAD_STATE_TTL_MS, TextInput, type Thread, ThreadImpl, type ThreadInfo, type ThreadSummary, type WebhookOptions, type WellKnownEmoji, blockquote, codeBlock, convertEmojiPlaceholders, createEmoji, defaultEmojiResolver, deriveChannelId, emoji, emphasis, fromReactElement, fromReactModalElement, getEmoji, getNodeChildren, getNodeValue, inlineCode, isBlockquoteNode, isCardElement, isCodeNode, isDeleteNode, isEmphasisNode, isInlineCodeNode, isJSX, isLinkNode, isListItemNode, isListNode, isModalElement, isParagraphNode, isStrongNode, isTextNode, link, markdownToPlainText, paragraph, parseMarkdown, root, strikethrough, stringifyMarkdown, strong, text, toCardElement, toModalElement, toPlainText, walkAst };