@sendbird/ai-agent-messenger-react-native 1.6.0 → 1.8.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
@@ -22,6 +22,8 @@ import { JSX } from 'react/jsx-runtime';
22
22
  import { LayoutChangeEvent } from 'react-native';
23
23
  import { LogLevel } from '@sendbird/chat';
24
24
  import { MMKV } from 'react-native-mmkv';
25
+ import { MultipleFilesMessage } from '@sendbird/chat/message';
26
+ import { MultipleFilesMessageCreateParams } from '@sendbird/chat/message';
25
27
  import { NativeScrollEvent } from 'react-native';
26
28
  import { NativeSyntheticEvent } from 'react-native';
27
29
  import { PropsWithChildren } from 'react';
@@ -51,16 +53,15 @@ declare interface ActionbookInfo {
51
53
  */
52
54
  declare interface ActiveChannel {
53
55
  url: string;
56
+ /**
57
+ * @deprecated Use `conversationStatus` instead. This field always returns 'open' or 'closed' for backward compatibility.
58
+ * */
59
+ status: 'open' | 'closed';
54
60
  /**
55
61
  * @description Conversation status of the active channel.
56
62
  * If the conversation is not started, this will be undefined.
57
63
  * */
58
64
  conversationStatus?: ConversationStatus;
59
- /**
60
- * @description Status of the active channel. This will be 'closed' if the conversation is closed. otherwise, 'open'.
61
- * @deprecated Please use `conversationStatus` field instead.
62
- * */
63
- status: 'open' | 'closed';
64
65
  }
65
66
 
66
67
  declare interface ActiveChannelUpdatedParams {
@@ -98,6 +99,94 @@ declare interface AgentMessageTemplateInfo {
98
99
  };
99
100
  }
100
101
 
102
+ declare abstract class AIAgentBaseStats {
103
+ protected timers: Map<string, TimerData> = new Map();
104
+ protected committed: boolean = false;
105
+ protected commitCallback: StatsAppendCallback | null = null;
106
+ protected conversationId: number | null = null;
107
+ protected channelUrl: string | null = null;
108
+ protected errorCode: number | null = null;
109
+ protected errorDescription: string | null = null;
110
+ protected extraData: Record<string, unknown> = {};
111
+
112
+ setCommitCallback(callback: StatsAppendCallback): this {
113
+ this.commitCallback = callback;
114
+ return this;
115
+ }
116
+
117
+ setConversationId(id: number): this {
118
+ this.conversationId = id;
119
+ return this;
120
+ }
121
+
122
+ setChannelUrl(url: string): this {
123
+ this.setExtra('channel_url', url);
124
+ return this;
125
+ }
126
+
127
+ setError(code: number | undefined, description: string): this {
128
+ this.errorCode = code ?? DEFAULT_ERROR_CODE;
129
+ this.errorDescription = description;
130
+ return this;
131
+ }
132
+
133
+ setExtra(key: string, value: unknown): this {
134
+ if (value !== null && value !== undefined) {
135
+ this.extraData[key] = value;
136
+ }
137
+ return this;
138
+ }
139
+
140
+ startTimer(key: string): this {
141
+ if (this.committed) return this;
142
+
143
+ const existing = this.timers.get(key);
144
+ if (existing?.startTime !== null && existing?.startTime !== undefined) return this;
145
+
146
+ this.timers.set(key, { startTime: Date.now(), endTime: null });
147
+ return this;
148
+ }
149
+
150
+ stopTimer(key: string): this {
151
+ if (this.committed) return this;
152
+
153
+ const existing = this.timers.get(key);
154
+ if (!existing || existing.startTime === null || existing.endTime !== null) return this;
155
+
156
+ this.timers.set(key, { ...existing, endTime: Date.now() });
157
+ return this;
158
+ }
159
+
160
+ protected getDuration(key: string): number | null {
161
+ const timer = this.timers.get(key);
162
+ if (!timer || timer.startTime === null || timer.endTime === null) return null;
163
+ return timer.endTime - timer.startTime;
164
+ }
165
+
166
+ isCommitted(): boolean {
167
+ return this.committed;
168
+ }
169
+
170
+ protected abstract buildPayload(): AIAgentStatPayload | null;
171
+ protected abstract getMetricKey(): string;
172
+
173
+ commit(): boolean {
174
+ if (this.committed || !this.commitCallback) {
175
+ return false;
176
+ }
177
+
178
+ const payload = this.buildPayload();
179
+
180
+ if (!payload) {
181
+ return false;
182
+ }
183
+
184
+ this.committed = true;
185
+ const result = this.commitCallback(AI_AGENT_STAT_TYPE, payload);
186
+ return result;
187
+ }
188
+ }
189
+
101
190
  declare interface AIAgentCache {
102
191
  template: MessageTemplateCache;
103
192
  messenger: MessengerSessionCache;
@@ -142,16 +231,21 @@ declare interface AIAgentConfig {
142
231
  photoEnabled?: boolean;
143
232
  };
144
233
  /**
145
- * (React-Native only) Whether to enable the gallery option in the attachment menu.
234
+ * Whether to enable the gallery/photo option in the attachment menu.
146
235
  * */
147
236
  gallery?: {
148
237
  photoEnabled?: boolean;
149
238
  };
150
239
  /**
151
- * (React-Native only) Whether to enable the file option in the attachment menu.
240
+ * Whether to enable the file option in the attachment menu.
152
241
  * */
153
242
  fileEnabled?: boolean;
154
243
  };
244
+ /**
245
+ * (React only) Whether to play an alert sound when a message is received from the AI agent while the browser is not focused.
246
+ * @default false
247
+ * */
248
+ messageAlertSoundEnabled?: boolean;
155
249
  /**
156
250
  * (React only) File viewer configuration.
157
251
  * */
@@ -202,8 +296,11 @@ declare interface AIAgentConversationContextValue {
202
296
  loadNext: () => Promise<void>;
203
297
  sendUserMessage: (params: UserMessageCreateParams) => Promise<UserMessage>;
204
298
  sendFileMessage: (params: FileMessageCreateParams) => Promise<FileMessage>;
205
- deleteMessage: (message: UserMessage | FileMessage) => Promise<void>;
206
- resendMessage: (message: UserMessage | FileMessage) => Promise<UserMessage | FileMessage>;
299
+ sendMultipleFilesMessage: (params: MultipleFilesMessageCreateParams) => Promise<MultipleFilesMessage>;
300
+ deleteMessage: (message: UserMessage | FileMessage | MultipleFilesMessage) => Promise<void>;
301
+ resendMessage: (
302
+ message: UserMessage | FileMessage | MultipleFilesMessage,
303
+ ) => Promise<UserMessage | FileMessage | MultipleFilesMessage>;
207
304
  resetNewMessages: () => void;
208
305
  };
209
306
 
@@ -298,6 +395,12 @@ declare interface AIAgentMessengerSessionContextValue {
298
395
  deauthenticate: () => Promise<void>;
299
396
 
300
397
  createAttachmentRules: (params: { channel?: GroupChannel; uploadSizeLimit?: number }) => AttachmentRules;
398
+ /**
399
+ * @internal
400
+ */
401
+ statsTrackers: {
402
+ initialRender: ConversationInitialRenderStatsTracker;
403
+ };
301
404
  }
302
405
 
303
406
  declare interface AIAgentMessengerSessionRef {
@@ -404,6 +507,15 @@ declare interface AIAgentSessionHandler extends SessionHandler {
404
507
  onExternalAuthTokenExpired?: (data: ExternalAuthTokenExpiredData) => void;
405
508
  }
406
509
 
510
+ declare interface AIAgentStatPayload {
511
+ key: string;
512
+ value?: string;
513
+ conversation_id?: number;
514
+ error_code?: number;
515
+ error_description?: string;
516
+ extra?: Record<string, unknown>;
517
+ }
518
+
407
519
  /**
408
520
  * Common string set interface shared between react and react-native packages
409
521
  * These are the base strings that both packages use
@@ -439,6 +551,7 @@ declare interface AIAgentStringSet {
439
551
  header_title: string;
440
552
  ended: string;
441
553
  footer_title: string;
554
+ multiple_files_count: (count: number) => string;
442
555
  };
443
556
 
444
557
  date_format: {
@@ -533,7 +646,9 @@ declare type BaseMessageProps<T> = T & {
533
646
  maxBodyWidth?: number;
534
647
 
535
648
  // handlers
649
+ /** @deprecated Use onClickMediaFiles instead */
536
650
  onClickMedia?: (params: { url: string; type: string }) => void;
651
+ onClickMediaFiles?: (params: { files: Array<{ url: string; type: string; name?: string }>; index: number }) => void;
537
652
  onClickFile?: (params: { url: string; type: string }) => void;
538
653
 
539
654
  children?: ReactNode;
@@ -600,12 +715,14 @@ declare interface CommandPayloads {
600
715
  [CommandType.ConversationClose]: undefined | CloseConversationCommandParams;
601
716
  [CommandType.MessengerSettingsUpdated]: MessengerSettingsUpdatedParams;
602
717
  [CommandType.ActiveChannelUpdated]: ActiveChannelUpdatedParams;
718
+ [CommandType.AnonymousSessionTokenExpired]: undefined;
603
719
  }
604
720
 
605
721
  declare enum CommandType {
606
722
  ConversationClose = 'conv.close',
607
723
  MessengerSettingsUpdated = 'messenger.settings.updated',
608
724
  ActiveChannelUpdated = 'active.channel.updated',
725
+ AnonymousSessionTokenExpired = 'anon.token.expired',
609
726
  }
610
727
 
611
728
  declare type CommunityDocumentPickerModule = typeof CommunityDocumentPicker;
@@ -710,6 +827,151 @@ declare interface ConversationHeaderTemplateProps {
710
827
  titleAlign?: 'start' | 'center' | 'end';
711
828
  }
712
829
 
830
+ declare class ConversationInitialRenderStats extends AIAgentBaseStats {
831
+ private presentMethod: PresentMethod = 'direct_present';
832
+
833
+ setPresentMethod(method: PresentMethod): this {
834
+ this.presentMethod = method;
835
+ return this;
836
+ }
837
+
838
+ protected getMetricKey(): string {
839
+ return METRIC_KEY_CONVERSATION_INITIAL_RENDER;
840
+ }
841
+
842
+ protected buildPayload(): AIAgentStatPayload | null {
843
+ const authDuration = this.getDuration(DurationKey.AUTH);
844
+ const getChannelDuration = this.getDuration(DurationKey.GET_CHANNEL);
845
+ const getMessagesDuration = this.getDuration(DurationKey.GET_MESSAGES);
846
+ const totalDurationFromCache = this.getDuration(DurationKey.TOTAL_DURATION_FROM_CACHE);
847
+ const totalDuration = this.getDuration(DurationKey.TOTAL_DURATION);
848
+
849
+ const extra: Record<string, unknown> = {
850
+ ...this.extraData,
851
+ present_method: this.presentMethod,
852
+ ...(authDuration !== null && { auth_duration: authDuration }),
853
+ ...(getChannelDuration !== null && { get_channel_duration: getChannelDuration }),
854
+ ...(getMessagesDuration !== null && { get_messages_duration: getMessagesDuration }),
855
+ ...(totalDurationFromCache !== null && { total_duration_from_cache: totalDurationFromCache }),
856
+ };
857
+
858
+ const payload: AIAgentStatPayload = {
859
+ key: this.getMetricKey(),
860
+ // Use "0" when totalDuration is null (error case)
861
+ value: totalDuration !== null ? String(totalDuration) : '0',
862
+ };
863
+
864
+ if (this.conversationId !== null) payload.conversation_id = this.conversationId;
865
+ if (this.errorCode !== null) payload.error_code = this.errorCode;
866
+ if (this.errorDescription !== null) payload.error_description = this.errorDescription;
867
+ if (Object.keys(extra).length > 0) payload.extra = extra;
868
+
869
+ return payload;
870
+ }
871
+ }
872
+
873
+ /**
874
+ * Manages ConversationInitialRenderStats lifecycle and encapsulates tracking logic.
875
+ */
876
+ declare class ConversationInitialRenderStatsTracker {
877
+ private readonly commitCallback: StatsAppendCallback;
878
+ private presentMethod: PresentMethod = 'direct_present';
879
+ private stats: ConversationInitialRenderStats | null = null;
880
+
881
+ constructor(commitCallback: StatsAppendCallback) {
882
+ this.commitCallback = commitCallback;
883
+ }
884
+
885
+ private getOrCreateStats(): ConversationInitialRenderStats {
886
+ if (!this.stats || this.stats.isCommitted()) {
887
+ this.stats = new ConversationInitialRenderStats()
888
+ .setCommitCallback(this.commitCallback)
889
+ .setPresentMethod(this.presentMethod);
890
+ }
891
+ return this.stats;
892
+ }
893
+
894
+ onAuthStart(): void {
895
+ this.getOrCreateStats()
896
+ .startTimer(DurationKey.TOTAL_DURATION)
897
+ .startTimer(DurationKey.TOTAL_DURATION_FROM_CACHE)
898
+ .startTimer(DurationKey.AUTH);
899
+ }
900
+
901
+ onAuthComplete(): void {
902
+ this.stats?.stopTimer(DurationKey.AUTH);
903
+ }
904
+
905
+ onAuthError(error: Error): void {
906
+ if (this.stats && !this.stats.isCommitted()) {
907
+ this.stats
908
+ .stopTimer(DurationKey.AUTH)
909
+ .setError(error instanceof SendbirdError ? error.code : undefined, error.message)
910
+ .stopTimer(DurationKey.TOTAL_DURATION)
911
+ .commit();
912
+ }
913
+ }
914
+
915
+ onGetChannelStart(): void {
916
+ this.stats?.startTimer(DurationKey.GET_CHANNEL);
917
+ }
918
+
919
+ onGetChannelComplete(conversationId?: number): void {
920
+ if (this.stats) {
921
+ this.stats.stopTimer(DurationKey.GET_CHANNEL);
922
+ if (conversationId !== undefined) {
923
+ this.stats.setConversationId(conversationId);
924
+ }
925
+ this.stats.startTimer(DurationKey.GET_MESSAGES);
926
+ }
927
+ }
928
+
929
+ onGetChannelError(error: Error): void {
930
+ if (this.stats && !this.stats.isCommitted()) {
931
+ this.stats
932
+ .stopTimer(DurationKey.GET_CHANNEL)
933
+ .setError(error instanceof SendbirdError ? error.code : undefined, error.message)
934
+ .stopTimer(DurationKey.TOTAL_DURATION)
935
+ .commit();
936
+ }
937
+ }
938
+
939
+ onCacheResult(error: Error | null): void {
940
+ if (this.stats && !this.stats.isCommitted()) {
941
+ if (error) {
942
+ this.stats.setError(error instanceof SendbirdError ? error.code : undefined, error.message);
943
+ }
944
+ this.stats.stopTimer(DurationKey.TOTAL_DURATION_FROM_CACHE);
945
+ }
946
+ }
947
+
948
+ onApiResult(error: Error | null): void {
949
+ if (this.stats && !this.stats.isCommitted()) {
950
+ if (error) {
951
+ this.stats.setError(error instanceof SendbirdError ? error.code : undefined, error.message);
952
+ }
953
+ this.stats.stopTimer(DurationKey.TOTAL_DURATION).stopTimer(DurationKey.GET_MESSAGES).commit();
954
+ }
955
+ }
956
+
957
+ setChannelUrl(url: string): void {
958
+ this.stats?.setChannelUrl(url);
959
+ }
960
+
961
+ cleanup(): void {
962
+ this.stats?.commit();
963
+ }
964
+
965
+ setPresentMethod(method: PresentMethod): void {
966
+ this.presentMethod = method;
967
+ this.stats?.setPresentMethod(method);
968
+ }
969
+
970
+ clear(): void {
971
+ this.stats = null;
972
+ }
973
+ }
974
+
713
975
  export declare const ConversationLayout: {
714
976
  (props: PropsWithChildren): ReactNode;
715
977
  defaults: {
@@ -1350,6 +1612,14 @@ export declare const IncomingMessageLayout: {
1350
1612
  url: string;
1351
1613
  type: string;
1352
1614
  }) => void;
1615
+ onClickMediaFiles?: (params: {
1616
+ files: Array<{
1617
+ url: string;
1618
+ type: string;
1619
+ name?: string;
1620
+ }>;
1621
+ index: number;
1622
+ }) => void;
1353
1623
  onClickFile?: (params: {
1354
1624
  url: string;
1355
1625
  type: string;
@@ -1414,6 +1684,86 @@ export declare const IncomingMessageLayout: {
1414
1684
  url: string;
1415
1685
  type: string;
1416
1686
  }) => void;
1687
+ onClickMediaFiles?: (params: {
1688
+ files: Array<{
1689
+ url: string;
1690
+ type: string;
1691
+ name?: string;
1692
+ }>;
1693
+ index: number;
1694
+ }) => void;
1695
+ onClickFile?: (params: {
1696
+ url: string;
1697
+ type: string;
1698
+ }) => void;
1699
+ children?: ReactNode;
1700
+ }) | ({
1701
+ messageType: "multipleFiles";
1702
+ message: string;
1703
+ files: {
1704
+ type: string;
1705
+ url: string;
1706
+ name: string;
1707
+ }[];
1708
+ } & {
1709
+ sender: {
1710
+ nickname: string;
1711
+ profileUrl?: string;
1712
+ };
1713
+ suggestedRepliesVisible?: boolean;
1714
+ suggestedRepliesDirection?: "vertical" | "horizontal";
1715
+ isBotMessage?: boolean;
1716
+ isTyping?: boolean;
1717
+ isStreaming?: boolean;
1718
+ isHandedOff?: boolean;
1719
+ isConversationClosed?: boolean;
1720
+ isFeedbackEnabled?: boolean;
1721
+ isFeedbackCommentEnabled?: boolean;
1722
+ isSenderAvatarVisible?: boolean;
1723
+ onGetCachedMessageTemplate?: (templateKey: string) => string | null;
1724
+ onRequestMessageTemplate?: (templateKey: string) => Promise<string>;
1725
+ onHandleTemplateInternalAction?: (action: Action) => void;
1726
+ onClickSuggestedReply?: (params: {
1727
+ reply: string;
1728
+ }) => void;
1729
+ onClickCTA?: (params: {
1730
+ url: string;
1731
+ }) => void;
1732
+ onClickCitation?: (citation: CitationInfo) => void;
1733
+ onFeedbackUpdate?: (params: {
1734
+ rating: "good" | "bad";
1735
+ comment?: string;
1736
+ } | null) => void;
1737
+ onSubmitForm?: (params: {
1738
+ key: string;
1739
+ data: Record<string, FormFieldValue>;
1740
+ }) => Promise<void>;
1741
+ onCancelForm?: (params: {
1742
+ key: string;
1743
+ }) => Promise<void>;
1744
+ onStreamAnimationStart?: () => void;
1745
+ onStreamAnimationProgress?: () => void;
1746
+ onStreamAnimationComplete?: () => void;
1747
+ messageTemplateErrorFallback?: ReactNode;
1748
+ messageTemplateLoadingFallback?: ReactNode;
1749
+ } & {
1750
+ data?: string;
1751
+ createdAt?: number;
1752
+ extendedMessagePayload?: Partial<ExtendedMessagePayload>;
1753
+ groupType?: MessageGroupType;
1754
+ maxBodyWidth?: number;
1755
+ onClickMedia?: (params: {
1756
+ url: string;
1757
+ type: string;
1758
+ }) => void;
1759
+ onClickMediaFiles?: (params: {
1760
+ files: Array<{
1761
+ url: string;
1762
+ type: string;
1763
+ name?: string;
1764
+ }>;
1765
+ index: number;
1766
+ }) => void;
1417
1767
  onClickFile?: (params: {
1418
1768
  url: string;
1419
1769
  type: string;
@@ -1511,6 +1861,14 @@ export declare const IncomingMessageLayout: {
1511
1861
  url: string;
1512
1862
  type: string;
1513
1863
  }) => void;
1864
+ onClickMediaFiles?: (params: {
1865
+ files: Array<{
1866
+ url: string;
1867
+ type: string;
1868
+ name?: string;
1869
+ }>;
1870
+ index: number;
1871
+ }) => void;
1514
1872
  onClickFile?: (params: {
1515
1873
  url: string;
1516
1874
  type: string;
@@ -1575,6 +1933,86 @@ export declare const IncomingMessageLayout: {
1575
1933
  url: string;
1576
1934
  type: string;
1577
1935
  }) => void;
1936
+ onClickMediaFiles?: (params: {
1937
+ files: Array<{
1938
+ url: string;
1939
+ type: string;
1940
+ name?: string;
1941
+ }>;
1942
+ index: number;
1943
+ }) => void;
1944
+ onClickFile?: (params: {
1945
+ url: string;
1946
+ type: string;
1947
+ }) => void;
1948
+ children?: ReactNode;
1949
+ }) | ({
1950
+ messageType: "multipleFiles";
1951
+ message: string;
1952
+ files: {
1953
+ type: string;
1954
+ url: string;
1955
+ name: string;
1956
+ }[];
1957
+ } & {
1958
+ sender: {
1959
+ nickname: string;
1960
+ profileUrl?: string;
1961
+ };
1962
+ suggestedRepliesVisible?: boolean;
1963
+ suggestedRepliesDirection?: "vertical" | "horizontal";
1964
+ isBotMessage?: boolean;
1965
+ isTyping?: boolean;
1966
+ isStreaming?: boolean;
1967
+ isHandedOff?: boolean;
1968
+ isConversationClosed?: boolean;
1969
+ isFeedbackEnabled?: boolean;
1970
+ isFeedbackCommentEnabled?: boolean;
1971
+ isSenderAvatarVisible?: boolean;
1972
+ onGetCachedMessageTemplate?: (templateKey: string) => string | null;
1973
+ onRequestMessageTemplate?: (templateKey: string) => Promise<string>;
1974
+ onHandleTemplateInternalAction?: (action: Action) => void;
1975
+ onClickSuggestedReply?: (params: {
1976
+ reply: string;
1977
+ }) => void;
1978
+ onClickCTA?: (params: {
1979
+ url: string;
1980
+ }) => void;
1981
+ onClickCitation?: (citation: CitationInfo) => void;
1982
+ onFeedbackUpdate?: (params: {
1983
+ rating: "good" | "bad";
1984
+ comment?: string;
1985
+ } | null) => void;
1986
+ onSubmitForm?: (params: {
1987
+ key: string;
1988
+ data: Record<string, FormFieldValue>;
1989
+ }) => Promise<void>;
1990
+ onCancelForm?: (params: {
1991
+ key: string;
1992
+ }) => Promise<void>;
1993
+ onStreamAnimationStart?: () => void;
1994
+ onStreamAnimationProgress?: () => void;
1995
+ onStreamAnimationComplete?: () => void;
1996
+ messageTemplateErrorFallback?: ReactNode;
1997
+ messageTemplateLoadingFallback?: ReactNode;
1998
+ } & {
1999
+ data?: string;
2000
+ createdAt?: number;
2001
+ extendedMessagePayload?: Partial<ExtendedMessagePayload>;
2002
+ groupType?: MessageGroupType;
2003
+ maxBodyWidth?: number;
2004
+ onClickMedia?: (params: {
2005
+ url: string;
2006
+ type: string;
2007
+ }) => void;
2008
+ onClickMediaFiles?: (params: {
2009
+ files: Array<{
2010
+ url: string;
2011
+ type: string;
2012
+ name?: string;
2013
+ }>;
2014
+ index: number;
2015
+ }) => void;
1578
2016
  onClickFile?: (params: {
1579
2017
  url: string;
1580
2018
  type: string;
@@ -1667,6 +2105,14 @@ export declare const IncomingMessageLayout: {
1667
2105
  url: string;
1668
2106
  type: string;
1669
2107
  }) => void;
2108
+ onClickMediaFiles?: (params: {
2109
+ files: Array<{
2110
+ url: string;
2111
+ type: string;
2112
+ name?: string;
2113
+ }>;
2114
+ index: number;
2115
+ }) => void;
1670
2116
  onClickFile?: (params: {
1671
2117
  url: string;
1672
2118
  type: string;
@@ -1731,6 +2177,86 @@ export declare const IncomingMessageLayout: {
1731
2177
  url: string;
1732
2178
  type: string;
1733
2179
  }) => void;
2180
+ onClickMediaFiles?: (params: {
2181
+ files: Array<{
2182
+ url: string;
2183
+ type: string;
2184
+ name?: string;
2185
+ }>;
2186
+ index: number;
2187
+ }) => void;
2188
+ onClickFile?: (params: {
2189
+ url: string;
2190
+ type: string;
2191
+ }) => void;
2192
+ children?: ReactNode;
2193
+ }) | ({
2194
+ messageType: "multipleFiles";
2195
+ message: string;
2196
+ files: {
2197
+ type: string;
2198
+ url: string;
2199
+ name: string;
2200
+ }[];
2201
+ } & {
2202
+ sender: {
2203
+ nickname: string;
2204
+ profileUrl?: string;
2205
+ };
2206
+ suggestedRepliesVisible?: boolean;
2207
+ suggestedRepliesDirection?: "vertical" | "horizontal";
2208
+ isBotMessage?: boolean;
2209
+ isTyping?: boolean;
2210
+ isStreaming?: boolean;
2211
+ isHandedOff?: boolean;
2212
+ isConversationClosed?: boolean;
2213
+ isFeedbackEnabled?: boolean;
2214
+ isFeedbackCommentEnabled?: boolean;
2215
+ isSenderAvatarVisible?: boolean;
2216
+ onGetCachedMessageTemplate?: (templateKey: string) => string | null;
2217
+ onRequestMessageTemplate?: (templateKey: string) => Promise<string>;
2218
+ onHandleTemplateInternalAction?: (action: Action) => void;
2219
+ onClickSuggestedReply?: (params: {
2220
+ reply: string;
2221
+ }) => void;
2222
+ onClickCTA?: (params: {
2223
+ url: string;
2224
+ }) => void;
2225
+ onClickCitation?: (citation: CitationInfo) => void;
2226
+ onFeedbackUpdate?: (params: {
2227
+ rating: "good" | "bad";
2228
+ comment?: string;
2229
+ } | null) => void;
2230
+ onSubmitForm?: (params: {
2231
+ key: string;
2232
+ data: Record<string, FormFieldValue>;
2233
+ }) => Promise<void>;
2234
+ onCancelForm?: (params: {
2235
+ key: string;
2236
+ }) => Promise<void>;
2237
+ onStreamAnimationStart?: () => void;
2238
+ onStreamAnimationProgress?: () => void;
2239
+ onStreamAnimationComplete?: () => void;
2240
+ messageTemplateErrorFallback?: ReactNode;
2241
+ messageTemplateLoadingFallback?: ReactNode;
2242
+ } & {
2243
+ data?: string;
2244
+ createdAt?: number;
2245
+ extendedMessagePayload?: Partial<ExtendedMessagePayload>;
2246
+ groupType?: MessageGroupType;
2247
+ maxBodyWidth?: number;
2248
+ onClickMedia?: (params: {
2249
+ url: string;
2250
+ type: string;
2251
+ }) => void;
2252
+ onClickMediaFiles?: (params: {
2253
+ files: Array<{
2254
+ url: string;
2255
+ type: string;
2256
+ name?: string;
2257
+ }>;
2258
+ index: number;
2259
+ }) => void;
1734
2260
  onClickFile?: (params: {
1735
2261
  url: string;
1736
2262
  type: string;
@@ -1838,6 +2364,14 @@ export declare const IncomingMessageLayout: {
1838
2364
  url: string;
1839
2365
  type: string;
1840
2366
  }) => void;
2367
+ onClickMediaFiles?: (params: {
2368
+ files: Array<{
2369
+ url: string;
2370
+ type: string;
2371
+ name?: string;
2372
+ }>;
2373
+ index: number;
2374
+ }) => void;
1841
2375
  onClickFile?: (params: {
1842
2376
  url: string;
1843
2377
  type: string;
@@ -1902,6 +2436,86 @@ export declare const IncomingMessageLayout: {
1902
2436
  url: string;
1903
2437
  type: string;
1904
2438
  }) => void;
2439
+ onClickMediaFiles?: (params: {
2440
+ files: Array<{
2441
+ url: string;
2442
+ type: string;
2443
+ name?: string;
2444
+ }>;
2445
+ index: number;
2446
+ }) => void;
2447
+ onClickFile?: (params: {
2448
+ url: string;
2449
+ type: string;
2450
+ }) => void;
2451
+ children?: ReactNode;
2452
+ }) | ({
2453
+ messageType: "multipleFiles";
2454
+ message: string;
2455
+ files: {
2456
+ type: string;
2457
+ url: string;
2458
+ name: string;
2459
+ }[];
2460
+ } & {
2461
+ sender: {
2462
+ nickname: string;
2463
+ profileUrl?: string;
2464
+ };
2465
+ suggestedRepliesVisible?: boolean;
2466
+ suggestedRepliesDirection?: "vertical" | "horizontal";
2467
+ isBotMessage?: boolean;
2468
+ isTyping?: boolean;
2469
+ isStreaming?: boolean;
2470
+ isHandedOff?: boolean;
2471
+ isConversationClosed?: boolean;
2472
+ isFeedbackEnabled?: boolean;
2473
+ isFeedbackCommentEnabled?: boolean;
2474
+ isSenderAvatarVisible?: boolean;
2475
+ onGetCachedMessageTemplate?: (templateKey: string) => string | null;
2476
+ onRequestMessageTemplate?: (templateKey: string) => Promise<string>;
2477
+ onHandleTemplateInternalAction?: (action: Action) => void;
2478
+ onClickSuggestedReply?: (params: {
2479
+ reply: string;
2480
+ }) => void;
2481
+ onClickCTA?: (params: {
2482
+ url: string;
2483
+ }) => void;
2484
+ onClickCitation?: (citation: CitationInfo) => void;
2485
+ onFeedbackUpdate?: (params: {
2486
+ rating: "good" | "bad";
2487
+ comment?: string;
2488
+ } | null) => void;
2489
+ onSubmitForm?: (params: {
2490
+ key: string;
2491
+ data: Record<string, FormFieldValue>;
2492
+ }) => Promise<void>;
2493
+ onCancelForm?: (params: {
2494
+ key: string;
2495
+ }) => Promise<void>;
2496
+ onStreamAnimationStart?: () => void;
2497
+ onStreamAnimationProgress?: () => void;
2498
+ onStreamAnimationComplete?: () => void;
2499
+ messageTemplateErrorFallback?: ReactNode;
2500
+ messageTemplateLoadingFallback?: ReactNode;
2501
+ } & {
2502
+ data?: string;
2503
+ createdAt?: number;
2504
+ extendedMessagePayload?: Partial<ExtendedMessagePayload>;
2505
+ groupType?: MessageGroupType;
2506
+ maxBodyWidth?: number;
2507
+ onClickMedia?: (params: {
2508
+ url: string;
2509
+ type: string;
2510
+ }) => void;
2511
+ onClickMediaFiles?: (params: {
2512
+ files: Array<{
2513
+ url: string;
2514
+ type: string;
2515
+ name?: string;
2516
+ }>;
2517
+ index: number;
2518
+ }) => void;
1905
2519
  onClickFile?: (params: {
1906
2520
  url: string;
1907
2521
  type: string;
@@ -1943,6 +2557,15 @@ declare type IncomingMessageUnion =
1943
2557
  url: string;
1944
2558
  name: string;
1945
2559
  };
2560
+ }>
2561
+ | IncomingBaseMessageProps<{
2562
+ messageType: 'multipleFiles';
2563
+ message: string;
2564
+ files: {
2565
+ type: string;
2566
+ url: string;
2567
+ name: string;
2568
+ }[];
1946
2569
  }>;
1947
2570
 
1948
2571
  declare type InputState = {
@@ -2142,6 +2765,7 @@ declare interface MessengerSettingsResponse {
2142
2765
  upload_size_limit_per_type: Record<string, number>;
2143
2766
  supported_image_mime_types: string[];
2144
2767
  supported_file_mime_types: string[];
2768
+ max_attachment_count?: number;
2145
2769
  };
2146
2770
  }
2147
2771
 
@@ -2271,10 +2895,10 @@ export declare const OutgoingMessageLayout: {
2271
2895
  defaults: {
2272
2896
  template: ComponentType<OutgoingMessageProps>;
2273
2897
  components: {
2274
- SendingStatus: ({ sendingStatus, containerStyle }: OutgoingMessageProps<"file" | "user"> & {
2898
+ SendingStatus: ({ sendingStatus, containerStyle }: OutgoingMessageProps<"file" | "user" | "multipleFiles"> & {
2275
2899
  containerStyle?: ViewStyle;
2276
2900
  }) => ReactNode;
2277
- SentTime: ({ createdAt, containerStyle }: OutgoingMessageProps<"file" | "user"> & {
2901
+ SentTime: ({ createdAt, containerStyle }: OutgoingMessageProps<"file" | "user" | "multipleFiles"> & {
2278
2902
  containerStyle?: ViewStyle;
2279
2903
  }) => ReactNode;
2280
2904
  MessageBody: (props: OutgoingMessageBodyProps) => ReactNode;
@@ -2285,26 +2909,26 @@ export declare const OutgoingMessageLayout: {
2285
2909
  children?: ReactNode;
2286
2910
  }) => JSX.Element;
2287
2911
  Context: Context<LayoutContextValue<OutgoingMessageProps, {
2288
- SendingStatus: ({ sendingStatus, containerStyle }: OutgoingMessageProps<"file" | "user"> & {
2912
+ SendingStatus: ({ sendingStatus, containerStyle }: OutgoingMessageProps<"file" | "user" | "multipleFiles"> & {
2289
2913
  containerStyle?: ViewStyle;
2290
2914
  }) => ReactNode;
2291
- SentTime: ({ createdAt, containerStyle }: OutgoingMessageProps<"file" | "user"> & {
2915
+ SentTime: ({ createdAt, containerStyle }: OutgoingMessageProps<"file" | "user" | "multipleFiles"> & {
2292
2916
  containerStyle?: ViewStyle;
2293
2917
  }) => ReactNode;
2294
2918
  MessageBody: (props: OutgoingMessageBodyProps) => ReactNode;
2295
2919
  }>>;
2296
2920
  useContext: () => LayoutContextValue<OutgoingMessageProps, {
2297
- SendingStatus: ({ sendingStatus, containerStyle }: OutgoingMessageProps<"file" | "user"> & {
2921
+ SendingStatus: ({ sendingStatus, containerStyle }: OutgoingMessageProps<"file" | "user" | "multipleFiles"> & {
2298
2922
  containerStyle?: ViewStyle;
2299
2923
  }) => ReactNode;
2300
- SentTime: ({ createdAt, containerStyle }: OutgoingMessageProps<"file" | "user"> & {
2924
+ SentTime: ({ createdAt, containerStyle }: OutgoingMessageProps<"file" | "user" | "multipleFiles"> & {
2301
2925
  containerStyle?: ViewStyle;
2302
2926
  }) => ReactNode;
2303
2927
  MessageBody: (props: OutgoingMessageBodyProps) => ReactNode;
2304
2928
  }>;
2305
2929
  } & {
2306
2930
  SentTime: (props: {
2307
- component: ({ createdAt, containerStyle }: OutgoingMessageProps<"file" | "user"> & {
2931
+ component: ({ createdAt, containerStyle }: OutgoingMessageProps<"file" | "user" | "multipleFiles"> & {
2308
2932
  containerStyle?: ViewStyle;
2309
2933
  }) => ReactNode;
2310
2934
  }) => null;
@@ -2312,7 +2936,7 @@ export declare const OutgoingMessageLayout: {
2312
2936
  component: (props: OutgoingMessageBodyProps) => ReactNode;
2313
2937
  }) => null;
2314
2938
  SendingStatus: (props: {
2315
- component: ({ sendingStatus, containerStyle }: OutgoingMessageProps<"file" | "user"> & {
2939
+ component: ({ sendingStatus, containerStyle }: OutgoingMessageProps<"file" | "user" | "multipleFiles"> & {
2316
2940
  containerStyle?: ViewStyle;
2317
2941
  }) => ReactNode;
2318
2942
  }) => null;
@@ -2338,6 +2962,18 @@ declare type OutgoingMessageUnion =
2338
2962
  aspectRatio: string;
2339
2963
  localFile?: unknown;
2340
2964
  };
2965
+ }>
2966
+ | OutgoingBaseMessageProps<{
2967
+ messageType: 'multipleFiles';
2968
+ message: string;
2969
+ files: {
2970
+ type: string;
2971
+ url: string;
2972
+ name: string;
2973
+ }[];
2974
+ metadata: {
2975
+ localFiles?: unknown[];
2976
+ };
2341
2977
  }>;
2342
2978
 
2343
2979
  declare interface PaletteColor {
@@ -2464,6 +3100,8 @@ declare type PositionHorizontal = 'start' | 'end';
2464
3100
 
2465
3101
  declare type PositionVertical = 'top' | 'bottom';
2466
3102
 
3103
+ declare type PresentMethod = 'launcher_toggle' | 'direct_present';
3104
+
2467
3105
  declare type RNPermissionsModule = typeof RNPermissions;
2468
3106
 
2469
3107
  export declare type ScrollToBottomButtonProps = {
@@ -2487,6 +3125,8 @@ declare type SingleSelectField = {
2487
3125
  layout: 'default';
2488
3126
  };
2489
3127
 
3128
+ declare type StatsAppendCallback = (type: string, data: AIAgentStatPayload) => boolean;
3129
+
2490
3130
  /**
2491
3131
  * Strings type for React Native components
2492
3132
  * Uses nested structure with lowercase keys
@@ -2557,6 +3197,7 @@ declare type SystemMessageUnion =
2557
3197
  csatExpireAt?: number;
2558
3198
  isResolvedWhenDeterminedByUser?: boolean;
2559
3199
  onSubmitCSAT: (params: CSATSubmitParams) => Promise<void>;
3200
+ onScrollToBottom?: () => void;
2560
3201
  }>;
2561
3202
 
2562
3203
  declare type TextField = {
@@ -2575,6 +3216,11 @@ declare type TextField = {
2575
3216
  };
2576
3217
  };
2577
3218
 
3219
+ declare interface TimerData {
3220
+ startTime: number | null;
3221
+ endTime: number | null;
3222
+ }
3223
+
2578
3224
  declare interface TypographyShape {
2579
3225
  h1: TypographyVariant;
2580
3226
  h2: TypographyVariant;