@bootdesk/js-web-adapter-core 0.1.0 → 0.3.4

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.
@@ -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 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 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 { generateId, generateConversationId } from \"../utils/eventIdGenerator\";\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\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: any) => 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 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 this.broadcastClient.subscribe(threadId, threadEvents);\n\n this.unsubscribeUserChannel = this.broadcastClient.subscribeToUser(\n threadId,\n this.currentUserId,\n {\n onTypingStarted: (event) => this.handleTypingStarted(event),\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 messages: Message[] = ((response.messages as any[]) || []).map((msg) => ({\n id: msg.id,\n threadId,\n content: { text: msg.text, cards: msg.card ? [msg.card] : undefined },\n author: {\n id: msg.author.id,\n name: msg.author.name,\n isBot: msg.author.isBot ?? false,\n isMe: msg.author.id === this.currentUserId,\n },\n timestamp: msg.timestamp,\n attachments: msg.attachments?.map((a: any) => ({\n id: `att-${msg.id}-${a.url}`,\n url: a.url,\n name: a.name,\n type: a.type,\n mimeType: a.mime_type,\n size: a.size,\n })),\n reactions: msg.reactions ?? [],\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: any[] = []): 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: any) => ({\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: any) => 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 any[])?.map((a, i) => ({\n id: `att-${response.id || \"msg\"}-${i}`,\n name: a.name || \"\",\n url: a.url || \"\",\n type: a.type,\n mimeType: a.mime_type,\n size: a.size,\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 any[]).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(\n handler: (event: import(\"../events/MessagePostedEvent\").MessagePostedEvent) => void,\n ): Unsubscribe {\n return this.addEventListener(\"message.posted\", handler);\n }\n\n onStreamingChunk(\n handler: (event: import(\"../events/StreamingChunkEvent\").StreamingChunkEvent) => void,\n ): Unsubscribe {\n return this.addEventListener(\"streaming.chunk\", handler);\n }\n\n onTypingStarted(\n handler: (event: import(\"../events/TypingStartedEvent\").TypingStartedEvent) => void,\n ): 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(eventType: string, handler: (event: any) => void): Unsubscribe {\n if (!this.subscribers.has(eventType)) this.subscribers.set(eventType, []);\n this.subscribers.get(eventType)!.push(handler);\n return () => {\n const handlers = this.subscribers.get(eventType);\n if (handlers) {\n const index = handlers.indexOf(handler);\n if (index !== -1) handlers.splice(index, 1);\n }\n };\n }\n\n private handleMessagePosted(event: any): 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: any) => ({\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,\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: any): 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\", {\n messageId: event.messageId,\n newText: event.newText,\n });\n }\n }\n\n private handleMessageDeleted(event: any): 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\", { messageId: event.messageId });\n }\n }\n\n private handleReactionAdded(event: any): 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\", { messageId: event.messageId, emoji: event.emoji });\n }\n\n private handleReactionRemoved(event: any): 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\", { messageId: event.messageId, emoji: event.emoji });\n }\n\n private handleStreamingChunk(event: any): 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\", { messageId });\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\", {\n messageId,\n chunk,\n fullText: state.accumulatedText,\n });\n }\n this.notifySubscribers(\"streaming.chunk\", event);\n }\n\n private handleTypingStarted(event: any): void {\n if (this.pendingTyping) clearTimeout(this.pendingTyping);\n this.notifySubscribers(\"typing:started\", { userId: event.userId });\n this.pendingTyping = setTimeout(() => {\n this.notifySubscribers(\"typing:stopped\", { userId: event.userId });\n }, 3000);\n this.notifySubscribers(\"typing.started\", event);\n }\n\n private handleDMRequested(event: any): void {\n this.notifySubscribers(\"dm.requested\", { userId: event.userId, threadId: event.threadId });\n }\n\n private notifySubscribers(eventType: string, data: any): 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);\n break;\n case \"message.edited\":\n this.handleMessageEdited(event);\n break;\n case \"message.deleted\":\n this.handleMessageDeleted(event);\n break;\n case \"reaction.added\":\n this.handleReactionAdded(event);\n break;\n case \"reaction.removed\":\n this.handleReactionRemoved(event);\n break;\n case \"typing.started\":\n this.handleTypingStarted(event);\n break;\n case \"streaming.chunk\":\n this.handleStreamingChunk(event);\n break;\n case \"dm.requested\":\n this.handleDMRequested(event);\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 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\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 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 subscribe(threadId: string, handlers: EventHandlers): Unsubscribe {\n const baseName = `${this.channelPrefix}.${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 ] 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 subscribeToUser(threadId: string, userId: string, handlers: EventHandlers): Unsubscribe {\n const baseName = `${this.channelPrefix}.${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 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 }\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 subscribe(threadId: string, handlers: EventHandlers): Unsubscribe {\n const channelName = `${this.channelPrefix}.${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 ];\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 subscribeToUser(threadId: string, userId: string, handlers: EventHandlers): Unsubscribe {\n const channelName = `${this.channelPrefix}.${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 { scope: this.config.serviceWorkerScope || \"/\" },\n );\n await navigator.serviceWorker.ready;\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 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 }\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 this.broadcastClient.subscribe(threadId, threadEvents);\n\n this.unsubscribeUserChannel = this.broadcastClient.subscribeToUser(\n threadId,\n this.currentUserId,\n {\n onTypingStarted: (event) => this.handleTypingStarted(event),\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 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\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 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 subscribe(threadId: string, handlers: EventHandlers): Unsubscribe {\n const baseName = `${this.channelPrefix}.${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 ] 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 subscribeToUser(threadId: string, userId: string, handlers: EventHandlers): Unsubscribe {\n const baseName = `${this.channelPrefix}.${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 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 }\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 subscribe(threadId: string, handlers: EventHandlers): Unsubscribe {\n const channelName = `${this.channelPrefix}.${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 ];\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 subscribeToUser(threadId: string, userId: string, handlers: EventHandlers): Unsubscribe {\n const channelName = `${this.channelPrefix}.${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":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACqBO,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;AAAA,EAC9C;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,WAAK,gBAAgB,UAAU,UAAU,YAAY;AAErD,WAAK,yBAAyB,KAAK,gBAAgB;AAAA,QACjD;AAAA,QACA,KAAK;AAAA,QACL;AAAA,UACE,iBAAiB,CAAC,UAAU,KAAK,oBAAoB,KAAK;AAAA,UAC1D,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;;;ACthBO,IAAM,wBAAN,MAAuD;AAAA,EAS5D,YACE,gBACA,gBAAwB,QACxB,cACA;AARF,SAAQ,gBAA4C,oBAAI,IAAI;AAS1D,SAAK,gBAAgB;AACrB,SAAK,oBAAoB,cAAc,iBAAiB;AACxD,SAAK,kBAAkB,cAAc,eAAe;AAEpD,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,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,UAAU,UAAkB,UAAsC;AAChE,UAAM,WAAW,GAAG,KAAK,aAAa,IAAI,QAAQ;AAClD,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,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,gBAAgB,UAAkB,QAAgB,UAAsC;AACtF,UAAM,WAAW,GAAG,KAAK,aAAa,IAAI,QAAQ,IAAI,MAAM;AAC5D,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;;;AC/IO,IAAM,6BAAN,MAA4D;AAAA,EAOjE,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;AAAA,EACtD;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,UAAU,UAAkB,UAAsC;AAChE,UAAM,cAAc,GAAG,KAAK,aAAa,IAAI,QAAQ;AACrD,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,IAC3D;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,gBAAgB,UAAkB,QAAgB,UAAsC;AACtF,UAAM,cAAc,GAAG,KAAK,aAAa,IAAI,QAAQ,IAAI,MAAM;AAC/D,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;;;ACrHO,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":[]}
package/dist/index.d.cts CHANGED
@@ -1,6 +1,54 @@
1
1
  import Pusher from 'pusher-js';
2
2
  import Echo from 'laravel-echo';
3
3
 
4
+ interface HttpClientConfig {
5
+ apiUrl: string;
6
+ headers?: Record<string, string>;
7
+ timeout?: number;
8
+ verifyToken?: string;
9
+ }
10
+ interface ChatResponse {
11
+ id: string;
12
+ role: "assistant" | "user";
13
+ text: string;
14
+ attachments?: Array<{
15
+ type: string;
16
+ url: string;
17
+ name?: string;
18
+ mime_type?: string;
19
+ size?: number;
20
+ }>;
21
+ events?: Array<Record<string, unknown>>;
22
+ }
23
+ declare class HttpClient {
24
+ private config;
25
+ constructor(config: HttpClientConfig);
26
+ get(url: string, signal?: AbortSignal): Promise<unknown>;
27
+ post(url: string, body: unknown, signal?: AbortSignal): Promise<unknown>;
28
+ delete(url: string, signal?: AbortSignal): Promise<unknown>;
29
+ sendMessage(messages: Array<{
30
+ id: string;
31
+ role: string;
32
+ text: string;
33
+ attachments?: Array<{
34
+ url: string;
35
+ name?: string;
36
+ mime_type?: string;
37
+ size?: number;
38
+ }>;
39
+ }>, endpoint?: string, conversationId?: string): Promise<ChatResponse>;
40
+ sendAction(actionId: string, value: string, messageId: string, conversationId: string, endpoint?: string): Promise<Record<string, unknown>>;
41
+ editMessage(messageId: string, newText: string, endpointTemplate?: string): Promise<void>;
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
+ postFormData(url: string, formData: FormData, signal?: AbortSignal): Promise<unknown>;
46
+ setHeader(name: string, value: string): void;
47
+ removeHeader(name: string): void;
48
+ private resolve;
49
+ private expandTemplate;
50
+ }
51
+
4
52
  declare abstract class ChatEvent {
5
53
  readonly type: string;
6
54
  readonly threadId: string;
@@ -13,7 +61,7 @@ declare class UnknownEvent extends ChatEvent {
13
61
  constructor(type: string, threadId: string, data: Record<string, unknown>, timestamp: number);
14
62
  }
15
63
 
16
- declare class TypingStartedEvent extends ChatEvent {
64
+ declare class DMRequestedEvent extends ChatEvent {
17
65
  readonly userId: string;
18
66
  constructor(threadId: string, userId: string, timestamp?: number);
19
67
  }
@@ -25,6 +73,11 @@ declare class StreamingChunkEvent extends ChatEvent {
25
73
  constructor(threadId: string, messageId: string, chunk: string, isFinal: boolean, timestamp?: number);
26
74
  }
27
75
 
76
+ declare class TypingStartedEvent extends ChatEvent {
77
+ readonly userId: string;
78
+ constructor(threadId: string, userId: string, timestamp?: number);
79
+ }
80
+
28
81
  interface BaseCard {
29
82
  type: string;
30
83
  }
@@ -143,77 +196,6 @@ interface Attachment {
143
196
  mimeType?: string;
144
197
  }
145
198
 
146
- declare class MessagePostedEvent extends ChatEvent {
147
- readonly messageId: string;
148
- readonly text: string;
149
- readonly author: User;
150
- readonly card?: Card;
151
- readonly attachments?: Array<{
152
- type: string;
153
- url?: string;
154
- name?: string;
155
- mimeType?: string;
156
- size?: number | null;
157
- }>;
158
- constructor(threadId: string, messageId: string, text: string, author: User, card?: Card, attachments?: Array<{
159
- type: string;
160
- url?: string;
161
- name?: string;
162
- mimeType?: string;
163
- size?: number | null;
164
- }>, timestamp?: number);
165
- }
166
-
167
- interface HttpClientConfig {
168
- apiUrl: string;
169
- headers?: Record<string, string>;
170
- timeout?: number;
171
- verifyToken?: string;
172
- }
173
- interface ChatResponse {
174
- id: string;
175
- role: "assistant" | "user";
176
- text: string;
177
- attachments?: Array<{
178
- type: string;
179
- url: string;
180
- name?: string;
181
- mime_type?: string;
182
- size?: number;
183
- }>;
184
- events?: Array<Record<string, unknown>>;
185
- }
186
- declare class HttpClient {
187
- private config;
188
- constructor(config: HttpClientConfig);
189
- get(url: string, signal?: AbortSignal): Promise<unknown>;
190
- post(url: string, body: unknown, signal?: AbortSignal): Promise<unknown>;
191
- delete(url: string, signal?: AbortSignal): Promise<unknown>;
192
- sendMessage(messages: Array<{
193
- id: string;
194
- role: string;
195
- text: string;
196
- attachments?: Array<{
197
- url: string;
198
- name?: string;
199
- mime_type?: string;
200
- size?: number;
201
- }>;
202
- }>, endpoint?: string, conversationId?: string): Promise<ChatResponse>;
203
- sendAction(actionId: string, value: string, messageId: string, conversationId: string, endpoint?: string): Promise<Record<string, unknown>>;
204
- editMessage(messageId: string, newText: string, endpointTemplate?: string): Promise<void>;
205
- deleteMessage(messageId: string, endpointTemplate?: string): Promise<void>;
206
- addReaction(messageId: string, emoji: string, endpointTemplate?: string): Promise<void>;
207
- removeReaction(messageId: string, emoji: string, endpointTemplate?: string): Promise<void>;
208
- private resolve;
209
- private expandTemplate;
210
- }
211
-
212
- declare class DMRequestedEvent extends ChatEvent {
213
- readonly userId: string;
214
- constructor(threadId: string, userId: string, timestamp?: number);
215
- }
216
-
217
199
  declare class ReactionRemovedEvent extends ChatEvent {
218
200
  readonly messageId: string;
219
201
  readonly emoji: string;
@@ -240,6 +222,27 @@ declare class MessageEditedEvent extends ChatEvent {
240
222
  constructor(threadId: string, messageId: string, newText: string, card?: Card, timestamp?: number);
241
223
  }
242
224
 
225
+ declare class MessagePostedEvent extends ChatEvent {
226
+ readonly messageId: string;
227
+ readonly text: string;
228
+ readonly author: User;
229
+ readonly card?: Card;
230
+ readonly attachments?: Array<{
231
+ type: string;
232
+ url?: string;
233
+ name?: string;
234
+ mimeType?: string;
235
+ size?: number | null;
236
+ }>;
237
+ constructor(threadId: string, messageId: string, text: string, author: User, card?: Card, attachments?: Array<{
238
+ type: string;
239
+ url?: string;
240
+ name?: string;
241
+ mimeType?: string;
242
+ size?: number | null;
243
+ }>, timestamp?: number);
244
+ }
245
+
243
246
  interface EventHandlers {
244
247
  onMessagePosted?: (event: MessagePostedEvent) => void;
245
248
  onMessageEdited?: (event: MessageEditedEvent) => void;
@@ -263,6 +266,13 @@ interface BroadcastClient {
263
266
  isConnected(): boolean;
264
267
  }
265
268
 
269
+ interface ReconfigureConfig {
270
+ userId?: string;
271
+ userName?: string;
272
+ verifyToken?: string;
273
+ conversationId?: string;
274
+ headers?: Record<string, string>;
275
+ }
266
276
  interface WebChatClientConfig {
267
277
  apiUrl: string;
268
278
  userId: string;
@@ -285,6 +295,12 @@ interface WebChatClientConfig {
285
295
  reactions?: boolean;
286
296
  };
287
297
  }
298
+ interface AttachmentInput {
299
+ url: string;
300
+ name?: string;
301
+ mimeType?: string;
302
+ size?: number;
303
+ }
288
304
  interface LoadMessagesOptions {
289
305
  limit?: number;
290
306
  before?: number;
@@ -310,16 +326,22 @@ declare class WebChatClient {
310
326
  private subscribers;
311
327
  private unsubscribeUserChannel?;
312
328
  constructor(config: WebChatClientConfig);
329
+ reconfigure(config: ReconfigureConfig): void;
330
+ setLocaleHeader(locale: string): void;
313
331
  connect(): Promise<void>;
314
332
  disconnect(): void;
315
333
  loadMessages(options?: LoadMessagesOptions, signal?: AbortSignal): Promise<LoadMessagesResult>;
316
- sendMessage(text: string, attachments?: any[]): Promise<void>;
334
+ sendMessage(text: string, attachments?: AttachmentInput[]): Promise<void>;
317
335
  sendAction(messageId: string, actionId: string, value: string): Promise<void>;
318
336
  editMessage(messageId: string, newText: string): Promise<void>;
319
337
  deleteMessage(messageId: string): Promise<void>;
320
338
  addReaction(messageId: string, emoji: string): Promise<void>;
321
339
  removeReaction(messageId: string, emoji: string): Promise<void>;
322
340
  onMessagePosted(handler: (event: MessagePostedEvent) => void): Unsubscribe;
341
+ onMessageEdited(handler: (event: MessageEditedEvent) => void): Unsubscribe;
342
+ onMessageDeleted(handler: (event: MessageDeletedEvent) => void): Unsubscribe;
343
+ onReactionAdded(handler: (event: ReactionAddedEvent) => void): Unsubscribe;
344
+ onReactionRemoved(handler: (event: ReactionRemovedEvent) => void): Unsubscribe;
323
345
  onStreamingChunk(handler: (event: StreamingChunkEvent) => void): Unsubscribe;
324
346
  onTypingStarted(handler: (event: TypingStartedEvent) => void): Unsubscribe;
325
347
  getConversationId(): string;
@@ -329,7 +351,7 @@ declare class WebChatClient {
329
351
  getFeatures(): NonNullable<WebChatClientConfig["features"]>;
330
352
  getEndpoints(): NonNullable<WebChatClientConfig["endpoints"]>;
331
353
  getHttpClient(): HttpClient;
332
- addEventListener(eventType: string, handler: (event: any) => void): Unsubscribe;
354
+ addEventListener<T = unknown>(eventType: string, handler: (event: T) => void): Unsubscribe;
333
355
  private handleMessagePosted;
334
356
  private handleMessageEdited;
335
357
  private handleMessageDeleted;
@@ -392,6 +414,7 @@ interface PushConfig {
392
414
  getVapidPublicKey: () => Promise<string>;
393
415
  serviceWorkerUrl?: string;
394
416
  serviceWorkerScope?: string;
417
+ serviceWorkerType?: "classic" | "module";
395
418
  onSubscribe: (subscription: PushSubscriptionJSON) => Promise<void>;
396
419
  onUnsubscribe: (subscription: PushSubscriptionJSON) => Promise<void>;
397
420
  notificationOptions?: {
@@ -430,4 +453,4 @@ declare class PushManager {
430
453
 
431
454
  declare function createPushSubscriptionHandlers(httpClient: HttpClient, userId: string): Pick<PushConfig, "onSubscribe" | "onUnsubscribe">;
432
455
 
433
- export { type Attachment, type BaseCard, type BroadcastClient, type Card, type CardAction, type CardElement, type CardField, type CardSection, type ChannelTypeConfig, ChatEvent, type ChatResponse, type CustomCard, DMRequestedEvent, type DividerElement, type EventHandlers, type FileCard, HttpClient, type HttpClientConfig, type ImageCard, type ImageElement, LaravelEchoBroadcastClient, type LinkButtonElement, type LinkElement, type LoadMessagesOptions, type LoadMessagesResult, type Message, type MessageContent, MessageDeletedEvent, MessageEditedEvent, MessagePostedEvent, type PHPCard, type PushConfig, type PushEventData, PushManager, type PushSubscriptionStatus, PusherBroadcastClient, type PusherConfig, type Reaction, ReactionAddedEvent, ReactionRemovedEvent, StreamingChunkEvent, type TableElement, type TextElement, TypingStartedEvent, UnknownEvent, type Unsubscribe, type User, WebChatClient, type WebChatClientConfig, createPushSubscriptionHandlers, generateConversationId, generateId, parseChatEvent };
456
+ export { type Attachment, type BaseCard, type BroadcastClient, type Card, type CardAction, type CardElement, type CardField, type CardSection, type ChannelTypeConfig, ChatEvent, type ChatResponse, type CustomCard, DMRequestedEvent, type DividerElement, type EventHandlers, type FileCard, HttpClient, type HttpClientConfig, type ImageCard, type ImageElement, LaravelEchoBroadcastClient, type LinkButtonElement, type LinkElement, type LoadMessagesOptions, type LoadMessagesResult, type Message, type MessageContent, MessageDeletedEvent, MessageEditedEvent, MessagePostedEvent, type PHPCard, type PushConfig, type PushEventData, PushManager, type PushSubscriptionStatus, PusherBroadcastClient, type PusherConfig, type Reaction, ReactionAddedEvent, ReactionRemovedEvent, type ReconfigureConfig, StreamingChunkEvent, type TableElement, type TextElement, TypingStartedEvent, UnknownEvent, type Unsubscribe, type User, WebChatClient, type WebChatClientConfig, createPushSubscriptionHandlers, generateConversationId, generateId, parseChatEvent };