wexa-chat 0.2.9 → 0.3.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/README.md CHANGED
@@ -125,6 +125,9 @@ export type InitOptions = {
125
125
  - `listMessages({ organizationId, conversationId, limit?, cursor? })`
126
126
  - `listMessagesWithSenders({ organizationId, conversationId, limit?, cursor?, populateSenders: true, populateOptions? })`
127
127
  - `markRead({ organizationId, conversationId, participantModel, participantId, messageId })`
128
+ - `receiveWhatsappMessage({ whatsappChatId, message })`
129
+ - `receiveLinkedinMessage({ linkedinChatId, message })`
130
+ - `receiveEmailMessage({ emailChatId, message })`
128
131
 
129
132
  DTO types live in `src/types/dto.ts`.
130
133
 
@@ -226,7 +229,90 @@ export type SourceType = (typeof sourceType)[keyof typeof sourceType];
226
229
 
227
230
  When sending a message via `sendMessage`, you must provide `source: SourceType[]`. For internal server‑generated messages, use `[sourceType.CORE]`.
228
231
 
229
- If you include external connectors in the `source` (e.g., `linkedin`, `whatsapp`), you can optionally pass `connectorIds` to perform the external send and to persist identifiers for quick follow‑ups:
232
+ If you include external connectors in the `source` (e.g., `linkedin`, `whatsapp`, `email`), you can optionally pass `connectorIds` to perform the external send and to persist identifiers for quick follow‑ups.
233
+
234
+ #### Email with Rich Metadata
235
+
236
+ Email supports advanced features like subject lines, CC/BCC, attachments, and tracking:
237
+
238
+ ```ts
239
+ // Simple email
240
+ await chat.services.messages.sendMessage({
241
+ organizationId: 'org-123',
242
+ conversationId: 'conv-456',
243
+ senderModel: 'User',
244
+ senderId: 'user-1',
245
+ text: 'Hi John,\n\nInterested in discussing a role?\n\nBest,\nJane',
246
+ source: [sourceType.EMAIL],
247
+ connectorIds: {
248
+ email: { connectorId: 'em-connector-1', contactId: 'john@candidate.com' },
249
+ },
250
+ metadata: {
251
+ email: {
252
+ subject: 'Job Opportunity at TechCorp',
253
+ recipientName: 'John Doe',
254
+ }
255
+ }
256
+ });
257
+
258
+ // Full-featured email with all options
259
+ await chat.services.messages.sendMessage({
260
+ organizationId: 'org-123',
261
+ conversationId: 'conv-456',
262
+ senderModel: 'User',
263
+ senderId: 'user-1',
264
+ text: 'Dear John,\n\nWe are looking for a Senior Software Engineer...',
265
+ source: [sourceType.EMAIL],
266
+ connectorIds: {
267
+ email: { connectorId: 'em-connector-1', contactId: 'john@candidate.com' },
268
+ },
269
+ metadata: {
270
+ email: {
271
+ subject: 'Senior Software Engineer Position - TechCorp',
272
+ recipientName: 'John Doe',
273
+ cc: [
274
+ { display_name: 'HR Manager', identifier: 'hr@techcorp.com' }
275
+ ],
276
+ bcc: [
277
+ { display_name: 'Recruiting Lead', identifier: 'lead@techcorp.com' }
278
+ ],
279
+ attachments: [
280
+ 'https://storage.company.com/job-description.pdf',
281
+ 'https://storage.company.com/company-overview.pdf'
282
+ ],
283
+ tracking: {
284
+ opens: true,
285
+ links: true,
286
+ label: 'q1_2024_recruitment'
287
+ }
288
+ }
289
+ }
290
+ });
291
+
292
+ // Email reply (threading)
293
+ await chat.services.messages.sendMessage({
294
+ organizationId: 'org-123',
295
+ conversationId: 'conv-456',
296
+ senderModel: 'User',
297
+ senderId: 'user-1',
298
+ text: 'Hi John,\n\nThank you for your response!...',
299
+ source: [sourceType.EMAIL],
300
+ connectorIds: {
301
+ email: { connectorId: 'em-connector-1', contactId: 'john@candidate.com' },
302
+ },
303
+ metadata: {
304
+ email: {
305
+ subject: 'Re: Senior Software Engineer Position',
306
+ recipientName: 'John Doe',
307
+ replyTo: 'email_provider_id_abc123xyz' // From previous email
308
+ }
309
+ },
310
+ parentMessageId: 'msg-previous-id',
311
+ rootThreadId: 'msg-root-id'
312
+ });
313
+ ```
314
+
315
+ #### Multi-Platform Messages
230
316
 
231
317
  ```ts
232
318
  await chat.services.messages.sendMessage({
@@ -245,14 +331,93 @@ await chat.services.messages.sendMessage({
245
331
 
246
332
  Under the hood (`src/services/messages.service.ts`):
247
333
 
248
- - LinkedIn: posts to the LinkedIn connector with `{ linkedin_url, text }`.
249
- - WhatsApp: posts to the WhatsApp connector with `{ phone_numbers, text }` (phone is sanitized to remove spaces and a leading `+`).
334
+ - **LinkedIn**: posts to the LinkedIn connector with `{ linkedin_url, text }`.
335
+ - **WhatsApp**: posts to the WhatsApp connector with `{ phone_numbers, text }` (phone is sanitized to remove spaces and a leading `+`).
336
+ - **Email**: posts to `/mail/send_email/:connectorId` with complete payload including `to` (array of recipients with display_name and identifier), `body`, `subject`, `cc`, `bcc`, `attachments` (URLs), `reply_to` (for threading), and `tracking_options`.
250
337
  - Each external task runs concurrently. A successful task's `source` remains in the stored message. Failures are collected into a `failed_source` array attached to the returned message instance at runtime: `message.failed_source: Array<{ source: string; message: string }>`.
251
338
  - The conversation document is updated with last message metadata and, when applicable, with connector identifiers:
252
339
  - `lastLinkedInId: string` — set from `connectorIds.linkedin.contactId` when `source` includes `linkedin`.
253
340
  - `lastWhatsAppId: string` — set from a sanitized `connectorIds.whatsapp.contactId` when `source` includes `whatsapp`.
341
+ - `lastEmailId: string` — set from `connectorIds.email.contactId` when `source` includes `email`.
342
+ - Message metadata (subjects, CC/BCC, attachments, tracking info) is stored in the `metadata.email` field for reference and UI rendering.
343
+
344
+ This allows subsequent UI actions to prefill the last known contact handles for LinkedIn, WhatsApp, and Email.
345
+
346
+ ### Receiving inbound connector messages
347
+
348
+ When an external connector delivers a new inbound message, you can persist it directly using the chat ID stored on the conversation.
349
+
350
+ **Important: Deduplication** - All receive methods support automatic deduplication via `messageId`. If a message with the same `messageId` already exists in the conversation, the existing message is returned instead of creating a duplicate. This prevents duplicate messages from webhooks that retry or are delivered multiple times.
351
+
352
+ #### WhatsApp Messages
353
+
354
+ ```ts
355
+ await chat.services.messages.receiveWhatsappMessage({
356
+ whatsappChatId: 'wa-chat-123',
357
+ message: 'Hello from WhatsApp',
358
+ messageId: 'wamid.HBgNMTIzNDU2Nzg5...', // For deduplication
359
+ senderName: 'John Doe', // Optional
360
+ });
361
+ ```
362
+
363
+ #### LinkedIn Messages
364
+
365
+ ```ts
366
+ await chat.services.messages.receiveLinkedinMessage({
367
+ linkedinChatId: 'li-chat-456',
368
+ message: 'Hello from LinkedIn',
369
+ messageId: 'msg-abc123', // For deduplication
370
+ senderName: 'Jane Smith', // Optional
371
+ senderProfileUrl: 'https://linkedin.com/in/janesmith', // Optional
372
+ });
373
+ ```
374
+
375
+ #### Email with Full Metadata
376
+
377
+ Email receives support enhanced metadata including subject, sender info, and threading:
378
+
379
+ ```ts
380
+ // Simple email reply
381
+ await chat.services.messages.receiveEmailMessage({
382
+ emailChatId: 'em-chat-789',
383
+ message: 'Hi! I\'m interested in the role.',
384
+ subject: 'Re: Job Opportunity',
385
+ senderEmail: 'candidate@example.com',
386
+ senderName: 'John Doe',
387
+ messageId: '<CANn6MZN...@mail.gmail.com>', // For deduplication
388
+ });
389
+
390
+ // Full email with threading and attachments
391
+ await chat.services.messages.receiveEmailMessage({
392
+ emailChatId: 'em-chat-789',
393
+ message: 'Hi Jane,\n\nThank you for reaching out...',
394
+ subject: 'Re: Senior Developer Position',
395
+ senderEmail: 'candidate@example.com',
396
+ senderName: 'John Doe',
397
+ providerId: '19bfed8cdc1d7148', // For threading - important!
398
+ messageId: '<CANn6MZN...@mail.gmail.com>', // For deduplication - important!
399
+ attachments: [
400
+ {
401
+ name: 'resume.pdf',
402
+ url: 'https://storage.example.com/resume.pdf',
403
+ size: 245000,
404
+ mimeType: 'application/pdf'
405
+ }
406
+ ]
407
+ });
408
+ ```
254
409
 
255
- This allows subsequent UI actions to prefill the last known contact handles for LinkedIn and WhatsApp.
410
+ All helpers will:
411
+
412
+ 1. **Check for duplicates** - If `messageId` is provided, check if a message with that ID already exists in the conversation and return it if found.
413
+ 2. Locate the conversation by the given chat ID.
414
+ 3. Use the `Application` participant from the conversation as the sender.
415
+ 4. Create a new message with `kind: 'text'` and `source` set to the respective connector.
416
+ 5. Store platform-specific metadata:
417
+ - **Email**: subject, sender info, attachments, threading data in `metadata.email`
418
+ - **LinkedIn**: sender name and profile URL in `metadata.linkedin`
419
+ - **WhatsApp**: sender name in `metadata.whatsapp`
420
+ 6. Update the conversation summary fields (`lastMessageAt`, `lastMessagePreview`, `lastMessageSenderId`, `lastMessageSenderModel`).
256
421
 
257
422
  ## Models
258
423
 
package/dist/index.d.cts CHANGED
@@ -137,6 +137,52 @@ interface IMessage extends Document {
137
137
  source: string;
138
138
  message: string;
139
139
  }>;
140
+ externalMessageId?: string;
141
+ metadata?: {
142
+ email?: {
143
+ subject?: string;
144
+ to?: Array<{
145
+ display_name: string;
146
+ identifier: string;
147
+ }>;
148
+ cc?: Array<{
149
+ display_name: string;
150
+ identifier: string;
151
+ }>;
152
+ bcc?: Array<{
153
+ display_name: string;
154
+ identifier: string;
155
+ }>;
156
+ from?: {
157
+ display_name: string;
158
+ identifier: string;
159
+ };
160
+ attachments?: Array<{
161
+ name: string;
162
+ url: string;
163
+ size?: number;
164
+ mimeType?: string;
165
+ }>;
166
+ providerId?: string;
167
+ messageId?: string;
168
+ replyTo?: string;
169
+ tracking?: {
170
+ opens?: boolean;
171
+ links?: boolean;
172
+ label?: string;
173
+ custom_domain?: string;
174
+ };
175
+ };
176
+ linkedin?: {
177
+ subject?: string;
178
+ isInMail?: boolean;
179
+ senderName?: string;
180
+ senderProfileUrl?: string;
181
+ };
182
+ whatsapp?: {
183
+ senderName?: string;
184
+ };
185
+ };
140
186
  parentMessageId?: string;
141
187
  rootThreadId?: string;
142
188
  editedAt?: Date;
@@ -202,6 +248,36 @@ type SendMessageArgs = {
202
248
  contactId: string;
203
249
  connectorId: string;
204
250
  }>;
251
+ metadata?: {
252
+ email?: {
253
+ subject?: string;
254
+ recipientName?: string;
255
+ additionalRecipients?: Array<{
256
+ display_name: string;
257
+ identifier: string;
258
+ }>;
259
+ cc?: Array<{
260
+ display_name: string;
261
+ identifier: string;
262
+ }>;
263
+ bcc?: Array<{
264
+ display_name: string;
265
+ identifier: string;
266
+ }>;
267
+ attachments?: string[];
268
+ replyTo?: string;
269
+ tracking?: {
270
+ opens?: boolean;
271
+ links?: boolean;
272
+ label?: string;
273
+ custom_domain?: string;
274
+ };
275
+ };
276
+ linkedin?: {
277
+ subject?: string;
278
+ isInMail?: boolean;
279
+ };
280
+ };
205
281
  };
206
282
  type ListMessagesArgs = {
207
283
  organizationId: string;
@@ -221,6 +297,34 @@ type MarkReadArgs = {
221
297
  participantId: string;
222
298
  messageId: string;
223
299
  };
300
+ type ReceiveWhatsappMessageArgs = {
301
+ whatsappChatId: string;
302
+ message: string;
303
+ messageId?: string;
304
+ senderName?: string;
305
+ };
306
+ type ReceiveLinkedinMessageArgs = {
307
+ linkedinChatId: string;
308
+ message: string;
309
+ messageId?: string;
310
+ senderName?: string;
311
+ senderProfileUrl?: string;
312
+ };
313
+ type ReceiveEmailMessageArgs = {
314
+ emailChatId: string;
315
+ message: string;
316
+ subject?: string;
317
+ senderEmail?: string;
318
+ senderName?: string;
319
+ providerId?: string;
320
+ messageId?: string;
321
+ attachments?: Array<{
322
+ name: string;
323
+ url: string;
324
+ size?: number;
325
+ mimeType?: string;
326
+ }>;
327
+ };
224
328
  type SearchMessagesArgs = {
225
329
  organizationId: string;
226
330
  query?: string;
@@ -277,8 +381,10 @@ interface IConversation extends Document {
277
381
  lastMessageSenderModel?: string;
278
382
  lastLinkedInId?: string;
279
383
  lastWhatsAppId?: string;
384
+ lastEmailId?: string;
280
385
  linkedinChatId?: string;
281
386
  whatsappChatId?: string;
387
+ emailChatId?: string;
282
388
  metadata?: Record<string, any>;
283
389
  createdAt: Date;
284
390
  updatedAt: Date;
@@ -375,6 +481,9 @@ interface MessagesService {
375
481
  populateSenders: true;
376
482
  }): Promise<PaginatedResult<MessageWithSender>>;
377
483
  markRead(args: MarkReadArgs): Promise<void>;
484
+ receiveWhatsappMessage(args: ReceiveWhatsappMessageArgs): Promise<IMessage>;
485
+ receiveLinkedinMessage(args: ReceiveLinkedinMessageArgs): Promise<IMessage>;
486
+ receiveEmailMessage(args: ReceiveEmailMessageArgs): Promise<IMessage>;
378
487
  }
379
488
  /**
380
489
  * Create messages service
@@ -598,4 +707,4 @@ interface ChatServices {
598
707
  */
599
708
  declare function initChat(mongooseInstance: typeof mongoose, options: InitOptions, server?: Server): Promise<ChatServices>;
600
709
 
601
- export { type Actor, type ChatApiResponse, type ChatServices, type ChatStartedResponse, type ConversationModel, type ConversationReadEvent, type ConversationsService, type CreateConversationArgs, type EnvironmentConfig, type IConversation, type IMessage, type InitOptions, type ListMessagesArgs, type MarkReadArgs, type MessageCreatedEvent, type MessageModel, type MessageServiceHooks, type MessageWithSender, type MessagesService, type PaginatedResult, type PresenceEvent, type RedisConfig, type RuntimeConfig, type SearchConversationsArgs, type SearchMessagesArgs, type SendMessageArgs, type SocketConfig$1 as SocketConfig, type SourceType, type Transport, type TransportConfig, type TypingEvent, createConversationId, createConversationModel, createConversationsService, createCursor, createMessageId, createMessageModel, createMessagesService, createModels, createPaginatedResponse, createThreadId, createTransport, ensureIndexes, generateId, getRedisConfig, getRuntimeConfig, initChat, modelRegistry, parseCursor, searchByParticipantPair, searchConversations, searchMessages, setRuntimeConfig, sourceType, validateCreateConversationArgs, validateInitOptions, validateMarkReadArgs, validatePagination, validateSendMessageArgs };
710
+ export { type Actor, type ChatApiResponse, type ChatServices, type ChatStartedResponse, type ConversationModel, type ConversationReadEvent, type ConversationsService, type CreateConversationArgs, type EnvironmentConfig, type IConversation, type IMessage, type InitOptions, type ListMessagesArgs, type MarkReadArgs, type MessageCreatedEvent, type MessageModel, type MessageServiceHooks, type MessageWithSender, type MessagesService, type PaginatedResult, type PresenceEvent, type ReceiveEmailMessageArgs, type ReceiveLinkedinMessageArgs, type ReceiveWhatsappMessageArgs, type RedisConfig, type RuntimeConfig, type SearchConversationsArgs, type SearchMessagesArgs, type SendMessageArgs, type SocketConfig$1 as SocketConfig, type SourceType, type Transport, type TransportConfig, type TypingEvent, createConversationId, createConversationModel, createConversationsService, createCursor, createMessageId, createMessageModel, createMessagesService, createModels, createPaginatedResponse, createThreadId, createTransport, ensureIndexes, generateId, getRedisConfig, getRuntimeConfig, initChat, modelRegistry, parseCursor, searchByParticipantPair, searchConversations, searchMessages, setRuntimeConfig, sourceType, validateCreateConversationArgs, validateInitOptions, validateMarkReadArgs, validatePagination, validateSendMessageArgs };
package/dist/index.d.ts CHANGED
@@ -137,6 +137,52 @@ interface IMessage extends Document {
137
137
  source: string;
138
138
  message: string;
139
139
  }>;
140
+ externalMessageId?: string;
141
+ metadata?: {
142
+ email?: {
143
+ subject?: string;
144
+ to?: Array<{
145
+ display_name: string;
146
+ identifier: string;
147
+ }>;
148
+ cc?: Array<{
149
+ display_name: string;
150
+ identifier: string;
151
+ }>;
152
+ bcc?: Array<{
153
+ display_name: string;
154
+ identifier: string;
155
+ }>;
156
+ from?: {
157
+ display_name: string;
158
+ identifier: string;
159
+ };
160
+ attachments?: Array<{
161
+ name: string;
162
+ url: string;
163
+ size?: number;
164
+ mimeType?: string;
165
+ }>;
166
+ providerId?: string;
167
+ messageId?: string;
168
+ replyTo?: string;
169
+ tracking?: {
170
+ opens?: boolean;
171
+ links?: boolean;
172
+ label?: string;
173
+ custom_domain?: string;
174
+ };
175
+ };
176
+ linkedin?: {
177
+ subject?: string;
178
+ isInMail?: boolean;
179
+ senderName?: string;
180
+ senderProfileUrl?: string;
181
+ };
182
+ whatsapp?: {
183
+ senderName?: string;
184
+ };
185
+ };
140
186
  parentMessageId?: string;
141
187
  rootThreadId?: string;
142
188
  editedAt?: Date;
@@ -202,6 +248,36 @@ type SendMessageArgs = {
202
248
  contactId: string;
203
249
  connectorId: string;
204
250
  }>;
251
+ metadata?: {
252
+ email?: {
253
+ subject?: string;
254
+ recipientName?: string;
255
+ additionalRecipients?: Array<{
256
+ display_name: string;
257
+ identifier: string;
258
+ }>;
259
+ cc?: Array<{
260
+ display_name: string;
261
+ identifier: string;
262
+ }>;
263
+ bcc?: Array<{
264
+ display_name: string;
265
+ identifier: string;
266
+ }>;
267
+ attachments?: string[];
268
+ replyTo?: string;
269
+ tracking?: {
270
+ opens?: boolean;
271
+ links?: boolean;
272
+ label?: string;
273
+ custom_domain?: string;
274
+ };
275
+ };
276
+ linkedin?: {
277
+ subject?: string;
278
+ isInMail?: boolean;
279
+ };
280
+ };
205
281
  };
206
282
  type ListMessagesArgs = {
207
283
  organizationId: string;
@@ -221,6 +297,34 @@ type MarkReadArgs = {
221
297
  participantId: string;
222
298
  messageId: string;
223
299
  };
300
+ type ReceiveWhatsappMessageArgs = {
301
+ whatsappChatId: string;
302
+ message: string;
303
+ messageId?: string;
304
+ senderName?: string;
305
+ };
306
+ type ReceiveLinkedinMessageArgs = {
307
+ linkedinChatId: string;
308
+ message: string;
309
+ messageId?: string;
310
+ senderName?: string;
311
+ senderProfileUrl?: string;
312
+ };
313
+ type ReceiveEmailMessageArgs = {
314
+ emailChatId: string;
315
+ message: string;
316
+ subject?: string;
317
+ senderEmail?: string;
318
+ senderName?: string;
319
+ providerId?: string;
320
+ messageId?: string;
321
+ attachments?: Array<{
322
+ name: string;
323
+ url: string;
324
+ size?: number;
325
+ mimeType?: string;
326
+ }>;
327
+ };
224
328
  type SearchMessagesArgs = {
225
329
  organizationId: string;
226
330
  query?: string;
@@ -277,8 +381,10 @@ interface IConversation extends Document {
277
381
  lastMessageSenderModel?: string;
278
382
  lastLinkedInId?: string;
279
383
  lastWhatsAppId?: string;
384
+ lastEmailId?: string;
280
385
  linkedinChatId?: string;
281
386
  whatsappChatId?: string;
387
+ emailChatId?: string;
282
388
  metadata?: Record<string, any>;
283
389
  createdAt: Date;
284
390
  updatedAt: Date;
@@ -375,6 +481,9 @@ interface MessagesService {
375
481
  populateSenders: true;
376
482
  }): Promise<PaginatedResult<MessageWithSender>>;
377
483
  markRead(args: MarkReadArgs): Promise<void>;
484
+ receiveWhatsappMessage(args: ReceiveWhatsappMessageArgs): Promise<IMessage>;
485
+ receiveLinkedinMessage(args: ReceiveLinkedinMessageArgs): Promise<IMessage>;
486
+ receiveEmailMessage(args: ReceiveEmailMessageArgs): Promise<IMessage>;
378
487
  }
379
488
  /**
380
489
  * Create messages service
@@ -598,4 +707,4 @@ interface ChatServices {
598
707
  */
599
708
  declare function initChat(mongooseInstance: typeof mongoose, options: InitOptions, server?: Server): Promise<ChatServices>;
600
709
 
601
- export { type Actor, type ChatApiResponse, type ChatServices, type ChatStartedResponse, type ConversationModel, type ConversationReadEvent, type ConversationsService, type CreateConversationArgs, type EnvironmentConfig, type IConversation, type IMessage, type InitOptions, type ListMessagesArgs, type MarkReadArgs, type MessageCreatedEvent, type MessageModel, type MessageServiceHooks, type MessageWithSender, type MessagesService, type PaginatedResult, type PresenceEvent, type RedisConfig, type RuntimeConfig, type SearchConversationsArgs, type SearchMessagesArgs, type SendMessageArgs, type SocketConfig$1 as SocketConfig, type SourceType, type Transport, type TransportConfig, type TypingEvent, createConversationId, createConversationModel, createConversationsService, createCursor, createMessageId, createMessageModel, createMessagesService, createModels, createPaginatedResponse, createThreadId, createTransport, ensureIndexes, generateId, getRedisConfig, getRuntimeConfig, initChat, modelRegistry, parseCursor, searchByParticipantPair, searchConversations, searchMessages, setRuntimeConfig, sourceType, validateCreateConversationArgs, validateInitOptions, validateMarkReadArgs, validatePagination, validateSendMessageArgs };
710
+ export { type Actor, type ChatApiResponse, type ChatServices, type ChatStartedResponse, type ConversationModel, type ConversationReadEvent, type ConversationsService, type CreateConversationArgs, type EnvironmentConfig, type IConversation, type IMessage, type InitOptions, type ListMessagesArgs, type MarkReadArgs, type MessageCreatedEvent, type MessageModel, type MessageServiceHooks, type MessageWithSender, type MessagesService, type PaginatedResult, type PresenceEvent, type ReceiveEmailMessageArgs, type ReceiveLinkedinMessageArgs, type ReceiveWhatsappMessageArgs, type RedisConfig, type RuntimeConfig, type SearchConversationsArgs, type SearchMessagesArgs, type SendMessageArgs, type SocketConfig$1 as SocketConfig, type SourceType, type Transport, type TransportConfig, type TypingEvent, createConversationId, createConversationModel, createConversationsService, createCursor, createMessageId, createMessageModel, createMessagesService, createModels, createPaginatedResponse, createThreadId, createTransport, ensureIndexes, generateId, getRedisConfig, getRuntimeConfig, initChat, modelRegistry, parseCursor, searchByParticipantPair, searchConversations, searchMessages, setRuntimeConfig, sourceType, validateCreateConversationArgs, validateInitOptions, validateMarkReadArgs, validatePagination, validateSendMessageArgs };