@bootdesk/js-web-adapter-core 0.4.24 → 0.4.26

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.cjs CHANGED
@@ -121,14 +121,6 @@ var HttpClient = class {
121
121
  const url = this.expandTemplate(endpointTemplate, { id: messageId });
122
122
  await this.delete(url);
123
123
  }
124
- async addReaction(messageId, emoji, endpointTemplate = "/api/chat/messages/{id}/reactions") {
125
- const url = this.expandTemplate(endpointTemplate, { id: messageId });
126
- await this.post(url, { emoji });
127
- }
128
- async removeReaction(messageId, emoji, endpointTemplate = "/api/chat/messages/{id}/reactions/{emoji}") {
129
- const url = this.expandTemplate(endpointTemplate, { id: messageId, emoji });
130
- await this.delete(url);
131
- }
132
124
  async postFormData(url, formData, signal) {
133
125
  const controller = new AbortController();
134
126
  const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
@@ -339,6 +331,8 @@ var WebChatClient = class {
339
331
  this.streamingMessages = /* @__PURE__ */ new Map();
340
332
  this.pendingTyping = null;
341
333
  this.subscribers = /* @__PURE__ */ new Map();
334
+ this.sendQueue = [];
335
+ this.isProcessingQueue = false;
342
336
  this.config = config;
343
337
  this.httpClient = new HttpClient({
344
338
  apiUrl: config.apiUrl,
@@ -467,6 +461,31 @@ var WebChatClient = class {
467
461
  };
468
462
  }
469
463
  async sendMessage(text, attachments = []) {
464
+ return new Promise((resolve, reject) => {
465
+ this.sendQueue.push(async () => {
466
+ try {
467
+ await this.executeSend(text, attachments);
468
+ resolve();
469
+ } catch (e) {
470
+ reject(e);
471
+ }
472
+ });
473
+ this.processQueue();
474
+ });
475
+ }
476
+ async processQueue() {
477
+ if (this.isProcessingQueue) return;
478
+ this.isProcessingQueue = true;
479
+ try {
480
+ while (this.sendQueue.length > 0) {
481
+ const task = this.sendQueue.shift();
482
+ await task();
483
+ }
484
+ } finally {
485
+ this.isProcessingQueue = false;
486
+ }
487
+ }
488
+ async executeSend(text, attachments = []) {
470
489
  const messageId = generateId();
471
490
  const userMessage = {
472
491
  id: messageId,
@@ -562,15 +581,39 @@ var WebChatClient = class {
562
581
  if (!this.config.features?.reactions) {
563
582
  throw new Error("Reactions not enabled. Set features.reactions = true in config.");
564
583
  }
565
- const endpoint = this.config.endpoints?.addReaction ?? "/api/chat/messages/{id}/reactions";
566
- await this.httpClient.addReaction(messageId, emoji, endpoint);
584
+ this.handleReactionAdded(
585
+ new ReactionAddedEvent(this.getThreadId(), messageId, emoji, { id: this.currentUserId })
586
+ );
587
+ const endpoint = this.config.endpoints?.sendMessage ?? "/api/webhooks/web";
588
+ const response = await this.httpClient.post(endpoint, {
589
+ id: this.conversationId,
590
+ reaction: { messageId, emoji, added: true }
591
+ });
592
+ if (response.events) {
593
+ response.events.forEach((eventData) => {
594
+ const event = parseChatEvent(eventData);
595
+ this.dispatchEvent(event);
596
+ });
597
+ }
567
598
  }
568
599
  async removeReaction(messageId, emoji) {
569
600
  if (!this.config.features?.reactions) {
570
601
  throw new Error("Reactions not enabled. Set features.reactions = true in config.");
571
602
  }
572
- const endpoint = this.config.endpoints?.removeReaction ?? "/api/chat/messages/{id}/reactions/{emoji}";
573
- await this.httpClient.removeReaction(messageId, emoji, endpoint);
603
+ this.handleReactionRemoved(
604
+ new ReactionRemovedEvent(this.getThreadId(), messageId, emoji, { id: this.currentUserId })
605
+ );
606
+ const endpoint = this.config.endpoints?.sendMessage ?? "/api/webhooks/web";
607
+ const response = await this.httpClient.post(endpoint, {
608
+ id: this.conversationId,
609
+ reaction: { messageId, emoji, added: false }
610
+ });
611
+ if (response.events) {
612
+ response.events.forEach((eventData) => {
613
+ const event = parseChatEvent(eventData);
614
+ this.dispatchEvent(event);
615
+ });
616
+ }
574
617
  }
575
618
  onMessagePosted(handler) {
576
619
  return this.addEventListener("message.posted", handler);
@@ -663,26 +706,28 @@ var WebChatClient = class {
663
706
  }
664
707
  handleReactionAdded(event) {
665
708
  const message = this.messages.find((m) => m.id === event.messageId);
666
- if (!message) return;
667
- if (!message.reactions) message.reactions = [];
668
- const existing = message.reactions.find((r) => r.emoji === event.emoji);
669
- if (existing) {
670
- existing.count++;
671
- existing.users.push(event.user.id);
672
- } else {
673
- message.reactions.push({ emoji: event.emoji, count: 1, users: [event.user.id] });
709
+ if (message) {
710
+ if (!message.reactions) message.reactions = [];
711
+ const existing = message.reactions.find((r) => r.emoji === event.emoji);
712
+ if (existing) {
713
+ existing.count++;
714
+ existing.users.push(event.user.id);
715
+ } else {
716
+ message.reactions.push({ emoji: event.emoji, count: 1, users: [event.user.id] });
717
+ }
674
718
  }
675
719
  this.notifySubscribers("reaction:added", event);
676
720
  }
677
721
  handleReactionRemoved(event) {
678
722
  const message = this.messages.find((m) => m.id === event.messageId);
679
- if (!message?.reactions) return;
680
- const index = message.reactions.findIndex((r) => r.emoji === event.emoji);
681
- if (index !== -1) {
682
- const reaction = message.reactions[index];
683
- reaction.count--;
684
- reaction.users = reaction.users.filter((id) => id !== event.user.id);
685
- if (reaction.count === 0) message.reactions.splice(index, 1);
723
+ if (message?.reactions) {
724
+ const index = message.reactions.findIndex((r) => r.emoji === event.emoji);
725
+ if (index !== -1) {
726
+ const reaction = message.reactions[index];
727
+ reaction.count--;
728
+ reaction.users = reaction.users.filter((id) => id !== event.user.id);
729
+ if (reaction.count === 0) message.reactions.splice(index, 1);
730
+ }
686
731
  }
687
732
  this.notifySubscribers("reaction:removed", event);
688
733
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/client/HttpClient.ts","../src/events/base/ChatEvent.ts","../src/events/MessagePostedEvent.ts","../src/events/MessageEditedEvent.ts","../src/events/MessageDeletedEvent.ts","../src/events/ReactionAddedEvent.ts","../src/events/ReactionRemovedEvent.ts","../src/events/TypingStartedEvent.ts","../src/events/StreamingChunkEvent.ts","../src/events/DMRequestedEvent.ts","../src/events/ChatEventFactory.ts","../src/utils/eventIdGenerator.ts","../src/client/WebChatClient.ts","../src/client/PusherBroadcastClient.ts","../src/client/LaravelEchoBroadcastClient.ts","../src/push/PushManager.ts","../src/push/PushSubscriptionManager.ts"],"sourcesContent":["export { WebChatClient } from \"./client/WebChatClient\";\nexport type {\n WebChatClientConfig,\n ReconfigureConfig,\n LoadMessagesOptions,\n LoadMessagesResult,\n} from \"./client/WebChatClient\";\n\nexport {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./client/BroadcastClient\";\nexport { PusherBroadcastClient } from \"./client/PusherBroadcastClient\";\nexport type { PusherConfig } from \"./client/PusherBroadcastClient\";\nexport { LaravelEchoBroadcastClient } from \"./client/LaravelEchoBroadcastClient\";\n\nexport { HttpClient } from \"./client/HttpClient\";\nexport type { HttpClientConfig, ChatResponse } from \"./client/HttpClient\";\n\nexport * from \"./types\";\n\nexport { ChatEvent, UnknownEvent } from \"./events/base/ChatEvent\";\nexport { parseChatEvent } from \"./events/ChatEventFactory\";\nexport { MessagePostedEvent } from \"./events/MessagePostedEvent\";\nexport { MessageEditedEvent } from \"./events/MessageEditedEvent\";\nexport { MessageDeletedEvent } from \"./events/MessageDeletedEvent\";\nexport { ReactionAddedEvent } from \"./events/ReactionAddedEvent\";\nexport { ReactionRemovedEvent } from \"./events/ReactionRemovedEvent\";\nexport { TypingStartedEvent } from \"./events/TypingStartedEvent\";\nexport { StreamingChunkEvent } from \"./events/StreamingChunkEvent\";\nexport { DMRequestedEvent } from \"./events/DMRequestedEvent\";\n\nexport { generateId, generateConversationId } from \"./utils/eventIdGenerator\";\n\nexport { PushManager } from \"./push/PushManager\";\nexport { createPushSubscriptionHandlers } from \"./push/PushSubscriptionManager\";\nexport type { PushSubscriptionStatus, PushConfig, PushEventData } from \"./push/types\";\n","export interface HttpClientConfig {\n apiUrl: string;\n headers?: Record<string, string>;\n timeout?: number;\n verifyToken?: string;\n}\n\nexport interface ChatResponse {\n id: string;\n role: \"assistant\" | \"user\";\n text: string;\n attachments?: Array<{\n type: string;\n url: string;\n name?: string;\n mime_type?: string;\n size?: number;\n }>;\n events?: Array<Record<string, unknown>>;\n}\n\nexport class HttpClient {\n private config: Required<Pick<HttpClientConfig, \"apiUrl\" | \"timeout\">> & {\n headers: Record<string, string>;\n };\n\n constructor(config: HttpClientConfig) {\n const headers: Record<string, string> = { ...config.headers };\n if (config.verifyToken) {\n headers[\"X-Verify-Token\"] = config.verifyToken;\n }\n this.config = { apiUrl: config.apiUrl, timeout: config.timeout ?? 30000, headers };\n }\n\n async get(url: string, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"GET\",\n headers: this.config.headers,\n signal: combined,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async post(url: string, body: unknown, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...this.config.headers },\n signal: combined,\n body: JSON.stringify(body),\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async delete(url: string, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"DELETE\",\n headers: this.config.headers,\n signal: combined,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n const text = await response.text();\n return text ? JSON.parse(text) : undefined;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async sendMessage(\n messages: Array<{\n id: string;\n role: string;\n text: string;\n attachments?: Array<{ url: string; name?: string; mime_type?: string; size?: number }>;\n }>,\n endpoint: string = \"/api/webhooks/web\",\n conversationId?: string,\n ): Promise<ChatResponse> {\n return this.post(endpoint, { id: conversationId, messages }) as Promise<ChatResponse>;\n }\n\n async sendAction(\n actionId: string,\n value: string,\n messageId: string,\n conversationId: string,\n endpoint: string = \"/api/webhooks/web\",\n ): Promise<Record<string, unknown>> {\n return this.post(endpoint, {\n id: conversationId,\n action: { actionId, value, messageId },\n }) as Promise<Record<string, unknown>>;\n }\n\n async editMessage(\n messageId: string,\n newText: string,\n endpointTemplate: string = \"/api/chat/messages/{id}/edit\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.post(url, { text: newText });\n }\n\n async deleteMessage(\n messageId: string,\n endpointTemplate: string = \"/api/chat/messages/{id}\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.delete(url);\n }\n\n async addReaction(\n messageId: string,\n emoji: string,\n endpointTemplate: string = \"/api/chat/messages/{id}/reactions\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.post(url, { emoji });\n }\n\n async removeReaction(\n messageId: string,\n emoji: string,\n endpointTemplate: string = \"/api/chat/messages/{id}/reactions/{emoji}\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId, emoji });\n await this.delete(url);\n }\n\n async postFormData(url: string, formData: FormData, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"POST\",\n headers: this.config.headers,\n signal: combined,\n body: formData,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n setHeader(name: string, value: string): void {\n this.config.headers[name] = value;\n }\n\n removeHeader(name: string): void {\n delete this.config.headers[name];\n }\n\n private resolve(url: string): string {\n return /^https?:\\/\\//.test(url) ? url : `${this.config.apiUrl}${url}`;\n }\n\n private expandTemplate(template: string, params: Record<string, string>): string {\n let url = template;\n for (const [key, value] of Object.entries(params)) {\n url = url.replace(`{${key}}`, encodeURIComponent(value));\n }\n return this.resolve(url);\n }\n}\n","export abstract class ChatEvent {\n readonly type: string;\n readonly threadId: string;\n readonly timestamp: number;\n\n constructor(type: string, threadId: string, timestamp: number) {\n this.type = type;\n this.threadId = threadId;\n this.timestamp = timestamp;\n }\n\n static fromJSON: ((json: Record<string, unknown>) => ChatEvent) | undefined;\n}\n\nexport class UnknownEvent extends ChatEvent {\n readonly data: Record<string, unknown>;\n\n constructor(type: string, threadId: string, data: Record<string, unknown>, timestamp: number) {\n super(type, threadId, timestamp);\n this.data = data;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User, Card } from \"../types\";\n\nexport class MessagePostedEvent extends ChatEvent {\n readonly messageId: string;\n readonly text: string;\n readonly author: User;\n readonly card?: Card;\n readonly attachments?: Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>;\n\n constructor(\n threadId: string,\n messageId: string,\n text: string,\n author: User,\n card?: Card,\n attachments?: Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>,\n timestamp?: number,\n ) {\n super(\"message.posted\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.text = text;\n this.author = author;\n this.card = card;\n this.attachments = attachments;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { Card } from \"../types\";\n\nexport class MessageEditedEvent extends ChatEvent {\n readonly messageId: string;\n readonly newText: string;\n readonly card?: Card;\n\n constructor(\n threadId: string,\n messageId: string,\n newText: string,\n card?: Card,\n timestamp?: number,\n ) {\n super(\"message.edited\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.newText = newText;\n this.card = card;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class MessageDeletedEvent extends ChatEvent {\n readonly messageId: string;\n\n constructor(threadId: string, messageId: string, timestamp?: number) {\n super(\"message.deleted\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User } from \"../types\";\n\nexport class ReactionAddedEvent extends ChatEvent {\n readonly messageId: string;\n readonly emoji: string;\n readonly user: User;\n\n constructor(threadId: string, messageId: string, emoji: string, user: User, timestamp?: number) {\n super(\"reaction.added\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.emoji = emoji;\n this.user = user;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User } from \"../types\";\n\nexport class ReactionRemovedEvent extends ChatEvent {\n readonly messageId: string;\n readonly emoji: string;\n readonly user: User;\n\n constructor(threadId: string, messageId: string, emoji: string, user: User, timestamp?: number) {\n super(\"reaction.removed\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.emoji = emoji;\n this.user = user;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class TypingStartedEvent extends ChatEvent {\n readonly userId: string;\n\n constructor(threadId: string, userId: string, timestamp?: number) {\n super(\"typing.started\", threadId, timestamp ?? Date.now());\n this.userId = userId;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class StreamingChunkEvent extends ChatEvent {\n readonly messageId: string;\n readonly chunk: string;\n readonly isFinal: boolean;\n\n constructor(\n threadId: string,\n messageId: string,\n chunk: string,\n isFinal: boolean,\n timestamp?: number,\n ) {\n super(\"streaming.chunk\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.chunk = chunk;\n this.isFinal = isFinal;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class DMRequestedEvent extends ChatEvent {\n readonly userId: string;\n\n constructor(threadId: string, userId: string, timestamp?: number) {\n super(\"dm.requested\", threadId, timestamp ?? Date.now());\n this.userId = userId;\n }\n}\n","import { ChatEvent, UnknownEvent } from \"./base/ChatEvent\";\nimport type { Card, User } from \"../types\";\nimport { MessagePostedEvent } from \"./MessagePostedEvent\";\nimport { MessageEditedEvent } from \"./MessageEditedEvent\";\nimport { MessageDeletedEvent } from \"./MessageDeletedEvent\";\nimport { ReactionAddedEvent } from \"./ReactionAddedEvent\";\nimport { ReactionRemovedEvent } from \"./ReactionRemovedEvent\";\nimport { TypingStartedEvent } from \"./TypingStartedEvent\";\nimport { StreamingChunkEvent } from \"./StreamingChunkEvent\";\nimport { DMRequestedEvent } from \"./DMRequestedEvent\";\n\nfunction parseCard(value: unknown): Card | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const obj = value as Record<string, unknown>;\n if (typeof obj.type !== \"string\") return undefined;\n return obj as unknown as Card;\n}\n\nexport function parseChatEvent(json: Record<string, unknown>): ChatEvent {\n const type = json.type as string;\n const threadId = json.threadId as string;\n const timestamp = json.timestamp as number;\n const data = (json.data ?? {}) as Record<string, unknown>;\n\n switch (type) {\n case \"message.posted\":\n return new MessagePostedEvent(\n threadId,\n data.messageId as string,\n data.text as string,\n data.author as User,\n parseCard(data.card),\n data.attachments as Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>,\n timestamp,\n );\n case \"message.edited\":\n return new MessageEditedEvent(\n threadId,\n data.messageId as string,\n data.newText as string,\n parseCard(data.card),\n timestamp,\n );\n case \"message.deleted\":\n return new MessageDeletedEvent(threadId, data.messageId as string, timestamp);\n case \"reaction.added\":\n return new ReactionAddedEvent(\n threadId,\n data.messageId as string,\n data.emoji as string,\n data.user as User,\n timestamp,\n );\n case \"reaction.removed\":\n return new ReactionRemovedEvent(\n threadId,\n data.messageId as string,\n data.emoji as string,\n data.user as User,\n timestamp,\n );\n case \"typing.started\":\n return new TypingStartedEvent(threadId, data.userId as string, timestamp);\n case \"streaming.chunk\":\n return new StreamingChunkEvent(\n threadId,\n data.messageId as string,\n data.chunk as string,\n data.isFinal as boolean,\n timestamp,\n );\n case \"dm.requested\":\n return new DMRequestedEvent(threadId, data.userId as string, timestamp);\n default:\n return new UnknownEvent(type, threadId, data, timestamp);\n }\n}\n\n// Wire up the static method\nChatEvent.fromJSON = parseChatEvent;\n","export function generateId(): string {\n return `msg-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n\nexport function generateConversationId(): string {\n return `conv-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n","import { HttpClient } from \"./HttpClient\";\nimport type { BroadcastClient, EventHandlers, Unsubscribe } from \"./BroadcastClient\";\nimport type { Message } from \"../types\";\nimport { ChatEvent } from \"../events/base/ChatEvent\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type { MessagePostedEvent } from \"../events/MessagePostedEvent\";\nimport type { MessageEditedEvent } from \"../events/MessageEditedEvent\";\nimport type { MessageDeletedEvent } from \"../events/MessageDeletedEvent\";\nimport type { ReactionAddedEvent } from \"../events/ReactionAddedEvent\";\nimport type { ReactionRemovedEvent } from \"../events/ReactionRemovedEvent\";\nimport type { TypingStartedEvent } from \"../events/TypingStartedEvent\";\nimport type { StreamingChunkEvent } from \"../events/StreamingChunkEvent\";\nimport type { DMRequestedEvent } from \"../events/DMRequestedEvent\";\nimport { generateId, generateConversationId } from \"../utils/eventIdGenerator\";\n\nexport interface ReconfigureConfig {\n userId?: string;\n userName?: string;\n verifyToken?: string;\n conversationId?: string;\n headers?: Record<string, string>;\n}\n\nexport interface WebChatClientConfig {\n apiUrl: string;\n userId: string;\n userName: string;\n broadcastClient?: BroadcastClient;\n headers?: Record<string, string>;\n verifyToken?: string;\n conversationId?: string;\n endpoints?: {\n sendMessage?: string;\n loadMessages?: string;\n editMessage?: string;\n deleteMessage?: string;\n addReaction?: string;\n removeReaction?: string;\n };\n features?: {\n editMessages?: boolean;\n deleteMessages?: boolean;\n reactions?: boolean;\n };\n}\n\ninterface StreamingState {\n messageId: string;\n accumulatedText: string;\n isComplete: boolean;\n}\n\ninterface AttachmentInput {\n url: string;\n name?: string;\n mimeType?: string;\n size?: number;\n}\n\nexport interface LoadMessagesOptions {\n limit?: number;\n before?: number;\n after?: number;\n skipStateSeed?: boolean;\n}\n\nexport interface LoadMessagesResult {\n messages: Message[];\n hasMore: boolean;\n nextCursor?: number;\n prevCursor?: number;\n}\n\nexport class WebChatClient {\n private config: WebChatClientConfig;\n private httpClient: HttpClient;\n private broadcastClient?: BroadcastClient;\n private conversationId: string;\n private messages: Message[] = [];\n private currentUserId: string;\n private eventHandlers: EventHandlers = {};\n private streamingMessages: Map<string, StreamingState> = new Map();\n private pendingTyping: ReturnType<typeof setTimeout> | null = null;\n private subscribers: Map<string, Array<(event: unknown) => void>> = new Map();\n private unsubscribeUserChannel?: Unsubscribe;\n\n constructor(config: WebChatClientConfig) {\n this.config = config;\n this.httpClient = new HttpClient({\n apiUrl: config.apiUrl,\n headers: {\n \"X-User-Id\": config.userId,\n \"X-User-Name\": config.userName,\n ...(config.headers ?? {}),\n },\n verifyToken: config.verifyToken,\n });\n this.broadcastClient = config.broadcastClient;\n this.conversationId = config.conversationId ?? generateConversationId();\n this.currentUserId = config.userId;\n }\n\n reconfigure(config: ReconfigureConfig): void {\n if (config.userId) {\n this.currentUserId = config.userId;\n this.httpClient.setHeader(\"X-User-Id\", config.userId);\n }\n if (config.userName) {\n this.config = { ...this.config, userName: config.userName };\n this.httpClient.setHeader(\"X-User-Name\", config.userName);\n }\n if (config.verifyToken) {\n this.config = { ...this.config, verifyToken: config.verifyToken };\n this.httpClient.setHeader(\"X-Verify-Token\", config.verifyToken);\n }\n if (config.conversationId) {\n this.conversationId = config.conversationId;\n }\n if (config.headers) {\n Object.entries(config.headers).forEach(([key, value]) => {\n this.httpClient.setHeader(key, value);\n });\n }\n }\n\n setLocaleHeader(locale: string): void {\n this.httpClient.setHeader(\"X-Locale\", locale);\n this.httpClient.setHeader(\"X-Language\", locale.split(\"-\")[0] ?? locale);\n }\n\n setTimezoneHeader(timezone: string): void {\n this.httpClient.setHeader(\"X-Timezone\", timezone);\n }\n\n async connect(): Promise<void> {\n if (this.broadcastClient) {\n this.broadcastClient.connect();\n\n const threadId = this.getThreadId();\n const threadEvents: EventHandlers = {\n onMessagePosted: (event) => this.handleMessagePosted(event),\n };\n\n if (this.config.features?.editMessages) {\n threadEvents.onMessageEdited = (event) => this.handleMessageEdited(event);\n }\n if (this.config.features?.deleteMessages) {\n threadEvents.onMessageDeleted = (event) => this.handleMessageDeleted(event);\n }\n if (this.config.features?.reactions) {\n threadEvents.onReactionAdded = (event) => this.handleReactionAdded(event);\n threadEvents.onReactionRemoved = (event) => this.handleReactionRemoved(event);\n }\n\n threadEvents.onTypingStarted = (event) => this.handleTypingStarted(event);\n\n await this.broadcastClient.subscribe(threadId, threadEvents);\n\n this.unsubscribeUserChannel = await this.broadcastClient.subscribeToUser(\n threadId,\n this.currentUserId,\n {\n onStreamingChunk: (event) => this.handleStreamingChunk(event),\n onDMRequested: (event) => this.handleDMRequested(event),\n },\n );\n }\n }\n\n disconnect(): void {\n this.unsubscribeUserChannel?.();\n this.unsubscribeUserChannel = undefined;\n this.broadcastClient?.disconnect();\n this.streamingMessages.clear();\n }\n\n async loadMessages(\n options?: LoadMessagesOptions,\n signal?: AbortSignal,\n ): Promise<LoadMessagesResult> {\n const endpoint = this.config.endpoints?.loadMessages ?? \"/api/chat/messages\";\n const threadId = this.getThreadId();\n const params = new URLSearchParams({\n threadId,\n limit: String(options?.limit ?? 50),\n });\n if (options?.before) params.set(\"before\", String(options.before));\n if (options?.after) params.set(\"after\", String(options.after));\n\n const response = (await this.httpClient.get(\n `${endpoint}?${params.toString()}`,\n signal,\n )) as Record<string, unknown>;\n const rawMessages = (response.messages as Record<string, unknown>[]) ?? [];\n const messages: Message[] = rawMessages.map((msg) => ({\n id: msg.id as string,\n threadId,\n content: {\n text: msg.text as string,\n cards: msg.card ? ([msg.card as Record<string, unknown>] as never[]) : undefined,\n },\n author: {\n id: (msg.author as Record<string, unknown>).id as string,\n name: (msg.author as Record<string, unknown>).name as string,\n isBot: ((msg.author as Record<string, unknown>).isBot as boolean) ?? false,\n isMe: (msg.author as Record<string, unknown>).id === this.currentUserId,\n },\n timestamp: msg.timestamp as number,\n attachments: (msg.attachments as Record<string, unknown>[])?.map((a) => ({\n id: `att-${msg.id as string}-${a.url as string}`,\n url: a.url as string,\n name: a.name as string,\n type: a.type as string,\n mimeType: a.mime_type as string,\n size: a.size as number,\n })),\n reactions: (msg.reactions as { emoji: string; count: number; users: string[] }[]) ?? [],\n }));\n\n if (!options?.before && !options?.after && !options?.skipStateSeed) {\n this.messages = messages;\n this.notifySubscribers(\"messages:loaded\", messages);\n }\n\n return {\n messages,\n hasMore: (response.hasMore as boolean) ?? false,\n nextCursor: response.nextCursor as number | undefined,\n prevCursor: response.prevCursor as number | undefined,\n };\n }\n\n async sendMessage(text: string, attachments: AttachmentInput[] = []): Promise<void> {\n const messageId = generateId();\n\n const userMessage: Message = {\n id: messageId,\n threadId: this.getThreadId(),\n content: { text },\n author: { id: this.currentUserId, name: this.config.userName, isMe: true },\n timestamp: Date.now(),\n attachments:\n attachments.length > 0\n ? attachments.map((a, i) => ({\n id: `att-${messageId}-${i}`,\n name: a.name ?? \"\",\n url: a.url,\n size: a.size,\n mimeType: a.mimeType,\n }))\n : undefined,\n };\n\n this.messages.push(userMessage);\n this.notifySubscribers(\"message:added\", userMessage);\n\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = await this.httpClient.sendMessage(\n [\n {\n id: messageId,\n role: \"user\",\n text,\n attachments: attachments.map((a) => ({\n url: a.url,\n name: a.name,\n mime_type: a.mimeType,\n size: a.size,\n })),\n },\n ],\n endpoint,\n this.conversationId,\n );\n\n if (response.events) {\n response.events.forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n\n if (response.text && !response.events?.some((e) => e.type === \"message.posted\")) {\n const assistantMessage: Message = {\n id: response.id ?? generateId(),\n threadId: this.getThreadId(),\n content: { text: response.text },\n author: { id: \"assistant\", name: \"Assistant\", isBot: true },\n timestamp: Date.now(),\n attachments: (response.attachments as Record<string, unknown>[])?.map((a, i) => ({\n id: `att-${response.id ?? \"msg\"}-${i}`,\n name: (a.name as string) ?? \"\",\n url: (a.url as string) ?? \"\",\n type: a.type as string,\n mimeType: a.mime_type as string,\n size: a.size as number,\n })),\n };\n this.messages.push(assistantMessage);\n this.notifySubscribers(\"message:added\", assistantMessage);\n }\n }\n\n async sendAction(messageId: string, actionId: string, value: string): Promise<void> {\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = await this.httpClient.sendAction(\n actionId,\n value,\n messageId,\n this.conversationId,\n endpoint,\n );\n\n if (response.events) {\n (response.events as Array<Record<string, unknown>>).forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n }\n\n async editMessage(messageId: string, newText: string): Promise<void> {\n if (!this.config.features?.editMessages) {\n throw new Error(\"Edit messages not enabled. Set features.editMessages = true in config.\");\n }\n const endpoint = this.config.endpoints?.editMessage ?? \"/api/chat/messages/{id}/edit\";\n await this.httpClient.editMessage(messageId, newText, endpoint);\n }\n\n async deleteMessage(messageId: string): Promise<void> {\n if (!this.config.features?.deleteMessages) {\n throw new Error(\"Delete messages not enabled. Set features.deleteMessages = true in config.\");\n }\n const endpoint = this.config.endpoints?.deleteMessage ?? \"/api/chat/messages/{id}\";\n await this.httpClient.deleteMessage(messageId, endpoint);\n }\n\n async addReaction(messageId: string, emoji: string): Promise<void> {\n if (!this.config.features?.reactions) {\n throw new Error(\"Reactions not enabled. Set features.reactions = true in config.\");\n }\n const endpoint = this.config.endpoints?.addReaction ?? \"/api/chat/messages/{id}/reactions\";\n await this.httpClient.addReaction(messageId, emoji, endpoint);\n }\n\n async removeReaction(messageId: string, emoji: string): Promise<void> {\n if (!this.config.features?.reactions) {\n throw new Error(\"Reactions not enabled. Set features.reactions = true in config.\");\n }\n const endpoint =\n this.config.endpoints?.removeReaction ?? \"/api/chat/messages/{id}/reactions/{emoji}\";\n await this.httpClient.removeReaction(messageId, emoji, endpoint);\n }\n\n onMessagePosted(handler: (event: MessagePostedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message.posted\", handler);\n }\n\n onMessageEdited(handler: (event: MessageEditedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message:edited\", handler);\n }\n\n onMessageDeleted(handler: (event: MessageDeletedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message:deleted\", handler);\n }\n\n onReactionAdded(handler: (event: ReactionAddedEvent) => void): Unsubscribe {\n return this.addEventListener(\"reaction:added\", handler);\n }\n\n onReactionRemoved(handler: (event: ReactionRemovedEvent) => void): Unsubscribe {\n return this.addEventListener(\"reaction:removed\", handler);\n }\n\n onStreamingChunk(handler: (event: StreamingChunkEvent) => void): Unsubscribe {\n return this.addEventListener(\"streaming:chunk\", handler);\n }\n\n onTypingStarted(handler: (event: TypingStartedEvent) => void): Unsubscribe {\n return this.addEventListener(\"typing:started\", handler);\n }\n\n getConversationId(): string {\n return this.conversationId;\n }\n getMessages(): Message[] {\n return [...this.messages];\n }\n getThreadId(): string {\n return `web:${this.currentUserId}:${this.conversationId}`;\n }\n getCurrentUserId(): string {\n return this.currentUserId;\n }\n getFeatures(): NonNullable<WebChatClientConfig[\"features\"]> {\n return this.config.features ?? {};\n }\n getEndpoints(): NonNullable<WebChatClientConfig[\"endpoints\"]> {\n return this.config.endpoints ?? {};\n }\n getHttpClient(): HttpClient {\n return this.httpClient;\n }\n\n addEventListener<T = unknown>(eventType: string, handler: (event: T) => void): Unsubscribe {\n if (!this.subscribers.has(eventType)) this.subscribers.set(eventType, []);\n this.subscribers.get(eventType)!.push(handler as (event: unknown) => void);\n return () => {\n const handlers = this.subscribers.get(eventType);\n if (handlers) {\n const index = handlers.indexOf(handler as (event: unknown) => void);\n if (index !== -1) handlers.splice(index, 1);\n }\n };\n }\n\n private handleMessagePosted(event: MessagePostedEvent): void {\n if (this.messages.some((m) => m.id === event.messageId)) return;\n if (this.streamingMessages.has(event.messageId)) return;\n\n const message: Message = {\n id: event.messageId,\n threadId: event.threadId,\n content: { text: event.text, cards: event.card ? [event.card] : undefined },\n author: event.author,\n timestamp: event.timestamp,\n attachments: event.attachments?.map((a) => ({\n id: `att-${event.messageId}-${Math.random().toString(36).slice(2, 8)}`,\n name: a.name ?? \"\",\n url: a.url ?? \"\",\n type: a.type,\n mimeType: a.mimeType,\n size: a.size ?? undefined,\n })),\n };\n this.messages.push(message);\n this.notifySubscribers(\"message:added\", message);\n this.notifySubscribers(\"message.posted\", event);\n }\n\n private handleMessageEdited(event: MessageEditedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (message?.content) {\n message.content.text = event.newText;\n this.notifySubscribers(\"message:edited\", event);\n }\n }\n\n private handleMessageDeleted(event: MessageDeletedEvent): void {\n const index = this.messages.findIndex((m) => m.id === event.messageId);\n if (index !== -1) {\n this.messages.splice(index, 1);\n this.notifySubscribers(\"message:deleted\", event);\n }\n }\n\n private handleReactionAdded(event: ReactionAddedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (!message) return;\n if (!message.reactions) message.reactions = [];\n\n const existing = message.reactions.find((r) => r.emoji === event.emoji);\n if (existing) {\n existing.count++;\n existing.users.push(event.user.id);\n } else {\n message.reactions.push({ emoji: event.emoji, count: 1, users: [event.user.id] });\n }\n this.notifySubscribers(\"reaction:added\", event);\n }\n\n private handleReactionRemoved(event: ReactionRemovedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (!message?.reactions) return;\n\n const index = message.reactions.findIndex((r) => r.emoji === event.emoji);\n if (index !== -1) {\n const reaction = message.reactions[index]!;\n reaction.count--;\n reaction.users = reaction.users.filter((id) => id !== event.user.id);\n if (reaction.count === 0) message.reactions.splice(index, 1);\n }\n this.notifySubscribers(\"reaction:removed\", event);\n }\n\n private handleStreamingChunk(event: StreamingChunkEvent): void {\n const { messageId, chunk, isFinal } = event;\n\n if (!this.streamingMessages.has(messageId)) {\n this.streamingMessages.set(messageId, { messageId, accumulatedText: \"\", isComplete: false });\n this.notifySubscribers(\"streaming:started\", event);\n }\n\n const state = this.streamingMessages.get(messageId)!;\n state.accumulatedText += chunk;\n\n if (isFinal) {\n state.isComplete = true;\n if (!this.messages.some((m) => m.id === messageId)) {\n const message: Message = {\n id: messageId,\n threadId: event.threadId,\n content: { text: state.accumulatedText },\n author: { id: \"assistant\", name: \"Assistant\", isBot: true },\n timestamp: event.timestamp,\n };\n this.messages.push(message);\n this.notifySubscribers(\"message:added\", message);\n }\n this.streamingMessages.delete(messageId);\n this.notifySubscribers(\"streaming:complete\", { messageId, text: state.accumulatedText });\n } else {\n this.notifySubscribers(\"streaming:chunk\", event);\n }\n }\n\n private handleTypingStarted(event: TypingStartedEvent): void {\n if (this.pendingTyping) clearTimeout(this.pendingTyping);\n this.notifySubscribers(\"typing:started\", event);\n this.pendingTyping = setTimeout(() => {\n this.notifySubscribers(\"typing:stopped\", { userId: event.userId });\n }, 3000);\n }\n\n private handleDMRequested(event: DMRequestedEvent): void {\n this.notifySubscribers(\"dm.requested\", event);\n }\n\n private notifySubscribers<T>(eventType: string, data: T): void {\n this.subscribers.get(eventType)?.forEach((handler) => handler(data));\n }\n\n private dispatchEvent(event: ChatEvent): void {\n switch (event.type) {\n case \"message.posted\":\n this.handleMessagePosted(event as MessagePostedEvent);\n break;\n case \"message.edited\":\n this.handleMessageEdited(event as MessageEditedEvent);\n break;\n case \"message.deleted\":\n this.handleMessageDeleted(event as MessageDeletedEvent);\n break;\n case \"reaction.added\":\n this.handleReactionAdded(event as ReactionAddedEvent);\n break;\n case \"reaction.removed\":\n this.handleReactionRemoved(event as ReactionRemovedEvent);\n break;\n case \"typing.started\":\n this.handleTypingStarted(event as TypingStartedEvent);\n break;\n case \"streaming.chunk\":\n this.handleStreamingChunk(event as StreamingChunkEvent);\n break;\n case \"dm.requested\":\n this.handleDMRequested(event as DMRequestedEvent);\n break;\n }\n }\n}\n","import {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./BroadcastClient\";\nimport { ChatEvent } from \"../events/base/ChatEvent\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type Pusher from \"pusher-js\";\nimport type { Channel as PusherChannel } from \"pusher-js\";\n\nexport interface PusherConfig {\n key: string;\n cluster?: string;\n host?: string;\n port?: number;\n forceTLS?: boolean;\n authEndpoint?: string;\n}\n\nexport class PusherBroadcastClient implements BroadcastClient {\n private pusher: Pusher;\n private channelPrefix: string;\n private threadChannelType: \"public\" | \"private\" | \"presence\";\n private userChannelType: \"private\" | \"presence\";\n private useHashChannel: boolean;\n private subscriptions: Map<string, PusherChannel> = new Map();\n\n constructor(pusher: Pusher, channelPrefix?: string, channelTypes?: ChannelTypeConfig);\n constructor(config: PusherConfig, channelPrefix?: string, channelTypes?: ChannelTypeConfig);\n constructor(\n pusherOrConfig: Pusher | PusherConfig,\n channelPrefix: string = \"chat\",\n channelTypes?: ChannelTypeConfig,\n ) {\n this.channelPrefix = channelPrefix;\n this.threadChannelType = channelTypes?.threadChannel ?? \"public\";\n this.userChannelType = channelTypes?.userChannel ?? \"private\";\n this.useHashChannel = channelTypes?.useHashChannel ?? false;\n\n if (\"key\" in pusherOrConfig) {\n const PusherCtor = (globalThis as any).Pusher ?? (globalThis as any).pusherJs;\n if (!PusherCtor) {\n throw new Error(\"pusher-js not found. Install it or pass a Pusher instance.\");\n }\n this.pusher = new PusherCtor((pusherOrConfig as PusherConfig).key, pusherOrConfig) as Pusher;\n } else {\n this.pusher = pusherOrConfig as Pusher;\n }\n }\n\n private buildChannelName(base: string, type: \"public\" | \"private\" | \"presence\"): string {\n switch (type) {\n case \"private\":\n return `private-${base}`;\n case \"presence\":\n return `presence-${base}`;\n default:\n return base;\n }\n }\n\n protected async buildResolvedChannelName(threadId: string): Promise<string> {\n const name = this.useHashChannel ? await this.hashChannelName(threadId) : threadId;\n\n return `${this.channelPrefix}.${name}`;\n }\n\n private async hashChannelName(name: string): Promise<string> {\n if (typeof crypto?.subtle?.digest !== \"function\") {\n throw new Error(\"Web Crypto API not available. Cannot hash channel names.\");\n }\n const encoder = new TextEncoder();\n const data = encoder.encode(name);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n connect(): void {\n if (this.pusher.connection?.state !== \"connected\") {\n this.pusher.connect();\n }\n }\n\n disconnect(): void {\n this.subscriptions.forEach((channel) => channel.unbind_all?.() ?? channel.unsubscribe?.());\n this.subscriptions.clear();\n this.pusher.disconnect?.();\n }\n\n async subscribe(threadId: string, handlers: EventHandlers): Promise<Unsubscribe> {\n const baseName = await this.buildResolvedChannelName(threadId);\n const channelName = this.buildChannelName(baseName, this.threadChannelType);\n const channel = this.pusher.subscribe(channelName);\n const key = `thread:${threadId}`;\n this.subscriptions.set(key, channel);\n\n const threadEvents = [\n \"message.posted\",\n \"message.edited\",\n \"message.deleted\",\n \"reaction.added\",\n \"reaction.removed\",\n \"typing.started\",\n ] as const;\n\n threadEvents.forEach((eventType) => {\n const eventName = `${this.channelPrefix}.${eventType}`;\n channel.bind(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n this.dispatchToHandler(event, handlers);\n });\n });\n\n return () => {\n channel.unbind_all?.();\n this.pusher.unsubscribe(channelName);\n this.subscriptions.delete(key);\n };\n }\n\n async subscribeToUser(\n threadId: string,\n userId: string,\n handlers: EventHandlers,\n ): Promise<Unsubscribe> {\n const baseName = `${await this.buildResolvedChannelName(threadId)}.${userId}`;\n const channelName = this.buildChannelName(baseName, this.userChannelType);\n const channel = this.pusher.subscribe(channelName);\n const key = `user:${threadId}:${userId}`;\n this.subscriptions.set(key, channel);\n\n const userEvents = [\"typing.started\", \"streaming.chunk\", \"dm.requested\"] as const;\n\n userEvents.forEach((eventType) => {\n const eventName = `${this.channelPrefix}.${eventType}`;\n channel.bind(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n this.dispatchToHandler(event, handlers);\n });\n });\n\n return () => {\n channel.unbind_all?.();\n this.pusher.unsubscribe(channelName);\n this.subscriptions.delete(key);\n };\n }\n\n isConnected(): boolean {\n return this.pusher.connection?.state === \"connected\";\n }\n\n private dispatchToHandler(event: ChatEvent, handlers: EventHandlers): void {\n switch (event.type) {\n case \"message.posted\":\n handlers.onMessagePosted?.(event as any);\n break;\n case \"message.edited\":\n handlers.onMessageEdited?.(event as any);\n break;\n case \"message.deleted\":\n handlers.onMessageDeleted?.(event as any);\n break;\n case \"reaction.added\":\n handlers.onReactionAdded?.(event as any);\n break;\n case \"reaction.removed\":\n handlers.onReactionRemoved?.(event as any);\n break;\n case \"typing.started\":\n handlers.onTypingStarted?.(event as any);\n break;\n case \"streaming.chunk\":\n handlers.onStreamingChunk?.(event as any);\n break;\n case \"dm.requested\":\n handlers.onDMRequested?.(event as any);\n break;\n }\n }\n}\n","import {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./BroadcastClient\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type Echo from \"laravel-echo\";\n\ninterface EchoChannel {\n listen(event: string, callback: (data: unknown) => void): this;\n unsubscribe(): void;\n stopListening(event?: string, callback?: (data: unknown) => void): this;\n}\n\nexport class LaravelEchoBroadcastClient implements BroadcastClient {\n private echo: Echo<any>;\n private channelPrefix: string;\n private threadChannelType: \"public\" | \"private\" | \"presence\";\n private userChannelType: \"private\" | \"presence\";\n private useHashChannel: boolean;\n private subscriptions: Map<string, EchoChannel> = new Map();\n\n constructor(echo: Echo<any>, channelPrefix: string = \"chat\", channelTypes?: ChannelTypeConfig) {\n this.echo = echo;\n this.channelPrefix = channelPrefix;\n this.threadChannelType = channelTypes?.threadChannel ?? \"public\";\n this.userChannelType = channelTypes?.userChannel ?? \"private\";\n this.useHashChannel = channelTypes?.useHashChannel ?? false;\n }\n\n private subscribeToEcho(name: string, type: \"public\" | \"private\" | \"presence\"): EchoChannel {\n switch (type) {\n case \"private\":\n return this.echo.private(name) as unknown as EchoChannel;\n case \"presence\":\n return this.echo.join(name) as unknown as EchoChannel;\n default:\n return this.echo.channel(name) as unknown as EchoChannel;\n }\n }\n\n connect(): void | Promise<void> {\n return Promise.resolve();\n }\n\n disconnect(): void {\n this.subscriptions.forEach((channel) => {\n channel.unsubscribe?.();\n channel.stopListening?.();\n });\n this.subscriptions.clear();\n }\n\n protected async buildResolvedChannelName(threadId: string): Promise<string> {\n const name = this.useHashChannel ? await this.hashChannelName(threadId) : threadId;\n\n return `${this.channelPrefix}.${name}`;\n }\n\n private async hashChannelName(name: string): Promise<string> {\n if (typeof crypto?.subtle?.digest !== \"function\") {\n throw new Error(\"Web Crypto API not available. Cannot hash channel names.\");\n }\n const encoder = new TextEncoder();\n const data = encoder.encode(name);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n async subscribe(threadId: string, handlers: EventHandlers): Promise<Unsubscribe> {\n const channelName = await this.buildResolvedChannelName(threadId);\n const channel = this.subscribeToEcho(channelName, this.threadChannelType);\n const key = `thread:${threadId}`;\n this.subscriptions.set(key, channel);\n\n const threadEvents: Array<{ type: string; handler: keyof EventHandlers }> = [\n { type: \"message.posted\", handler: \"onMessagePosted\" },\n { type: \"message.edited\", handler: \"onMessageEdited\" },\n { type: \"message.deleted\", handler: \"onMessageDeleted\" },\n { type: \"reaction.added\", handler: \"onReactionAdded\" },\n { type: \"reaction.removed\", handler: \"onReactionRemoved\" },\n { type: \"typing.started\", handler: \"onTypingStarted\" },\n ];\n\n threadEvents.forEach(({ type, handler }) => {\n const eventName = `.${this.channelPrefix}.${type}`;\n channel.listen(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n (handlers[handler] as any)?.(event);\n });\n });\n\n return () => {\n channel.unsubscribe?.();\n this.subscriptions.delete(key);\n };\n }\n\n async subscribeToUser(\n threadId: string,\n userId: string,\n handlers: EventHandlers,\n ): Promise<Unsubscribe> {\n const channelName = `${await this.buildResolvedChannelName(threadId)}.${userId}`;\n const channel = this.subscribeToEcho(channelName, this.userChannelType);\n const key = `user:${threadId}:${userId}`;\n this.subscriptions.set(key, channel);\n\n const userEvents: Array<{ type: string; handler: keyof EventHandlers }> = [\n { type: \"typing.started\", handler: \"onTypingStarted\" },\n { type: \"streaming.chunk\", handler: \"onStreamingChunk\" },\n { type: \"dm.requested\", handler: \"onDMRequested\" },\n ];\n\n userEvents.forEach(({ type, handler }) => {\n const eventName = `.${this.channelPrefix}.${type}`;\n channel.listen(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n (handlers[handler] as any)?.(event);\n });\n });\n\n return () => {\n channel.unsubscribe?.();\n this.subscriptions.delete(key);\n };\n }\n\n isConnected(): boolean {\n try {\n const connector = (this.echo as any).connector;\n if (!connector) return false;\n\n if (connector.pusher?.connection?.state === \"connected\") return true;\n if (connector.socket?.connected) return true;\n\n return false;\n } catch {\n return false;\n }\n }\n}\n","import type { PushConfig, PushSubscriptionStatus, PushEventData } from \"./types\";\n\nexport class PushManager {\n private config: PushConfig;\n private registration: ServiceWorkerRegistration | null = null;\n private status: PushSubscriptionStatus = \"unsupported\";\n private statusListeners: Set<(status: PushSubscriptionStatus) => void> = new Set();\n private messageListeners: Set<(data: PushEventData) => void> = new Set();\n\n constructor(config: PushConfig) {\n this.config = config;\n }\n\n static isSupported(): boolean {\n return (\n typeof navigator !== \"undefined\" &&\n \"serviceWorker\" in navigator &&\n \"PushManager\" in window &&\n \"Notification\" in window\n );\n }\n\n getStatus(): PushSubscriptionStatus {\n return this.status;\n }\n\n onStatusChange(listener: (status: PushSubscriptionStatus) => void): () => void {\n this.statusListeners.add(listener);\n return () => {\n this.statusListeners.delete(listener);\n };\n }\n\n onMessage(listener: (data: PushEventData) => void): () => void {\n this.messageListeners.add(listener);\n return () => {\n this.messageListeners.delete(listener);\n };\n }\n\n async initialize(): Promise<void> {\n if (!PushManager.isSupported()) {\n this.setStatus(\"unsupported\");\n return;\n }\n if (Notification.permission === \"denied\") {\n this.setStatus(\"denied\");\n return;\n }\n\n try {\n this.registration = await navigator.serviceWorker.register(\n this.config.serviceWorkerUrl || \"/chat-service-worker.js\",\n {\n scope: this.config.serviceWorkerScope || \"/\",\n type: this.config.serviceWorkerType,\n },\n );\n await navigator.serviceWorker.ready;\n\n navigator.serviceWorker.addEventListener(\"message\", (event: MessageEvent) => {\n const msg = event.data as Record<string, unknown>;\n if (msg?.type === \"chat-widget:push-data\") {\n const pushData = msg.data as PushEventData;\n this.messageListeners.forEach((listener) => listener(pushData));\n }\n });\n\n const subscription = await this.registration.pushManager.getSubscription();\n this.setStatus(subscription ? \"subscribed\" : \"default\");\n } catch {\n this.setStatus(\"error\");\n }\n }\n\n async subscribe(): Promise<void> {\n if (!this.registration)\n throw new Error(\"PushManager not initialized. Call initialize() first.\");\n\n this.setStatus(\"subscribing\");\n\n try {\n let subscription = await this.registration.pushManager.getSubscription();\n\n if (!subscription) {\n const permission = await Notification.requestPermission();\n if (permission !== \"granted\") {\n this.setStatus(permission === \"denied\" ? \"denied\" : \"default\");\n return;\n }\n\n const vapidPublicKey = await this.config.getVapidPublicKey();\n const convertedKey = this.urlBase64ToUint8Array(vapidPublicKey);\n subscription = await this.registration.pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: convertedKey.buffer as ArrayBuffer,\n });\n }\n\n await this.config.onSubscribe(subscription.toJSON());\n this.setStatus(\"subscribed\");\n } catch {\n this.setStatus(\"error\");\n throw new Error(\"Push subscription failed\");\n }\n }\n\n async unsubscribe(): Promise<void> {\n if (!this.registration) return;\n\n try {\n const subscription = await this.registration.pushManager.getSubscription();\n if (subscription) {\n await this.config.onUnsubscribe(subscription.toJSON());\n await subscription.unsubscribe();\n }\n this.setStatus(\"default\");\n } catch {\n this.setStatus(\"error\");\n throw new Error(\"Push unsubscription failed\");\n }\n }\n\n private urlBase64ToUint8Array(base64String: string): Uint8Array {\n const padding = \"=\".repeat((4 - (base64String.length % 4)) % 4);\n const base64 = (base64String + padding).replace(/-/g, \"+\").replace(/_/g, \"/\");\n const rawData = atob(base64);\n return Uint8Array.from([...rawData].map((char) => char.charCodeAt(0)));\n }\n\n private setStatus(status: PushSubscriptionStatus): void {\n this.status = status;\n this.statusListeners.forEach((listener) => listener(status));\n }\n}\n","import { HttpClient } from \"../client/HttpClient\";\nimport type { PushConfig } from \"./types\";\n\nexport function createPushSubscriptionHandlers(\n httpClient: HttpClient,\n userId: string,\n): Pick<PushConfig, \"onSubscribe\" | \"onUnsubscribe\"> {\n return {\n onSubscribe: async (subscription: PushSubscriptionJSON) => {\n await httpClient.post(\"/api/push/subscriptions\", {\n userId,\n subscription,\n userAgent: navigator.userAgent,\n });\n },\n onUnsubscribe: async (subscription: PushSubscriptionJSON) => {\n await httpClient.delete(\n `/api/push/subscriptions?userId=${encodeURIComponent(userId)}&endpoint=${encodeURIComponent(subscription.endpoint || \"\")}`,\n );\n },\n };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/client/HttpClient.ts","../src/events/base/ChatEvent.ts","../src/events/MessagePostedEvent.ts","../src/events/MessageEditedEvent.ts","../src/events/MessageDeletedEvent.ts","../src/events/ReactionAddedEvent.ts","../src/events/ReactionRemovedEvent.ts","../src/events/TypingStartedEvent.ts","../src/events/StreamingChunkEvent.ts","../src/events/DMRequestedEvent.ts","../src/events/ChatEventFactory.ts","../src/utils/eventIdGenerator.ts","../src/client/WebChatClient.ts","../src/client/PusherBroadcastClient.ts","../src/client/LaravelEchoBroadcastClient.ts","../src/push/PushManager.ts","../src/push/PushSubscriptionManager.ts"],"sourcesContent":["export { WebChatClient } from \"./client/WebChatClient\";\nexport type {\n WebChatClientConfig,\n ReconfigureConfig,\n LoadMessagesOptions,\n LoadMessagesResult,\n} from \"./client/WebChatClient\";\n\nexport {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./client/BroadcastClient\";\nexport { PusherBroadcastClient } from \"./client/PusherBroadcastClient\";\nexport type { PusherConfig } from \"./client/PusherBroadcastClient\";\nexport { LaravelEchoBroadcastClient } from \"./client/LaravelEchoBroadcastClient\";\n\nexport { HttpClient } from \"./client/HttpClient\";\nexport type { HttpClientConfig, ChatResponse } from \"./client/HttpClient\";\n\nexport * from \"./types\";\n\nexport { ChatEvent, UnknownEvent } from \"./events/base/ChatEvent\";\nexport { parseChatEvent } from \"./events/ChatEventFactory\";\nexport { MessagePostedEvent } from \"./events/MessagePostedEvent\";\nexport { MessageEditedEvent } from \"./events/MessageEditedEvent\";\nexport { MessageDeletedEvent } from \"./events/MessageDeletedEvent\";\nexport { ReactionAddedEvent } from \"./events/ReactionAddedEvent\";\nexport { ReactionRemovedEvent } from \"./events/ReactionRemovedEvent\";\nexport { TypingStartedEvent } from \"./events/TypingStartedEvent\";\nexport { StreamingChunkEvent } from \"./events/StreamingChunkEvent\";\nexport { DMRequestedEvent } from \"./events/DMRequestedEvent\";\n\nexport { generateId, generateConversationId } from \"./utils/eventIdGenerator\";\n\nexport { PushManager } from \"./push/PushManager\";\nexport { createPushSubscriptionHandlers } from \"./push/PushSubscriptionManager\";\nexport type { PushSubscriptionStatus, PushConfig, PushEventData } from \"./push/types\";\n","export interface HttpClientConfig {\n apiUrl: string;\n headers?: Record<string, string>;\n timeout?: number;\n verifyToken?: string;\n}\n\nexport interface ChatResponse {\n id: string;\n role: \"assistant\" | \"user\";\n text: string;\n attachments?: Array<{\n type: string;\n url: string;\n name?: string;\n mime_type?: string;\n size?: number;\n }>;\n events?: Array<Record<string, unknown>>;\n}\n\nexport class HttpClient {\n private config: Required<Pick<HttpClientConfig, \"apiUrl\" | \"timeout\">> & {\n headers: Record<string, string>;\n };\n\n constructor(config: HttpClientConfig) {\n const headers: Record<string, string> = { ...config.headers };\n if (config.verifyToken) {\n headers[\"X-Verify-Token\"] = config.verifyToken;\n }\n this.config = { apiUrl: config.apiUrl, timeout: config.timeout ?? 30000, headers };\n }\n\n async get(url: string, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"GET\",\n headers: this.config.headers,\n signal: combined,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async post(url: string, body: unknown, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...this.config.headers },\n signal: combined,\n body: JSON.stringify(body),\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async delete(url: string, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"DELETE\",\n headers: this.config.headers,\n signal: combined,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n const text = await response.text();\n return text ? JSON.parse(text) : undefined;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async sendMessage(\n messages: Array<{\n id: string;\n role: string;\n text: string;\n attachments?: Array<{ url: string; name?: string; mime_type?: string; size?: number }>;\n }>,\n endpoint: string = \"/api/webhooks/web\",\n conversationId?: string,\n ): Promise<ChatResponse> {\n return this.post(endpoint, { id: conversationId, messages }) as Promise<ChatResponse>;\n }\n\n async sendAction(\n actionId: string,\n value: string,\n messageId: string,\n conversationId: string,\n endpoint: string = \"/api/webhooks/web\",\n ): Promise<Record<string, unknown>> {\n return this.post(endpoint, {\n id: conversationId,\n action: { actionId, value, messageId },\n }) as Promise<Record<string, unknown>>;\n }\n\n async editMessage(\n messageId: string,\n newText: string,\n endpointTemplate: string = \"/api/chat/messages/{id}/edit\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.post(url, { text: newText });\n }\n\n async deleteMessage(\n messageId: string,\n endpointTemplate: string = \"/api/chat/messages/{id}\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.delete(url);\n }\n\n async postFormData(url: string, formData: FormData, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"POST\",\n headers: this.config.headers,\n signal: combined,\n body: formData,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n setHeader(name: string, value: string): void {\n this.config.headers[name] = value;\n }\n\n removeHeader(name: string): void {\n delete this.config.headers[name];\n }\n\n private resolve(url: string): string {\n return /^https?:\\/\\//.test(url) ? url : `${this.config.apiUrl}${url}`;\n }\n\n private expandTemplate(template: string, params: Record<string, string>): string {\n let url = template;\n for (const [key, value] of Object.entries(params)) {\n url = url.replace(`{${key}}`, encodeURIComponent(value));\n }\n return this.resolve(url);\n }\n}\n","export abstract class ChatEvent {\n readonly type: string;\n readonly threadId: string;\n readonly timestamp: number;\n\n constructor(type: string, threadId: string, timestamp: number) {\n this.type = type;\n this.threadId = threadId;\n this.timestamp = timestamp;\n }\n\n static fromJSON: ((json: Record<string, unknown>) => ChatEvent) | undefined;\n}\n\nexport class UnknownEvent extends ChatEvent {\n readonly data: Record<string, unknown>;\n\n constructor(type: string, threadId: string, data: Record<string, unknown>, timestamp: number) {\n super(type, threadId, timestamp);\n this.data = data;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User, Card } from \"../types\";\n\nexport class MessagePostedEvent extends ChatEvent {\n readonly messageId: string;\n readonly text: string;\n readonly author: User;\n readonly card?: Card;\n readonly attachments?: Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>;\n\n constructor(\n threadId: string,\n messageId: string,\n text: string,\n author: User,\n card?: Card,\n attachments?: Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>,\n timestamp?: number,\n ) {\n super(\"message.posted\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.text = text;\n this.author = author;\n this.card = card;\n this.attachments = attachments;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { Card } from \"../types\";\n\nexport class MessageEditedEvent extends ChatEvent {\n readonly messageId: string;\n readonly newText: string;\n readonly card?: Card;\n\n constructor(\n threadId: string,\n messageId: string,\n newText: string,\n card?: Card,\n timestamp?: number,\n ) {\n super(\"message.edited\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.newText = newText;\n this.card = card;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class MessageDeletedEvent extends ChatEvent {\n readonly messageId: string;\n\n constructor(threadId: string, messageId: string, timestamp?: number) {\n super(\"message.deleted\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User } from \"../types\";\n\nexport class ReactionAddedEvent extends ChatEvent {\n readonly messageId: string;\n readonly emoji: string;\n readonly user: User;\n\n constructor(threadId: string, messageId: string, emoji: string, user: User, timestamp?: number) {\n super(\"reaction.added\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.emoji = emoji;\n this.user = user;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User } from \"../types\";\n\nexport class ReactionRemovedEvent extends ChatEvent {\n readonly messageId: string;\n readonly emoji: string;\n readonly user: User;\n\n constructor(threadId: string, messageId: string, emoji: string, user: User, timestamp?: number) {\n super(\"reaction.removed\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.emoji = emoji;\n this.user = user;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class TypingStartedEvent extends ChatEvent {\n readonly userId: string;\n\n constructor(threadId: string, userId: string, timestamp?: number) {\n super(\"typing.started\", threadId, timestamp ?? Date.now());\n this.userId = userId;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class StreamingChunkEvent extends ChatEvent {\n readonly messageId: string;\n readonly chunk: string;\n readonly isFinal: boolean;\n\n constructor(\n threadId: string,\n messageId: string,\n chunk: string,\n isFinal: boolean,\n timestamp?: number,\n ) {\n super(\"streaming.chunk\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.chunk = chunk;\n this.isFinal = isFinal;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class DMRequestedEvent extends ChatEvent {\n readonly userId: string;\n\n constructor(threadId: string, userId: string, timestamp?: number) {\n super(\"dm.requested\", threadId, timestamp ?? Date.now());\n this.userId = userId;\n }\n}\n","import { ChatEvent, UnknownEvent } from \"./base/ChatEvent\";\nimport type { Card, User } from \"../types\";\nimport { MessagePostedEvent } from \"./MessagePostedEvent\";\nimport { MessageEditedEvent } from \"./MessageEditedEvent\";\nimport { MessageDeletedEvent } from \"./MessageDeletedEvent\";\nimport { ReactionAddedEvent } from \"./ReactionAddedEvent\";\nimport { ReactionRemovedEvent } from \"./ReactionRemovedEvent\";\nimport { TypingStartedEvent } from \"./TypingStartedEvent\";\nimport { StreamingChunkEvent } from \"./StreamingChunkEvent\";\nimport { DMRequestedEvent } from \"./DMRequestedEvent\";\n\nfunction parseCard(value: unknown): Card | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const obj = value as Record<string, unknown>;\n if (typeof obj.type !== \"string\") return undefined;\n return obj as unknown as Card;\n}\n\nexport function parseChatEvent(json: Record<string, unknown>): ChatEvent {\n const type = json.type as string;\n const threadId = json.threadId as string;\n const timestamp = json.timestamp as number;\n const data = (json.data ?? {}) as Record<string, unknown>;\n\n switch (type) {\n case \"message.posted\":\n return new MessagePostedEvent(\n threadId,\n data.messageId as string,\n data.text as string,\n data.author as User,\n parseCard(data.card),\n data.attachments as Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>,\n timestamp,\n );\n case \"message.edited\":\n return new MessageEditedEvent(\n threadId,\n data.messageId as string,\n data.newText as string,\n parseCard(data.card),\n timestamp,\n );\n case \"message.deleted\":\n return new MessageDeletedEvent(threadId, data.messageId as string, timestamp);\n case \"reaction.added\":\n return new ReactionAddedEvent(\n threadId,\n data.messageId as string,\n data.emoji as string,\n data.user as User,\n timestamp,\n );\n case \"reaction.removed\":\n return new ReactionRemovedEvent(\n threadId,\n data.messageId as string,\n data.emoji as string,\n data.user as User,\n timestamp,\n );\n case \"typing.started\":\n return new TypingStartedEvent(threadId, data.userId as string, timestamp);\n case \"streaming.chunk\":\n return new StreamingChunkEvent(\n threadId,\n data.messageId as string,\n data.chunk as string,\n data.isFinal as boolean,\n timestamp,\n );\n case \"dm.requested\":\n return new DMRequestedEvent(threadId, data.userId as string, timestamp);\n default:\n return new UnknownEvent(type, threadId, data, timestamp);\n }\n}\n\n// Wire up the static method\nChatEvent.fromJSON = parseChatEvent;\n","export function generateId(): string {\n return `msg-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n\nexport function generateConversationId(): string {\n return `conv-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n","import { HttpClient } from \"./HttpClient\";\nimport type { BroadcastClient, EventHandlers, Unsubscribe } from \"./BroadcastClient\";\nimport type { Message } from \"../types\";\nimport { ChatEvent } from \"../events/base/ChatEvent\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type { MessagePostedEvent } from \"../events/MessagePostedEvent\";\nimport type { MessageEditedEvent } from \"../events/MessageEditedEvent\";\nimport type { MessageDeletedEvent } from \"../events/MessageDeletedEvent\";\nimport { ReactionAddedEvent } from \"../events/ReactionAddedEvent\";\nimport { ReactionRemovedEvent } from \"../events/ReactionRemovedEvent\";\nimport type { TypingStartedEvent } from \"../events/TypingStartedEvent\";\nimport type { StreamingChunkEvent } from \"../events/StreamingChunkEvent\";\nimport type { DMRequestedEvent } from \"../events/DMRequestedEvent\";\nimport { generateId, generateConversationId } from \"../utils/eventIdGenerator\";\n\nexport interface ReconfigureConfig {\n userId?: string;\n userName?: string;\n verifyToken?: string;\n conversationId?: string;\n headers?: Record<string, string>;\n}\n\nexport interface WebChatClientConfig {\n apiUrl: string;\n userId: string;\n userName: string;\n broadcastClient?: BroadcastClient;\n headers?: Record<string, string>;\n verifyToken?: string;\n conversationId?: string;\n endpoints?: {\n sendMessage?: string;\n loadMessages?: string;\n editMessage?: string;\n deleteMessage?: string;\n };\n features?: {\n editMessages?: boolean;\n deleteMessages?: boolean;\n reactions?: boolean;\n };\n}\n\ninterface StreamingState {\n messageId: string;\n accumulatedText: string;\n isComplete: boolean;\n}\n\ninterface AttachmentInput {\n url: string;\n name?: string;\n mimeType?: string;\n size?: number;\n}\n\nexport interface LoadMessagesOptions {\n limit?: number;\n before?: number;\n after?: number;\n skipStateSeed?: boolean;\n}\n\nexport interface LoadMessagesResult {\n messages: Message[];\n hasMore: boolean;\n nextCursor?: number;\n prevCursor?: number;\n}\n\nexport class WebChatClient {\n private config: WebChatClientConfig;\n private httpClient: HttpClient;\n private broadcastClient?: BroadcastClient;\n private conversationId: string;\n private messages: Message[] = [];\n private currentUserId: string;\n private eventHandlers: EventHandlers = {};\n private streamingMessages: Map<string, StreamingState> = new Map();\n private pendingTyping: ReturnType<typeof setTimeout> | null = null;\n private subscribers: Map<string, Array<(event: unknown) => void>> = new Map();\n private sendQueue: Array<() => Promise<void>> = [];\n private isProcessingQueue = false;\n private unsubscribeUserChannel?: Unsubscribe;\n\n constructor(config: WebChatClientConfig) {\n this.config = config;\n this.httpClient = new HttpClient({\n apiUrl: config.apiUrl,\n headers: {\n \"X-User-Id\": config.userId,\n \"X-User-Name\": config.userName,\n ...(config.headers ?? {}),\n },\n verifyToken: config.verifyToken,\n });\n this.broadcastClient = config.broadcastClient;\n this.conversationId = config.conversationId ?? generateConversationId();\n this.currentUserId = config.userId;\n }\n\n reconfigure(config: ReconfigureConfig): void {\n if (config.userId) {\n this.currentUserId = config.userId;\n this.httpClient.setHeader(\"X-User-Id\", config.userId);\n }\n if (config.userName) {\n this.config = { ...this.config, userName: config.userName };\n this.httpClient.setHeader(\"X-User-Name\", config.userName);\n }\n if (config.verifyToken) {\n this.config = { ...this.config, verifyToken: config.verifyToken };\n this.httpClient.setHeader(\"X-Verify-Token\", config.verifyToken);\n }\n if (config.conversationId) {\n this.conversationId = config.conversationId;\n }\n if (config.headers) {\n Object.entries(config.headers).forEach(([key, value]) => {\n this.httpClient.setHeader(key, value);\n });\n }\n }\n\n setLocaleHeader(locale: string): void {\n this.httpClient.setHeader(\"X-Locale\", locale);\n this.httpClient.setHeader(\"X-Language\", locale.split(\"-\")[0] ?? locale);\n }\n\n setTimezoneHeader(timezone: string): void {\n this.httpClient.setHeader(\"X-Timezone\", timezone);\n }\n\n async connect(): Promise<void> {\n if (this.broadcastClient) {\n this.broadcastClient.connect();\n\n const threadId = this.getThreadId();\n const threadEvents: EventHandlers = {\n onMessagePosted: (event) => this.handleMessagePosted(event),\n };\n\n if (this.config.features?.editMessages) {\n threadEvents.onMessageEdited = (event) => this.handleMessageEdited(event);\n }\n if (this.config.features?.deleteMessages) {\n threadEvents.onMessageDeleted = (event) => this.handleMessageDeleted(event);\n }\n if (this.config.features?.reactions) {\n threadEvents.onReactionAdded = (event) => this.handleReactionAdded(event);\n threadEvents.onReactionRemoved = (event) => this.handleReactionRemoved(event);\n }\n\n threadEvents.onTypingStarted = (event) => this.handleTypingStarted(event);\n\n await this.broadcastClient.subscribe(threadId, threadEvents);\n\n this.unsubscribeUserChannel = await this.broadcastClient.subscribeToUser(\n threadId,\n this.currentUserId,\n {\n onStreamingChunk: (event) => this.handleStreamingChunk(event),\n onDMRequested: (event) => this.handleDMRequested(event),\n },\n );\n }\n }\n\n disconnect(): void {\n this.unsubscribeUserChannel?.();\n this.unsubscribeUserChannel = undefined;\n this.broadcastClient?.disconnect();\n this.streamingMessages.clear();\n }\n\n async loadMessages(\n options?: LoadMessagesOptions,\n signal?: AbortSignal,\n ): Promise<LoadMessagesResult> {\n const endpoint = this.config.endpoints?.loadMessages ?? \"/api/chat/messages\";\n const threadId = this.getThreadId();\n const params = new URLSearchParams({\n threadId,\n limit: String(options?.limit ?? 50),\n });\n if (options?.before) params.set(\"before\", String(options.before));\n if (options?.after) params.set(\"after\", String(options.after));\n\n const response = (await this.httpClient.get(\n `${endpoint}?${params.toString()}`,\n signal,\n )) as Record<string, unknown>;\n const rawMessages = (response.messages as Record<string, unknown>[]) ?? [];\n const messages: Message[] = rawMessages.map((msg) => ({\n id: msg.id as string,\n threadId,\n content: {\n text: msg.text as string,\n cards: msg.card ? ([msg.card as Record<string, unknown>] as never[]) : undefined,\n },\n author: {\n id: (msg.author as Record<string, unknown>).id as string,\n name: (msg.author as Record<string, unknown>).name as string,\n isBot: ((msg.author as Record<string, unknown>).isBot as boolean) ?? false,\n isMe: (msg.author as Record<string, unknown>).id === this.currentUserId,\n },\n timestamp: msg.timestamp as number,\n attachments: (msg.attachments as Record<string, unknown>[])?.map((a) => ({\n id: `att-${msg.id as string}-${a.url as string}`,\n url: a.url as string,\n name: a.name as string,\n type: a.type as string,\n mimeType: a.mime_type as string,\n size: a.size as number,\n })),\n reactions: (msg.reactions as { emoji: string; count: number; users: string[] }[]) ?? [],\n }));\n\n if (!options?.before && !options?.after && !options?.skipStateSeed) {\n this.messages = messages;\n this.notifySubscribers(\"messages:loaded\", messages);\n }\n\n return {\n messages,\n hasMore: (response.hasMore as boolean) ?? false,\n nextCursor: response.nextCursor as number | undefined,\n prevCursor: response.prevCursor as number | undefined,\n };\n }\n\n async sendMessage(text: string, attachments: AttachmentInput[] = []): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n this.sendQueue.push(async () => {\n try {\n await this.executeSend(text, attachments);\n resolve();\n } catch (e) {\n reject(e);\n }\n });\n this.processQueue();\n });\n }\n\n private async processQueue(): Promise<void> {\n if (this.isProcessingQueue) return;\n this.isProcessingQueue = true;\n try {\n while (this.sendQueue.length > 0) {\n const task = this.sendQueue.shift()!;\n await task();\n }\n } finally {\n this.isProcessingQueue = false;\n }\n }\n\n private async executeSend(text: string, attachments: AttachmentInput[] = []): Promise<void> {\n const messageId = generateId();\n\n const userMessage: Message = {\n id: messageId,\n threadId: this.getThreadId(),\n content: { text },\n author: { id: this.currentUserId, name: this.config.userName, isMe: true },\n timestamp: Date.now(),\n attachments:\n attachments.length > 0\n ? attachments.map((a, i) => ({\n id: `att-${messageId}-${i}`,\n name: a.name ?? \"\",\n url: a.url,\n size: a.size,\n mimeType: a.mimeType,\n }))\n : undefined,\n };\n\n this.messages.push(userMessage);\n this.notifySubscribers(\"message:added\", userMessage);\n\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = await this.httpClient.sendMessage(\n [\n {\n id: messageId,\n role: \"user\",\n text,\n attachments: attachments.map((a) => ({\n url: a.url,\n name: a.name,\n mime_type: a.mimeType,\n size: a.size,\n })),\n },\n ],\n endpoint,\n this.conversationId,\n );\n\n if (response.events) {\n response.events.forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n\n if (response.text && !response.events?.some((e) => e.type === \"message.posted\")) {\n const assistantMessage: Message = {\n id: response.id ?? generateId(),\n threadId: this.getThreadId(),\n content: { text: response.text },\n author: { id: \"assistant\", name: \"Assistant\", isBot: true },\n timestamp: Date.now(),\n attachments: (response.attachments as Record<string, unknown>[])?.map((a, i) => ({\n id: `att-${response.id ?? \"msg\"}-${i}`,\n name: (a.name as string) ?? \"\",\n url: (a.url as string) ?? \"\",\n type: a.type as string,\n mimeType: a.mime_type as string,\n size: a.size as number,\n })),\n };\n this.messages.push(assistantMessage);\n this.notifySubscribers(\"message:added\", assistantMessage);\n }\n }\n\n async sendAction(messageId: string, actionId: string, value: string): Promise<void> {\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = await this.httpClient.sendAction(\n actionId,\n value,\n messageId,\n this.conversationId,\n endpoint,\n );\n\n if (response.events) {\n (response.events as Array<Record<string, unknown>>).forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n }\n\n async editMessage(messageId: string, newText: string): Promise<void> {\n if (!this.config.features?.editMessages) {\n throw new Error(\"Edit messages not enabled. Set features.editMessages = true in config.\");\n }\n const endpoint = this.config.endpoints?.editMessage ?? \"/api/chat/messages/{id}/edit\";\n await this.httpClient.editMessage(messageId, newText, endpoint);\n }\n\n async deleteMessage(messageId: string): Promise<void> {\n if (!this.config.features?.deleteMessages) {\n throw new Error(\"Delete messages not enabled. Set features.deleteMessages = true in config.\");\n }\n const endpoint = this.config.endpoints?.deleteMessage ?? \"/api/chat/messages/{id}\";\n await this.httpClient.deleteMessage(messageId, endpoint);\n }\n\n async addReaction(messageId: string, emoji: string): Promise<void> {\n if (!this.config.features?.reactions) {\n throw new Error(\"Reactions not enabled. Set features.reactions = true in config.\");\n }\n\n // Optimistic local update\n this.handleReactionAdded(\n new ReactionAddedEvent(this.getThreadId(), messageId, emoji, { id: this.currentUserId }),\n );\n\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = (await this.httpClient.post(endpoint, {\n id: this.conversationId,\n reaction: { messageId, emoji, added: true },\n })) as Record<string, unknown>;\n\n if (response.events) {\n (response.events as Array<Record<string, unknown>>).forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n }\n\n async removeReaction(messageId: string, emoji: string): Promise<void> {\n if (!this.config.features?.reactions) {\n throw new Error(\"Reactions not enabled. Set features.reactions = true in config.\");\n }\n\n // Optimistic local update\n this.handleReactionRemoved(\n new ReactionRemovedEvent(this.getThreadId(), messageId, emoji, { id: this.currentUserId }),\n );\n\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = (await this.httpClient.post(endpoint, {\n id: this.conversationId,\n reaction: { messageId, emoji, added: false },\n })) as Record<string, unknown>;\n\n if (response.events) {\n (response.events as Array<Record<string, unknown>>).forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n }\n\n onMessagePosted(handler: (event: MessagePostedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message.posted\", handler);\n }\n\n onMessageEdited(handler: (event: MessageEditedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message:edited\", handler);\n }\n\n onMessageDeleted(handler: (event: MessageDeletedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message:deleted\", handler);\n }\n\n onReactionAdded(handler: (event: ReactionAddedEvent) => void): Unsubscribe {\n return this.addEventListener(\"reaction:added\", handler);\n }\n\n onReactionRemoved(handler: (event: ReactionRemovedEvent) => void): Unsubscribe {\n return this.addEventListener(\"reaction:removed\", handler);\n }\n\n onStreamingChunk(handler: (event: StreamingChunkEvent) => void): Unsubscribe {\n return this.addEventListener(\"streaming:chunk\", handler);\n }\n\n onTypingStarted(handler: (event: TypingStartedEvent) => void): Unsubscribe {\n return this.addEventListener(\"typing:started\", handler);\n }\n\n getConversationId(): string {\n return this.conversationId;\n }\n getMessages(): Message[] {\n return [...this.messages];\n }\n getThreadId(): string {\n return `web:${this.currentUserId}:${this.conversationId}`;\n }\n getCurrentUserId(): string {\n return this.currentUserId;\n }\n getFeatures(): NonNullable<WebChatClientConfig[\"features\"]> {\n return this.config.features ?? {};\n }\n getEndpoints(): NonNullable<WebChatClientConfig[\"endpoints\"]> {\n return this.config.endpoints ?? {};\n }\n getHttpClient(): HttpClient {\n return this.httpClient;\n }\n\n addEventListener<T = unknown>(eventType: string, handler: (event: T) => void): Unsubscribe {\n if (!this.subscribers.has(eventType)) this.subscribers.set(eventType, []);\n this.subscribers.get(eventType)!.push(handler as (event: unknown) => void);\n return () => {\n const handlers = this.subscribers.get(eventType);\n if (handlers) {\n const index = handlers.indexOf(handler as (event: unknown) => void);\n if (index !== -1) handlers.splice(index, 1);\n }\n };\n }\n\n private handleMessagePosted(event: MessagePostedEvent): void {\n if (this.messages.some((m) => m.id === event.messageId)) return;\n if (this.streamingMessages.has(event.messageId)) return;\n\n const message: Message = {\n id: event.messageId,\n threadId: event.threadId,\n content: { text: event.text, cards: event.card ? [event.card] : undefined },\n author: event.author,\n timestamp: event.timestamp,\n attachments: event.attachments?.map((a) => ({\n id: `att-${event.messageId}-${Math.random().toString(36).slice(2, 8)}`,\n name: a.name ?? \"\",\n url: a.url ?? \"\",\n type: a.type,\n mimeType: a.mimeType,\n size: a.size ?? undefined,\n })),\n };\n this.messages.push(message);\n this.notifySubscribers(\"message:added\", message);\n this.notifySubscribers(\"message.posted\", event);\n }\n\n private handleMessageEdited(event: MessageEditedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (message?.content) {\n message.content.text = event.newText;\n this.notifySubscribers(\"message:edited\", event);\n }\n }\n\n private handleMessageDeleted(event: MessageDeletedEvent): void {\n const index = this.messages.findIndex((m) => m.id === event.messageId);\n if (index !== -1) {\n this.messages.splice(index, 1);\n this.notifySubscribers(\"message:deleted\", event);\n }\n }\n\n private handleReactionAdded(event: ReactionAddedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (message) {\n if (!message.reactions) message.reactions = [];\n\n const existing = message.reactions.find((r) => r.emoji === event.emoji);\n if (existing) {\n existing.count++;\n existing.users.push(event.user.id);\n } else {\n message.reactions.push({ emoji: event.emoji, count: 1, users: [event.user.id] });\n }\n }\n this.notifySubscribers(\"reaction:added\", event);\n }\n\n private handleReactionRemoved(event: ReactionRemovedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (message?.reactions) {\n const index = message.reactions.findIndex((r) => r.emoji === event.emoji);\n if (index !== -1) {\n const reaction = message.reactions[index]!;\n reaction.count--;\n reaction.users = reaction.users.filter((id) => id !== event.user.id);\n if (reaction.count === 0) message.reactions.splice(index, 1);\n }\n }\n this.notifySubscribers(\"reaction:removed\", event);\n }\n\n private handleStreamingChunk(event: StreamingChunkEvent): void {\n const { messageId, chunk, isFinal } = event;\n\n if (!this.streamingMessages.has(messageId)) {\n this.streamingMessages.set(messageId, { messageId, accumulatedText: \"\", isComplete: false });\n this.notifySubscribers(\"streaming:started\", event);\n }\n\n const state = this.streamingMessages.get(messageId)!;\n state.accumulatedText += chunk;\n\n if (isFinal) {\n state.isComplete = true;\n if (!this.messages.some((m) => m.id === messageId)) {\n const message: Message = {\n id: messageId,\n threadId: event.threadId,\n content: { text: state.accumulatedText },\n author: { id: \"assistant\", name: \"Assistant\", isBot: true },\n timestamp: event.timestamp,\n };\n this.messages.push(message);\n this.notifySubscribers(\"message:added\", message);\n }\n this.streamingMessages.delete(messageId);\n this.notifySubscribers(\"streaming:complete\", { messageId, text: state.accumulatedText });\n } else {\n this.notifySubscribers(\"streaming:chunk\", event);\n }\n }\n\n private handleTypingStarted(event: TypingStartedEvent): void {\n if (this.pendingTyping) clearTimeout(this.pendingTyping);\n this.notifySubscribers(\"typing:started\", event);\n this.pendingTyping = setTimeout(() => {\n this.notifySubscribers(\"typing:stopped\", { userId: event.userId });\n }, 3000);\n }\n\n private handleDMRequested(event: DMRequestedEvent): void {\n this.notifySubscribers(\"dm.requested\", event);\n }\n\n private notifySubscribers<T>(eventType: string, data: T): void {\n this.subscribers.get(eventType)?.forEach((handler) => handler(data));\n }\n\n private dispatchEvent(event: ChatEvent): void {\n switch (event.type) {\n case \"message.posted\":\n this.handleMessagePosted(event as MessagePostedEvent);\n break;\n case \"message.edited\":\n this.handleMessageEdited(event as MessageEditedEvent);\n break;\n case \"message.deleted\":\n this.handleMessageDeleted(event as MessageDeletedEvent);\n break;\n case \"reaction.added\":\n this.handleReactionAdded(event as ReactionAddedEvent);\n break;\n case \"reaction.removed\":\n this.handleReactionRemoved(event as ReactionRemovedEvent);\n break;\n case \"typing.started\":\n this.handleTypingStarted(event as TypingStartedEvent);\n break;\n case \"streaming.chunk\":\n this.handleStreamingChunk(event as StreamingChunkEvent);\n break;\n case \"dm.requested\":\n this.handleDMRequested(event as DMRequestedEvent);\n break;\n }\n }\n}\n","import {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./BroadcastClient\";\nimport { ChatEvent } from \"../events/base/ChatEvent\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type Pusher from \"pusher-js\";\nimport type { Channel as PusherChannel } from \"pusher-js\";\n\nexport interface PusherConfig {\n key: string;\n cluster?: string;\n host?: string;\n port?: number;\n forceTLS?: boolean;\n authEndpoint?: string;\n}\n\nexport class PusherBroadcastClient implements BroadcastClient {\n private pusher: Pusher;\n private channelPrefix: string;\n private threadChannelType: \"public\" | \"private\" | \"presence\";\n private userChannelType: \"private\" | \"presence\";\n private useHashChannel: boolean;\n private subscriptions: Map<string, PusherChannel> = new Map();\n\n constructor(pusher: Pusher, channelPrefix?: string, channelTypes?: ChannelTypeConfig);\n constructor(config: PusherConfig, channelPrefix?: string, channelTypes?: ChannelTypeConfig);\n constructor(\n pusherOrConfig: Pusher | PusherConfig,\n channelPrefix: string = \"chat\",\n channelTypes?: ChannelTypeConfig,\n ) {\n this.channelPrefix = channelPrefix;\n this.threadChannelType = channelTypes?.threadChannel ?? \"public\";\n this.userChannelType = channelTypes?.userChannel ?? \"private\";\n this.useHashChannel = channelTypes?.useHashChannel ?? false;\n\n if (\"key\" in pusherOrConfig) {\n const PusherCtor = (globalThis as any).Pusher ?? (globalThis as any).pusherJs;\n if (!PusherCtor) {\n throw new Error(\"pusher-js not found. Install it or pass a Pusher instance.\");\n }\n this.pusher = new PusherCtor((pusherOrConfig as PusherConfig).key, pusherOrConfig) as Pusher;\n } else {\n this.pusher = pusherOrConfig as Pusher;\n }\n }\n\n private buildChannelName(base: string, type: \"public\" | \"private\" | \"presence\"): string {\n switch (type) {\n case \"private\":\n return `private-${base}`;\n case \"presence\":\n return `presence-${base}`;\n default:\n return base;\n }\n }\n\n protected async buildResolvedChannelName(threadId: string): Promise<string> {\n const name = this.useHashChannel ? await this.hashChannelName(threadId) : threadId;\n\n return `${this.channelPrefix}.${name}`;\n }\n\n private async hashChannelName(name: string): Promise<string> {\n if (typeof crypto?.subtle?.digest !== \"function\") {\n throw new Error(\"Web Crypto API not available. Cannot hash channel names.\");\n }\n const encoder = new TextEncoder();\n const data = encoder.encode(name);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n connect(): void {\n if (this.pusher.connection?.state !== \"connected\") {\n this.pusher.connect();\n }\n }\n\n disconnect(): void {\n this.subscriptions.forEach((channel) => channel.unbind_all?.() ?? channel.unsubscribe?.());\n this.subscriptions.clear();\n this.pusher.disconnect?.();\n }\n\n async subscribe(threadId: string, handlers: EventHandlers): Promise<Unsubscribe> {\n const baseName = await this.buildResolvedChannelName(threadId);\n const channelName = this.buildChannelName(baseName, this.threadChannelType);\n const channel = this.pusher.subscribe(channelName);\n const key = `thread:${threadId}`;\n this.subscriptions.set(key, channel);\n\n const threadEvents = [\n \"message.posted\",\n \"message.edited\",\n \"message.deleted\",\n \"reaction.added\",\n \"reaction.removed\",\n \"typing.started\",\n ] as const;\n\n threadEvents.forEach((eventType) => {\n const eventName = `${this.channelPrefix}.${eventType}`;\n channel.bind(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n this.dispatchToHandler(event, handlers);\n });\n });\n\n return () => {\n channel.unbind_all?.();\n this.pusher.unsubscribe(channelName);\n this.subscriptions.delete(key);\n };\n }\n\n async subscribeToUser(\n threadId: string,\n userId: string,\n handlers: EventHandlers,\n ): Promise<Unsubscribe> {\n const baseName = `${await this.buildResolvedChannelName(threadId)}.${userId}`;\n const channelName = this.buildChannelName(baseName, this.userChannelType);\n const channel = this.pusher.subscribe(channelName);\n const key = `user:${threadId}:${userId}`;\n this.subscriptions.set(key, channel);\n\n const userEvents = [\"typing.started\", \"streaming.chunk\", \"dm.requested\"] as const;\n\n userEvents.forEach((eventType) => {\n const eventName = `${this.channelPrefix}.${eventType}`;\n channel.bind(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n this.dispatchToHandler(event, handlers);\n });\n });\n\n return () => {\n channel.unbind_all?.();\n this.pusher.unsubscribe(channelName);\n this.subscriptions.delete(key);\n };\n }\n\n isConnected(): boolean {\n return this.pusher.connection?.state === \"connected\";\n }\n\n private dispatchToHandler(event: ChatEvent, handlers: EventHandlers): void {\n switch (event.type) {\n case \"message.posted\":\n handlers.onMessagePosted?.(event as any);\n break;\n case \"message.edited\":\n handlers.onMessageEdited?.(event as any);\n break;\n case \"message.deleted\":\n handlers.onMessageDeleted?.(event as any);\n break;\n case \"reaction.added\":\n handlers.onReactionAdded?.(event as any);\n break;\n case \"reaction.removed\":\n handlers.onReactionRemoved?.(event as any);\n break;\n case \"typing.started\":\n handlers.onTypingStarted?.(event as any);\n break;\n case \"streaming.chunk\":\n handlers.onStreamingChunk?.(event as any);\n break;\n case \"dm.requested\":\n handlers.onDMRequested?.(event as any);\n break;\n }\n }\n}\n","import {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./BroadcastClient\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type Echo from \"laravel-echo\";\n\ninterface EchoChannel {\n listen(event: string, callback: (data: unknown) => void): this;\n unsubscribe(): void;\n stopListening(event?: string, callback?: (data: unknown) => void): this;\n}\n\nexport class LaravelEchoBroadcastClient implements BroadcastClient {\n private echo: Echo<any>;\n private channelPrefix: string;\n private threadChannelType: \"public\" | \"private\" | \"presence\";\n private userChannelType: \"private\" | \"presence\";\n private useHashChannel: boolean;\n private subscriptions: Map<string, EchoChannel> = new Map();\n\n constructor(echo: Echo<any>, channelPrefix: string = \"chat\", channelTypes?: ChannelTypeConfig) {\n this.echo = echo;\n this.channelPrefix = channelPrefix;\n this.threadChannelType = channelTypes?.threadChannel ?? \"public\";\n this.userChannelType = channelTypes?.userChannel ?? \"private\";\n this.useHashChannel = channelTypes?.useHashChannel ?? false;\n }\n\n private subscribeToEcho(name: string, type: \"public\" | \"private\" | \"presence\"): EchoChannel {\n switch (type) {\n case \"private\":\n return this.echo.private(name) as unknown as EchoChannel;\n case \"presence\":\n return this.echo.join(name) as unknown as EchoChannel;\n default:\n return this.echo.channel(name) as unknown as EchoChannel;\n }\n }\n\n connect(): void | Promise<void> {\n return Promise.resolve();\n }\n\n disconnect(): void {\n this.subscriptions.forEach((channel) => {\n channel.unsubscribe?.();\n channel.stopListening?.();\n });\n this.subscriptions.clear();\n }\n\n protected async buildResolvedChannelName(threadId: string): Promise<string> {\n const name = this.useHashChannel ? await this.hashChannelName(threadId) : threadId;\n\n return `${this.channelPrefix}.${name}`;\n }\n\n private async hashChannelName(name: string): Promise<string> {\n if (typeof crypto?.subtle?.digest !== \"function\") {\n throw new Error(\"Web Crypto API not available. Cannot hash channel names.\");\n }\n const encoder = new TextEncoder();\n const data = encoder.encode(name);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n async subscribe(threadId: string, handlers: EventHandlers): Promise<Unsubscribe> {\n const channelName = await this.buildResolvedChannelName(threadId);\n const channel = this.subscribeToEcho(channelName, this.threadChannelType);\n const key = `thread:${threadId}`;\n this.subscriptions.set(key, channel);\n\n const threadEvents: Array<{ type: string; handler: keyof EventHandlers }> = [\n { type: \"message.posted\", handler: \"onMessagePosted\" },\n { type: \"message.edited\", handler: \"onMessageEdited\" },\n { type: \"message.deleted\", handler: \"onMessageDeleted\" },\n { type: \"reaction.added\", handler: \"onReactionAdded\" },\n { type: \"reaction.removed\", handler: \"onReactionRemoved\" },\n { type: \"typing.started\", handler: \"onTypingStarted\" },\n ];\n\n threadEvents.forEach(({ type, handler }) => {\n const eventName = `.${this.channelPrefix}.${type}`;\n channel.listen(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n (handlers[handler] as any)?.(event);\n });\n });\n\n return () => {\n channel.unsubscribe?.();\n this.subscriptions.delete(key);\n };\n }\n\n async subscribeToUser(\n threadId: string,\n userId: string,\n handlers: EventHandlers,\n ): Promise<Unsubscribe> {\n const channelName = `${await this.buildResolvedChannelName(threadId)}.${userId}`;\n const channel = this.subscribeToEcho(channelName, this.userChannelType);\n const key = `user:${threadId}:${userId}`;\n this.subscriptions.set(key, channel);\n\n const userEvents: Array<{ type: string; handler: keyof EventHandlers }> = [\n { type: \"typing.started\", handler: \"onTypingStarted\" },\n { type: \"streaming.chunk\", handler: \"onStreamingChunk\" },\n { type: \"dm.requested\", handler: \"onDMRequested\" },\n ];\n\n userEvents.forEach(({ type, handler }) => {\n const eventName = `.${this.channelPrefix}.${type}`;\n channel.listen(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n (handlers[handler] as any)?.(event);\n });\n });\n\n return () => {\n channel.unsubscribe?.();\n this.subscriptions.delete(key);\n };\n }\n\n isConnected(): boolean {\n try {\n const connector = (this.echo as any).connector;\n if (!connector) return false;\n\n if (connector.pusher?.connection?.state === \"connected\") return true;\n if (connector.socket?.connected) return true;\n\n return false;\n } catch {\n return false;\n }\n }\n}\n","import type { PushConfig, PushSubscriptionStatus, PushEventData } from \"./types\";\n\nexport class PushManager {\n private config: PushConfig;\n private registration: ServiceWorkerRegistration | null = null;\n private status: PushSubscriptionStatus = \"unsupported\";\n private statusListeners: Set<(status: PushSubscriptionStatus) => void> = new Set();\n private messageListeners: Set<(data: PushEventData) => void> = new Set();\n\n constructor(config: PushConfig) {\n this.config = config;\n }\n\n static isSupported(): boolean {\n return (\n typeof navigator !== \"undefined\" &&\n \"serviceWorker\" in navigator &&\n \"PushManager\" in window &&\n \"Notification\" in window\n );\n }\n\n getStatus(): PushSubscriptionStatus {\n return this.status;\n }\n\n onStatusChange(listener: (status: PushSubscriptionStatus) => void): () => void {\n this.statusListeners.add(listener);\n return () => {\n this.statusListeners.delete(listener);\n };\n }\n\n onMessage(listener: (data: PushEventData) => void): () => void {\n this.messageListeners.add(listener);\n return () => {\n this.messageListeners.delete(listener);\n };\n }\n\n async initialize(): Promise<void> {\n if (!PushManager.isSupported()) {\n this.setStatus(\"unsupported\");\n return;\n }\n if (Notification.permission === \"denied\") {\n this.setStatus(\"denied\");\n return;\n }\n\n try {\n this.registration = await navigator.serviceWorker.register(\n this.config.serviceWorkerUrl || \"/chat-service-worker.js\",\n {\n scope: this.config.serviceWorkerScope || \"/\",\n type: this.config.serviceWorkerType,\n },\n );\n await navigator.serviceWorker.ready;\n\n navigator.serviceWorker.addEventListener(\"message\", (event: MessageEvent) => {\n const msg = event.data as Record<string, unknown>;\n if (msg?.type === \"chat-widget:push-data\") {\n const pushData = msg.data as PushEventData;\n this.messageListeners.forEach((listener) => listener(pushData));\n }\n });\n\n const subscription = await this.registration.pushManager.getSubscription();\n this.setStatus(subscription ? \"subscribed\" : \"default\");\n } catch {\n this.setStatus(\"error\");\n }\n }\n\n async subscribe(): Promise<void> {\n if (!this.registration)\n throw new Error(\"PushManager not initialized. Call initialize() first.\");\n\n this.setStatus(\"subscribing\");\n\n try {\n let subscription = await this.registration.pushManager.getSubscription();\n\n if (!subscription) {\n const permission = await Notification.requestPermission();\n if (permission !== \"granted\") {\n this.setStatus(permission === \"denied\" ? \"denied\" : \"default\");\n return;\n }\n\n const vapidPublicKey = await this.config.getVapidPublicKey();\n const convertedKey = this.urlBase64ToUint8Array(vapidPublicKey);\n subscription = await this.registration.pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: convertedKey.buffer as ArrayBuffer,\n });\n }\n\n await this.config.onSubscribe(subscription.toJSON());\n this.setStatus(\"subscribed\");\n } catch {\n this.setStatus(\"error\");\n throw new Error(\"Push subscription failed\");\n }\n }\n\n async unsubscribe(): Promise<void> {\n if (!this.registration) return;\n\n try {\n const subscription = await this.registration.pushManager.getSubscription();\n if (subscription) {\n await this.config.onUnsubscribe(subscription.toJSON());\n await subscription.unsubscribe();\n }\n this.setStatus(\"default\");\n } catch {\n this.setStatus(\"error\");\n throw new Error(\"Push unsubscription failed\");\n }\n }\n\n private urlBase64ToUint8Array(base64String: string): Uint8Array {\n const padding = \"=\".repeat((4 - (base64String.length % 4)) % 4);\n const base64 = (base64String + padding).replace(/-/g, \"+\").replace(/_/g, \"/\");\n const rawData = atob(base64);\n return Uint8Array.from([...rawData].map((char) => char.charCodeAt(0)));\n }\n\n private setStatus(status: PushSubscriptionStatus): void {\n this.status = status;\n this.statusListeners.forEach((listener) => listener(status));\n }\n}\n","import { HttpClient } from \"../client/HttpClient\";\nimport type { PushConfig } from \"./types\";\n\nexport function createPushSubscriptionHandlers(\n httpClient: HttpClient,\n userId: string,\n): Pick<PushConfig, \"onSubscribe\" | \"onUnsubscribe\"> {\n return {\n onSubscribe: async (subscription: PushSubscriptionJSON) => {\n await httpClient.post(\"/api/push/subscriptions\", {\n userId,\n subscription,\n userAgent: navigator.userAgent,\n });\n },\n onUnsubscribe: async (subscription: PushSubscriptionJSON) => {\n await httpClient.delete(\n `/api/push/subscriptions?userId=${encodeURIComponent(userId)}&endpoint=${encodeURIComponent(subscription.endpoint || \"\")}`,\n );\n },\n };\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -40,8 +40,6 @@ declare class HttpClient {
40
40
  sendAction(actionId: string, value: string, messageId: string, conversationId: string, endpoint?: string): Promise<Record<string, unknown>>;
41
41
  editMessage(messageId: string, newText: string, endpointTemplate?: string): Promise<void>;
42
42
  deleteMessage(messageId: string, endpointTemplate?: string): Promise<void>;
43
- addReaction(messageId: string, emoji: string, endpointTemplate?: string): Promise<void>;
44
- removeReaction(messageId: string, emoji: string, endpointTemplate?: string): Promise<void>;
45
43
  postFormData(url: string, formData: FormData, signal?: AbortSignal): Promise<unknown>;
46
44
  setHeader(name: string, value: string): void;
47
45
  removeHeader(name: string): void;
@@ -287,8 +285,6 @@ interface WebChatClientConfig {
287
285
  loadMessages?: string;
288
286
  editMessage?: string;
289
287
  deleteMessage?: string;
290
- addReaction?: string;
291
- removeReaction?: string;
292
288
  };
293
289
  features?: {
294
290
  editMessages?: boolean;
@@ -325,6 +321,8 @@ declare class WebChatClient {
325
321
  private streamingMessages;
326
322
  private pendingTyping;
327
323
  private subscribers;
324
+ private sendQueue;
325
+ private isProcessingQueue;
328
326
  private unsubscribeUserChannel?;
329
327
  constructor(config: WebChatClientConfig);
330
328
  reconfigure(config: ReconfigureConfig): void;
@@ -334,6 +332,8 @@ declare class WebChatClient {
334
332
  disconnect(): void;
335
333
  loadMessages(options?: LoadMessagesOptions, signal?: AbortSignal): Promise<LoadMessagesResult>;
336
334
  sendMessage(text: string, attachments?: AttachmentInput[]): Promise<void>;
335
+ private processQueue;
336
+ private executeSend;
337
337
  sendAction(messageId: string, actionId: string, value: string): Promise<void>;
338
338
  editMessage(messageId: string, newText: string): Promise<void>;
339
339
  deleteMessage(messageId: string): Promise<void>;
package/dist/index.d.ts CHANGED
@@ -40,8 +40,6 @@ declare class HttpClient {
40
40
  sendAction(actionId: string, value: string, messageId: string, conversationId: string, endpoint?: string): Promise<Record<string, unknown>>;
41
41
  editMessage(messageId: string, newText: string, endpointTemplate?: string): Promise<void>;
42
42
  deleteMessage(messageId: string, endpointTemplate?: string): Promise<void>;
43
- addReaction(messageId: string, emoji: string, endpointTemplate?: string): Promise<void>;
44
- removeReaction(messageId: string, emoji: string, endpointTemplate?: string): Promise<void>;
45
43
  postFormData(url: string, formData: FormData, signal?: AbortSignal): Promise<unknown>;
46
44
  setHeader(name: string, value: string): void;
47
45
  removeHeader(name: string): void;
@@ -287,8 +285,6 @@ interface WebChatClientConfig {
287
285
  loadMessages?: string;
288
286
  editMessage?: string;
289
287
  deleteMessage?: string;
290
- addReaction?: string;
291
- removeReaction?: string;
292
288
  };
293
289
  features?: {
294
290
  editMessages?: boolean;
@@ -325,6 +321,8 @@ declare class WebChatClient {
325
321
  private streamingMessages;
326
322
  private pendingTyping;
327
323
  private subscribers;
324
+ private sendQueue;
325
+ private isProcessingQueue;
328
326
  private unsubscribeUserChannel?;
329
327
  constructor(config: WebChatClientConfig);
330
328
  reconfigure(config: ReconfigureConfig): void;
@@ -334,6 +332,8 @@ declare class WebChatClient {
334
332
  disconnect(): void;
335
333
  loadMessages(options?: LoadMessagesOptions, signal?: AbortSignal): Promise<LoadMessagesResult>;
336
334
  sendMessage(text: string, attachments?: AttachmentInput[]): Promise<void>;
335
+ private processQueue;
336
+ private executeSend;
337
337
  sendAction(messageId: string, actionId: string, value: string): Promise<void>;
338
338
  editMessage(messageId: string, newText: string): Promise<void>;
339
339
  deleteMessage(messageId: string): Promise<void>;
package/dist/index.js CHANGED
@@ -77,14 +77,6 @@ var HttpClient = class {
77
77
  const url = this.expandTemplate(endpointTemplate, { id: messageId });
78
78
  await this.delete(url);
79
79
  }
80
- async addReaction(messageId, emoji, endpointTemplate = "/api/chat/messages/{id}/reactions") {
81
- const url = this.expandTemplate(endpointTemplate, { id: messageId });
82
- await this.post(url, { emoji });
83
- }
84
- async removeReaction(messageId, emoji, endpointTemplate = "/api/chat/messages/{id}/reactions/{emoji}") {
85
- const url = this.expandTemplate(endpointTemplate, { id: messageId, emoji });
86
- await this.delete(url);
87
- }
88
80
  async postFormData(url, formData, signal) {
89
81
  const controller = new AbortController();
90
82
  const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
@@ -295,6 +287,8 @@ var WebChatClient = class {
295
287
  this.streamingMessages = /* @__PURE__ */ new Map();
296
288
  this.pendingTyping = null;
297
289
  this.subscribers = /* @__PURE__ */ new Map();
290
+ this.sendQueue = [];
291
+ this.isProcessingQueue = false;
298
292
  this.config = config;
299
293
  this.httpClient = new HttpClient({
300
294
  apiUrl: config.apiUrl,
@@ -423,6 +417,31 @@ var WebChatClient = class {
423
417
  };
424
418
  }
425
419
  async sendMessage(text, attachments = []) {
420
+ return new Promise((resolve, reject) => {
421
+ this.sendQueue.push(async () => {
422
+ try {
423
+ await this.executeSend(text, attachments);
424
+ resolve();
425
+ } catch (e) {
426
+ reject(e);
427
+ }
428
+ });
429
+ this.processQueue();
430
+ });
431
+ }
432
+ async processQueue() {
433
+ if (this.isProcessingQueue) return;
434
+ this.isProcessingQueue = true;
435
+ try {
436
+ while (this.sendQueue.length > 0) {
437
+ const task = this.sendQueue.shift();
438
+ await task();
439
+ }
440
+ } finally {
441
+ this.isProcessingQueue = false;
442
+ }
443
+ }
444
+ async executeSend(text, attachments = []) {
426
445
  const messageId = generateId();
427
446
  const userMessage = {
428
447
  id: messageId,
@@ -518,15 +537,39 @@ var WebChatClient = class {
518
537
  if (!this.config.features?.reactions) {
519
538
  throw new Error("Reactions not enabled. Set features.reactions = true in config.");
520
539
  }
521
- const endpoint = this.config.endpoints?.addReaction ?? "/api/chat/messages/{id}/reactions";
522
- await this.httpClient.addReaction(messageId, emoji, endpoint);
540
+ this.handleReactionAdded(
541
+ new ReactionAddedEvent(this.getThreadId(), messageId, emoji, { id: this.currentUserId })
542
+ );
543
+ const endpoint = this.config.endpoints?.sendMessage ?? "/api/webhooks/web";
544
+ const response = await this.httpClient.post(endpoint, {
545
+ id: this.conversationId,
546
+ reaction: { messageId, emoji, added: true }
547
+ });
548
+ if (response.events) {
549
+ response.events.forEach((eventData) => {
550
+ const event = parseChatEvent(eventData);
551
+ this.dispatchEvent(event);
552
+ });
553
+ }
523
554
  }
524
555
  async removeReaction(messageId, emoji) {
525
556
  if (!this.config.features?.reactions) {
526
557
  throw new Error("Reactions not enabled. Set features.reactions = true in config.");
527
558
  }
528
- const endpoint = this.config.endpoints?.removeReaction ?? "/api/chat/messages/{id}/reactions/{emoji}";
529
- await this.httpClient.removeReaction(messageId, emoji, endpoint);
559
+ this.handleReactionRemoved(
560
+ new ReactionRemovedEvent(this.getThreadId(), messageId, emoji, { id: this.currentUserId })
561
+ );
562
+ const endpoint = this.config.endpoints?.sendMessage ?? "/api/webhooks/web";
563
+ const response = await this.httpClient.post(endpoint, {
564
+ id: this.conversationId,
565
+ reaction: { messageId, emoji, added: false }
566
+ });
567
+ if (response.events) {
568
+ response.events.forEach((eventData) => {
569
+ const event = parseChatEvent(eventData);
570
+ this.dispatchEvent(event);
571
+ });
572
+ }
530
573
  }
531
574
  onMessagePosted(handler) {
532
575
  return this.addEventListener("message.posted", handler);
@@ -619,26 +662,28 @@ var WebChatClient = class {
619
662
  }
620
663
  handleReactionAdded(event) {
621
664
  const message = this.messages.find((m) => m.id === event.messageId);
622
- if (!message) return;
623
- if (!message.reactions) message.reactions = [];
624
- const existing = message.reactions.find((r) => r.emoji === event.emoji);
625
- if (existing) {
626
- existing.count++;
627
- existing.users.push(event.user.id);
628
- } else {
629
- message.reactions.push({ emoji: event.emoji, count: 1, users: [event.user.id] });
665
+ if (message) {
666
+ if (!message.reactions) message.reactions = [];
667
+ const existing = message.reactions.find((r) => r.emoji === event.emoji);
668
+ if (existing) {
669
+ existing.count++;
670
+ existing.users.push(event.user.id);
671
+ } else {
672
+ message.reactions.push({ emoji: event.emoji, count: 1, users: [event.user.id] });
673
+ }
630
674
  }
631
675
  this.notifySubscribers("reaction:added", event);
632
676
  }
633
677
  handleReactionRemoved(event) {
634
678
  const message = this.messages.find((m) => m.id === event.messageId);
635
- if (!message?.reactions) return;
636
- const index = message.reactions.findIndex((r) => r.emoji === event.emoji);
637
- if (index !== -1) {
638
- const reaction = message.reactions[index];
639
- reaction.count--;
640
- reaction.users = reaction.users.filter((id) => id !== event.user.id);
641
- if (reaction.count === 0) message.reactions.splice(index, 1);
679
+ if (message?.reactions) {
680
+ const index = message.reactions.findIndex((r) => r.emoji === event.emoji);
681
+ if (index !== -1) {
682
+ const reaction = message.reactions[index];
683
+ reaction.count--;
684
+ reaction.users = reaction.users.filter((id) => id !== event.user.id);
685
+ if (reaction.count === 0) message.reactions.splice(index, 1);
686
+ }
642
687
  }
643
688
  this.notifySubscribers("reaction:removed", event);
644
689
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client/HttpClient.ts","../src/events/base/ChatEvent.ts","../src/events/MessagePostedEvent.ts","../src/events/MessageEditedEvent.ts","../src/events/MessageDeletedEvent.ts","../src/events/ReactionAddedEvent.ts","../src/events/ReactionRemovedEvent.ts","../src/events/TypingStartedEvent.ts","../src/events/StreamingChunkEvent.ts","../src/events/DMRequestedEvent.ts","../src/events/ChatEventFactory.ts","../src/utils/eventIdGenerator.ts","../src/client/WebChatClient.ts","../src/client/PusherBroadcastClient.ts","../src/client/LaravelEchoBroadcastClient.ts","../src/push/PushManager.ts","../src/push/PushSubscriptionManager.ts"],"sourcesContent":["export interface HttpClientConfig {\n apiUrl: string;\n headers?: Record<string, string>;\n timeout?: number;\n verifyToken?: string;\n}\n\nexport interface ChatResponse {\n id: string;\n role: \"assistant\" | \"user\";\n text: string;\n attachments?: Array<{\n type: string;\n url: string;\n name?: string;\n mime_type?: string;\n size?: number;\n }>;\n events?: Array<Record<string, unknown>>;\n}\n\nexport class HttpClient {\n private config: Required<Pick<HttpClientConfig, \"apiUrl\" | \"timeout\">> & {\n headers: Record<string, string>;\n };\n\n constructor(config: HttpClientConfig) {\n const headers: Record<string, string> = { ...config.headers };\n if (config.verifyToken) {\n headers[\"X-Verify-Token\"] = config.verifyToken;\n }\n this.config = { apiUrl: config.apiUrl, timeout: config.timeout ?? 30000, headers };\n }\n\n async get(url: string, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"GET\",\n headers: this.config.headers,\n signal: combined,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async post(url: string, body: unknown, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...this.config.headers },\n signal: combined,\n body: JSON.stringify(body),\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async delete(url: string, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"DELETE\",\n headers: this.config.headers,\n signal: combined,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n const text = await response.text();\n return text ? JSON.parse(text) : undefined;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async sendMessage(\n messages: Array<{\n id: string;\n role: string;\n text: string;\n attachments?: Array<{ url: string; name?: string; mime_type?: string; size?: number }>;\n }>,\n endpoint: string = \"/api/webhooks/web\",\n conversationId?: string,\n ): Promise<ChatResponse> {\n return this.post(endpoint, { id: conversationId, messages }) as Promise<ChatResponse>;\n }\n\n async sendAction(\n actionId: string,\n value: string,\n messageId: string,\n conversationId: string,\n endpoint: string = \"/api/webhooks/web\",\n ): Promise<Record<string, unknown>> {\n return this.post(endpoint, {\n id: conversationId,\n action: { actionId, value, messageId },\n }) as Promise<Record<string, unknown>>;\n }\n\n async editMessage(\n messageId: string,\n newText: string,\n endpointTemplate: string = \"/api/chat/messages/{id}/edit\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.post(url, { text: newText });\n }\n\n async deleteMessage(\n messageId: string,\n endpointTemplate: string = \"/api/chat/messages/{id}\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.delete(url);\n }\n\n async addReaction(\n messageId: string,\n emoji: string,\n endpointTemplate: string = \"/api/chat/messages/{id}/reactions\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.post(url, { emoji });\n }\n\n async removeReaction(\n messageId: string,\n emoji: string,\n endpointTemplate: string = \"/api/chat/messages/{id}/reactions/{emoji}\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId, emoji });\n await this.delete(url);\n }\n\n async postFormData(url: string, formData: FormData, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"POST\",\n headers: this.config.headers,\n signal: combined,\n body: formData,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n setHeader(name: string, value: string): void {\n this.config.headers[name] = value;\n }\n\n removeHeader(name: string): void {\n delete this.config.headers[name];\n }\n\n private resolve(url: string): string {\n return /^https?:\\/\\//.test(url) ? url : `${this.config.apiUrl}${url}`;\n }\n\n private expandTemplate(template: string, params: Record<string, string>): string {\n let url = template;\n for (const [key, value] of Object.entries(params)) {\n url = url.replace(`{${key}}`, encodeURIComponent(value));\n }\n return this.resolve(url);\n }\n}\n","export abstract class ChatEvent {\n readonly type: string;\n readonly threadId: string;\n readonly timestamp: number;\n\n constructor(type: string, threadId: string, timestamp: number) {\n this.type = type;\n this.threadId = threadId;\n this.timestamp = timestamp;\n }\n\n static fromJSON: ((json: Record<string, unknown>) => ChatEvent) | undefined;\n}\n\nexport class UnknownEvent extends ChatEvent {\n readonly data: Record<string, unknown>;\n\n constructor(type: string, threadId: string, data: Record<string, unknown>, timestamp: number) {\n super(type, threadId, timestamp);\n this.data = data;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User, Card } from \"../types\";\n\nexport class MessagePostedEvent extends ChatEvent {\n readonly messageId: string;\n readonly text: string;\n readonly author: User;\n readonly card?: Card;\n readonly attachments?: Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>;\n\n constructor(\n threadId: string,\n messageId: string,\n text: string,\n author: User,\n card?: Card,\n attachments?: Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>,\n timestamp?: number,\n ) {\n super(\"message.posted\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.text = text;\n this.author = author;\n this.card = card;\n this.attachments = attachments;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { Card } from \"../types\";\n\nexport class MessageEditedEvent extends ChatEvent {\n readonly messageId: string;\n readonly newText: string;\n readonly card?: Card;\n\n constructor(\n threadId: string,\n messageId: string,\n newText: string,\n card?: Card,\n timestamp?: number,\n ) {\n super(\"message.edited\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.newText = newText;\n this.card = card;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class MessageDeletedEvent extends ChatEvent {\n readonly messageId: string;\n\n constructor(threadId: string, messageId: string, timestamp?: number) {\n super(\"message.deleted\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User } from \"../types\";\n\nexport class ReactionAddedEvent extends ChatEvent {\n readonly messageId: string;\n readonly emoji: string;\n readonly user: User;\n\n constructor(threadId: string, messageId: string, emoji: string, user: User, timestamp?: number) {\n super(\"reaction.added\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.emoji = emoji;\n this.user = user;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User } from \"../types\";\n\nexport class ReactionRemovedEvent extends ChatEvent {\n readonly messageId: string;\n readonly emoji: string;\n readonly user: User;\n\n constructor(threadId: string, messageId: string, emoji: string, user: User, timestamp?: number) {\n super(\"reaction.removed\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.emoji = emoji;\n this.user = user;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class TypingStartedEvent extends ChatEvent {\n readonly userId: string;\n\n constructor(threadId: string, userId: string, timestamp?: number) {\n super(\"typing.started\", threadId, timestamp ?? Date.now());\n this.userId = userId;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class StreamingChunkEvent extends ChatEvent {\n readonly messageId: string;\n readonly chunk: string;\n readonly isFinal: boolean;\n\n constructor(\n threadId: string,\n messageId: string,\n chunk: string,\n isFinal: boolean,\n timestamp?: number,\n ) {\n super(\"streaming.chunk\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.chunk = chunk;\n this.isFinal = isFinal;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class DMRequestedEvent extends ChatEvent {\n readonly userId: string;\n\n constructor(threadId: string, userId: string, timestamp?: number) {\n super(\"dm.requested\", threadId, timestamp ?? Date.now());\n this.userId = userId;\n }\n}\n","import { ChatEvent, UnknownEvent } from \"./base/ChatEvent\";\nimport type { Card, User } from \"../types\";\nimport { MessagePostedEvent } from \"./MessagePostedEvent\";\nimport { MessageEditedEvent } from \"./MessageEditedEvent\";\nimport { MessageDeletedEvent } from \"./MessageDeletedEvent\";\nimport { ReactionAddedEvent } from \"./ReactionAddedEvent\";\nimport { ReactionRemovedEvent } from \"./ReactionRemovedEvent\";\nimport { TypingStartedEvent } from \"./TypingStartedEvent\";\nimport { StreamingChunkEvent } from \"./StreamingChunkEvent\";\nimport { DMRequestedEvent } from \"./DMRequestedEvent\";\n\nfunction parseCard(value: unknown): Card | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const obj = value as Record<string, unknown>;\n if (typeof obj.type !== \"string\") return undefined;\n return obj as unknown as Card;\n}\n\nexport function parseChatEvent(json: Record<string, unknown>): ChatEvent {\n const type = json.type as string;\n const threadId = json.threadId as string;\n const timestamp = json.timestamp as number;\n const data = (json.data ?? {}) as Record<string, unknown>;\n\n switch (type) {\n case \"message.posted\":\n return new MessagePostedEvent(\n threadId,\n data.messageId as string,\n data.text as string,\n data.author as User,\n parseCard(data.card),\n data.attachments as Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>,\n timestamp,\n );\n case \"message.edited\":\n return new MessageEditedEvent(\n threadId,\n data.messageId as string,\n data.newText as string,\n parseCard(data.card),\n timestamp,\n );\n case \"message.deleted\":\n return new MessageDeletedEvent(threadId, data.messageId as string, timestamp);\n case \"reaction.added\":\n return new ReactionAddedEvent(\n threadId,\n data.messageId as string,\n data.emoji as string,\n data.user as User,\n timestamp,\n );\n case \"reaction.removed\":\n return new ReactionRemovedEvent(\n threadId,\n data.messageId as string,\n data.emoji as string,\n data.user as User,\n timestamp,\n );\n case \"typing.started\":\n return new TypingStartedEvent(threadId, data.userId as string, timestamp);\n case \"streaming.chunk\":\n return new StreamingChunkEvent(\n threadId,\n data.messageId as string,\n data.chunk as string,\n data.isFinal as boolean,\n timestamp,\n );\n case \"dm.requested\":\n return new DMRequestedEvent(threadId, data.userId as string, timestamp);\n default:\n return new UnknownEvent(type, threadId, data, timestamp);\n }\n}\n\n// Wire up the static method\nChatEvent.fromJSON = parseChatEvent;\n","export function generateId(): string {\n return `msg-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n\nexport function generateConversationId(): string {\n return `conv-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n","import { HttpClient } from \"./HttpClient\";\nimport type { BroadcastClient, EventHandlers, Unsubscribe } from \"./BroadcastClient\";\nimport type { Message } from \"../types\";\nimport { ChatEvent } from \"../events/base/ChatEvent\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type { MessagePostedEvent } from \"../events/MessagePostedEvent\";\nimport type { MessageEditedEvent } from \"../events/MessageEditedEvent\";\nimport type { MessageDeletedEvent } from \"../events/MessageDeletedEvent\";\nimport type { ReactionAddedEvent } from \"../events/ReactionAddedEvent\";\nimport type { ReactionRemovedEvent } from \"../events/ReactionRemovedEvent\";\nimport type { TypingStartedEvent } from \"../events/TypingStartedEvent\";\nimport type { StreamingChunkEvent } from \"../events/StreamingChunkEvent\";\nimport type { DMRequestedEvent } from \"../events/DMRequestedEvent\";\nimport { generateId, generateConversationId } from \"../utils/eventIdGenerator\";\n\nexport interface ReconfigureConfig {\n userId?: string;\n userName?: string;\n verifyToken?: string;\n conversationId?: string;\n headers?: Record<string, string>;\n}\n\nexport interface WebChatClientConfig {\n apiUrl: string;\n userId: string;\n userName: string;\n broadcastClient?: BroadcastClient;\n headers?: Record<string, string>;\n verifyToken?: string;\n conversationId?: string;\n endpoints?: {\n sendMessage?: string;\n loadMessages?: string;\n editMessage?: string;\n deleteMessage?: string;\n addReaction?: string;\n removeReaction?: string;\n };\n features?: {\n editMessages?: boolean;\n deleteMessages?: boolean;\n reactions?: boolean;\n };\n}\n\ninterface StreamingState {\n messageId: string;\n accumulatedText: string;\n isComplete: boolean;\n}\n\ninterface AttachmentInput {\n url: string;\n name?: string;\n mimeType?: string;\n size?: number;\n}\n\nexport interface LoadMessagesOptions {\n limit?: number;\n before?: number;\n after?: number;\n skipStateSeed?: boolean;\n}\n\nexport interface LoadMessagesResult {\n messages: Message[];\n hasMore: boolean;\n nextCursor?: number;\n prevCursor?: number;\n}\n\nexport class WebChatClient {\n private config: WebChatClientConfig;\n private httpClient: HttpClient;\n private broadcastClient?: BroadcastClient;\n private conversationId: string;\n private messages: Message[] = [];\n private currentUserId: string;\n private eventHandlers: EventHandlers = {};\n private streamingMessages: Map<string, StreamingState> = new Map();\n private pendingTyping: ReturnType<typeof setTimeout> | null = null;\n private subscribers: Map<string, Array<(event: unknown) => void>> = new Map();\n private unsubscribeUserChannel?: Unsubscribe;\n\n constructor(config: WebChatClientConfig) {\n this.config = config;\n this.httpClient = new HttpClient({\n apiUrl: config.apiUrl,\n headers: {\n \"X-User-Id\": config.userId,\n \"X-User-Name\": config.userName,\n ...(config.headers ?? {}),\n },\n verifyToken: config.verifyToken,\n });\n this.broadcastClient = config.broadcastClient;\n this.conversationId = config.conversationId ?? generateConversationId();\n this.currentUserId = config.userId;\n }\n\n reconfigure(config: ReconfigureConfig): void {\n if (config.userId) {\n this.currentUserId = config.userId;\n this.httpClient.setHeader(\"X-User-Id\", config.userId);\n }\n if (config.userName) {\n this.config = { ...this.config, userName: config.userName };\n this.httpClient.setHeader(\"X-User-Name\", config.userName);\n }\n if (config.verifyToken) {\n this.config = { ...this.config, verifyToken: config.verifyToken };\n this.httpClient.setHeader(\"X-Verify-Token\", config.verifyToken);\n }\n if (config.conversationId) {\n this.conversationId = config.conversationId;\n }\n if (config.headers) {\n Object.entries(config.headers).forEach(([key, value]) => {\n this.httpClient.setHeader(key, value);\n });\n }\n }\n\n setLocaleHeader(locale: string): void {\n this.httpClient.setHeader(\"X-Locale\", locale);\n this.httpClient.setHeader(\"X-Language\", locale.split(\"-\")[0] ?? locale);\n }\n\n setTimezoneHeader(timezone: string): void {\n this.httpClient.setHeader(\"X-Timezone\", timezone);\n }\n\n async connect(): Promise<void> {\n if (this.broadcastClient) {\n this.broadcastClient.connect();\n\n const threadId = this.getThreadId();\n const threadEvents: EventHandlers = {\n onMessagePosted: (event) => this.handleMessagePosted(event),\n };\n\n if (this.config.features?.editMessages) {\n threadEvents.onMessageEdited = (event) => this.handleMessageEdited(event);\n }\n if (this.config.features?.deleteMessages) {\n threadEvents.onMessageDeleted = (event) => this.handleMessageDeleted(event);\n }\n if (this.config.features?.reactions) {\n threadEvents.onReactionAdded = (event) => this.handleReactionAdded(event);\n threadEvents.onReactionRemoved = (event) => this.handleReactionRemoved(event);\n }\n\n threadEvents.onTypingStarted = (event) => this.handleTypingStarted(event);\n\n await this.broadcastClient.subscribe(threadId, threadEvents);\n\n this.unsubscribeUserChannel = await this.broadcastClient.subscribeToUser(\n threadId,\n this.currentUserId,\n {\n onStreamingChunk: (event) => this.handleStreamingChunk(event),\n onDMRequested: (event) => this.handleDMRequested(event),\n },\n );\n }\n }\n\n disconnect(): void {\n this.unsubscribeUserChannel?.();\n this.unsubscribeUserChannel = undefined;\n this.broadcastClient?.disconnect();\n this.streamingMessages.clear();\n }\n\n async loadMessages(\n options?: LoadMessagesOptions,\n signal?: AbortSignal,\n ): Promise<LoadMessagesResult> {\n const endpoint = this.config.endpoints?.loadMessages ?? \"/api/chat/messages\";\n const threadId = this.getThreadId();\n const params = new URLSearchParams({\n threadId,\n limit: String(options?.limit ?? 50),\n });\n if (options?.before) params.set(\"before\", String(options.before));\n if (options?.after) params.set(\"after\", String(options.after));\n\n const response = (await this.httpClient.get(\n `${endpoint}?${params.toString()}`,\n signal,\n )) as Record<string, unknown>;\n const rawMessages = (response.messages as Record<string, unknown>[]) ?? [];\n const messages: Message[] = rawMessages.map((msg) => ({\n id: msg.id as string,\n threadId,\n content: {\n text: msg.text as string,\n cards: msg.card ? ([msg.card as Record<string, unknown>] as never[]) : undefined,\n },\n author: {\n id: (msg.author as Record<string, unknown>).id as string,\n name: (msg.author as Record<string, unknown>).name as string,\n isBot: ((msg.author as Record<string, unknown>).isBot as boolean) ?? false,\n isMe: (msg.author as Record<string, unknown>).id === this.currentUserId,\n },\n timestamp: msg.timestamp as number,\n attachments: (msg.attachments as Record<string, unknown>[])?.map((a) => ({\n id: `att-${msg.id as string}-${a.url as string}`,\n url: a.url as string,\n name: a.name as string,\n type: a.type as string,\n mimeType: a.mime_type as string,\n size: a.size as number,\n })),\n reactions: (msg.reactions as { emoji: string; count: number; users: string[] }[]) ?? [],\n }));\n\n if (!options?.before && !options?.after && !options?.skipStateSeed) {\n this.messages = messages;\n this.notifySubscribers(\"messages:loaded\", messages);\n }\n\n return {\n messages,\n hasMore: (response.hasMore as boolean) ?? false,\n nextCursor: response.nextCursor as number | undefined,\n prevCursor: response.prevCursor as number | undefined,\n };\n }\n\n async sendMessage(text: string, attachments: AttachmentInput[] = []): Promise<void> {\n const messageId = generateId();\n\n const userMessage: Message = {\n id: messageId,\n threadId: this.getThreadId(),\n content: { text },\n author: { id: this.currentUserId, name: this.config.userName, isMe: true },\n timestamp: Date.now(),\n attachments:\n attachments.length > 0\n ? attachments.map((a, i) => ({\n id: `att-${messageId}-${i}`,\n name: a.name ?? \"\",\n url: a.url,\n size: a.size,\n mimeType: a.mimeType,\n }))\n : undefined,\n };\n\n this.messages.push(userMessage);\n this.notifySubscribers(\"message:added\", userMessage);\n\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = await this.httpClient.sendMessage(\n [\n {\n id: messageId,\n role: \"user\",\n text,\n attachments: attachments.map((a) => ({\n url: a.url,\n name: a.name,\n mime_type: a.mimeType,\n size: a.size,\n })),\n },\n ],\n endpoint,\n this.conversationId,\n );\n\n if (response.events) {\n response.events.forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n\n if (response.text && !response.events?.some((e) => e.type === \"message.posted\")) {\n const assistantMessage: Message = {\n id: response.id ?? generateId(),\n threadId: this.getThreadId(),\n content: { text: response.text },\n author: { id: \"assistant\", name: \"Assistant\", isBot: true },\n timestamp: Date.now(),\n attachments: (response.attachments as Record<string, unknown>[])?.map((a, i) => ({\n id: `att-${response.id ?? \"msg\"}-${i}`,\n name: (a.name as string) ?? \"\",\n url: (a.url as string) ?? \"\",\n type: a.type as string,\n mimeType: a.mime_type as string,\n size: a.size as number,\n })),\n };\n this.messages.push(assistantMessage);\n this.notifySubscribers(\"message:added\", assistantMessage);\n }\n }\n\n async sendAction(messageId: string, actionId: string, value: string): Promise<void> {\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = await this.httpClient.sendAction(\n actionId,\n value,\n messageId,\n this.conversationId,\n endpoint,\n );\n\n if (response.events) {\n (response.events as Array<Record<string, unknown>>).forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n }\n\n async editMessage(messageId: string, newText: string): Promise<void> {\n if (!this.config.features?.editMessages) {\n throw new Error(\"Edit messages not enabled. Set features.editMessages = true in config.\");\n }\n const endpoint = this.config.endpoints?.editMessage ?? \"/api/chat/messages/{id}/edit\";\n await this.httpClient.editMessage(messageId, newText, endpoint);\n }\n\n async deleteMessage(messageId: string): Promise<void> {\n if (!this.config.features?.deleteMessages) {\n throw new Error(\"Delete messages not enabled. Set features.deleteMessages = true in config.\");\n }\n const endpoint = this.config.endpoints?.deleteMessage ?? \"/api/chat/messages/{id}\";\n await this.httpClient.deleteMessage(messageId, endpoint);\n }\n\n async addReaction(messageId: string, emoji: string): Promise<void> {\n if (!this.config.features?.reactions) {\n throw new Error(\"Reactions not enabled. Set features.reactions = true in config.\");\n }\n const endpoint = this.config.endpoints?.addReaction ?? \"/api/chat/messages/{id}/reactions\";\n await this.httpClient.addReaction(messageId, emoji, endpoint);\n }\n\n async removeReaction(messageId: string, emoji: string): Promise<void> {\n if (!this.config.features?.reactions) {\n throw new Error(\"Reactions not enabled. Set features.reactions = true in config.\");\n }\n const endpoint =\n this.config.endpoints?.removeReaction ?? \"/api/chat/messages/{id}/reactions/{emoji}\";\n await this.httpClient.removeReaction(messageId, emoji, endpoint);\n }\n\n onMessagePosted(handler: (event: MessagePostedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message.posted\", handler);\n }\n\n onMessageEdited(handler: (event: MessageEditedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message:edited\", handler);\n }\n\n onMessageDeleted(handler: (event: MessageDeletedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message:deleted\", handler);\n }\n\n onReactionAdded(handler: (event: ReactionAddedEvent) => void): Unsubscribe {\n return this.addEventListener(\"reaction:added\", handler);\n }\n\n onReactionRemoved(handler: (event: ReactionRemovedEvent) => void): Unsubscribe {\n return this.addEventListener(\"reaction:removed\", handler);\n }\n\n onStreamingChunk(handler: (event: StreamingChunkEvent) => void): Unsubscribe {\n return this.addEventListener(\"streaming:chunk\", handler);\n }\n\n onTypingStarted(handler: (event: TypingStartedEvent) => void): Unsubscribe {\n return this.addEventListener(\"typing:started\", handler);\n }\n\n getConversationId(): string {\n return this.conversationId;\n }\n getMessages(): Message[] {\n return [...this.messages];\n }\n getThreadId(): string {\n return `web:${this.currentUserId}:${this.conversationId}`;\n }\n getCurrentUserId(): string {\n return this.currentUserId;\n }\n getFeatures(): NonNullable<WebChatClientConfig[\"features\"]> {\n return this.config.features ?? {};\n }\n getEndpoints(): NonNullable<WebChatClientConfig[\"endpoints\"]> {\n return this.config.endpoints ?? {};\n }\n getHttpClient(): HttpClient {\n return this.httpClient;\n }\n\n addEventListener<T = unknown>(eventType: string, handler: (event: T) => void): Unsubscribe {\n if (!this.subscribers.has(eventType)) this.subscribers.set(eventType, []);\n this.subscribers.get(eventType)!.push(handler as (event: unknown) => void);\n return () => {\n const handlers = this.subscribers.get(eventType);\n if (handlers) {\n const index = handlers.indexOf(handler as (event: unknown) => void);\n if (index !== -1) handlers.splice(index, 1);\n }\n };\n }\n\n private handleMessagePosted(event: MessagePostedEvent): void {\n if (this.messages.some((m) => m.id === event.messageId)) return;\n if (this.streamingMessages.has(event.messageId)) return;\n\n const message: Message = {\n id: event.messageId,\n threadId: event.threadId,\n content: { text: event.text, cards: event.card ? [event.card] : undefined },\n author: event.author,\n timestamp: event.timestamp,\n attachments: event.attachments?.map((a) => ({\n id: `att-${event.messageId}-${Math.random().toString(36).slice(2, 8)}`,\n name: a.name ?? \"\",\n url: a.url ?? \"\",\n type: a.type,\n mimeType: a.mimeType,\n size: a.size ?? undefined,\n })),\n };\n this.messages.push(message);\n this.notifySubscribers(\"message:added\", message);\n this.notifySubscribers(\"message.posted\", event);\n }\n\n private handleMessageEdited(event: MessageEditedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (message?.content) {\n message.content.text = event.newText;\n this.notifySubscribers(\"message:edited\", event);\n }\n }\n\n private handleMessageDeleted(event: MessageDeletedEvent): void {\n const index = this.messages.findIndex((m) => m.id === event.messageId);\n if (index !== -1) {\n this.messages.splice(index, 1);\n this.notifySubscribers(\"message:deleted\", event);\n }\n }\n\n private handleReactionAdded(event: ReactionAddedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (!message) return;\n if (!message.reactions) message.reactions = [];\n\n const existing = message.reactions.find((r) => r.emoji === event.emoji);\n if (existing) {\n existing.count++;\n existing.users.push(event.user.id);\n } else {\n message.reactions.push({ emoji: event.emoji, count: 1, users: [event.user.id] });\n }\n this.notifySubscribers(\"reaction:added\", event);\n }\n\n private handleReactionRemoved(event: ReactionRemovedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (!message?.reactions) return;\n\n const index = message.reactions.findIndex((r) => r.emoji === event.emoji);\n if (index !== -1) {\n const reaction = message.reactions[index]!;\n reaction.count--;\n reaction.users = reaction.users.filter((id) => id !== event.user.id);\n if (reaction.count === 0) message.reactions.splice(index, 1);\n }\n this.notifySubscribers(\"reaction:removed\", event);\n }\n\n private handleStreamingChunk(event: StreamingChunkEvent): void {\n const { messageId, chunk, isFinal } = event;\n\n if (!this.streamingMessages.has(messageId)) {\n this.streamingMessages.set(messageId, { messageId, accumulatedText: \"\", isComplete: false });\n this.notifySubscribers(\"streaming:started\", event);\n }\n\n const state = this.streamingMessages.get(messageId)!;\n state.accumulatedText += chunk;\n\n if (isFinal) {\n state.isComplete = true;\n if (!this.messages.some((m) => m.id === messageId)) {\n const message: Message = {\n id: messageId,\n threadId: event.threadId,\n content: { text: state.accumulatedText },\n author: { id: \"assistant\", name: \"Assistant\", isBot: true },\n timestamp: event.timestamp,\n };\n this.messages.push(message);\n this.notifySubscribers(\"message:added\", message);\n }\n this.streamingMessages.delete(messageId);\n this.notifySubscribers(\"streaming:complete\", { messageId, text: state.accumulatedText });\n } else {\n this.notifySubscribers(\"streaming:chunk\", event);\n }\n }\n\n private handleTypingStarted(event: TypingStartedEvent): void {\n if (this.pendingTyping) clearTimeout(this.pendingTyping);\n this.notifySubscribers(\"typing:started\", event);\n this.pendingTyping = setTimeout(() => {\n this.notifySubscribers(\"typing:stopped\", { userId: event.userId });\n }, 3000);\n }\n\n private handleDMRequested(event: DMRequestedEvent): void {\n this.notifySubscribers(\"dm.requested\", event);\n }\n\n private notifySubscribers<T>(eventType: string, data: T): void {\n this.subscribers.get(eventType)?.forEach((handler) => handler(data));\n }\n\n private dispatchEvent(event: ChatEvent): void {\n switch (event.type) {\n case \"message.posted\":\n this.handleMessagePosted(event as MessagePostedEvent);\n break;\n case \"message.edited\":\n this.handleMessageEdited(event as MessageEditedEvent);\n break;\n case \"message.deleted\":\n this.handleMessageDeleted(event as MessageDeletedEvent);\n break;\n case \"reaction.added\":\n this.handleReactionAdded(event as ReactionAddedEvent);\n break;\n case \"reaction.removed\":\n this.handleReactionRemoved(event as ReactionRemovedEvent);\n break;\n case \"typing.started\":\n this.handleTypingStarted(event as TypingStartedEvent);\n break;\n case \"streaming.chunk\":\n this.handleStreamingChunk(event as StreamingChunkEvent);\n break;\n case \"dm.requested\":\n this.handleDMRequested(event as DMRequestedEvent);\n break;\n }\n }\n}\n","import {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./BroadcastClient\";\nimport { ChatEvent } from \"../events/base/ChatEvent\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type Pusher from \"pusher-js\";\nimport type { Channel as PusherChannel } from \"pusher-js\";\n\nexport interface PusherConfig {\n key: string;\n cluster?: string;\n host?: string;\n port?: number;\n forceTLS?: boolean;\n authEndpoint?: string;\n}\n\nexport class PusherBroadcastClient implements BroadcastClient {\n private pusher: Pusher;\n private channelPrefix: string;\n private threadChannelType: \"public\" | \"private\" | \"presence\";\n private userChannelType: \"private\" | \"presence\";\n private useHashChannel: boolean;\n private subscriptions: Map<string, PusherChannel> = new Map();\n\n constructor(pusher: Pusher, channelPrefix?: string, channelTypes?: ChannelTypeConfig);\n constructor(config: PusherConfig, channelPrefix?: string, channelTypes?: ChannelTypeConfig);\n constructor(\n pusherOrConfig: Pusher | PusherConfig,\n channelPrefix: string = \"chat\",\n channelTypes?: ChannelTypeConfig,\n ) {\n this.channelPrefix = channelPrefix;\n this.threadChannelType = channelTypes?.threadChannel ?? \"public\";\n this.userChannelType = channelTypes?.userChannel ?? \"private\";\n this.useHashChannel = channelTypes?.useHashChannel ?? false;\n\n if (\"key\" in pusherOrConfig) {\n const PusherCtor = (globalThis as any).Pusher ?? (globalThis as any).pusherJs;\n if (!PusherCtor) {\n throw new Error(\"pusher-js not found. Install it or pass a Pusher instance.\");\n }\n this.pusher = new PusherCtor((pusherOrConfig as PusherConfig).key, pusherOrConfig) as Pusher;\n } else {\n this.pusher = pusherOrConfig as Pusher;\n }\n }\n\n private buildChannelName(base: string, type: \"public\" | \"private\" | \"presence\"): string {\n switch (type) {\n case \"private\":\n return `private-${base}`;\n case \"presence\":\n return `presence-${base}`;\n default:\n return base;\n }\n }\n\n protected async buildResolvedChannelName(threadId: string): Promise<string> {\n const name = this.useHashChannel ? await this.hashChannelName(threadId) : threadId;\n\n return `${this.channelPrefix}.${name}`;\n }\n\n private async hashChannelName(name: string): Promise<string> {\n if (typeof crypto?.subtle?.digest !== \"function\") {\n throw new Error(\"Web Crypto API not available. Cannot hash channel names.\");\n }\n const encoder = new TextEncoder();\n const data = encoder.encode(name);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n connect(): void {\n if (this.pusher.connection?.state !== \"connected\") {\n this.pusher.connect();\n }\n }\n\n disconnect(): void {\n this.subscriptions.forEach((channel) => channel.unbind_all?.() ?? channel.unsubscribe?.());\n this.subscriptions.clear();\n this.pusher.disconnect?.();\n }\n\n async subscribe(threadId: string, handlers: EventHandlers): Promise<Unsubscribe> {\n const baseName = await this.buildResolvedChannelName(threadId);\n const channelName = this.buildChannelName(baseName, this.threadChannelType);\n const channel = this.pusher.subscribe(channelName);\n const key = `thread:${threadId}`;\n this.subscriptions.set(key, channel);\n\n const threadEvents = [\n \"message.posted\",\n \"message.edited\",\n \"message.deleted\",\n \"reaction.added\",\n \"reaction.removed\",\n \"typing.started\",\n ] as const;\n\n threadEvents.forEach((eventType) => {\n const eventName = `${this.channelPrefix}.${eventType}`;\n channel.bind(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n this.dispatchToHandler(event, handlers);\n });\n });\n\n return () => {\n channel.unbind_all?.();\n this.pusher.unsubscribe(channelName);\n this.subscriptions.delete(key);\n };\n }\n\n async subscribeToUser(\n threadId: string,\n userId: string,\n handlers: EventHandlers,\n ): Promise<Unsubscribe> {\n const baseName = `${await this.buildResolvedChannelName(threadId)}.${userId}`;\n const channelName = this.buildChannelName(baseName, this.userChannelType);\n const channel = this.pusher.subscribe(channelName);\n const key = `user:${threadId}:${userId}`;\n this.subscriptions.set(key, channel);\n\n const userEvents = [\"typing.started\", \"streaming.chunk\", \"dm.requested\"] as const;\n\n userEvents.forEach((eventType) => {\n const eventName = `${this.channelPrefix}.${eventType}`;\n channel.bind(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n this.dispatchToHandler(event, handlers);\n });\n });\n\n return () => {\n channel.unbind_all?.();\n this.pusher.unsubscribe(channelName);\n this.subscriptions.delete(key);\n };\n }\n\n isConnected(): boolean {\n return this.pusher.connection?.state === \"connected\";\n }\n\n private dispatchToHandler(event: ChatEvent, handlers: EventHandlers): void {\n switch (event.type) {\n case \"message.posted\":\n handlers.onMessagePosted?.(event as any);\n break;\n case \"message.edited\":\n handlers.onMessageEdited?.(event as any);\n break;\n case \"message.deleted\":\n handlers.onMessageDeleted?.(event as any);\n break;\n case \"reaction.added\":\n handlers.onReactionAdded?.(event as any);\n break;\n case \"reaction.removed\":\n handlers.onReactionRemoved?.(event as any);\n break;\n case \"typing.started\":\n handlers.onTypingStarted?.(event as any);\n break;\n case \"streaming.chunk\":\n handlers.onStreamingChunk?.(event as any);\n break;\n case \"dm.requested\":\n handlers.onDMRequested?.(event as any);\n break;\n }\n }\n}\n","import {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./BroadcastClient\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type Echo from \"laravel-echo\";\n\ninterface EchoChannel {\n listen(event: string, callback: (data: unknown) => void): this;\n unsubscribe(): void;\n stopListening(event?: string, callback?: (data: unknown) => void): this;\n}\n\nexport class LaravelEchoBroadcastClient implements BroadcastClient {\n private echo: Echo<any>;\n private channelPrefix: string;\n private threadChannelType: \"public\" | \"private\" | \"presence\";\n private userChannelType: \"private\" | \"presence\";\n private useHashChannel: boolean;\n private subscriptions: Map<string, EchoChannel> = new Map();\n\n constructor(echo: Echo<any>, channelPrefix: string = \"chat\", channelTypes?: ChannelTypeConfig) {\n this.echo = echo;\n this.channelPrefix = channelPrefix;\n this.threadChannelType = channelTypes?.threadChannel ?? \"public\";\n this.userChannelType = channelTypes?.userChannel ?? \"private\";\n this.useHashChannel = channelTypes?.useHashChannel ?? false;\n }\n\n private subscribeToEcho(name: string, type: \"public\" | \"private\" | \"presence\"): EchoChannel {\n switch (type) {\n case \"private\":\n return this.echo.private(name) as unknown as EchoChannel;\n case \"presence\":\n return this.echo.join(name) as unknown as EchoChannel;\n default:\n return this.echo.channel(name) as unknown as EchoChannel;\n }\n }\n\n connect(): void | Promise<void> {\n return Promise.resolve();\n }\n\n disconnect(): void {\n this.subscriptions.forEach((channel) => {\n channel.unsubscribe?.();\n channel.stopListening?.();\n });\n this.subscriptions.clear();\n }\n\n protected async buildResolvedChannelName(threadId: string): Promise<string> {\n const name = this.useHashChannel ? await this.hashChannelName(threadId) : threadId;\n\n return `${this.channelPrefix}.${name}`;\n }\n\n private async hashChannelName(name: string): Promise<string> {\n if (typeof crypto?.subtle?.digest !== \"function\") {\n throw new Error(\"Web Crypto API not available. Cannot hash channel names.\");\n }\n const encoder = new TextEncoder();\n const data = encoder.encode(name);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n async subscribe(threadId: string, handlers: EventHandlers): Promise<Unsubscribe> {\n const channelName = await this.buildResolvedChannelName(threadId);\n const channel = this.subscribeToEcho(channelName, this.threadChannelType);\n const key = `thread:${threadId}`;\n this.subscriptions.set(key, channel);\n\n const threadEvents: Array<{ type: string; handler: keyof EventHandlers }> = [\n { type: \"message.posted\", handler: \"onMessagePosted\" },\n { type: \"message.edited\", handler: \"onMessageEdited\" },\n { type: \"message.deleted\", handler: \"onMessageDeleted\" },\n { type: \"reaction.added\", handler: \"onReactionAdded\" },\n { type: \"reaction.removed\", handler: \"onReactionRemoved\" },\n { type: \"typing.started\", handler: \"onTypingStarted\" },\n ];\n\n threadEvents.forEach(({ type, handler }) => {\n const eventName = `.${this.channelPrefix}.${type}`;\n channel.listen(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n (handlers[handler] as any)?.(event);\n });\n });\n\n return () => {\n channel.unsubscribe?.();\n this.subscriptions.delete(key);\n };\n }\n\n async subscribeToUser(\n threadId: string,\n userId: string,\n handlers: EventHandlers,\n ): Promise<Unsubscribe> {\n const channelName = `${await this.buildResolvedChannelName(threadId)}.${userId}`;\n const channel = this.subscribeToEcho(channelName, this.userChannelType);\n const key = `user:${threadId}:${userId}`;\n this.subscriptions.set(key, channel);\n\n const userEvents: Array<{ type: string; handler: keyof EventHandlers }> = [\n { type: \"typing.started\", handler: \"onTypingStarted\" },\n { type: \"streaming.chunk\", handler: \"onStreamingChunk\" },\n { type: \"dm.requested\", handler: \"onDMRequested\" },\n ];\n\n userEvents.forEach(({ type, handler }) => {\n const eventName = `.${this.channelPrefix}.${type}`;\n channel.listen(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n (handlers[handler] as any)?.(event);\n });\n });\n\n return () => {\n channel.unsubscribe?.();\n this.subscriptions.delete(key);\n };\n }\n\n isConnected(): boolean {\n try {\n const connector = (this.echo as any).connector;\n if (!connector) return false;\n\n if (connector.pusher?.connection?.state === \"connected\") return true;\n if (connector.socket?.connected) return true;\n\n return false;\n } catch {\n return false;\n }\n }\n}\n","import type { PushConfig, PushSubscriptionStatus, PushEventData } from \"./types\";\n\nexport class PushManager {\n private config: PushConfig;\n private registration: ServiceWorkerRegistration | null = null;\n private status: PushSubscriptionStatus = \"unsupported\";\n private statusListeners: Set<(status: PushSubscriptionStatus) => void> = new Set();\n private messageListeners: Set<(data: PushEventData) => void> = new Set();\n\n constructor(config: PushConfig) {\n this.config = config;\n }\n\n static isSupported(): boolean {\n return (\n typeof navigator !== \"undefined\" &&\n \"serviceWorker\" in navigator &&\n \"PushManager\" in window &&\n \"Notification\" in window\n );\n }\n\n getStatus(): PushSubscriptionStatus {\n return this.status;\n }\n\n onStatusChange(listener: (status: PushSubscriptionStatus) => void): () => void {\n this.statusListeners.add(listener);\n return () => {\n this.statusListeners.delete(listener);\n };\n }\n\n onMessage(listener: (data: PushEventData) => void): () => void {\n this.messageListeners.add(listener);\n return () => {\n this.messageListeners.delete(listener);\n };\n }\n\n async initialize(): Promise<void> {\n if (!PushManager.isSupported()) {\n this.setStatus(\"unsupported\");\n return;\n }\n if (Notification.permission === \"denied\") {\n this.setStatus(\"denied\");\n return;\n }\n\n try {\n this.registration = await navigator.serviceWorker.register(\n this.config.serviceWorkerUrl || \"/chat-service-worker.js\",\n {\n scope: this.config.serviceWorkerScope || \"/\",\n type: this.config.serviceWorkerType,\n },\n );\n await navigator.serviceWorker.ready;\n\n navigator.serviceWorker.addEventListener(\"message\", (event: MessageEvent) => {\n const msg = event.data as Record<string, unknown>;\n if (msg?.type === \"chat-widget:push-data\") {\n const pushData = msg.data as PushEventData;\n this.messageListeners.forEach((listener) => listener(pushData));\n }\n });\n\n const subscription = await this.registration.pushManager.getSubscription();\n this.setStatus(subscription ? \"subscribed\" : \"default\");\n } catch {\n this.setStatus(\"error\");\n }\n }\n\n async subscribe(): Promise<void> {\n if (!this.registration)\n throw new Error(\"PushManager not initialized. Call initialize() first.\");\n\n this.setStatus(\"subscribing\");\n\n try {\n let subscription = await this.registration.pushManager.getSubscription();\n\n if (!subscription) {\n const permission = await Notification.requestPermission();\n if (permission !== \"granted\") {\n this.setStatus(permission === \"denied\" ? \"denied\" : \"default\");\n return;\n }\n\n const vapidPublicKey = await this.config.getVapidPublicKey();\n const convertedKey = this.urlBase64ToUint8Array(vapidPublicKey);\n subscription = await this.registration.pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: convertedKey.buffer as ArrayBuffer,\n });\n }\n\n await this.config.onSubscribe(subscription.toJSON());\n this.setStatus(\"subscribed\");\n } catch {\n this.setStatus(\"error\");\n throw new Error(\"Push subscription failed\");\n }\n }\n\n async unsubscribe(): Promise<void> {\n if (!this.registration) return;\n\n try {\n const subscription = await this.registration.pushManager.getSubscription();\n if (subscription) {\n await this.config.onUnsubscribe(subscription.toJSON());\n await subscription.unsubscribe();\n }\n this.setStatus(\"default\");\n } catch {\n this.setStatus(\"error\");\n throw new Error(\"Push unsubscription failed\");\n }\n }\n\n private urlBase64ToUint8Array(base64String: string): Uint8Array {\n const padding = \"=\".repeat((4 - (base64String.length % 4)) % 4);\n const base64 = (base64String + padding).replace(/-/g, \"+\").replace(/_/g, \"/\");\n const rawData = atob(base64);\n return Uint8Array.from([...rawData].map((char) => char.charCodeAt(0)));\n }\n\n private setStatus(status: PushSubscriptionStatus): void {\n this.status = status;\n this.statusListeners.forEach((listener) => listener(status));\n }\n}\n","import { HttpClient } from \"../client/HttpClient\";\nimport type { PushConfig } from \"./types\";\n\nexport function createPushSubscriptionHandlers(\n httpClient: HttpClient,\n userId: string,\n): Pick<PushConfig, \"onSubscribe\" | \"onUnsubscribe\"> {\n return {\n onSubscribe: async (subscription: PushSubscriptionJSON) => {\n await httpClient.post(\"/api/push/subscriptions\", {\n userId,\n subscription,\n userAgent: navigator.userAgent,\n });\n },\n onUnsubscribe: async (subscription: PushSubscriptionJSON) => {\n await httpClient.delete(\n `/api/push/subscriptions?userId=${encodeURIComponent(userId)}&endpoint=${encodeURIComponent(subscription.endpoint || \"\")}`,\n );\n },\n };\n}\n"],"mappings":";AAqBO,IAAM,aAAN,MAAiB;AAAA,EAKtB,YAAY,QAA0B;AACpC,UAAM,UAAkC,EAAE,GAAG,OAAO,QAAQ;AAC5D,QAAI,OAAO,aAAa;AACtB,cAAQ,gBAAgB,IAAI,OAAO;AAAA,IACrC;AACA,SAAK,SAAS,EAAE,QAAQ,OAAO,QAAQ,SAAS,OAAO,WAAW,KAAO,QAAQ;AAAA,EACnF;AAAA,EAEA,MAAM,IAAI,KAAa,QAAwC;AAC7D,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO,OAAO;AAE1E,QAAI;AACF,YAAM,UAAU,KAAK,QAAQ,GAAG;AAChC,YAAM,WAAW,SAAS,YAAY,IAAI,CAAC,WAAW,QAAQ,MAAM,CAAC,IAAI,WAAW;AACpF,YAAM,WAAW,MAAM,MAAM,SAAS;AAAA,QACpC,QAAQ;AAAA,QACR,SAAS,KAAK,OAAO;AAAA,QACrB,QAAQ;AAAA,MACV,CAAC;AACD,UAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,QAAQ,SAAS,MAAM,KAAK,SAAS,UAAU,EAAE;AACnF,aAAO,SAAS,KAAK;AAAA,IACvB,UAAE;AACA,mBAAa,SAAS;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,KAAa,MAAe,QAAwC;AAC7E,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO,OAAO;AAE1E,QAAI;AACF,YAAM,UAAU,KAAK,QAAQ,GAAG;AAChC,YAAM,WAAW,SAAS,YAAY,IAAI,CAAC,WAAW,QAAQ,MAAM,CAAC,IAAI,WAAW;AACpF,YAAM,WAAW,MAAM,MAAM,SAAS;AAAA,QACpC,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,oBAAoB,GAAG,KAAK,OAAO,QAAQ;AAAA,QACtE,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU,IAAI;AAAA,MAC3B,CAAC;AACD,UAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,QAAQ,SAAS,MAAM,KAAK,SAAS,UAAU,EAAE;AACnF,aAAO,SAAS,KAAK;AAAA,IACvB,UAAE;AACA,mBAAa,SAAS;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,MAAM,OAAO,KAAa,QAAwC;AAChE,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO,OAAO;AAE1E,QAAI;AACF,YAAM,UAAU,KAAK,QAAQ,GAAG;AAChC,YAAM,WAAW,SAAS,YAAY,IAAI,CAAC,WAAW,QAAQ,MAAM,CAAC,IAAI,WAAW;AACpF,YAAM,WAAW,MAAM,MAAM,SAAS;AAAA,QACpC,QAAQ;AAAA,QACR,SAAS,KAAK,OAAO;AAAA,QACrB,QAAQ;AAAA,MACV,CAAC;AACD,UAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,QAAQ,SAAS,MAAM,KAAK,SAAS,UAAU,EAAE;AACnF,YAAM,OAAO,MAAM,SAAS,KAAK;AACjC,aAAO,OAAO,KAAK,MAAM,IAAI,IAAI;AAAA,IACnC,UAAE;AACA,mBAAa,SAAS;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,MAAM,YACJ,UAMA,WAAmB,qBACnB,gBACuB;AACvB,WAAO,KAAK,KAAK,UAAU,EAAE,IAAI,gBAAgB,SAAS,CAAC;AAAA,EAC7D;AAAA,EAEA,MAAM,WACJ,UACA,OACA,WACA,gBACA,WAAmB,qBACe;AAClC,WAAO,KAAK,KAAK,UAAU;AAAA,MACzB,IAAI;AAAA,MACJ,QAAQ,EAAE,UAAU,OAAO,UAAU;AAAA,IACvC,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,YACJ,WACA,SACA,mBAA2B,gCACZ;AACf,UAAM,MAAM,KAAK,eAAe,kBAAkB,EAAE,IAAI,UAAU,CAAC;AACnE,UAAM,KAAK,KAAK,KAAK,EAAE,MAAM,QAAQ,CAAC;AAAA,EACxC;AAAA,EAEA,MAAM,cACJ,WACA,mBAA2B,2BACZ;AACf,UAAM,MAAM,KAAK,eAAe,kBAAkB,EAAE,IAAI,UAAU,CAAC;AACnE,UAAM,KAAK,OAAO,GAAG;AAAA,EACvB;AAAA,EAEA,MAAM,YACJ,WACA,OACA,mBAA2B,qCACZ;AACf,UAAM,MAAM,KAAK,eAAe,kBAAkB,EAAE,IAAI,UAAU,CAAC;AACnE,UAAM,KAAK,KAAK,KAAK,EAAE,MAAM,CAAC;AAAA,EAChC;AAAA,EAEA,MAAM,eACJ,WACA,OACA,mBAA2B,6CACZ;AACf,UAAM,MAAM,KAAK,eAAe,kBAAkB,EAAE,IAAI,WAAW,MAAM,CAAC;AAC1E,UAAM,KAAK,OAAO,GAAG;AAAA,EACvB;AAAA,EAEA,MAAM,aAAa,KAAa,UAAoB,QAAwC;AAC1F,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO,OAAO;AAE1E,QAAI;AACF,YAAM,UAAU,KAAK,QAAQ,GAAG;AAChC,YAAM,WAAW,SAAS,YAAY,IAAI,CAAC,WAAW,QAAQ,MAAM,CAAC,IAAI,WAAW;AACpF,YAAM,WAAW,MAAM,MAAM,SAAS;AAAA,QACpC,QAAQ;AAAA,QACR,SAAS,KAAK,OAAO;AAAA,QACrB,QAAQ;AAAA,QACR,MAAM;AAAA,MACR,CAAC;AACD,UAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,QAAQ,SAAS,MAAM,KAAK,SAAS,UAAU,EAAE;AACnF,aAAO,SAAS,KAAK;AAAA,IACvB,UAAE;AACA,mBAAa,SAAS;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,UAAU,MAAc,OAAqB;AAC3C,SAAK,OAAO,QAAQ,IAAI,IAAI;AAAA,EAC9B;AAAA,EAEA,aAAa,MAAoB;AAC/B,WAAO,KAAK,OAAO,QAAQ,IAAI;AAAA,EACjC;AAAA,EAEQ,QAAQ,KAAqB;AACnC,WAAO,eAAe,KAAK,GAAG,IAAI,MAAM,GAAG,KAAK,OAAO,MAAM,GAAG,GAAG;AAAA,EACrE;AAAA,EAEQ,eAAe,UAAkB,QAAwC;AAC/E,QAAI,MAAM;AACV,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,YAAM,IAAI,QAAQ,IAAI,GAAG,KAAK,mBAAmB,KAAK,CAAC;AAAA,IACzD;AACA,WAAO,KAAK,QAAQ,GAAG;AAAA,EACzB;AACF;;;ACjMO,IAAe,YAAf,MAAyB;AAAA,EAK9B,YAAY,MAAc,UAAkB,WAAmB;AAC7D,SAAK,OAAO;AACZ,SAAK,WAAW;AAChB,SAAK,YAAY;AAAA,EACnB;AAGF;AAEO,IAAM,eAAN,cAA2B,UAAU;AAAA,EAG1C,YAAY,MAAc,UAAkB,MAA+B,WAAmB;AAC5F,UAAM,MAAM,UAAU,SAAS;AAC/B,SAAK,OAAO;AAAA,EACd;AACF;;;AClBO,IAAM,qBAAN,cAAiC,UAAU;AAAA,EAahD,YACE,UACA,WACA,MACA,QACA,MACA,aAOA,WACA;AACA,UAAM,kBAAkB,UAAU,aAAa,KAAK,IAAI,CAAC;AACzD,SAAK,YAAY;AACjB,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,OAAO;AACZ,SAAK,cAAc;AAAA,EACrB;AACF;;;ACnCO,IAAM,qBAAN,cAAiC,UAAU;AAAA,EAKhD,YACE,UACA,WACA,SACA,MACA,WACA;AACA,UAAM,kBAAkB,UAAU,aAAa,KAAK,IAAI,CAAC;AACzD,SAAK,YAAY;AACjB,SAAK,UAAU;AACf,SAAK,OAAO;AAAA,EACd;AACF;;;AClBO,IAAM,sBAAN,cAAkC,UAAU;AAAA,EAGjD,YAAY,UAAkB,WAAmB,WAAoB;AACnE,UAAM,mBAAmB,UAAU,aAAa,KAAK,IAAI,CAAC;AAC1D,SAAK,YAAY;AAAA,EACnB;AACF;;;ACNO,IAAM,qBAAN,cAAiC,UAAU;AAAA,EAKhD,YAAY,UAAkB,WAAmB,OAAe,MAAY,WAAoB;AAC9F,UAAM,kBAAkB,UAAU,aAAa,KAAK,IAAI,CAAC;AACzD,SAAK,YAAY;AACjB,SAAK,QAAQ;AACb,SAAK,OAAO;AAAA,EACd;AACF;;;ACXO,IAAM,uBAAN,cAAmC,UAAU;AAAA,EAKlD,YAAY,UAAkB,WAAmB,OAAe,MAAY,WAAoB;AAC9F,UAAM,oBAAoB,UAAU,aAAa,KAAK,IAAI,CAAC;AAC3D,SAAK,YAAY;AACjB,SAAK,QAAQ;AACb,SAAK,OAAO;AAAA,EACd;AACF;;;ACZO,IAAM,qBAAN,cAAiC,UAAU;AAAA,EAGhD,YAAY,UAAkB,QAAgB,WAAoB;AAChE,UAAM,kBAAkB,UAAU,aAAa,KAAK,IAAI,CAAC;AACzD,SAAK,SAAS;AAAA,EAChB;AACF;;;ACPO,IAAM,sBAAN,cAAkC,UAAU;AAAA,EAKjD,YACE,UACA,WACA,OACA,SACA,WACA;AACA,UAAM,mBAAmB,UAAU,aAAa,KAAK,IAAI,CAAC;AAC1D,SAAK,YAAY;AACjB,SAAK,QAAQ;AACb,SAAK,UAAU;AAAA,EACjB;AACF;;;ACjBO,IAAM,mBAAN,cAA+B,UAAU;AAAA,EAG9C,YAAY,UAAkB,QAAgB,WAAoB;AAChE,UAAM,gBAAgB,UAAU,aAAa,KAAK,IAAI,CAAC;AACvD,SAAK,SAAS;AAAA,EAChB;AACF;;;ACEA,SAAS,UAAU,OAAkC;AACnD,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,MAAM;AACZ,MAAI,OAAO,IAAI,SAAS,SAAU,QAAO;AACzC,SAAO;AACT;AAEO,SAAS,eAAe,MAA0C;AACvE,QAAM,OAAO,KAAK;AAClB,QAAM,WAAW,KAAK;AACtB,QAAM,YAAY,KAAK;AACvB,QAAM,OAAQ,KAAK,QAAQ,CAAC;AAE5B,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,IAAI;AAAA,QACT;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL,UAAU,KAAK,IAAI;AAAA,QACnB,KAAK;AAAA,QAOL;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO,IAAI;AAAA,QACT;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,QACL,UAAU,KAAK,IAAI;AAAA,QACnB;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO,IAAI,oBAAoB,UAAU,KAAK,WAAqB,SAAS;AAAA,IAC9E,KAAK;AACH,aAAO,IAAI;AAAA,QACT;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO,IAAI;AAAA,QACT;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO,IAAI,mBAAmB,UAAU,KAAK,QAAkB,SAAS;AAAA,IAC1E,KAAK;AACH,aAAO,IAAI;AAAA,QACT;AAAA,QACA,KAAK;AAAA,QACL,KAAK;AAAA,QACL,KAAK;AAAA,QACL;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO,IAAI,iBAAiB,UAAU,KAAK,QAAkB,SAAS;AAAA,IACxE;AACE,aAAO,IAAI,aAAa,MAAM,UAAU,MAAM,SAAS;AAAA,EAC3D;AACF;AAGA,UAAU,WAAW;;;ACrFd,SAAS,aAAqB;AACnC,SAAO,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,EAAE,CAAC;AACzE;AAEO,SAAS,yBAAiC;AAC/C,SAAO,QAAQ,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,UAAU,GAAG,EAAE,CAAC;AAC1E;;;ACmEO,IAAM,gBAAN,MAAoB;AAAA,EAazB,YAAY,QAA6B;AARzC,SAAQ,WAAsB,CAAC;AAE/B,SAAQ,gBAA+B,CAAC;AACxC,SAAQ,oBAAiD,oBAAI,IAAI;AACjE,SAAQ,gBAAsD;AAC9D,SAAQ,cAA4D,oBAAI,IAAI;AAI1E,SAAK,SAAS;AACd,SAAK,aAAa,IAAI,WAAW;AAAA,MAC/B,QAAQ,OAAO;AAAA,MACf,SAAS;AAAA,QACP,aAAa,OAAO;AAAA,QACpB,eAAe,OAAO;AAAA,QACtB,GAAI,OAAO,WAAW,CAAC;AAAA,MACzB;AAAA,MACA,aAAa,OAAO;AAAA,IACtB,CAAC;AACD,SAAK,kBAAkB,OAAO;AAC9B,SAAK,iBAAiB,OAAO,kBAAkB,uBAAuB;AACtE,SAAK,gBAAgB,OAAO;AAAA,EAC9B;AAAA,EAEA,YAAY,QAAiC;AAC3C,QAAI,OAAO,QAAQ;AACjB,WAAK,gBAAgB,OAAO;AAC5B,WAAK,WAAW,UAAU,aAAa,OAAO,MAAM;AAAA,IACtD;AACA,QAAI,OAAO,UAAU;AACnB,WAAK,SAAS,EAAE,GAAG,KAAK,QAAQ,UAAU,OAAO,SAAS;AAC1D,WAAK,WAAW,UAAU,eAAe,OAAO,QAAQ;AAAA,IAC1D;AACA,QAAI,OAAO,aAAa;AACtB,WAAK,SAAS,EAAE,GAAG,KAAK,QAAQ,aAAa,OAAO,YAAY;AAChE,WAAK,WAAW,UAAU,kBAAkB,OAAO,WAAW;AAAA,IAChE;AACA,QAAI,OAAO,gBAAgB;AACzB,WAAK,iBAAiB,OAAO;AAAA,IAC/B;AACA,QAAI,OAAO,SAAS;AAClB,aAAO,QAAQ,OAAO,OAAO,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AACvD,aAAK,WAAW,UAAU,KAAK,KAAK;AAAA,MACtC,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,gBAAgB,QAAsB;AACpC,SAAK,WAAW,UAAU,YAAY,MAAM;AAC5C,SAAK,WAAW,UAAU,cAAc,OAAO,MAAM,GAAG,EAAE,CAAC,KAAK,MAAM;AAAA,EACxE;AAAA,EAEA,kBAAkB,UAAwB;AACxC,SAAK,WAAW,UAAU,cAAc,QAAQ;AAAA,EAClD;AAAA,EAEA,MAAM,UAAyB;AAC7B,QAAI,KAAK,iBAAiB;AACxB,WAAK,gBAAgB,QAAQ;AAE7B,YAAM,WAAW,KAAK,YAAY;AAClC,YAAM,eAA8B;AAAA,QAClC,iBAAiB,CAAC,UAAU,KAAK,oBAAoB,KAAK;AAAA,MAC5D;AAEA,UAAI,KAAK,OAAO,UAAU,cAAc;AACtC,qBAAa,kBAAkB,CAAC,UAAU,KAAK,oBAAoB,KAAK;AAAA,MAC1E;AACA,UAAI,KAAK,OAAO,UAAU,gBAAgB;AACxC,qBAAa,mBAAmB,CAAC,UAAU,KAAK,qBAAqB,KAAK;AAAA,MAC5E;AACA,UAAI,KAAK,OAAO,UAAU,WAAW;AACnC,qBAAa,kBAAkB,CAAC,UAAU,KAAK,oBAAoB,KAAK;AACxE,qBAAa,oBAAoB,CAAC,UAAU,KAAK,sBAAsB,KAAK;AAAA,MAC9E;AAEA,mBAAa,kBAAkB,CAAC,UAAU,KAAK,oBAAoB,KAAK;AAExE,YAAM,KAAK,gBAAgB,UAAU,UAAU,YAAY;AAE3D,WAAK,yBAAyB,MAAM,KAAK,gBAAgB;AAAA,QACvD;AAAA,QACA,KAAK;AAAA,QACL;AAAA,UACE,kBAAkB,CAAC,UAAU,KAAK,qBAAqB,KAAK;AAAA,UAC5D,eAAe,CAAC,UAAU,KAAK,kBAAkB,KAAK;AAAA,QACxD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,aAAmB;AACjB,SAAK,yBAAyB;AAC9B,SAAK,yBAAyB;AAC9B,SAAK,iBAAiB,WAAW;AACjC,SAAK,kBAAkB,MAAM;AAAA,EAC/B;AAAA,EAEA,MAAM,aACJ,SACA,QAC6B;AAC7B,UAAM,WAAW,KAAK,OAAO,WAAW,gBAAgB;AACxD,UAAM,WAAW,KAAK,YAAY;AAClC,UAAM,SAAS,IAAI,gBAAgB;AAAA,MACjC;AAAA,MACA,OAAO,OAAO,SAAS,SAAS,EAAE;AAAA,IACpC,CAAC;AACD,QAAI,SAAS,OAAQ,QAAO,IAAI,UAAU,OAAO,QAAQ,MAAM,CAAC;AAChE,QAAI,SAAS,MAAO,QAAO,IAAI,SAAS,OAAO,QAAQ,KAAK,CAAC;AAE7D,UAAM,WAAY,MAAM,KAAK,WAAW;AAAA,MACtC,GAAG,QAAQ,IAAI,OAAO,SAAS,CAAC;AAAA,MAChC;AAAA,IACF;AACA,UAAM,cAAe,SAAS,YAA0C,CAAC;AACzE,UAAM,WAAsB,YAAY,IAAI,CAAC,SAAS;AAAA,MACpD,IAAI,IAAI;AAAA,MACR;AAAA,MACA,SAAS;AAAA,QACP,MAAM,IAAI;AAAA,QACV,OAAO,IAAI,OAAQ,CAAC,IAAI,IAA+B,IAAgB;AAAA,MACzE;AAAA,MACA,QAAQ;AAAA,QACN,IAAK,IAAI,OAAmC;AAAA,QAC5C,MAAO,IAAI,OAAmC;AAAA,QAC9C,OAAS,IAAI,OAAmC,SAAqB;AAAA,QACrE,MAAO,IAAI,OAAmC,OAAO,KAAK;AAAA,MAC5D;AAAA,MACA,WAAW,IAAI;AAAA,MACf,aAAc,IAAI,aAA2C,IAAI,CAAC,OAAO;AAAA,QACvE,IAAI,OAAO,IAAI,EAAY,IAAI,EAAE,GAAa;AAAA,QAC9C,KAAK,EAAE;AAAA,QACP,MAAM,EAAE;AAAA,QACR,MAAM,EAAE;AAAA,QACR,UAAU,EAAE;AAAA,QACZ,MAAM,EAAE;AAAA,MACV,EAAE;AAAA,MACF,WAAY,IAAI,aAAqE,CAAC;AAAA,IACxF,EAAE;AAEF,QAAI,CAAC,SAAS,UAAU,CAAC,SAAS,SAAS,CAAC,SAAS,eAAe;AAClE,WAAK,WAAW;AAChB,WAAK,kBAAkB,mBAAmB,QAAQ;AAAA,IACpD;AAEA,WAAO;AAAA,MACL;AAAA,MACA,SAAU,SAAS,WAAuB;AAAA,MAC1C,YAAY,SAAS;AAAA,MACrB,YAAY,SAAS;AAAA,IACvB;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,MAAc,cAAiC,CAAC,GAAkB;AAClF,UAAM,YAAY,WAAW;AAE7B,UAAM,cAAuB;AAAA,MAC3B,IAAI;AAAA,MACJ,UAAU,KAAK,YAAY;AAAA,MAC3B,SAAS,EAAE,KAAK;AAAA,MAChB,QAAQ,EAAE,IAAI,KAAK,eAAe,MAAM,KAAK,OAAO,UAAU,MAAM,KAAK;AAAA,MACzE,WAAW,KAAK,IAAI;AAAA,MACpB,aACE,YAAY,SAAS,IACjB,YAAY,IAAI,CAAC,GAAG,OAAO;AAAA,QACzB,IAAI,OAAO,SAAS,IAAI,CAAC;AAAA,QACzB,MAAM,EAAE,QAAQ;AAAA,QAChB,KAAK,EAAE;AAAA,QACP,MAAM,EAAE;AAAA,QACR,UAAU,EAAE;AAAA,MACd,EAAE,IACF;AAAA,IACR;AAEA,SAAK,SAAS,KAAK,WAAW;AAC9B,SAAK,kBAAkB,iBAAiB,WAAW;AAEnD,UAAM,WAAW,KAAK,OAAO,WAAW,eAAe;AACvD,UAAM,WAAW,MAAM,KAAK,WAAW;AAAA,MACrC;AAAA,QACE;AAAA,UACE,IAAI;AAAA,UACJ,MAAM;AAAA,UACN;AAAA,UACA,aAAa,YAAY,IAAI,CAAC,OAAO;AAAA,YACnC,KAAK,EAAE;AAAA,YACP,MAAM,EAAE;AAAA,YACR,WAAW,EAAE;AAAA,YACb,MAAM,EAAE;AAAA,UACV,EAAE;AAAA,QACJ;AAAA,MACF;AAAA,MACA;AAAA,MACA,KAAK;AAAA,IACP;AAEA,QAAI,SAAS,QAAQ;AACnB,eAAS,OAAO,QAAQ,CAAC,cAAc;AACrC,cAAM,QAAQ,eAAe,SAAS;AACtC,aAAK,cAAc,KAAK;AAAA,MAC1B,CAAC;AAAA,IACH;AAEA,QAAI,SAAS,QAAQ,CAAC,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,SAAS,gBAAgB,GAAG;AAC/E,YAAM,mBAA4B;AAAA,QAChC,IAAI,SAAS,MAAM,WAAW;AAAA,QAC9B,UAAU,KAAK,YAAY;AAAA,QAC3B,SAAS,EAAE,MAAM,SAAS,KAAK;AAAA,QAC/B,QAAQ,EAAE,IAAI,aAAa,MAAM,aAAa,OAAO,KAAK;AAAA,QAC1D,WAAW,KAAK,IAAI;AAAA,QACpB,aAAc,SAAS,aAA2C,IAAI,CAAC,GAAG,OAAO;AAAA,UAC/E,IAAI,OAAO,SAAS,MAAM,KAAK,IAAI,CAAC;AAAA,UACpC,MAAO,EAAE,QAAmB;AAAA,UAC5B,KAAM,EAAE,OAAkB;AAAA,UAC1B,MAAM,EAAE;AAAA,UACR,UAAU,EAAE;AAAA,UACZ,MAAM,EAAE;AAAA,QACV,EAAE;AAAA,MACJ;AACA,WAAK,SAAS,KAAK,gBAAgB;AACnC,WAAK,kBAAkB,iBAAiB,gBAAgB;AAAA,IAC1D;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,WAAmB,UAAkB,OAA8B;AAClF,UAAM,WAAW,KAAK,OAAO,WAAW,eAAe;AACvD,UAAM,WAAW,MAAM,KAAK,WAAW;AAAA,MACrC;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK;AAAA,MACL;AAAA,IACF;AAEA,QAAI,SAAS,QAAQ;AACnB,MAAC,SAAS,OAA0C,QAAQ,CAAC,cAAc;AACzE,cAAM,QAAQ,eAAe,SAAS;AACtC,aAAK,cAAc,KAAK;AAAA,MAC1B,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAM,YAAY,WAAmB,SAAgC;AACnE,QAAI,CAAC,KAAK,OAAO,UAAU,cAAc;AACvC,YAAM,IAAI,MAAM,wEAAwE;AAAA,IAC1F;AACA,UAAM,WAAW,KAAK,OAAO,WAAW,eAAe;AACvD,UAAM,KAAK,WAAW,YAAY,WAAW,SAAS,QAAQ;AAAA,EAChE;AAAA,EAEA,MAAM,cAAc,WAAkC;AACpD,QAAI,CAAC,KAAK,OAAO,UAAU,gBAAgB;AACzC,YAAM,IAAI,MAAM,4EAA4E;AAAA,IAC9F;AACA,UAAM,WAAW,KAAK,OAAO,WAAW,iBAAiB;AACzD,UAAM,KAAK,WAAW,cAAc,WAAW,QAAQ;AAAA,EACzD;AAAA,EAEA,MAAM,YAAY,WAAmB,OAA8B;AACjE,QAAI,CAAC,KAAK,OAAO,UAAU,WAAW;AACpC,YAAM,IAAI,MAAM,iEAAiE;AAAA,IACnF;AACA,UAAM,WAAW,KAAK,OAAO,WAAW,eAAe;AACvD,UAAM,KAAK,WAAW,YAAY,WAAW,OAAO,QAAQ;AAAA,EAC9D;AAAA,EAEA,MAAM,eAAe,WAAmB,OAA8B;AACpE,QAAI,CAAC,KAAK,OAAO,UAAU,WAAW;AACpC,YAAM,IAAI,MAAM,iEAAiE;AAAA,IACnF;AACA,UAAM,WACJ,KAAK,OAAO,WAAW,kBAAkB;AAC3C,UAAM,KAAK,WAAW,eAAe,WAAW,OAAO,QAAQ;AAAA,EACjE;AAAA,EAEA,gBAAgB,SAA2D;AACzE,WAAO,KAAK,iBAAiB,kBAAkB,OAAO;AAAA,EACxD;AAAA,EAEA,gBAAgB,SAA2D;AACzE,WAAO,KAAK,iBAAiB,kBAAkB,OAAO;AAAA,EACxD;AAAA,EAEA,iBAAiB,SAA4D;AAC3E,WAAO,KAAK,iBAAiB,mBAAmB,OAAO;AAAA,EACzD;AAAA,EAEA,gBAAgB,SAA2D;AACzE,WAAO,KAAK,iBAAiB,kBAAkB,OAAO;AAAA,EACxD;AAAA,EAEA,kBAAkB,SAA6D;AAC7E,WAAO,KAAK,iBAAiB,oBAAoB,OAAO;AAAA,EAC1D;AAAA,EAEA,iBAAiB,SAA4D;AAC3E,WAAO,KAAK,iBAAiB,mBAAmB,OAAO;AAAA,EACzD;AAAA,EAEA,gBAAgB,SAA2D;AACzE,WAAO,KAAK,iBAAiB,kBAAkB,OAAO;AAAA,EACxD;AAAA,EAEA,oBAA4B;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA,EACA,cAAyB;AACvB,WAAO,CAAC,GAAG,KAAK,QAAQ;AAAA,EAC1B;AAAA,EACA,cAAsB;AACpB,WAAO,OAAO,KAAK,aAAa,IAAI,KAAK,cAAc;AAAA,EACzD;AAAA,EACA,mBAA2B;AACzB,WAAO,KAAK;AAAA,EACd;AAAA,EACA,cAA4D;AAC1D,WAAO,KAAK,OAAO,YAAY,CAAC;AAAA,EAClC;AAAA,EACA,eAA8D;AAC5D,WAAO,KAAK,OAAO,aAAa,CAAC;AAAA,EACnC;AAAA,EACA,gBAA4B;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,iBAA8B,WAAmB,SAA0C;AACzF,QAAI,CAAC,KAAK,YAAY,IAAI,SAAS,EAAG,MAAK,YAAY,IAAI,WAAW,CAAC,CAAC;AACxE,SAAK,YAAY,IAAI,SAAS,EAAG,KAAK,OAAmC;AACzE,WAAO,MAAM;AACX,YAAM,WAAW,KAAK,YAAY,IAAI,SAAS;AAC/C,UAAI,UAAU;AACZ,cAAM,QAAQ,SAAS,QAAQ,OAAmC;AAClE,YAAI,UAAU,GAAI,UAAS,OAAO,OAAO,CAAC;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,oBAAoB,OAAiC;AAC3D,QAAI,KAAK,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,SAAS,EAAG;AACzD,QAAI,KAAK,kBAAkB,IAAI,MAAM,SAAS,EAAG;AAEjD,UAAM,UAAmB;AAAA,MACvB,IAAI,MAAM;AAAA,MACV,UAAU,MAAM;AAAA,MAChB,SAAS,EAAE,MAAM,MAAM,MAAM,OAAO,MAAM,OAAO,CAAC,MAAM,IAAI,IAAI,OAAU;AAAA,MAC1E,QAAQ,MAAM;AAAA,MACd,WAAW,MAAM;AAAA,MACjB,aAAa,MAAM,aAAa,IAAI,CAAC,OAAO;AAAA,QAC1C,IAAI,OAAO,MAAM,SAAS,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,QACpE,MAAM,EAAE,QAAQ;AAAA,QAChB,KAAK,EAAE,OAAO;AAAA,QACd,MAAM,EAAE;AAAA,QACR,UAAU,EAAE;AAAA,QACZ,MAAM,EAAE,QAAQ;AAAA,MAClB,EAAE;AAAA,IACJ;AACA,SAAK,SAAS,KAAK,OAAO;AAC1B,SAAK,kBAAkB,iBAAiB,OAAO;AAC/C,SAAK,kBAAkB,kBAAkB,KAAK;AAAA,EAChD;AAAA,EAEQ,oBAAoB,OAAiC;AAC3D,UAAM,UAAU,KAAK,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,SAAS;AAClE,QAAI,SAAS,SAAS;AACpB,cAAQ,QAAQ,OAAO,MAAM;AAC7B,WAAK,kBAAkB,kBAAkB,KAAK;AAAA,IAChD;AAAA,EACF;AAAA,EAEQ,qBAAqB,OAAkC;AAC7D,UAAM,QAAQ,KAAK,SAAS,UAAU,CAAC,MAAM,EAAE,OAAO,MAAM,SAAS;AACrE,QAAI,UAAU,IAAI;AAChB,WAAK,SAAS,OAAO,OAAO,CAAC;AAC7B,WAAK,kBAAkB,mBAAmB,KAAK;AAAA,IACjD;AAAA,EACF;AAAA,EAEQ,oBAAoB,OAAiC;AAC3D,UAAM,UAAU,KAAK,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,SAAS;AAClE,QAAI,CAAC,QAAS;AACd,QAAI,CAAC,QAAQ,UAAW,SAAQ,YAAY,CAAC;AAE7C,UAAM,WAAW,QAAQ,UAAU,KAAK,CAAC,MAAM,EAAE,UAAU,MAAM,KAAK;AACtE,QAAI,UAAU;AACZ,eAAS;AACT,eAAS,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,IACnC,OAAO;AACL,cAAQ,UAAU,KAAK,EAAE,OAAO,MAAM,OAAO,OAAO,GAAG,OAAO,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;AAAA,IACjF;AACA,SAAK,kBAAkB,kBAAkB,KAAK;AAAA,EAChD;AAAA,EAEQ,sBAAsB,OAAmC;AAC/D,UAAM,UAAU,KAAK,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,SAAS;AAClE,QAAI,CAAC,SAAS,UAAW;AAEzB,UAAM,QAAQ,QAAQ,UAAU,UAAU,CAAC,MAAM,EAAE,UAAU,MAAM,KAAK;AACxE,QAAI,UAAU,IAAI;AAChB,YAAM,WAAW,QAAQ,UAAU,KAAK;AACxC,eAAS;AACT,eAAS,QAAQ,SAAS,MAAM,OAAO,CAAC,OAAO,OAAO,MAAM,KAAK,EAAE;AACnE,UAAI,SAAS,UAAU,EAAG,SAAQ,UAAU,OAAO,OAAO,CAAC;AAAA,IAC7D;AACA,SAAK,kBAAkB,oBAAoB,KAAK;AAAA,EAClD;AAAA,EAEQ,qBAAqB,OAAkC;AAC7D,UAAM,EAAE,WAAW,OAAO,QAAQ,IAAI;AAEtC,QAAI,CAAC,KAAK,kBAAkB,IAAI,SAAS,GAAG;AAC1C,WAAK,kBAAkB,IAAI,WAAW,EAAE,WAAW,iBAAiB,IAAI,YAAY,MAAM,CAAC;AAC3F,WAAK,kBAAkB,qBAAqB,KAAK;AAAA,IACnD;AAEA,UAAM,QAAQ,KAAK,kBAAkB,IAAI,SAAS;AAClD,UAAM,mBAAmB;AAEzB,QAAI,SAAS;AACX,YAAM,aAAa;AACnB,UAAI,CAAC,KAAK,SAAS,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS,GAAG;AAClD,cAAM,UAAmB;AAAA,UACvB,IAAI;AAAA,UACJ,UAAU,MAAM;AAAA,UAChB,SAAS,EAAE,MAAM,MAAM,gBAAgB;AAAA,UACvC,QAAQ,EAAE,IAAI,aAAa,MAAM,aAAa,OAAO,KAAK;AAAA,UAC1D,WAAW,MAAM;AAAA,QACnB;AACA,aAAK,SAAS,KAAK,OAAO;AAC1B,aAAK,kBAAkB,iBAAiB,OAAO;AAAA,MACjD;AACA,WAAK,kBAAkB,OAAO,SAAS;AACvC,WAAK,kBAAkB,sBAAsB,EAAE,WAAW,MAAM,MAAM,gBAAgB,CAAC;AAAA,IACzF,OAAO;AACL,WAAK,kBAAkB,mBAAmB,KAAK;AAAA,IACjD;AAAA,EACF;AAAA,EAEQ,oBAAoB,OAAiC;AAC3D,QAAI,KAAK,cAAe,cAAa,KAAK,aAAa;AACvD,SAAK,kBAAkB,kBAAkB,KAAK;AAC9C,SAAK,gBAAgB,WAAW,MAAM;AACpC,WAAK,kBAAkB,kBAAkB,EAAE,QAAQ,MAAM,OAAO,CAAC;AAAA,IACnE,GAAG,GAAI;AAAA,EACT;AAAA,EAEQ,kBAAkB,OAA+B;AACvD,SAAK,kBAAkB,gBAAgB,KAAK;AAAA,EAC9C;AAAA,EAEQ,kBAAqB,WAAmB,MAAe;AAC7D,SAAK,YAAY,IAAI,SAAS,GAAG,QAAQ,CAAC,YAAY,QAAQ,IAAI,CAAC;AAAA,EACrE;AAAA,EAEQ,cAAc,OAAwB;AAC5C,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK;AACH,aAAK,oBAAoB,KAA2B;AACpD;AAAA,MACF,KAAK;AACH,aAAK,oBAAoB,KAA2B;AACpD;AAAA,MACF,KAAK;AACH,aAAK,qBAAqB,KAA4B;AACtD;AAAA,MACF,KAAK;AACH,aAAK,oBAAoB,KAA2B;AACpD;AAAA,MACF,KAAK;AACH,aAAK,sBAAsB,KAA6B;AACxD;AAAA,MACF,KAAK;AACH,aAAK,oBAAoB,KAA2B;AACpD;AAAA,MACF,KAAK;AACH,aAAK,qBAAqB,KAA4B;AACtD;AAAA,MACF,KAAK;AACH,aAAK,kBAAkB,KAAyB;AAChD;AAAA,IACJ;AAAA,EACF;AACF;;;AC5hBO,IAAM,wBAAN,MAAuD;AAAA,EAU5D,YACE,gBACA,gBAAwB,QACxB,cACA;AARF,SAAQ,gBAA4C,oBAAI,IAAI;AAS1D,SAAK,gBAAgB;AACrB,SAAK,oBAAoB,cAAc,iBAAiB;AACxD,SAAK,kBAAkB,cAAc,eAAe;AACpD,SAAK,iBAAiB,cAAc,kBAAkB;AAEtD,QAAI,SAAS,gBAAgB;AAC3B,YAAM,aAAc,WAAmB,UAAW,WAAmB;AACrE,UAAI,CAAC,YAAY;AACf,cAAM,IAAI,MAAM,4DAA4D;AAAA,MAC9E;AACA,WAAK,SAAS,IAAI,WAAY,eAAgC,KAAK,cAAc;AAAA,IACnF,OAAO;AACL,WAAK,SAAS;AAAA,IAChB;AAAA,EACF;AAAA,EAEQ,iBAAiB,MAAc,MAAiD;AACtF,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,eAAO,WAAW,IAAI;AAAA,MACxB,KAAK;AACH,eAAO,YAAY,IAAI;AAAA,MACzB;AACE,eAAO;AAAA,IACX;AAAA,EACF;AAAA,EAEA,MAAgB,yBAAyB,UAAmC;AAC1E,UAAM,OAAO,KAAK,iBAAiB,MAAM,KAAK,gBAAgB,QAAQ,IAAI;AAE1E,WAAO,GAAG,KAAK,aAAa,IAAI,IAAI;AAAA,EACtC;AAAA,EAEA,MAAc,gBAAgB,MAA+B;AAC3D,QAAI,OAAO,QAAQ,QAAQ,WAAW,YAAY;AAChD,YAAM,IAAI,MAAM,0DAA0D;AAAA,IAC5E;AACA,UAAM,UAAU,IAAI,YAAY;AAChC,UAAM,OAAO,QAAQ,OAAO,IAAI;AAChC,UAAM,aAAa,MAAM,OAAO,OAAO,OAAO,WAAW,IAAI;AAC7D,UAAM,YAAY,MAAM,KAAK,IAAI,WAAW,UAAU,CAAC;AACvD,WAAO,UAAU,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AAAA,EACtE;AAAA,EAEA,UAAgB;AACd,QAAI,KAAK,OAAO,YAAY,UAAU,aAAa;AACjD,WAAK,OAAO,QAAQ;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,aAAmB;AACjB,SAAK,cAAc,QAAQ,CAAC,YAAY,QAAQ,aAAa,KAAK,QAAQ,cAAc,CAAC;AACzF,SAAK,cAAc,MAAM;AACzB,SAAK,OAAO,aAAa;AAAA,EAC3B;AAAA,EAEA,MAAM,UAAU,UAAkB,UAA+C;AAC/E,UAAM,WAAW,MAAM,KAAK,yBAAyB,QAAQ;AAC7D,UAAM,cAAc,KAAK,iBAAiB,UAAU,KAAK,iBAAiB;AAC1E,UAAM,UAAU,KAAK,OAAO,UAAU,WAAW;AACjD,UAAM,MAAM,UAAU,QAAQ;AAC9B,SAAK,cAAc,IAAI,KAAK,OAAO;AAEnC,UAAM,eAAe;AAAA,MACnB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,iBAAa,QAAQ,CAAC,cAAc;AAClC,YAAM,YAAY,GAAG,KAAK,aAAa,IAAI,SAAS;AACpD,cAAQ,KAAK,WAAW,CAAC,SAAkB;AACzC,cAAM,QAAQ,eAAe,IAA+B;AAC5D,aAAK,kBAAkB,OAAO,QAAQ;AAAA,MACxC,CAAC;AAAA,IACH,CAAC;AAED,WAAO,MAAM;AACX,cAAQ,aAAa;AACrB,WAAK,OAAO,YAAY,WAAW;AACnC,WAAK,cAAc,OAAO,GAAG;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,MAAM,gBACJ,UACA,QACA,UACsB;AACtB,UAAM,WAAW,GAAG,MAAM,KAAK,yBAAyB,QAAQ,CAAC,IAAI,MAAM;AAC3E,UAAM,cAAc,KAAK,iBAAiB,UAAU,KAAK,eAAe;AACxE,UAAM,UAAU,KAAK,OAAO,UAAU,WAAW;AACjD,UAAM,MAAM,QAAQ,QAAQ,IAAI,MAAM;AACtC,SAAK,cAAc,IAAI,KAAK,OAAO;AAEnC,UAAM,aAAa,CAAC,kBAAkB,mBAAmB,cAAc;AAEvE,eAAW,QAAQ,CAAC,cAAc;AAChC,YAAM,YAAY,GAAG,KAAK,aAAa,IAAI,SAAS;AACpD,cAAQ,KAAK,WAAW,CAAC,SAAkB;AACzC,cAAM,QAAQ,eAAe,IAA+B;AAC5D,aAAK,kBAAkB,OAAO,QAAQ;AAAA,MACxC,CAAC;AAAA,IACH,CAAC;AAED,WAAO,MAAM;AACX,cAAQ,aAAa;AACrB,WAAK,OAAO,YAAY,WAAW;AACnC,WAAK,cAAc,OAAO,GAAG;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,cAAuB;AACrB,WAAO,KAAK,OAAO,YAAY,UAAU;AAAA,EAC3C;AAAA,EAEQ,kBAAkB,OAAkB,UAA+B;AACzE,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK;AACH,iBAAS,kBAAkB,KAAY;AACvC;AAAA,MACF,KAAK;AACH,iBAAS,kBAAkB,KAAY;AACvC;AAAA,MACF,KAAK;AACH,iBAAS,mBAAmB,KAAY;AACxC;AAAA,MACF,KAAK;AACH,iBAAS,kBAAkB,KAAY;AACvC;AAAA,MACF,KAAK;AACH,iBAAS,oBAAoB,KAAY;AACzC;AAAA,MACF,KAAK;AACH,iBAAS,kBAAkB,KAAY;AACvC;AAAA,MACF,KAAK;AACH,iBAAS,mBAAmB,KAAY;AACxC;AAAA,MACF,KAAK;AACH,iBAAS,gBAAgB,KAAY;AACrC;AAAA,IACJ;AAAA,EACF;AACF;;;ACvKO,IAAM,6BAAN,MAA4D;AAAA,EAQjE,YAAY,MAAiB,gBAAwB,QAAQ,cAAkC;AAF/F,SAAQ,gBAA0C,oBAAI,IAAI;AAGxD,SAAK,OAAO;AACZ,SAAK,gBAAgB;AACrB,SAAK,oBAAoB,cAAc,iBAAiB;AACxD,SAAK,kBAAkB,cAAc,eAAe;AACpD,SAAK,iBAAiB,cAAc,kBAAkB;AAAA,EACxD;AAAA,EAEQ,gBAAgB,MAAc,MAAsD;AAC1F,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,eAAO,KAAK,KAAK,QAAQ,IAAI;AAAA,MAC/B,KAAK;AACH,eAAO,KAAK,KAAK,KAAK,IAAI;AAAA,MAC5B;AACE,eAAO,KAAK,KAAK,QAAQ,IAAI;AAAA,IACjC;AAAA,EACF;AAAA,EAEA,UAAgC;AAC9B,WAAO,QAAQ,QAAQ;AAAA,EACzB;AAAA,EAEA,aAAmB;AACjB,SAAK,cAAc,QAAQ,CAAC,YAAY;AACtC,cAAQ,cAAc;AACtB,cAAQ,gBAAgB;AAAA,IAC1B,CAAC;AACD,SAAK,cAAc,MAAM;AAAA,EAC3B;AAAA,EAEA,MAAgB,yBAAyB,UAAmC;AAC1E,UAAM,OAAO,KAAK,iBAAiB,MAAM,KAAK,gBAAgB,QAAQ,IAAI;AAE1E,WAAO,GAAG,KAAK,aAAa,IAAI,IAAI;AAAA,EACtC;AAAA,EAEA,MAAc,gBAAgB,MAA+B;AAC3D,QAAI,OAAO,QAAQ,QAAQ,WAAW,YAAY;AAChD,YAAM,IAAI,MAAM,0DAA0D;AAAA,IAC5E;AACA,UAAM,UAAU,IAAI,YAAY;AAChC,UAAM,OAAO,QAAQ,OAAO,IAAI;AAChC,UAAM,aAAa,MAAM,OAAO,OAAO,OAAO,WAAW,IAAI;AAC7D,UAAM,YAAY,MAAM,KAAK,IAAI,WAAW,UAAU,CAAC;AACvD,WAAO,UAAU,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AAAA,EACtE;AAAA,EAEA,MAAM,UAAU,UAAkB,UAA+C;AAC/E,UAAM,cAAc,MAAM,KAAK,yBAAyB,QAAQ;AAChE,UAAM,UAAU,KAAK,gBAAgB,aAAa,KAAK,iBAAiB;AACxE,UAAM,MAAM,UAAU,QAAQ;AAC9B,SAAK,cAAc,IAAI,KAAK,OAAO;AAEnC,UAAM,eAAsE;AAAA,MAC1E,EAAE,MAAM,kBAAkB,SAAS,kBAAkB;AAAA,MACrD,EAAE,MAAM,kBAAkB,SAAS,kBAAkB;AAAA,MACrD,EAAE,MAAM,mBAAmB,SAAS,mBAAmB;AAAA,MACvD,EAAE,MAAM,kBAAkB,SAAS,kBAAkB;AAAA,MACrD,EAAE,MAAM,oBAAoB,SAAS,oBAAoB;AAAA,MACzD,EAAE,MAAM,kBAAkB,SAAS,kBAAkB;AAAA,IACvD;AAEA,iBAAa,QAAQ,CAAC,EAAE,MAAM,QAAQ,MAAM;AAC1C,YAAM,YAAY,IAAI,KAAK,aAAa,IAAI,IAAI;AAChD,cAAQ,OAAO,WAAW,CAAC,SAAkB;AAC3C,cAAM,QAAQ,eAAe,IAA+B;AAC5D,QAAC,SAAS,OAAO,IAAY,KAAK;AAAA,MACpC,CAAC;AAAA,IACH,CAAC;AAED,WAAO,MAAM;AACX,cAAQ,cAAc;AACtB,WAAK,cAAc,OAAO,GAAG;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,MAAM,gBACJ,UACA,QACA,UACsB;AACtB,UAAM,cAAc,GAAG,MAAM,KAAK,yBAAyB,QAAQ,CAAC,IAAI,MAAM;AAC9E,UAAM,UAAU,KAAK,gBAAgB,aAAa,KAAK,eAAe;AACtE,UAAM,MAAM,QAAQ,QAAQ,IAAI,MAAM;AACtC,SAAK,cAAc,IAAI,KAAK,OAAO;AAEnC,UAAM,aAAoE;AAAA,MACxE,EAAE,MAAM,kBAAkB,SAAS,kBAAkB;AAAA,MACrD,EAAE,MAAM,mBAAmB,SAAS,mBAAmB;AAAA,MACvD,EAAE,MAAM,gBAAgB,SAAS,gBAAgB;AAAA,IACnD;AAEA,eAAW,QAAQ,CAAC,EAAE,MAAM,QAAQ,MAAM;AACxC,YAAM,YAAY,IAAI,KAAK,aAAa,IAAI,IAAI;AAChD,cAAQ,OAAO,WAAW,CAAC,SAAkB;AAC3C,cAAM,QAAQ,eAAe,IAA+B;AAC5D,QAAC,SAAS,OAAO,IAAY,KAAK;AAAA,MACpC,CAAC;AAAA,IACH,CAAC;AAED,WAAO,MAAM;AACX,cAAQ,cAAc;AACtB,WAAK,cAAc,OAAO,GAAG;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,cAAuB;AACrB,QAAI;AACF,YAAM,YAAa,KAAK,KAAa;AACrC,UAAI,CAAC,UAAW,QAAO;AAEvB,UAAI,UAAU,QAAQ,YAAY,UAAU,YAAa,QAAO;AAChE,UAAI,UAAU,QAAQ,UAAW,QAAO;AAExC,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AC7IO,IAAM,cAAN,MAAM,aAAY;AAAA,EAOvB,YAAY,QAAoB;AALhC,SAAQ,eAAiD;AACzD,SAAQ,SAAiC;AACzC,SAAQ,kBAAiE,oBAAI,IAAI;AACjF,SAAQ,mBAAuD,oBAAI,IAAI;AAGrE,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,OAAO,cAAuB;AAC5B,WACE,OAAO,cAAc,eACrB,mBAAmB,aACnB,iBAAiB,UACjB,kBAAkB;AAAA,EAEtB;AAAA,EAEA,YAAoC;AAClC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,eAAe,UAAgE;AAC7E,SAAK,gBAAgB,IAAI,QAAQ;AACjC,WAAO,MAAM;AACX,WAAK,gBAAgB,OAAO,QAAQ;AAAA,IACtC;AAAA,EACF;AAAA,EAEA,UAAU,UAAqD;AAC7D,SAAK,iBAAiB,IAAI,QAAQ;AAClC,WAAO,MAAM;AACX,WAAK,iBAAiB,OAAO,QAAQ;AAAA,IACvC;AAAA,EACF;AAAA,EAEA,MAAM,aAA4B;AAChC,QAAI,CAAC,aAAY,YAAY,GAAG;AAC9B,WAAK,UAAU,aAAa;AAC5B;AAAA,IACF;AACA,QAAI,aAAa,eAAe,UAAU;AACxC,WAAK,UAAU,QAAQ;AACvB;AAAA,IACF;AAEA,QAAI;AACF,WAAK,eAAe,MAAM,UAAU,cAAc;AAAA,QAChD,KAAK,OAAO,oBAAoB;AAAA,QAChC;AAAA,UACE,OAAO,KAAK,OAAO,sBAAsB;AAAA,UACzC,MAAM,KAAK,OAAO;AAAA,QACpB;AAAA,MACF;AACA,YAAM,UAAU,cAAc;AAE9B,gBAAU,cAAc,iBAAiB,WAAW,CAAC,UAAwB;AAC3E,cAAM,MAAM,MAAM;AAClB,YAAI,KAAK,SAAS,yBAAyB;AACzC,gBAAM,WAAW,IAAI;AACrB,eAAK,iBAAiB,QAAQ,CAAC,aAAa,SAAS,QAAQ,CAAC;AAAA,QAChE;AAAA,MACF,CAAC;AAED,YAAM,eAAe,MAAM,KAAK,aAAa,YAAY,gBAAgB;AACzE,WAAK,UAAU,eAAe,eAAe,SAAS;AAAA,IACxD,QAAQ;AACN,WAAK,UAAU,OAAO;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,MAAM,YAA2B;AAC/B,QAAI,CAAC,KAAK;AACR,YAAM,IAAI,MAAM,uDAAuD;AAEzE,SAAK,UAAU,aAAa;AAE5B,QAAI;AACF,UAAI,eAAe,MAAM,KAAK,aAAa,YAAY,gBAAgB;AAEvE,UAAI,CAAC,cAAc;AACjB,cAAM,aAAa,MAAM,aAAa,kBAAkB;AACxD,YAAI,eAAe,WAAW;AAC5B,eAAK,UAAU,eAAe,WAAW,WAAW,SAAS;AAC7D;AAAA,QACF;AAEA,cAAM,iBAAiB,MAAM,KAAK,OAAO,kBAAkB;AAC3D,cAAM,eAAe,KAAK,sBAAsB,cAAc;AAC9D,uBAAe,MAAM,KAAK,aAAa,YAAY,UAAU;AAAA,UAC3D,iBAAiB;AAAA,UACjB,sBAAsB,aAAa;AAAA,QACrC,CAAC;AAAA,MACH;AAEA,YAAM,KAAK,OAAO,YAAY,aAAa,OAAO,CAAC;AACnD,WAAK,UAAU,YAAY;AAAA,IAC7B,QAAQ;AACN,WAAK,UAAU,OAAO;AACtB,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,MAAM,cAA6B;AACjC,QAAI,CAAC,KAAK,aAAc;AAExB,QAAI;AACF,YAAM,eAAe,MAAM,KAAK,aAAa,YAAY,gBAAgB;AACzE,UAAI,cAAc;AAChB,cAAM,KAAK,OAAO,cAAc,aAAa,OAAO,CAAC;AACrD,cAAM,aAAa,YAAY;AAAA,MACjC;AACA,WAAK,UAAU,SAAS;AAAA,IAC1B,QAAQ;AACN,WAAK,UAAU,OAAO;AACtB,YAAM,IAAI,MAAM,4BAA4B;AAAA,IAC9C;AAAA,EACF;AAAA,EAEQ,sBAAsB,cAAkC;AAC9D,UAAM,UAAU,IAAI,QAAQ,IAAK,aAAa,SAAS,KAAM,CAAC;AAC9D,UAAM,UAAU,eAAe,SAAS,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG;AAC5E,UAAM,UAAU,KAAK,MAAM;AAC3B,WAAO,WAAW,KAAK,CAAC,GAAG,OAAO,EAAE,IAAI,CAAC,SAAS,KAAK,WAAW,CAAC,CAAC,CAAC;AAAA,EACvE;AAAA,EAEQ,UAAU,QAAsC;AACtD,SAAK,SAAS;AACd,SAAK,gBAAgB,QAAQ,CAAC,aAAa,SAAS,MAAM,CAAC;AAAA,EAC7D;AACF;;;ACnIO,SAAS,+BACd,YACA,QACmD;AACnD,SAAO;AAAA,IACL,aAAa,OAAO,iBAAuC;AACzD,YAAM,WAAW,KAAK,2BAA2B;AAAA,QAC/C;AAAA,QACA;AAAA,QACA,WAAW,UAAU;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,IACA,eAAe,OAAO,iBAAuC;AAC3D,YAAM,WAAW;AAAA,QACf,kCAAkC,mBAAmB,MAAM,CAAC,aAAa,mBAAmB,aAAa,YAAY,EAAE,CAAC;AAAA,MAC1H;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/client/HttpClient.ts","../src/events/base/ChatEvent.ts","../src/events/MessagePostedEvent.ts","../src/events/MessageEditedEvent.ts","../src/events/MessageDeletedEvent.ts","../src/events/ReactionAddedEvent.ts","../src/events/ReactionRemovedEvent.ts","../src/events/TypingStartedEvent.ts","../src/events/StreamingChunkEvent.ts","../src/events/DMRequestedEvent.ts","../src/events/ChatEventFactory.ts","../src/utils/eventIdGenerator.ts","../src/client/WebChatClient.ts","../src/client/PusherBroadcastClient.ts","../src/client/LaravelEchoBroadcastClient.ts","../src/push/PushManager.ts","../src/push/PushSubscriptionManager.ts"],"sourcesContent":["export interface HttpClientConfig {\n apiUrl: string;\n headers?: Record<string, string>;\n timeout?: number;\n verifyToken?: string;\n}\n\nexport interface ChatResponse {\n id: string;\n role: \"assistant\" | \"user\";\n text: string;\n attachments?: Array<{\n type: string;\n url: string;\n name?: string;\n mime_type?: string;\n size?: number;\n }>;\n events?: Array<Record<string, unknown>>;\n}\n\nexport class HttpClient {\n private config: Required<Pick<HttpClientConfig, \"apiUrl\" | \"timeout\">> & {\n headers: Record<string, string>;\n };\n\n constructor(config: HttpClientConfig) {\n const headers: Record<string, string> = { ...config.headers };\n if (config.verifyToken) {\n headers[\"X-Verify-Token\"] = config.verifyToken;\n }\n this.config = { apiUrl: config.apiUrl, timeout: config.timeout ?? 30000, headers };\n }\n\n async get(url: string, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"GET\",\n headers: this.config.headers,\n signal: combined,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async post(url: string, body: unknown, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\", ...this.config.headers },\n signal: combined,\n body: JSON.stringify(body),\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async delete(url: string, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"DELETE\",\n headers: this.config.headers,\n signal: combined,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n const text = await response.text();\n return text ? JSON.parse(text) : undefined;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n async sendMessage(\n messages: Array<{\n id: string;\n role: string;\n text: string;\n attachments?: Array<{ url: string; name?: string; mime_type?: string; size?: number }>;\n }>,\n endpoint: string = \"/api/webhooks/web\",\n conversationId?: string,\n ): Promise<ChatResponse> {\n return this.post(endpoint, { id: conversationId, messages }) as Promise<ChatResponse>;\n }\n\n async sendAction(\n actionId: string,\n value: string,\n messageId: string,\n conversationId: string,\n endpoint: string = \"/api/webhooks/web\",\n ): Promise<Record<string, unknown>> {\n return this.post(endpoint, {\n id: conversationId,\n action: { actionId, value, messageId },\n }) as Promise<Record<string, unknown>>;\n }\n\n async editMessage(\n messageId: string,\n newText: string,\n endpointTemplate: string = \"/api/chat/messages/{id}/edit\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.post(url, { text: newText });\n }\n\n async deleteMessage(\n messageId: string,\n endpointTemplate: string = \"/api/chat/messages/{id}\",\n ): Promise<void> {\n const url = this.expandTemplate(endpointTemplate, { id: messageId });\n await this.delete(url);\n }\n\n async postFormData(url: string, formData: FormData, signal?: AbortSignal): Promise<unknown> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);\n\n try {\n const fullUrl = this.resolve(url);\n const combined = signal ? AbortSignal.any([controller.signal, signal]) : controller.signal;\n const response = await fetch(fullUrl, {\n method: \"POST\",\n headers: this.config.headers,\n signal: combined,\n body: formData,\n });\n if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n return response.json();\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n setHeader(name: string, value: string): void {\n this.config.headers[name] = value;\n }\n\n removeHeader(name: string): void {\n delete this.config.headers[name];\n }\n\n private resolve(url: string): string {\n return /^https?:\\/\\//.test(url) ? url : `${this.config.apiUrl}${url}`;\n }\n\n private expandTemplate(template: string, params: Record<string, string>): string {\n let url = template;\n for (const [key, value] of Object.entries(params)) {\n url = url.replace(`{${key}}`, encodeURIComponent(value));\n }\n return this.resolve(url);\n }\n}\n","export abstract class ChatEvent {\n readonly type: string;\n readonly threadId: string;\n readonly timestamp: number;\n\n constructor(type: string, threadId: string, timestamp: number) {\n this.type = type;\n this.threadId = threadId;\n this.timestamp = timestamp;\n }\n\n static fromJSON: ((json: Record<string, unknown>) => ChatEvent) | undefined;\n}\n\nexport class UnknownEvent extends ChatEvent {\n readonly data: Record<string, unknown>;\n\n constructor(type: string, threadId: string, data: Record<string, unknown>, timestamp: number) {\n super(type, threadId, timestamp);\n this.data = data;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User, Card } from \"../types\";\n\nexport class MessagePostedEvent extends ChatEvent {\n readonly messageId: string;\n readonly text: string;\n readonly author: User;\n readonly card?: Card;\n readonly attachments?: Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>;\n\n constructor(\n threadId: string,\n messageId: string,\n text: string,\n author: User,\n card?: Card,\n attachments?: Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>,\n timestamp?: number,\n ) {\n super(\"message.posted\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.text = text;\n this.author = author;\n this.card = card;\n this.attachments = attachments;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { Card } from \"../types\";\n\nexport class MessageEditedEvent extends ChatEvent {\n readonly messageId: string;\n readonly newText: string;\n readonly card?: Card;\n\n constructor(\n threadId: string,\n messageId: string,\n newText: string,\n card?: Card,\n timestamp?: number,\n ) {\n super(\"message.edited\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.newText = newText;\n this.card = card;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class MessageDeletedEvent extends ChatEvent {\n readonly messageId: string;\n\n constructor(threadId: string, messageId: string, timestamp?: number) {\n super(\"message.deleted\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User } from \"../types\";\n\nexport class ReactionAddedEvent extends ChatEvent {\n readonly messageId: string;\n readonly emoji: string;\n readonly user: User;\n\n constructor(threadId: string, messageId: string, emoji: string, user: User, timestamp?: number) {\n super(\"reaction.added\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.emoji = emoji;\n this.user = user;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\nimport type { User } from \"../types\";\n\nexport class ReactionRemovedEvent extends ChatEvent {\n readonly messageId: string;\n readonly emoji: string;\n readonly user: User;\n\n constructor(threadId: string, messageId: string, emoji: string, user: User, timestamp?: number) {\n super(\"reaction.removed\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.emoji = emoji;\n this.user = user;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class TypingStartedEvent extends ChatEvent {\n readonly userId: string;\n\n constructor(threadId: string, userId: string, timestamp?: number) {\n super(\"typing.started\", threadId, timestamp ?? Date.now());\n this.userId = userId;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class StreamingChunkEvent extends ChatEvent {\n readonly messageId: string;\n readonly chunk: string;\n readonly isFinal: boolean;\n\n constructor(\n threadId: string,\n messageId: string,\n chunk: string,\n isFinal: boolean,\n timestamp?: number,\n ) {\n super(\"streaming.chunk\", threadId, timestamp ?? Date.now());\n this.messageId = messageId;\n this.chunk = chunk;\n this.isFinal = isFinal;\n }\n}\n","import { ChatEvent } from \"./base/ChatEvent\";\n\nexport class DMRequestedEvent extends ChatEvent {\n readonly userId: string;\n\n constructor(threadId: string, userId: string, timestamp?: number) {\n super(\"dm.requested\", threadId, timestamp ?? Date.now());\n this.userId = userId;\n }\n}\n","import { ChatEvent, UnknownEvent } from \"./base/ChatEvent\";\nimport type { Card, User } from \"../types\";\nimport { MessagePostedEvent } from \"./MessagePostedEvent\";\nimport { MessageEditedEvent } from \"./MessageEditedEvent\";\nimport { MessageDeletedEvent } from \"./MessageDeletedEvent\";\nimport { ReactionAddedEvent } from \"./ReactionAddedEvent\";\nimport { ReactionRemovedEvent } from \"./ReactionRemovedEvent\";\nimport { TypingStartedEvent } from \"./TypingStartedEvent\";\nimport { StreamingChunkEvent } from \"./StreamingChunkEvent\";\nimport { DMRequestedEvent } from \"./DMRequestedEvent\";\n\nfunction parseCard(value: unknown): Card | undefined {\n if (!value || typeof value !== \"object\") return undefined;\n const obj = value as Record<string, unknown>;\n if (typeof obj.type !== \"string\") return undefined;\n return obj as unknown as Card;\n}\n\nexport function parseChatEvent(json: Record<string, unknown>): ChatEvent {\n const type = json.type as string;\n const threadId = json.threadId as string;\n const timestamp = json.timestamp as number;\n const data = (json.data ?? {}) as Record<string, unknown>;\n\n switch (type) {\n case \"message.posted\":\n return new MessagePostedEvent(\n threadId,\n data.messageId as string,\n data.text as string,\n data.author as User,\n parseCard(data.card),\n data.attachments as Array<{\n type: string;\n url?: string;\n name?: string;\n mimeType?: string;\n size?: number | null;\n }>,\n timestamp,\n );\n case \"message.edited\":\n return new MessageEditedEvent(\n threadId,\n data.messageId as string,\n data.newText as string,\n parseCard(data.card),\n timestamp,\n );\n case \"message.deleted\":\n return new MessageDeletedEvent(threadId, data.messageId as string, timestamp);\n case \"reaction.added\":\n return new ReactionAddedEvent(\n threadId,\n data.messageId as string,\n data.emoji as string,\n data.user as User,\n timestamp,\n );\n case \"reaction.removed\":\n return new ReactionRemovedEvent(\n threadId,\n data.messageId as string,\n data.emoji as string,\n data.user as User,\n timestamp,\n );\n case \"typing.started\":\n return new TypingStartedEvent(threadId, data.userId as string, timestamp);\n case \"streaming.chunk\":\n return new StreamingChunkEvent(\n threadId,\n data.messageId as string,\n data.chunk as string,\n data.isFinal as boolean,\n timestamp,\n );\n case \"dm.requested\":\n return new DMRequestedEvent(threadId, data.userId as string, timestamp);\n default:\n return new UnknownEvent(type, threadId, data, timestamp);\n }\n}\n\n// Wire up the static method\nChatEvent.fromJSON = parseChatEvent;\n","export function generateId(): string {\n return `msg-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n\nexport function generateConversationId(): string {\n return `conv-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n}\n","import { HttpClient } from \"./HttpClient\";\nimport type { BroadcastClient, EventHandlers, Unsubscribe } from \"./BroadcastClient\";\nimport type { Message } from \"../types\";\nimport { ChatEvent } from \"../events/base/ChatEvent\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type { MessagePostedEvent } from \"../events/MessagePostedEvent\";\nimport type { MessageEditedEvent } from \"../events/MessageEditedEvent\";\nimport type { MessageDeletedEvent } from \"../events/MessageDeletedEvent\";\nimport { ReactionAddedEvent } from \"../events/ReactionAddedEvent\";\nimport { ReactionRemovedEvent } from \"../events/ReactionRemovedEvent\";\nimport type { TypingStartedEvent } from \"../events/TypingStartedEvent\";\nimport type { StreamingChunkEvent } from \"../events/StreamingChunkEvent\";\nimport type { DMRequestedEvent } from \"../events/DMRequestedEvent\";\nimport { generateId, generateConversationId } from \"../utils/eventIdGenerator\";\n\nexport interface ReconfigureConfig {\n userId?: string;\n userName?: string;\n verifyToken?: string;\n conversationId?: string;\n headers?: Record<string, string>;\n}\n\nexport interface WebChatClientConfig {\n apiUrl: string;\n userId: string;\n userName: string;\n broadcastClient?: BroadcastClient;\n headers?: Record<string, string>;\n verifyToken?: string;\n conversationId?: string;\n endpoints?: {\n sendMessage?: string;\n loadMessages?: string;\n editMessage?: string;\n deleteMessage?: string;\n };\n features?: {\n editMessages?: boolean;\n deleteMessages?: boolean;\n reactions?: boolean;\n };\n}\n\ninterface StreamingState {\n messageId: string;\n accumulatedText: string;\n isComplete: boolean;\n}\n\ninterface AttachmentInput {\n url: string;\n name?: string;\n mimeType?: string;\n size?: number;\n}\n\nexport interface LoadMessagesOptions {\n limit?: number;\n before?: number;\n after?: number;\n skipStateSeed?: boolean;\n}\n\nexport interface LoadMessagesResult {\n messages: Message[];\n hasMore: boolean;\n nextCursor?: number;\n prevCursor?: number;\n}\n\nexport class WebChatClient {\n private config: WebChatClientConfig;\n private httpClient: HttpClient;\n private broadcastClient?: BroadcastClient;\n private conversationId: string;\n private messages: Message[] = [];\n private currentUserId: string;\n private eventHandlers: EventHandlers = {};\n private streamingMessages: Map<string, StreamingState> = new Map();\n private pendingTyping: ReturnType<typeof setTimeout> | null = null;\n private subscribers: Map<string, Array<(event: unknown) => void>> = new Map();\n private sendQueue: Array<() => Promise<void>> = [];\n private isProcessingQueue = false;\n private unsubscribeUserChannel?: Unsubscribe;\n\n constructor(config: WebChatClientConfig) {\n this.config = config;\n this.httpClient = new HttpClient({\n apiUrl: config.apiUrl,\n headers: {\n \"X-User-Id\": config.userId,\n \"X-User-Name\": config.userName,\n ...(config.headers ?? {}),\n },\n verifyToken: config.verifyToken,\n });\n this.broadcastClient = config.broadcastClient;\n this.conversationId = config.conversationId ?? generateConversationId();\n this.currentUserId = config.userId;\n }\n\n reconfigure(config: ReconfigureConfig): void {\n if (config.userId) {\n this.currentUserId = config.userId;\n this.httpClient.setHeader(\"X-User-Id\", config.userId);\n }\n if (config.userName) {\n this.config = { ...this.config, userName: config.userName };\n this.httpClient.setHeader(\"X-User-Name\", config.userName);\n }\n if (config.verifyToken) {\n this.config = { ...this.config, verifyToken: config.verifyToken };\n this.httpClient.setHeader(\"X-Verify-Token\", config.verifyToken);\n }\n if (config.conversationId) {\n this.conversationId = config.conversationId;\n }\n if (config.headers) {\n Object.entries(config.headers).forEach(([key, value]) => {\n this.httpClient.setHeader(key, value);\n });\n }\n }\n\n setLocaleHeader(locale: string): void {\n this.httpClient.setHeader(\"X-Locale\", locale);\n this.httpClient.setHeader(\"X-Language\", locale.split(\"-\")[0] ?? locale);\n }\n\n setTimezoneHeader(timezone: string): void {\n this.httpClient.setHeader(\"X-Timezone\", timezone);\n }\n\n async connect(): Promise<void> {\n if (this.broadcastClient) {\n this.broadcastClient.connect();\n\n const threadId = this.getThreadId();\n const threadEvents: EventHandlers = {\n onMessagePosted: (event) => this.handleMessagePosted(event),\n };\n\n if (this.config.features?.editMessages) {\n threadEvents.onMessageEdited = (event) => this.handleMessageEdited(event);\n }\n if (this.config.features?.deleteMessages) {\n threadEvents.onMessageDeleted = (event) => this.handleMessageDeleted(event);\n }\n if (this.config.features?.reactions) {\n threadEvents.onReactionAdded = (event) => this.handleReactionAdded(event);\n threadEvents.onReactionRemoved = (event) => this.handleReactionRemoved(event);\n }\n\n threadEvents.onTypingStarted = (event) => this.handleTypingStarted(event);\n\n await this.broadcastClient.subscribe(threadId, threadEvents);\n\n this.unsubscribeUserChannel = await this.broadcastClient.subscribeToUser(\n threadId,\n this.currentUserId,\n {\n onStreamingChunk: (event) => this.handleStreamingChunk(event),\n onDMRequested: (event) => this.handleDMRequested(event),\n },\n );\n }\n }\n\n disconnect(): void {\n this.unsubscribeUserChannel?.();\n this.unsubscribeUserChannel = undefined;\n this.broadcastClient?.disconnect();\n this.streamingMessages.clear();\n }\n\n async loadMessages(\n options?: LoadMessagesOptions,\n signal?: AbortSignal,\n ): Promise<LoadMessagesResult> {\n const endpoint = this.config.endpoints?.loadMessages ?? \"/api/chat/messages\";\n const threadId = this.getThreadId();\n const params = new URLSearchParams({\n threadId,\n limit: String(options?.limit ?? 50),\n });\n if (options?.before) params.set(\"before\", String(options.before));\n if (options?.after) params.set(\"after\", String(options.after));\n\n const response = (await this.httpClient.get(\n `${endpoint}?${params.toString()}`,\n signal,\n )) as Record<string, unknown>;\n const rawMessages = (response.messages as Record<string, unknown>[]) ?? [];\n const messages: Message[] = rawMessages.map((msg) => ({\n id: msg.id as string,\n threadId,\n content: {\n text: msg.text as string,\n cards: msg.card ? ([msg.card as Record<string, unknown>] as never[]) : undefined,\n },\n author: {\n id: (msg.author as Record<string, unknown>).id as string,\n name: (msg.author as Record<string, unknown>).name as string,\n isBot: ((msg.author as Record<string, unknown>).isBot as boolean) ?? false,\n isMe: (msg.author as Record<string, unknown>).id === this.currentUserId,\n },\n timestamp: msg.timestamp as number,\n attachments: (msg.attachments as Record<string, unknown>[])?.map((a) => ({\n id: `att-${msg.id as string}-${a.url as string}`,\n url: a.url as string,\n name: a.name as string,\n type: a.type as string,\n mimeType: a.mime_type as string,\n size: a.size as number,\n })),\n reactions: (msg.reactions as { emoji: string; count: number; users: string[] }[]) ?? [],\n }));\n\n if (!options?.before && !options?.after && !options?.skipStateSeed) {\n this.messages = messages;\n this.notifySubscribers(\"messages:loaded\", messages);\n }\n\n return {\n messages,\n hasMore: (response.hasMore as boolean) ?? false,\n nextCursor: response.nextCursor as number | undefined,\n prevCursor: response.prevCursor as number | undefined,\n };\n }\n\n async sendMessage(text: string, attachments: AttachmentInput[] = []): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n this.sendQueue.push(async () => {\n try {\n await this.executeSend(text, attachments);\n resolve();\n } catch (e) {\n reject(e);\n }\n });\n this.processQueue();\n });\n }\n\n private async processQueue(): Promise<void> {\n if (this.isProcessingQueue) return;\n this.isProcessingQueue = true;\n try {\n while (this.sendQueue.length > 0) {\n const task = this.sendQueue.shift()!;\n await task();\n }\n } finally {\n this.isProcessingQueue = false;\n }\n }\n\n private async executeSend(text: string, attachments: AttachmentInput[] = []): Promise<void> {\n const messageId = generateId();\n\n const userMessage: Message = {\n id: messageId,\n threadId: this.getThreadId(),\n content: { text },\n author: { id: this.currentUserId, name: this.config.userName, isMe: true },\n timestamp: Date.now(),\n attachments:\n attachments.length > 0\n ? attachments.map((a, i) => ({\n id: `att-${messageId}-${i}`,\n name: a.name ?? \"\",\n url: a.url,\n size: a.size,\n mimeType: a.mimeType,\n }))\n : undefined,\n };\n\n this.messages.push(userMessage);\n this.notifySubscribers(\"message:added\", userMessage);\n\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = await this.httpClient.sendMessage(\n [\n {\n id: messageId,\n role: \"user\",\n text,\n attachments: attachments.map((a) => ({\n url: a.url,\n name: a.name,\n mime_type: a.mimeType,\n size: a.size,\n })),\n },\n ],\n endpoint,\n this.conversationId,\n );\n\n if (response.events) {\n response.events.forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n\n if (response.text && !response.events?.some((e) => e.type === \"message.posted\")) {\n const assistantMessage: Message = {\n id: response.id ?? generateId(),\n threadId: this.getThreadId(),\n content: { text: response.text },\n author: { id: \"assistant\", name: \"Assistant\", isBot: true },\n timestamp: Date.now(),\n attachments: (response.attachments as Record<string, unknown>[])?.map((a, i) => ({\n id: `att-${response.id ?? \"msg\"}-${i}`,\n name: (a.name as string) ?? \"\",\n url: (a.url as string) ?? \"\",\n type: a.type as string,\n mimeType: a.mime_type as string,\n size: a.size as number,\n })),\n };\n this.messages.push(assistantMessage);\n this.notifySubscribers(\"message:added\", assistantMessage);\n }\n }\n\n async sendAction(messageId: string, actionId: string, value: string): Promise<void> {\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = await this.httpClient.sendAction(\n actionId,\n value,\n messageId,\n this.conversationId,\n endpoint,\n );\n\n if (response.events) {\n (response.events as Array<Record<string, unknown>>).forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n }\n\n async editMessage(messageId: string, newText: string): Promise<void> {\n if (!this.config.features?.editMessages) {\n throw new Error(\"Edit messages not enabled. Set features.editMessages = true in config.\");\n }\n const endpoint = this.config.endpoints?.editMessage ?? \"/api/chat/messages/{id}/edit\";\n await this.httpClient.editMessage(messageId, newText, endpoint);\n }\n\n async deleteMessage(messageId: string): Promise<void> {\n if (!this.config.features?.deleteMessages) {\n throw new Error(\"Delete messages not enabled. Set features.deleteMessages = true in config.\");\n }\n const endpoint = this.config.endpoints?.deleteMessage ?? \"/api/chat/messages/{id}\";\n await this.httpClient.deleteMessage(messageId, endpoint);\n }\n\n async addReaction(messageId: string, emoji: string): Promise<void> {\n if (!this.config.features?.reactions) {\n throw new Error(\"Reactions not enabled. Set features.reactions = true in config.\");\n }\n\n // Optimistic local update\n this.handleReactionAdded(\n new ReactionAddedEvent(this.getThreadId(), messageId, emoji, { id: this.currentUserId }),\n );\n\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = (await this.httpClient.post(endpoint, {\n id: this.conversationId,\n reaction: { messageId, emoji, added: true },\n })) as Record<string, unknown>;\n\n if (response.events) {\n (response.events as Array<Record<string, unknown>>).forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n }\n\n async removeReaction(messageId: string, emoji: string): Promise<void> {\n if (!this.config.features?.reactions) {\n throw new Error(\"Reactions not enabled. Set features.reactions = true in config.\");\n }\n\n // Optimistic local update\n this.handleReactionRemoved(\n new ReactionRemovedEvent(this.getThreadId(), messageId, emoji, { id: this.currentUserId }),\n );\n\n const endpoint = this.config.endpoints?.sendMessage ?? \"/api/webhooks/web\";\n const response = (await this.httpClient.post(endpoint, {\n id: this.conversationId,\n reaction: { messageId, emoji, added: false },\n })) as Record<string, unknown>;\n\n if (response.events) {\n (response.events as Array<Record<string, unknown>>).forEach((eventData) => {\n const event = parseChatEvent(eventData);\n this.dispatchEvent(event);\n });\n }\n }\n\n onMessagePosted(handler: (event: MessagePostedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message.posted\", handler);\n }\n\n onMessageEdited(handler: (event: MessageEditedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message:edited\", handler);\n }\n\n onMessageDeleted(handler: (event: MessageDeletedEvent) => void): Unsubscribe {\n return this.addEventListener(\"message:deleted\", handler);\n }\n\n onReactionAdded(handler: (event: ReactionAddedEvent) => void): Unsubscribe {\n return this.addEventListener(\"reaction:added\", handler);\n }\n\n onReactionRemoved(handler: (event: ReactionRemovedEvent) => void): Unsubscribe {\n return this.addEventListener(\"reaction:removed\", handler);\n }\n\n onStreamingChunk(handler: (event: StreamingChunkEvent) => void): Unsubscribe {\n return this.addEventListener(\"streaming:chunk\", handler);\n }\n\n onTypingStarted(handler: (event: TypingStartedEvent) => void): Unsubscribe {\n return this.addEventListener(\"typing:started\", handler);\n }\n\n getConversationId(): string {\n return this.conversationId;\n }\n getMessages(): Message[] {\n return [...this.messages];\n }\n getThreadId(): string {\n return `web:${this.currentUserId}:${this.conversationId}`;\n }\n getCurrentUserId(): string {\n return this.currentUserId;\n }\n getFeatures(): NonNullable<WebChatClientConfig[\"features\"]> {\n return this.config.features ?? {};\n }\n getEndpoints(): NonNullable<WebChatClientConfig[\"endpoints\"]> {\n return this.config.endpoints ?? {};\n }\n getHttpClient(): HttpClient {\n return this.httpClient;\n }\n\n addEventListener<T = unknown>(eventType: string, handler: (event: T) => void): Unsubscribe {\n if (!this.subscribers.has(eventType)) this.subscribers.set(eventType, []);\n this.subscribers.get(eventType)!.push(handler as (event: unknown) => void);\n return () => {\n const handlers = this.subscribers.get(eventType);\n if (handlers) {\n const index = handlers.indexOf(handler as (event: unknown) => void);\n if (index !== -1) handlers.splice(index, 1);\n }\n };\n }\n\n private handleMessagePosted(event: MessagePostedEvent): void {\n if (this.messages.some((m) => m.id === event.messageId)) return;\n if (this.streamingMessages.has(event.messageId)) return;\n\n const message: Message = {\n id: event.messageId,\n threadId: event.threadId,\n content: { text: event.text, cards: event.card ? [event.card] : undefined },\n author: event.author,\n timestamp: event.timestamp,\n attachments: event.attachments?.map((a) => ({\n id: `att-${event.messageId}-${Math.random().toString(36).slice(2, 8)}`,\n name: a.name ?? \"\",\n url: a.url ?? \"\",\n type: a.type,\n mimeType: a.mimeType,\n size: a.size ?? undefined,\n })),\n };\n this.messages.push(message);\n this.notifySubscribers(\"message:added\", message);\n this.notifySubscribers(\"message.posted\", event);\n }\n\n private handleMessageEdited(event: MessageEditedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (message?.content) {\n message.content.text = event.newText;\n this.notifySubscribers(\"message:edited\", event);\n }\n }\n\n private handleMessageDeleted(event: MessageDeletedEvent): void {\n const index = this.messages.findIndex((m) => m.id === event.messageId);\n if (index !== -1) {\n this.messages.splice(index, 1);\n this.notifySubscribers(\"message:deleted\", event);\n }\n }\n\n private handleReactionAdded(event: ReactionAddedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (message) {\n if (!message.reactions) message.reactions = [];\n\n const existing = message.reactions.find((r) => r.emoji === event.emoji);\n if (existing) {\n existing.count++;\n existing.users.push(event.user.id);\n } else {\n message.reactions.push({ emoji: event.emoji, count: 1, users: [event.user.id] });\n }\n }\n this.notifySubscribers(\"reaction:added\", event);\n }\n\n private handleReactionRemoved(event: ReactionRemovedEvent): void {\n const message = this.messages.find((m) => m.id === event.messageId);\n if (message?.reactions) {\n const index = message.reactions.findIndex((r) => r.emoji === event.emoji);\n if (index !== -1) {\n const reaction = message.reactions[index]!;\n reaction.count--;\n reaction.users = reaction.users.filter((id) => id !== event.user.id);\n if (reaction.count === 0) message.reactions.splice(index, 1);\n }\n }\n this.notifySubscribers(\"reaction:removed\", event);\n }\n\n private handleStreamingChunk(event: StreamingChunkEvent): void {\n const { messageId, chunk, isFinal } = event;\n\n if (!this.streamingMessages.has(messageId)) {\n this.streamingMessages.set(messageId, { messageId, accumulatedText: \"\", isComplete: false });\n this.notifySubscribers(\"streaming:started\", event);\n }\n\n const state = this.streamingMessages.get(messageId)!;\n state.accumulatedText += chunk;\n\n if (isFinal) {\n state.isComplete = true;\n if (!this.messages.some((m) => m.id === messageId)) {\n const message: Message = {\n id: messageId,\n threadId: event.threadId,\n content: { text: state.accumulatedText },\n author: { id: \"assistant\", name: \"Assistant\", isBot: true },\n timestamp: event.timestamp,\n };\n this.messages.push(message);\n this.notifySubscribers(\"message:added\", message);\n }\n this.streamingMessages.delete(messageId);\n this.notifySubscribers(\"streaming:complete\", { messageId, text: state.accumulatedText });\n } else {\n this.notifySubscribers(\"streaming:chunk\", event);\n }\n }\n\n private handleTypingStarted(event: TypingStartedEvent): void {\n if (this.pendingTyping) clearTimeout(this.pendingTyping);\n this.notifySubscribers(\"typing:started\", event);\n this.pendingTyping = setTimeout(() => {\n this.notifySubscribers(\"typing:stopped\", { userId: event.userId });\n }, 3000);\n }\n\n private handleDMRequested(event: DMRequestedEvent): void {\n this.notifySubscribers(\"dm.requested\", event);\n }\n\n private notifySubscribers<T>(eventType: string, data: T): void {\n this.subscribers.get(eventType)?.forEach((handler) => handler(data));\n }\n\n private dispatchEvent(event: ChatEvent): void {\n switch (event.type) {\n case \"message.posted\":\n this.handleMessagePosted(event as MessagePostedEvent);\n break;\n case \"message.edited\":\n this.handleMessageEdited(event as MessageEditedEvent);\n break;\n case \"message.deleted\":\n this.handleMessageDeleted(event as MessageDeletedEvent);\n break;\n case \"reaction.added\":\n this.handleReactionAdded(event as ReactionAddedEvent);\n break;\n case \"reaction.removed\":\n this.handleReactionRemoved(event as ReactionRemovedEvent);\n break;\n case \"typing.started\":\n this.handleTypingStarted(event as TypingStartedEvent);\n break;\n case \"streaming.chunk\":\n this.handleStreamingChunk(event as StreamingChunkEvent);\n break;\n case \"dm.requested\":\n this.handleDMRequested(event as DMRequestedEvent);\n break;\n }\n }\n}\n","import {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./BroadcastClient\";\nimport { ChatEvent } from \"../events/base/ChatEvent\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type Pusher from \"pusher-js\";\nimport type { Channel as PusherChannel } from \"pusher-js\";\n\nexport interface PusherConfig {\n key: string;\n cluster?: string;\n host?: string;\n port?: number;\n forceTLS?: boolean;\n authEndpoint?: string;\n}\n\nexport class PusherBroadcastClient implements BroadcastClient {\n private pusher: Pusher;\n private channelPrefix: string;\n private threadChannelType: \"public\" | \"private\" | \"presence\";\n private userChannelType: \"private\" | \"presence\";\n private useHashChannel: boolean;\n private subscriptions: Map<string, PusherChannel> = new Map();\n\n constructor(pusher: Pusher, channelPrefix?: string, channelTypes?: ChannelTypeConfig);\n constructor(config: PusherConfig, channelPrefix?: string, channelTypes?: ChannelTypeConfig);\n constructor(\n pusherOrConfig: Pusher | PusherConfig,\n channelPrefix: string = \"chat\",\n channelTypes?: ChannelTypeConfig,\n ) {\n this.channelPrefix = channelPrefix;\n this.threadChannelType = channelTypes?.threadChannel ?? \"public\";\n this.userChannelType = channelTypes?.userChannel ?? \"private\";\n this.useHashChannel = channelTypes?.useHashChannel ?? false;\n\n if (\"key\" in pusherOrConfig) {\n const PusherCtor = (globalThis as any).Pusher ?? (globalThis as any).pusherJs;\n if (!PusherCtor) {\n throw new Error(\"pusher-js not found. Install it or pass a Pusher instance.\");\n }\n this.pusher = new PusherCtor((pusherOrConfig as PusherConfig).key, pusherOrConfig) as Pusher;\n } else {\n this.pusher = pusherOrConfig as Pusher;\n }\n }\n\n private buildChannelName(base: string, type: \"public\" | \"private\" | \"presence\"): string {\n switch (type) {\n case \"private\":\n return `private-${base}`;\n case \"presence\":\n return `presence-${base}`;\n default:\n return base;\n }\n }\n\n protected async buildResolvedChannelName(threadId: string): Promise<string> {\n const name = this.useHashChannel ? await this.hashChannelName(threadId) : threadId;\n\n return `${this.channelPrefix}.${name}`;\n }\n\n private async hashChannelName(name: string): Promise<string> {\n if (typeof crypto?.subtle?.digest !== \"function\") {\n throw new Error(\"Web Crypto API not available. Cannot hash channel names.\");\n }\n const encoder = new TextEncoder();\n const data = encoder.encode(name);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n connect(): void {\n if (this.pusher.connection?.state !== \"connected\") {\n this.pusher.connect();\n }\n }\n\n disconnect(): void {\n this.subscriptions.forEach((channel) => channel.unbind_all?.() ?? channel.unsubscribe?.());\n this.subscriptions.clear();\n this.pusher.disconnect?.();\n }\n\n async subscribe(threadId: string, handlers: EventHandlers): Promise<Unsubscribe> {\n const baseName = await this.buildResolvedChannelName(threadId);\n const channelName = this.buildChannelName(baseName, this.threadChannelType);\n const channel = this.pusher.subscribe(channelName);\n const key = `thread:${threadId}`;\n this.subscriptions.set(key, channel);\n\n const threadEvents = [\n \"message.posted\",\n \"message.edited\",\n \"message.deleted\",\n \"reaction.added\",\n \"reaction.removed\",\n \"typing.started\",\n ] as const;\n\n threadEvents.forEach((eventType) => {\n const eventName = `${this.channelPrefix}.${eventType}`;\n channel.bind(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n this.dispatchToHandler(event, handlers);\n });\n });\n\n return () => {\n channel.unbind_all?.();\n this.pusher.unsubscribe(channelName);\n this.subscriptions.delete(key);\n };\n }\n\n async subscribeToUser(\n threadId: string,\n userId: string,\n handlers: EventHandlers,\n ): Promise<Unsubscribe> {\n const baseName = `${await this.buildResolvedChannelName(threadId)}.${userId}`;\n const channelName = this.buildChannelName(baseName, this.userChannelType);\n const channel = this.pusher.subscribe(channelName);\n const key = `user:${threadId}:${userId}`;\n this.subscriptions.set(key, channel);\n\n const userEvents = [\"typing.started\", \"streaming.chunk\", \"dm.requested\"] as const;\n\n userEvents.forEach((eventType) => {\n const eventName = `${this.channelPrefix}.${eventType}`;\n channel.bind(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n this.dispatchToHandler(event, handlers);\n });\n });\n\n return () => {\n channel.unbind_all?.();\n this.pusher.unsubscribe(channelName);\n this.subscriptions.delete(key);\n };\n }\n\n isConnected(): boolean {\n return this.pusher.connection?.state === \"connected\";\n }\n\n private dispatchToHandler(event: ChatEvent, handlers: EventHandlers): void {\n switch (event.type) {\n case \"message.posted\":\n handlers.onMessagePosted?.(event as any);\n break;\n case \"message.edited\":\n handlers.onMessageEdited?.(event as any);\n break;\n case \"message.deleted\":\n handlers.onMessageDeleted?.(event as any);\n break;\n case \"reaction.added\":\n handlers.onReactionAdded?.(event as any);\n break;\n case \"reaction.removed\":\n handlers.onReactionRemoved?.(event as any);\n break;\n case \"typing.started\":\n handlers.onTypingStarted?.(event as any);\n break;\n case \"streaming.chunk\":\n handlers.onStreamingChunk?.(event as any);\n break;\n case \"dm.requested\":\n handlers.onDMRequested?.(event as any);\n break;\n }\n }\n}\n","import {\n type BroadcastClient,\n type EventHandlers,\n type Unsubscribe,\n type ChannelTypeConfig,\n} from \"./BroadcastClient\";\nimport { parseChatEvent } from \"../events/ChatEventFactory\";\nimport type Echo from \"laravel-echo\";\n\ninterface EchoChannel {\n listen(event: string, callback: (data: unknown) => void): this;\n unsubscribe(): void;\n stopListening(event?: string, callback?: (data: unknown) => void): this;\n}\n\nexport class LaravelEchoBroadcastClient implements BroadcastClient {\n private echo: Echo<any>;\n private channelPrefix: string;\n private threadChannelType: \"public\" | \"private\" | \"presence\";\n private userChannelType: \"private\" | \"presence\";\n private useHashChannel: boolean;\n private subscriptions: Map<string, EchoChannel> = new Map();\n\n constructor(echo: Echo<any>, channelPrefix: string = \"chat\", channelTypes?: ChannelTypeConfig) {\n this.echo = echo;\n this.channelPrefix = channelPrefix;\n this.threadChannelType = channelTypes?.threadChannel ?? \"public\";\n this.userChannelType = channelTypes?.userChannel ?? \"private\";\n this.useHashChannel = channelTypes?.useHashChannel ?? false;\n }\n\n private subscribeToEcho(name: string, type: \"public\" | \"private\" | \"presence\"): EchoChannel {\n switch (type) {\n case \"private\":\n return this.echo.private(name) as unknown as EchoChannel;\n case \"presence\":\n return this.echo.join(name) as unknown as EchoChannel;\n default:\n return this.echo.channel(name) as unknown as EchoChannel;\n }\n }\n\n connect(): void | Promise<void> {\n return Promise.resolve();\n }\n\n disconnect(): void {\n this.subscriptions.forEach((channel) => {\n channel.unsubscribe?.();\n channel.stopListening?.();\n });\n this.subscriptions.clear();\n }\n\n protected async buildResolvedChannelName(threadId: string): Promise<string> {\n const name = this.useHashChannel ? await this.hashChannelName(threadId) : threadId;\n\n return `${this.channelPrefix}.${name}`;\n }\n\n private async hashChannelName(name: string): Promise<string> {\n if (typeof crypto?.subtle?.digest !== \"function\") {\n throw new Error(\"Web Crypto API not available. Cannot hash channel names.\");\n }\n const encoder = new TextEncoder();\n const data = encoder.encode(name);\n const hashBuffer = await crypto.subtle.digest(\"SHA-256\", data);\n const hashArray = Array.from(new Uint8Array(hashBuffer));\n return hashArray.map((b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n }\n\n async subscribe(threadId: string, handlers: EventHandlers): Promise<Unsubscribe> {\n const channelName = await this.buildResolvedChannelName(threadId);\n const channel = this.subscribeToEcho(channelName, this.threadChannelType);\n const key = `thread:${threadId}`;\n this.subscriptions.set(key, channel);\n\n const threadEvents: Array<{ type: string; handler: keyof EventHandlers }> = [\n { type: \"message.posted\", handler: \"onMessagePosted\" },\n { type: \"message.edited\", handler: \"onMessageEdited\" },\n { type: \"message.deleted\", handler: \"onMessageDeleted\" },\n { type: \"reaction.added\", handler: \"onReactionAdded\" },\n { type: \"reaction.removed\", handler: \"onReactionRemoved\" },\n { type: \"typing.started\", handler: \"onTypingStarted\" },\n ];\n\n threadEvents.forEach(({ type, handler }) => {\n const eventName = `.${this.channelPrefix}.${type}`;\n channel.listen(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n (handlers[handler] as any)?.(event);\n });\n });\n\n return () => {\n channel.unsubscribe?.();\n this.subscriptions.delete(key);\n };\n }\n\n async subscribeToUser(\n threadId: string,\n userId: string,\n handlers: EventHandlers,\n ): Promise<Unsubscribe> {\n const channelName = `${await this.buildResolvedChannelName(threadId)}.${userId}`;\n const channel = this.subscribeToEcho(channelName, this.userChannelType);\n const key = `user:${threadId}:${userId}`;\n this.subscriptions.set(key, channel);\n\n const userEvents: Array<{ type: string; handler: keyof EventHandlers }> = [\n { type: \"typing.started\", handler: \"onTypingStarted\" },\n { type: \"streaming.chunk\", handler: \"onStreamingChunk\" },\n { type: \"dm.requested\", handler: \"onDMRequested\" },\n ];\n\n userEvents.forEach(({ type, handler }) => {\n const eventName = `.${this.channelPrefix}.${type}`;\n channel.listen(eventName, (data: unknown) => {\n const event = parseChatEvent(data as Record<string, unknown>);\n (handlers[handler] as any)?.(event);\n });\n });\n\n return () => {\n channel.unsubscribe?.();\n this.subscriptions.delete(key);\n };\n }\n\n isConnected(): boolean {\n try {\n const connector = (this.echo as any).connector;\n if (!connector) return false;\n\n if (connector.pusher?.connection?.state === \"connected\") return true;\n if (connector.socket?.connected) return true;\n\n return false;\n } catch {\n return false;\n }\n }\n}\n","import type { PushConfig, PushSubscriptionStatus, PushEventData } from \"./types\";\n\nexport class PushManager {\n private config: PushConfig;\n private registration: ServiceWorkerRegistration | null = null;\n private status: PushSubscriptionStatus = \"unsupported\";\n private statusListeners: Set<(status: PushSubscriptionStatus) => void> = new Set();\n private messageListeners: Set<(data: PushEventData) => void> = new Set();\n\n constructor(config: PushConfig) {\n this.config = config;\n }\n\n static isSupported(): boolean {\n return (\n typeof navigator !== \"undefined\" &&\n \"serviceWorker\" in navigator &&\n \"PushManager\" in window &&\n \"Notification\" in window\n );\n }\n\n getStatus(): PushSubscriptionStatus {\n return this.status;\n }\n\n onStatusChange(listener: (status: PushSubscriptionStatus) => void): () => void {\n this.statusListeners.add(listener);\n return () => {\n this.statusListeners.delete(listener);\n };\n }\n\n onMessage(listener: (data: PushEventData) => void): () => void {\n this.messageListeners.add(listener);\n return () => {\n this.messageListeners.delete(listener);\n };\n }\n\n async initialize(): Promise<void> {\n if (!PushManager.isSupported()) {\n this.setStatus(\"unsupported\");\n return;\n }\n if (Notification.permission === \"denied\") {\n this.setStatus(\"denied\");\n return;\n }\n\n try {\n this.registration = await navigator.serviceWorker.register(\n this.config.serviceWorkerUrl || \"/chat-service-worker.js\",\n {\n scope: this.config.serviceWorkerScope || \"/\",\n type: this.config.serviceWorkerType,\n },\n );\n await navigator.serviceWorker.ready;\n\n navigator.serviceWorker.addEventListener(\"message\", (event: MessageEvent) => {\n const msg = event.data as Record<string, unknown>;\n if (msg?.type === \"chat-widget:push-data\") {\n const pushData = msg.data as PushEventData;\n this.messageListeners.forEach((listener) => listener(pushData));\n }\n });\n\n const subscription = await this.registration.pushManager.getSubscription();\n this.setStatus(subscription ? \"subscribed\" : \"default\");\n } catch {\n this.setStatus(\"error\");\n }\n }\n\n async subscribe(): Promise<void> {\n if (!this.registration)\n throw new Error(\"PushManager not initialized. Call initialize() first.\");\n\n this.setStatus(\"subscribing\");\n\n try {\n let subscription = await this.registration.pushManager.getSubscription();\n\n if (!subscription) {\n const permission = await Notification.requestPermission();\n if (permission !== \"granted\") {\n this.setStatus(permission === \"denied\" ? \"denied\" : \"default\");\n return;\n }\n\n const vapidPublicKey = await this.config.getVapidPublicKey();\n const convertedKey = this.urlBase64ToUint8Array(vapidPublicKey);\n subscription = await this.registration.pushManager.subscribe({\n userVisibleOnly: true,\n applicationServerKey: convertedKey.buffer as ArrayBuffer,\n });\n }\n\n await this.config.onSubscribe(subscription.toJSON());\n this.setStatus(\"subscribed\");\n } catch {\n this.setStatus(\"error\");\n throw new Error(\"Push subscription failed\");\n }\n }\n\n async unsubscribe(): Promise<void> {\n if (!this.registration) return;\n\n try {\n const subscription = await this.registration.pushManager.getSubscription();\n if (subscription) {\n await this.config.onUnsubscribe(subscription.toJSON());\n await subscription.unsubscribe();\n }\n this.setStatus(\"default\");\n } catch {\n this.setStatus(\"error\");\n throw new Error(\"Push unsubscription failed\");\n }\n }\n\n private urlBase64ToUint8Array(base64String: string): Uint8Array {\n const padding = \"=\".repeat((4 - (base64String.length % 4)) % 4);\n const base64 = (base64String + padding).replace(/-/g, \"+\").replace(/_/g, \"/\");\n const rawData = atob(base64);\n return Uint8Array.from([...rawData].map((char) => char.charCodeAt(0)));\n }\n\n private setStatus(status: PushSubscriptionStatus): void {\n this.status = status;\n this.statusListeners.forEach((listener) => listener(status));\n }\n}\n","import { HttpClient } from \"../client/HttpClient\";\nimport type { PushConfig } from \"./types\";\n\nexport function createPushSubscriptionHandlers(\n httpClient: HttpClient,\n userId: string,\n): Pick<PushConfig, \"onSubscribe\" | \"onUnsubscribe\"> {\n return {\n onSubscribe: async (subscription: PushSubscriptionJSON) => {\n await httpClient.post(\"/api/push/subscriptions\", {\n userId,\n subscription,\n userAgent: navigator.userAgent,\n });\n },\n onUnsubscribe: async (subscription: PushSubscriptionJSON) => {\n await httpClient.delete(\n `/api/push/subscriptions?userId=${encodeURIComponent(userId)}&endpoint=${encodeURIComponent(subscription.endpoint || \"\")}`,\n );\n },\n };\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bootdesk/js-web-adapter-core",
3
- "version": "0.4.24",
3
+ "version": "0.4.26",
4
4
  "description": "Core JavaScript SDK for BootDesk Chat SDK WebAdapter",
5
5
  "repository": "https://github.com/bootdesk/chat-sdk",
6
6
  "type": "module",