chat 4.22.0 → 4.24.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.
@@ -353,7 +353,8 @@ function Button(options) {
353
353
  label: options.label,
354
354
  style: options.style,
355
355
  value: options.value,
356
- disabled: options.disabled
356
+ disabled: options.disabled,
357
+ actionType: options.actionType
357
358
  };
358
359
  }
359
360
  function LinkButton(options) {
@@ -475,7 +476,9 @@ function fromReactElement(element) {
475
476
  id: props.id,
476
477
  label: props.label ?? label,
477
478
  style: props.style,
478
- value: props.value
479
+ value: props.value,
480
+ actionType: props.actionType,
481
+ disabled: props.disabled
479
482
  });
480
483
  }
481
484
  case "LinkButton": {
@@ -851,7 +854,9 @@ function resolveJSXElement(element) {
851
854
  id: props.id,
852
855
  label,
853
856
  style: props.style,
854
- value: props.value
857
+ value: props.value,
858
+ actionType: props.actionType,
859
+ disabled: props.disabled
855
860
  });
856
861
  }
857
862
  if (type === LinkButton) {
@@ -1103,4 +1108,3 @@ export {
1103
1108
  toModalElement,
1104
1109
  isJSX
1105
1110
  };
1106
- //# sourceMappingURL=chunk-JW7GYSMH.js.map
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
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 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';
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';
6
6
 
7
7
  interface MessageHistoryConfig {
8
8
  /** Maximum messages to keep per thread (default: 100) */
@@ -42,6 +42,7 @@ declare class MessageHistoryCache {
42
42
  interface SerializedChannel {
43
43
  _type: "chat:Channel";
44
44
  adapterName: string;
45
+ channelVisibility?: ChannelVisibility;
45
46
  id: string;
46
47
  isDM: boolean;
47
48
  }
@@ -50,6 +51,7 @@ interface SerializedChannel {
50
51
  */
51
52
  interface ChannelImplConfigWithAdapter {
52
53
  adapter: Adapter;
54
+ channelVisibility?: ChannelVisibility;
53
55
  id: string;
54
56
  isDM?: boolean;
55
57
  messageHistory?: MessageHistoryCache;
@@ -60,6 +62,7 @@ interface ChannelImplConfigWithAdapter {
60
62
  */
61
63
  interface ChannelImplConfigLazy {
62
64
  adapterName: string;
65
+ channelVisibility?: ChannelVisibility;
63
66
  id: string;
64
67
  isDM?: boolean;
65
68
  }
@@ -67,6 +70,7 @@ type ChannelImplConfig = ChannelImplConfigWithAdapter | ChannelImplConfigLazy;
67
70
  declare class ChannelImpl<TState = Record<string, unknown>> implements Channel<TState> {
68
71
  readonly id: string;
69
72
  readonly isDM: boolean;
73
+ readonly channelVisibility: ChannelVisibility;
70
74
  private _adapter?;
71
75
  private readonly _adapterName?;
72
76
  private _stateAdapterInstance?;
@@ -144,6 +148,7 @@ interface SerializedThread {
144
148
  _type: "chat:Thread";
145
149
  adapterName: string;
146
150
  channelId: string;
151
+ channelVisibility?: ChannelVisibility;
147
152
  currentMessage?: SerializedMessage;
148
153
  id: string;
149
154
  isDM: boolean;
@@ -154,6 +159,7 @@ interface SerializedThread {
154
159
  interface ThreadImplConfigWithAdapter {
155
160
  adapter: Adapter;
156
161
  channelId: string;
162
+ channelVisibility?: ChannelVisibility;
157
163
  currentMessage?: Message;
158
164
  fallbackStreamingPlaceholderText?: string | null;
159
165
  id: string;
@@ -172,6 +178,7 @@ interface ThreadImplConfigWithAdapter {
172
178
  interface ThreadImplConfigLazy {
173
179
  adapterName: string;
174
180
  channelId: string;
181
+ channelVisibility?: ChannelVisibility;
175
182
  currentMessage?: Message;
176
183
  fallbackStreamingPlaceholderText?: string | null;
177
184
  id: string;
@@ -186,6 +193,7 @@ declare class ThreadImpl<TState = Record<string, unknown>> implements Thread<TSt
186
193
  readonly id: string;
187
194
  readonly channelId: string;
188
195
  readonly isDM: boolean;
196
+ readonly channelVisibility: ChannelVisibility;
189
197
  /** Direct adapter instance (if provided) */
190
198
  private _adapter?;
191
199
  /** Adapter name for lazy resolution */
@@ -329,6 +337,16 @@ declare class NotImplementedError extends ChatError {
329
337
  constructor(message: string, feature?: string, cause?: unknown);
330
338
  }
331
339
 
340
+ /**
341
+ * Represents the visibility scope of a channel.
342
+ *
343
+ * - `private`: Channel is only visible to invited members (e.g., private Slack channels)
344
+ * - `workspace`: Channel is visible to all workspace members (e.g., public Slack channels)
345
+ * - `external`: Channel is shared with external organizations (e.g., Slack Connect)
346
+ * - `unknown`: Visibility cannot be determined
347
+ */
348
+ type ChannelVisibility = "private" | "workspace" | "external" | "unknown";
349
+
332
350
  /**
333
351
  * Chat configuration with type-safe adapter inference.
334
352
  * @template TAdapters - Record of adapter name to adapter instance
@@ -418,6 +436,18 @@ interface ChatConfig<TAdapters extends Record<string, Adapter> = Record<string,
418
436
  * Options for webhook handling.
419
437
  */
420
438
  interface WebhookOptions {
439
+ /**
440
+ * Override the default modal-opening behavior to handle it inline
441
+ * within the current webhook response cycle.
442
+ * When provided, called instead of adapter.openModal().
443
+ * Used by Teams to return modal content in the HTTP invoke response.
444
+ *
445
+ * The returned `viewId` is platform-specific (e.g. Slack's view ID).
446
+ * Adapters that don't produce a view ID may return void.
447
+ */
448
+ onOpenModal?: (modal: ModalElement, contextId: string) => Promise<{
449
+ viewId: string;
450
+ } | undefined>;
421
451
  /**
422
452
  * Function to run message handling in the background.
423
453
  * Use this to ensure fast webhook responses while processing continues.
@@ -513,6 +543,16 @@ interface Adapter<TThreadId = unknown, TRawMessage = unknown> {
513
543
  fetchMessages(threadId: string, options?: FetchOptions): Promise<FetchResult<TRawMessage>>;
514
544
  /** Fetch thread metadata */
515
545
  fetchThread(threadId: string): Promise<ThreadInfo>;
546
+ /**
547
+ * Get the visibility scope of a channel containing the thread.
548
+ *
549
+ * This distinguishes between private channels, workspace-visible channels,
550
+ * and externally shared channels (e.g., Slack Connect).
551
+ *
552
+ * @param threadId - The thread ID to check
553
+ * @returns The channel visibility scope
554
+ */
555
+ getChannelVisibility?(threadId: string): ChannelVisibility;
516
556
  /** Handle incoming webhook request */
517
557
  handleWebhook(request: Request, options?: WebhookOptions): Promise<Response>;
518
558
  /** Called when Chat instance is created (internal use) */
@@ -698,7 +738,7 @@ interface ChatInstance {
698
738
  */
699
739
  processAction(event: Omit<ActionEvent, "thread" | "openModal"> & {
700
740
  adapter: Adapter;
701
- }, options?: WebhookOptions): void;
741
+ }, options: WebhookOptions | undefined): Promise<void>;
702
742
  processAppHomeOpened(event: AppHomeOpenedEvent, options?: WebhookOptions): void;
703
743
  processAssistantContextChanged(event: AssistantContextChangedEvent, options?: WebhookOptions): void;
704
744
  processAssistantThreadStarted(event: AssistantThreadStartedEvent, options?: WebhookOptions): void;
@@ -749,7 +789,7 @@ interface ChatInstance {
749
789
  processSlashCommand(event: Omit<SlashCommandEvent, "channel" | "openModal"> & {
750
790
  adapter: Adapter;
751
791
  channelId: string;
752
- }, options?: WebhookOptions): void;
792
+ }, options: WebhookOptions | undefined): void;
753
793
  }
754
794
  /** Lock scope determines which messages contend for the same lock. */
755
795
  type LockScope = "thread" | "channel";
@@ -862,6 +902,8 @@ interface Lock {
862
902
  interface Postable<TState = Record<string, unknown>, TRawMessage = unknown> {
863
903
  /** The adapter this entity belongs to */
864
904
  readonly adapter: Adapter;
905
+ /** The visibility scope of this channel */
906
+ readonly channelVisibility: ChannelVisibility;
865
907
  /** Unique ID */
866
908
  readonly id: string;
867
909
  /** Whether this is a direct message conversation */
@@ -961,6 +1003,8 @@ interface ThreadSummary<TRawMessage = unknown> {
961
1003
  * Channel metadata returned by fetchInfo().
962
1004
  */
963
1005
  interface ChannelInfo {
1006
+ /** The visibility scope of this channel */
1007
+ channelVisibility?: ChannelVisibility;
964
1008
  id: string;
965
1009
  isDM?: boolean;
966
1010
  memberCount?: number;
@@ -1130,6 +1174,8 @@ interface Thread<TState = Record<string, unknown>, TRawMessage = unknown> extend
1130
1174
  interface ThreadInfo {
1131
1175
  channelId: string;
1132
1176
  channelName?: string;
1177
+ /** The visibility scope of this channel */
1178
+ channelVisibility?: ChannelVisibility;
1133
1179
  id: string;
1134
1180
  /** Whether this is a direct message conversation */
1135
1181
  isDM?: boolean;
@@ -1753,7 +1799,7 @@ interface ModalCloseResponse {
1753
1799
  action: "close";
1754
1800
  }
1755
1801
  type ModalResponse = ModalCloseResponse | ModalErrorsResponse | ModalUpdateResponse | ModalPushResponse;
1756
- type ModalSubmitHandler = (event: ModalSubmitEvent) => void | Promise<ModalResponse | undefined>;
1802
+ type ModalSubmitHandler = (event: ModalSubmitEvent) => void | Promise<ModalResponse | void | undefined>;
1757
1803
  type ModalCloseHandler = (event: ModalCloseEvent) => void | Promise<void>;
1758
1804
  /**
1759
1805
  * Event emitted when a user invokes a slash command.
@@ -2377,8 +2423,48 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
2377
2423
  */
2378
2424
  onAction(handler: ActionHandler): void;
2379
2425
  onAction(actionIds: string[] | string, handler: ActionHandler): void;
2426
+ /**
2427
+ * Register a handler for modal form submissions.
2428
+ *
2429
+ * @example
2430
+ * ```typescript
2431
+ * // Handle specific modal
2432
+ * chat.onModalSubmit("settings-modal", async (event) => {
2433
+ * const name = event.values["name"];
2434
+ * await event.relatedThread?.post(`Updated name to ${name}`);
2435
+ * });
2436
+ *
2437
+ * // Handle all modal submissions
2438
+ * chat.onModalSubmit(async (event) => {
2439
+ * console.log(`Modal ${event.callbackId} submitted`);
2440
+ * });
2441
+ * ```
2442
+ *
2443
+ * @param callbackIdOrHandler - Either a callback ID, array of callback IDs, or the handler
2444
+ * @param handler - The handler (if callback ID filter is provided)
2445
+ */
2380
2446
  onModalSubmit(handler: ModalSubmitHandler): void;
2381
2447
  onModalSubmit(callbackIds: string[] | string, handler: ModalSubmitHandler): void;
2448
+ /**
2449
+ * Register a handler for modal close/cancel events.
2450
+ * Only fires when the modal was created with `notifyOnClose: true`.
2451
+ *
2452
+ * @example
2453
+ * ```typescript
2454
+ * // Handle specific modal close
2455
+ * chat.onModalClose("settings-modal", async (event) => {
2456
+ * console.log("User cancelled settings");
2457
+ * });
2458
+ *
2459
+ * // Handle all modal close events
2460
+ * chat.onModalClose(async (event) => {
2461
+ * console.log(`Modal ${event.callbackId} closed`);
2462
+ * });
2463
+ * ```
2464
+ *
2465
+ * @param callbackIdOrHandler - Either a callback ID, array of callback IDs, or the handler
2466
+ * @param handler - The handler (if callback ID filter is provided)
2467
+ */
2382
2468
  onModalClose(handler: ModalCloseHandler): void;
2383
2469
  onModalClose(callbackIds: string[] | string, handler: ModalCloseHandler): void;
2384
2470
  /**
@@ -2466,7 +2552,7 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
2466
2552
  */
2467
2553
  processAction(event: Omit<ActionEvent, "thread" | "openModal"> & {
2468
2554
  adapter: Adapter;
2469
- }, options?: WebhookOptions): void;
2555
+ }, options: WebhookOptions | undefined): Promise<void>;
2470
2556
  processModalSubmit(event: Omit<ModalSubmitEvent, "relatedThread" | "relatedMessage" | "relatedChannel">, contextId?: string, _options?: WebhookOptions): Promise<ModalResponse | undefined>;
2471
2557
  processModalClose(event: Omit<ModalCloseEvent, "relatedThread" | "relatedMessage" | "relatedChannel">, contextId?: string, options?: WebhookOptions): void;
2472
2558
  /**
@@ -2476,7 +2562,7 @@ declare class Chat<TAdapters extends Record<string, Adapter> = Record<string, Ad
2476
2562
  processSlashCommand(event: Omit<SlashCommandEvent, "channel" | "openModal"> & {
2477
2563
  adapter: Adapter;
2478
2564
  channelId: string;
2479
- }, options?: WebhookOptions): void;
2565
+ }, options: WebhookOptions | undefined): void;
2480
2566
  processAssistantThreadStarted(event: AssistantThreadStartedEvent, options?: WebhookOptions): void;
2481
2567
  processAssistantContextChanged(event: AssistantContextChangedEvent, options?: WebhookOptions): void;
2482
2568
  processAppHomeOpened(event: AppHomeOpenedEvent, options?: WebhookOptions): void;
@@ -3136,4 +3222,4 @@ declare const Select: SelectComponent;
3136
3222
  declare const SelectOption: SelectOptionComponent;
3137
3223
  declare const TextInput: TextInputComponent;
3138
3224
 
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 };
3225
+ 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, type ChannelVisibility, 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 };
package/dist/index.js CHANGED
@@ -59,7 +59,7 @@ import {
59
59
  toModalElement,
60
60
  toPlainText,
61
61
  walkAst
62
- } from "./chunk-JW7GYSMH.js";
62
+ } from "./chunk-OPV5U4WG.js";
63
63
 
64
64
  // src/ai.ts
65
65
  var TEXT_MIME_PREFIXES = [
@@ -469,6 +469,7 @@ function isAsyncIterable(value) {
469
469
  var ChannelImpl = class _ChannelImpl {
470
470
  id;
471
471
  isDM;
472
+ channelVisibility;
472
473
  _adapter;
473
474
  _adapterName;
474
475
  _stateAdapterInstance;
@@ -477,6 +478,7 @@ var ChannelImpl = class _ChannelImpl {
477
478
  constructor(config) {
478
479
  this.id = config.id;
479
480
  this.isDM = config.isDM ?? false;
481
+ this.channelVisibility = config.channelVisibility ?? "unknown";
480
482
  if (isLazyConfig(config)) {
481
483
  this._adapterName = config.adapterName;
482
484
  } else {
@@ -695,6 +697,7 @@ var ChannelImpl = class _ChannelImpl {
695
697
  _type: "chat:Channel",
696
698
  id: this.id,
697
699
  adapterName: this.adapter.name,
700
+ channelVisibility: this.channelVisibility,
698
701
  isDM: this.isDM
699
702
  };
700
703
  }
@@ -702,6 +705,7 @@ var ChannelImpl = class _ChannelImpl {
702
705
  const channel = new _ChannelImpl({
703
706
  id: json.id,
704
707
  adapterName: json.adapterName,
708
+ channelVisibility: json.channelVisibility,
705
709
  isDM: json.isDM
706
710
  });
707
711
  if (adapter) {
@@ -1099,6 +1103,7 @@ var ThreadImpl = class _ThreadImpl {
1099
1103
  id;
1100
1104
  channelId;
1101
1105
  isDM;
1106
+ channelVisibility;
1102
1107
  /** Direct adapter instance (if provided) */
1103
1108
  _adapter;
1104
1109
  /** Adapter name for lazy resolution */
@@ -1122,6 +1127,7 @@ var ThreadImpl = class _ThreadImpl {
1122
1127
  this.id = config.id;
1123
1128
  this.channelId = config.channelId;
1124
1129
  this.isDM = config.isDM ?? false;
1130
+ this.channelVisibility = config.channelVisibility ?? "unknown";
1125
1131
  this._isSubscribedContext = config.isSubscribedContext ?? false;
1126
1132
  this._currentMessage = config.currentMessage;
1127
1133
  this._logger = config.logger;
@@ -1212,6 +1218,7 @@ var ThreadImpl = class _ThreadImpl {
1212
1218
  adapter: this.adapter,
1213
1219
  stateAdapter: this._stateAdapter,
1214
1220
  isDM: this.isDM,
1221
+ channelVisibility: this.channelVisibility,
1215
1222
  messageHistory: this._messageHistory
1216
1223
  });
1217
1224
  }
@@ -1573,6 +1580,7 @@ var ThreadImpl = class _ThreadImpl {
1573
1580
  _type: "chat:Thread",
1574
1581
  id: this.id,
1575
1582
  channelId: this.channelId,
1583
+ channelVisibility: this.channelVisibility,
1576
1584
  currentMessage: this._currentMessage?.toJSON(),
1577
1585
  isDM: this.isDM,
1578
1586
  adapterName: this.adapter.name
@@ -1597,6 +1605,7 @@ var ThreadImpl = class _ThreadImpl {
1597
1605
  id: json.id,
1598
1606
  adapterName: json.adapterName,
1599
1607
  channelId: json.channelId,
1608
+ channelVisibility: json.channelVisibility,
1600
1609
  currentMessage: json.currentMessage ? Message.fromJSON(json.currentMessage) : void 0,
1601
1610
  isDM: json.isDM
1602
1611
  });
@@ -2234,7 +2243,7 @@ var Chat = class {
2234
2243
  * Handles waitUntil registration and error catching internally.
2235
2244
  */
2236
2245
  processAction(event, options) {
2237
- const task = this.handleActionEvent(event).catch((err) => {
2246
+ const task = this.handleActionEvent(event, options).catch((err) => {
2238
2247
  this.logger.error("Action processing error", {
2239
2248
  error: err,
2240
2249
  actionId: event.actionId,
@@ -2244,6 +2253,7 @@ var Chat = class {
2244
2253
  if (options?.waitUntil) {
2245
2254
  options.waitUntil(task);
2246
2255
  }
2256
+ return task;
2247
2257
  }
2248
2258
  async processModalSubmit(event, contextId, _options) {
2249
2259
  const { relatedThread, relatedMessage, relatedChannel } = await this.retrieveModalContext(event.adapter.name, contextId);
@@ -2298,7 +2308,7 @@ var Chat = class {
2298
2308
  * Handles waitUntil registration and error catching internally.
2299
2309
  */
2300
2310
  processSlashCommand(event, options) {
2301
- const task = this.handleSlashCommandEvent(event).catch((err) => {
2311
+ const task = this.handleSlashCommandEvent(event, options).catch((err) => {
2302
2312
  this.logger.error("Slash command processing error", {
2303
2313
  error: err,
2304
2314
  command: event.command,
@@ -2373,7 +2383,7 @@ var Chat = class {
2373
2383
  /**
2374
2384
  * Handle a slash command event internally.
2375
2385
  */
2376
- async handleSlashCommandEvent(event) {
2386
+ async handleSlashCommandEvent(event, options) {
2377
2387
  this.logger.debug("Incoming slash command", {
2378
2388
  adapter: event.adapter.name,
2379
2389
  command: event.command,
@@ -2395,11 +2405,11 @@ var Chat = class {
2395
2405
  ...event,
2396
2406
  channel,
2397
2407
  openModal: async (modal) => {
2398
- if (!event.triggerId) {
2408
+ if (!(event.triggerId || options?.onOpenModal)) {
2399
2409
  this.logger.warn("Cannot open modal: no triggerId available");
2400
2410
  return void 0;
2401
2411
  }
2402
- if (!event.adapter.openModal) {
2412
+ if (!(options?.onOpenModal || event.adapter.openModal)) {
2403
2413
  this.logger.warn(
2404
2414
  `Cannot open modal: ${event.adapter.name} does not support modals`
2405
2415
  );
@@ -2414,18 +2424,24 @@ var Chat = class {
2414
2424
  modalElement = converted;
2415
2425
  }
2416
2426
  const contextId = crypto.randomUUID();
2417
- this.storeModalContext(
2427
+ await this.storeModalContext(
2418
2428
  event.adapter.name,
2419
2429
  contextId,
2420
2430
  void 0,
2421
2431
  void 0,
2422
2432
  channel
2423
2433
  );
2424
- return event.adapter.openModal(
2425
- event.triggerId,
2426
- modalElement,
2427
- contextId
2428
- );
2434
+ if (options?.onOpenModal) {
2435
+ return options.onOpenModal(modalElement, contextId);
2436
+ }
2437
+ if (event.triggerId && event.adapter.openModal) {
2438
+ return event.adapter.openModal(
2439
+ event.triggerId,
2440
+ modalElement,
2441
+ contextId
2442
+ );
2443
+ }
2444
+ return void 0;
2429
2445
  }
2430
2446
  };
2431
2447
  this.logger.debug("Checking slash command handlers", {
@@ -2450,19 +2466,21 @@ var Chat = class {
2450
2466
  * Store modal context server-side with a context ID.
2451
2467
  * Called when opening a modal to preserve thread/message/channel for the submit handler.
2452
2468
  */
2453
- storeModalContext(adapterName, contextId, thread, message, channel) {
2469
+ async storeModalContext(adapterName, contextId, thread, message, channel) {
2454
2470
  const key = `modal-context:${adapterName}:${contextId}`;
2455
2471
  const context = {
2456
2472
  thread: thread?.toJSON(),
2457
2473
  message: message?.toJSON(),
2458
2474
  channel: channel?.toJSON()
2459
2475
  };
2460
- this._stateAdapter.set(key, context, MODAL_CONTEXT_TTL_MS).catch((err) => {
2476
+ try {
2477
+ await this._stateAdapter.set(key, context, MODAL_CONTEXT_TTL_MS);
2478
+ } catch (err) {
2461
2479
  this.logger.error("Failed to store modal context", {
2462
2480
  contextId,
2463
2481
  error: err
2464
2482
  });
2465
- });
2483
+ }
2466
2484
  }
2467
2485
  /**
2468
2486
  * Retrieve and delete modal context from server-side storage.
@@ -2485,6 +2503,7 @@ var Chat = class {
2485
2503
  relatedChannel: void 0
2486
2504
  };
2487
2505
  }
2506
+ await this._stateAdapter.delete(key);
2488
2507
  const adapter = this.adapters.get(adapterName);
2489
2508
  let relatedThread;
2490
2509
  if (stored.thread) {
@@ -2504,7 +2523,7 @@ var Chat = class {
2504
2523
  /**
2505
2524
  * Handle an action event internally.
2506
2525
  */
2507
- async handleActionEvent(event) {
2526
+ async handleActionEvent(event, options) {
2508
2527
  this.logger.debug("Incoming action", {
2509
2528
  adapter: event.adapter.name,
2510
2529
  actionId: event.actionId,
@@ -2540,11 +2559,11 @@ var Chat = class {
2540
2559
  ...event,
2541
2560
  thread,
2542
2561
  openModal: async (modal) => {
2543
- if (!event.triggerId) {
2562
+ if (!(event.triggerId || options?.onOpenModal)) {
2544
2563
  this.logger.warn("Cannot open modal: no triggerId available");
2545
2564
  return void 0;
2546
2565
  }
2547
- if (!event.adapter.openModal) {
2566
+ if (!(options?.onOpenModal || event.adapter.openModal)) {
2548
2567
  this.logger.warn(
2549
2568
  `Cannot open modal: ${event.adapter.name} does not support modals`
2550
2569
  );
@@ -2580,18 +2599,24 @@ var Chat = class {
2580
2599
  }
2581
2600
  const contextId = crypto.randomUUID();
2582
2601
  const channel = thread ? thread.channel : void 0;
2583
- this.storeModalContext(
2602
+ await this.storeModalContext(
2584
2603
  event.adapter.name,
2585
2604
  contextId,
2586
2605
  thread ? thread : void 0,
2587
2606
  message,
2588
2607
  channel
2589
2608
  );
2590
- return event.adapter.openModal(
2591
- event.triggerId,
2592
- modalElement,
2593
- contextId
2594
- );
2609
+ if (options?.onOpenModal) {
2610
+ return options.onOpenModal(modalElement, contextId);
2611
+ }
2612
+ if (event.triggerId && event.adapter.openModal) {
2613
+ return event.adapter.openModal(
2614
+ event.triggerId,
2615
+ modalElement,
2616
+ contextId
2617
+ );
2618
+ }
2619
+ return void 0;
2595
2620
  }
2596
2621
  };
2597
2622
  this.logger.debug("Checking action handlers", {
@@ -3189,9 +3214,9 @@ var Chat = class {
3189
3214
  }
3190
3215
  }
3191
3216
  createThread(adapter, threadId, initialMessage, isSubscribedContext = false) {
3192
- const parts = threadId.split(":");
3193
- const channelId = parts[1] || "";
3217
+ const channelId = adapter.channelIdFromThreadId(threadId);
3194
3218
  const isDM = adapter.isDM?.(threadId) ?? false;
3219
+ const channelVisibility = adapter.getChannelVisibility?.(threadId) ?? "unknown";
3195
3220
  return new ThreadImpl({
3196
3221
  id: threadId,
3197
3222
  adapter,
@@ -3200,6 +3225,7 @@ var Chat = class {
3200
3225
  initialMessage,
3201
3226
  isSubscribedContext,
3202
3227
  isDM,
3228
+ channelVisibility,
3203
3229
  currentMessage: initialMessage,
3204
3230
  logger: this.logger,
3205
3231
  streamingUpdateIntervalMs: this._streamingUpdateIntervalMs,
@@ -3783,4 +3809,3 @@ export {
3783
3809
  toPlainText,
3784
3810
  walkAst
3785
3811
  };
3786
- //# sourceMappingURL=index.js.map
@@ -50,6 +50,8 @@ type ButtonStyle = "primary" | "danger" | "default";
50
50
  type TextStyle = "plain" | "bold" | "muted";
51
51
  /** Button element for interactive actions */
52
52
  interface ButtonElement {
53
+ /** Whether this button triggers a regular action or opens a modal dialog. Default: "action" */
54
+ actionType?: "action" | "modal";
53
55
  /** If true, the button is displayed in an inactive state and doesn't respond to user actions */
54
56
  disabled?: boolean;
55
57
  /** Unique action ID for callback routing */
@@ -237,6 +239,8 @@ declare function Section(children: CardChild[]): SectionElement;
237
239
  declare function Actions(children: (ButtonElement | LinkButtonElement | SelectElement | RadioSelectElement)[]): ActionsElement;
238
240
  /** Options for Button */
239
241
  interface ButtonOptions {
242
+ /** Whether this button triggers a regular action or opens a modal dialog. Default: "action" */
243
+ actionType?: "action" | "modal";
240
244
  /** If true, the button is displayed in an inactive state and doesn't respond to user actions */
241
245
  disabled?: boolean;
242
246
  /** Unique action ID for callback routing */
@@ -504,7 +508,9 @@ interface TextProps {
504
508
  }
505
509
  /** Props for Button component in JSX */
506
510
  interface ButtonProps {
511
+ actionType?: "action" | "modal";
507
512
  children?: string | number | (string | number | undefined)[];
513
+ disabled?: boolean;
508
514
  id: string;
509
515
  label?: string;
510
516
  style?: ButtonStyle;
@@ -1 +1 @@
1
- export { A as ActionsComponent, B as ButtonComponent, V as ButtonProps, c as CardComponent, W as CardJSXElement, X as CardJSXProps, e as CardLinkComponent, Y as CardLinkProps, Z as CardProps, C as ChatElement, _ as ContainerProps, D as DividerComponent, $ as DividerProps, F as FieldComponent, a0 as FieldProps, f as FieldsComponent, an as Fragment, I as ImageComponent, a1 as ImageProps, ao as JSX, L as LinkButtonComponent, a2 as LinkButtonProps, n as ModalComponent, a3 as ModalProps, R as RadioSelectComponent, S as SectionComponent, o as SelectComponent, p as SelectOptionComponent, a4 as SelectOptionProps, a5 as SelectProps, ai as TableComponent, ah as TableProps, T as TextComponent, q as TextInputComponent, a6 as TextInputProps, a7 as TextProps, aj as isCardLinkProps, h as isJSX, ak as jsx, am as jsxDEV, al as jsxs, t as toCardElement, k as toModalElement } from './jsx-runtime-DraWieqP.js';
1
+ export { A as ActionsComponent, B as ButtonComponent, V as ButtonProps, c as CardComponent, W as CardJSXElement, X as CardJSXProps, e as CardLinkComponent, Y as CardLinkProps, Z as CardProps, C as ChatElement, _ as ContainerProps, D as DividerComponent, $ as DividerProps, F as FieldComponent, a0 as FieldProps, f as FieldsComponent, an as Fragment, I as ImageComponent, a1 as ImageProps, ao as JSX, L as LinkButtonComponent, a2 as LinkButtonProps, n as ModalComponent, a3 as ModalProps, R as RadioSelectComponent, S as SectionComponent, o as SelectComponent, p as SelectOptionComponent, a4 as SelectOptionProps, a5 as SelectProps, ai as TableComponent, ah as TableProps, T as TextComponent, q as TextInputComponent, a6 as TextInputProps, a7 as TextProps, aj as isCardLinkProps, h as isJSX, ak as jsx, am as jsxDEV, al as jsxs, t as toCardElement, k as toModalElement } from './jsx-runtime-DxATbnrP.js';
@@ -7,7 +7,7 @@ import {
7
7
  jsxs,
8
8
  toCardElement,
9
9
  toModalElement
10
- } from "./chunk-JW7GYSMH.js";
10
+ } from "./chunk-OPV5U4WG.js";
11
11
  export {
12
12
  Fragment,
13
13
  isCardLinkProps,
@@ -18,4 +18,3 @@ export {
18
18
  toCardElement,
19
19
  toModalElement
20
20
  };
21
- //# sourceMappingURL=jsx-runtime.js.map
package/docs/adapters.mdx CHANGED
@@ -64,7 +64,7 @@ Ready to build your own? Follow the [building](/docs/contributing/building) guid
64
64
  ⚠️ indicates partial support — the feature works with limitations. See individual adapter pages for details.
65
65
  </Callout>
66
66
 
67
- ## How adapters work
67
+ ## How [adapters](/adapters) work
68
68
 
69
69
  Each adapter implements a standard interface that the `Chat` class uses to route events and send messages. When a webhook arrives:
70
70
 
@@ -73,9 +73,9 @@ Each adapter implements a standard interface that the `Chat` class uses to route
73
73
  3. Routes to your handlers via the `Chat` class
74
74
  4. Converts outgoing messages from markdown/AST/cards to the platform's native format
75
75
 
76
- ## Using multiple adapters
76
+ ## Using multiple [adapters](/adapters)
77
77
 
78
- Register multiple adapters and your event handlers work across all of them:
78
+ Register multiple [adapters](/adapters) and your event handlers work across all of them:
79
79
 
80
80
  ```typescript title="lib/bot.ts" lineNumbers
81
81
  import { Chat } from "chat";
@@ -1,5 +1,5 @@
1
1
  ---
2
- title: Concurrency
2
+ title: Overlapping Messages
3
3
  description: Control how overlapping messages on the same thread are handled — queue, debounce, drop, or process concurrently.
4
4
  type: guide
5
5
  prerequisites:
@@ -14,7 +14,7 @@ Learn the core patterns for handling incoming events and posting messages back t
14
14
  <Card title="Posting Messages" description="Different ways to render and send messages with thread.post()." href="/docs/posting-messages" />
15
15
  </Cards>
16
16
 
17
- ## Adapters
17
+ ## [Adapters](/adapters)
18
18
 
19
19
  Connect your bot to chat platforms and persist state across restarts.
20
20
 
@@ -23,6 +23,8 @@ Connect your bot to chat platforms and persist state across restarts.
23
23
  <Card title="State Adapters" description="Pluggable state adapters for thread subscriptions, distributed locking, and caching." href="/docs/state" />
24
24
  </Cards>
25
25
 
26
+ Browse all official and community adapters on the [Adapters](/adapters) page.
27
+
26
28
  ## Guides
27
29
 
28
30
  Step-by-step tutorials to get up and running on your platform of choice.