@elqnt/chat 3.0.0 → 3.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,12 @@
1
1
  # @elqnt/chat
2
2
 
3
- Platform-agnostic chat SDK for React and React Native. Uses POST + SSE (no WebSocket) for reliable real-time communication.
3
+ Platform-agnostic chat SDK for React and React Native. Uses HTTP + SSE for reliable real-time communication.
4
+
5
+ **Key Features:**
6
+ - **Mutations via HTTP** - `startChat()`, `loadChat()` return data directly (no waiting for SSE events)
7
+ - **Events via SSE** - Real-time messages, typing indicators, agent updates
8
+ - **Multi-transport** - Browser EventSource, React Native fetch-based SSE, WhatsApp webhooks
9
+ - **TypeScript-first** - Full type definitions for all models and events
4
10
 
5
11
  ## Installation
6
12
 
@@ -18,9 +24,11 @@ function ChatComponent() {
18
24
  connect,
19
25
  disconnect,
20
26
  sendMessage,
27
+ startChat,
28
+ loadChat,
21
29
  messages,
22
30
  isConnected,
23
- startChat,
31
+ currentChat,
24
32
  } = useChat({
25
33
  baseUrl: "https://api.example.com/chat",
26
34
  orgId: "org-123",
@@ -32,6 +40,18 @@ function ChatComponent() {
32
40
  return () => disconnect();
33
41
  }, []);
34
42
 
43
+ // Start a new chat - returns chatKey immediately
44
+ const handleNewChat = async () => {
45
+ const chatKey = await startChat({ agentId: "support-agent" });
46
+ console.log("Created chat:", chatKey);
47
+ };
48
+
49
+ // Load existing chat - returns Chat immediately
50
+ const handleLoadChat = async (chatKey: string) => {
51
+ const chat = await loadChat(chatKey);
52
+ console.log("Loaded chat with", chat.messages.length, "messages");
53
+ };
54
+
35
55
  const handleSend = async (text: string) => {
36
56
  await sendMessage(text);
37
57
  };
@@ -107,29 +127,34 @@ interface UseChatReturn {
107
127
  connectionState: TransportState;
108
128
  isConnected: boolean;
109
129
 
110
- // Chat Operations
111
- startChat: (metadata?: Record<string, unknown>) => Promise<string>;
112
- loadChat: (chatKey: string) => Promise<void>;
130
+ // Chat Operations (return data directly via HTTP)
131
+ startChat: (metadata?: Record<string, unknown>) => Promise<string>; // Returns chatKey
132
+ loadChat: (chatKey: string) => Promise<Chat>; // Returns loaded Chat
113
133
  sendMessage: (content: string, attachments?: unknown[]) => Promise<void>;
134
+ sendEvent: (event: Omit<ChatEvent, "timestamp">) => Promise<void>;
114
135
  endChat: (reason?: string) => Promise<void>;
115
136
 
116
137
  // Typing Indicators
117
138
  startTyping: () => void;
118
139
  stopTyping: () => void;
119
140
 
120
- // State
141
+ // State (auto-updated by hook)
121
142
  currentChat: Chat | null;
122
143
  chatKey: string | null;
123
144
  messages: ChatMessage[];
124
145
  error: TransportError | null;
125
146
  metrics: ConnectionMetrics;
126
147
 
127
- // Events
148
+ // Events (SSE push events)
128
149
  on: (eventType: string, handler: (event: ChatEvent) => void) => () => void;
129
150
  clearError: () => void;
130
151
  }
131
152
  ```
132
153
 
154
+ > **Note:** `startChat()` and `loadChat()` use direct HTTP calls and return data immediately.
155
+ > You don't need to listen for `new_chat_created` or `load_chat_response` events - those are
156
+ > only broadcast for multi-tab synchronization.
157
+
133
158
  ### `/api` - Low-Level API Functions
134
159
 
135
160
  ```typescript
@@ -182,6 +207,10 @@ import type {
182
207
  TransportState,
183
208
  TransportError,
184
209
  ConnectionMetrics,
210
+ CreateChatOptions,
211
+ CreateChatResponse,
212
+ LoadChatOptions,
213
+ LoadChatResponse,
185
214
  } from "@elqnt/chat/transport";
186
215
  ```
187
216
 
@@ -225,15 +254,26 @@ Implement the `ChatTransport` interface for custom integrations:
225
254
  import type { ChatTransport } from "@elqnt/chat/transport";
226
255
 
227
256
  const customTransport: ChatTransport = {
257
+ // Connection
228
258
  async connect(config) { /* ... */ },
229
259
  disconnect() { /* ... */ },
260
+
261
+ // Mutations (return data directly)
262
+ async createChat(options) { /* returns { chatKey } */ },
263
+ async loadChatData(options) { /* returns { chat, agentId? } */ },
264
+
265
+ // Fire-and-forget operations
230
266
  async send(event) { /* ... */ },
231
267
  async sendMessage(message) { /* ... */ },
232
- onMessage(handler) { /* ... */ },
233
- on(eventType, handler) { /* ... */ },
234
- getState() { /* ... */ },
235
- getMetrics() { /* ... */ },
236
- getError() { /* ... */ },
268
+
269
+ // Event subscriptions
270
+ onMessage(handler) { /* returns unsubscribe */ },
271
+ on(eventType, handler) { /* returns unsubscribe */ },
272
+
273
+ // State
274
+ getState() { /* returns TransportState */ },
275
+ getMetrics() { /* returns ConnectionMetrics */ },
276
+ getError() { /* returns TransportError | undefined */ },
237
277
  clearError() { /* ... */ },
238
278
  };
239
279
  ```
@@ -314,13 +354,20 @@ events.forEach(event => publishToChatService(event));
314
354
 
315
355
  ## Migration from v2
316
356
 
317
- ### Breaking Changes
357
+ ### Breaking Changes in v3.0
318
358
 
319
359
  1. **UI Components Removed** - Build your own UI
320
360
  2. **Contexts Removed** - Use `useChat` hook directly
321
361
  3. **WebSocket Removed** - SSE only (more reliable)
322
362
  4. **Redux Integration Removed** - Use hook state
323
363
 
364
+ ### Changes in v3.0.1
365
+
366
+ 1. **`loadChat()` returns `Promise<Chat>`** - Previously returned `Promise<void>`, now returns the loaded chat directly
367
+ 2. **`startChat()` returns immediately** - No longer waits for SSE event, returns chatKey from HTTP response
368
+ 3. **Transport interface extended** - Added `createChat()` and `loadChatData()` methods for direct HTTP responses
369
+ 4. **Event handlers simplified** - `new_chat_created` and `load_chat_response` events are now only for multi-tab sync
370
+
324
371
  ### Migration Steps
325
372
 
326
373
  ```tsx
@@ -1,6 +1,8 @@
1
1
  import { ApiClientOptions, ApiResponse } from '@elqnt/api-client';
2
2
  import { ResponseMetadata } from '@elqnt/types';
3
3
  import { Chat, ChatSummary } from '../models/index.mjs';
4
+ import '@elqnt/kg';
5
+ import '@elqnt/docs';
4
6
 
5
7
  /**
6
8
  * Stream API
@@ -1,6 +1,8 @@
1
1
  import { ApiClientOptions, ApiResponse } from '@elqnt/api-client';
2
2
  import { ResponseMetadata } from '@elqnt/types';
3
3
  import { Chat, ChatSummary } from '../models/index.js';
4
+ import '@elqnt/kg';
5
+ import '@elqnt/docs';
4
6
 
5
7
  /**
6
8
  * Stream API
@@ -1,6 +1,8 @@
1
1
  import { ChatEvent, Chat, ChatMessage } from '../models/index.mjs';
2
- import { C as ChatTransport, e as TransportError, g as TransportState, R as RetryConfig, b as ConnectionMetrics, U as Unsubscribe } from '../types-BB5nRdZs.mjs';
2
+ import { C as ChatTransport, e as TransportError, g as TransportState, R as RetryConfig, b as ConnectionMetrics, U as Unsubscribe } from '../types-CQHtUQ6p.mjs';
3
+ import '@elqnt/kg';
3
4
  import '@elqnt/types';
5
+ import '@elqnt/docs';
4
6
 
5
7
  /**
6
8
  * Chat hook options
@@ -43,10 +45,12 @@ interface UseChatReturn {
43
45
  isConnected: boolean;
44
46
  /** Start a new chat session */
45
47
  startChat: (metadata?: Record<string, unknown>) => Promise<string>;
46
- /** Load an existing chat */
47
- loadChat: (chatKey: string) => Promise<void>;
48
+ /** Load an existing chat, returns the loaded chat */
49
+ loadChat: (chatKey: string) => Promise<Chat>;
48
50
  /** Send a text message */
49
51
  sendMessage: (content: string, attachments?: unknown[]) => Promise<void>;
52
+ /** Send a raw chat event (for custom event types) */
53
+ sendEvent: (event: Omit<ChatEvent, "timestamp">) => Promise<void>;
50
54
  /** End the current chat */
51
55
  endChat: (reason?: string) => Promise<void>;
52
56
  /** Signal that user is typing */
@@ -1,6 +1,8 @@
1
1
  import { ChatEvent, Chat, ChatMessage } from '../models/index.js';
2
- import { C as ChatTransport, e as TransportError, g as TransportState, R as RetryConfig, b as ConnectionMetrics, U as Unsubscribe } from '../types-CNvuxtcv.js';
2
+ import { C as ChatTransport, e as TransportError, g as TransportState, R as RetryConfig, b as ConnectionMetrics, U as Unsubscribe } from '../types-7UNI1iYv.js';
3
+ import '@elqnt/kg';
3
4
  import '@elqnt/types';
5
+ import '@elqnt/docs';
4
6
 
5
7
  /**
6
8
  * Chat hook options
@@ -43,10 +45,12 @@ interface UseChatReturn {
43
45
  isConnected: boolean;
44
46
  /** Start a new chat session */
45
47
  startChat: (metadata?: Record<string, unknown>) => Promise<string>;
46
- /** Load an existing chat */
47
- loadChat: (chatKey: string) => Promise<void>;
48
+ /** Load an existing chat, returns the loaded chat */
49
+ loadChat: (chatKey: string) => Promise<Chat>;
48
50
  /** Send a text message */
49
51
  sendMessage: (content: string, attachments?: unknown[]) => Promise<void>;
52
+ /** Send a raw chat event (for custom event types) */
53
+ sendEvent: (event: Omit<ChatEvent, "timestamp">) => Promise<void>;
50
54
  /** End the current chat */
51
55
  endChat: (reason?: string) => Promise<void>;
52
56
  /** Signal that user is typing */
@@ -118,7 +118,11 @@ function createSSETransport(options = {}) {
118
118
  const errorText = await response.text();
119
119
  throw new Error(`API error: ${response.status} - ${errorText}`);
120
120
  }
121
- return response.json();
121
+ const json = await response.json();
122
+ if (json && typeof json === "object" && "data" in json) {
123
+ return json.data;
124
+ }
125
+ return json;
122
126
  }
123
127
  function handleMessage(event) {
124
128
  if (!event.data || event.data === "") return;
@@ -327,6 +331,37 @@ function createSSETransport(options = {}) {
327
331
  });
328
332
  metrics.messagesSent++;
329
333
  },
334
+ async createChat(options2) {
335
+ if (!config) {
336
+ throw new Error("Transport not connected");
337
+ }
338
+ const response = await sendRest("create", {
339
+ orgId: options2.orgId,
340
+ userId: options2.userId,
341
+ metadata: options2.metadata
342
+ });
343
+ if (!response?.chatKey) {
344
+ throw new Error("Failed to create chat: no chatKey returned");
345
+ }
346
+ return { chatKey: response.chatKey };
347
+ },
348
+ async loadChatData(options2) {
349
+ if (!config) {
350
+ throw new Error("Transport not connected");
351
+ }
352
+ const response = await sendRest("load", {
353
+ orgId: options2.orgId,
354
+ chatKey: options2.chatKey,
355
+ userId: options2.userId
356
+ });
357
+ if (!response?.chat) {
358
+ throw new Error("Failed to load chat: no chat data returned");
359
+ }
360
+ return {
361
+ chat: response.chat,
362
+ agentId: response.agentId
363
+ };
364
+ },
330
365
  onMessage(handler) {
331
366
  globalHandlers.add(handler);
332
367
  return () => globalHandlers.delete(handler);
@@ -396,7 +431,6 @@ function useChat(options) {
396
431
  const mountedRef = (0, import_react.useRef)(false);
397
432
  const onMessageRef = (0, import_react.useRef)(onMessage);
398
433
  const onErrorRef = (0, import_react.useRef)(onError);
399
- const chatCreationResolverRef = (0, import_react.useRef)(null);
400
434
  const typingTimeoutRef = (0, import_react.useRef)(null);
401
435
  (0, import_react.useEffect)(() => {
402
436
  onMessageRef.current = onMessage;
@@ -424,10 +458,6 @@ function useChat(options) {
424
458
  const newChatKey = event.data?.chatKey;
425
459
  if (newChatKey) {
426
460
  setChatKey(newChatKey);
427
- if (chatCreationResolverRef.current) {
428
- chatCreationResolverRef.current.resolve(newChatKey);
429
- chatCreationResolverRef.current = null;
430
- }
431
461
  }
432
462
  break;
433
463
  case "load_chat_response":
@@ -516,26 +546,13 @@ function useChat(options) {
516
546
  if (!transport) {
517
547
  throw new Error("Transport not initialized");
518
548
  }
519
- return new Promise((resolve, reject) => {
520
- chatCreationResolverRef.current = { resolve, reject };
521
- transport.send({
522
- type: "new_chat",
523
- orgId,
524
- chatKey: "",
525
- userId,
526
- timestamp: Date.now(),
527
- data: metadata
528
- }).catch((err) => {
529
- chatCreationResolverRef.current = null;
530
- reject(err);
531
- });
532
- setTimeout(() => {
533
- if (chatCreationResolverRef.current) {
534
- chatCreationResolverRef.current = null;
535
- reject(new Error("Chat creation timed out"));
536
- }
537
- }, 3e4);
549
+ const response = await transport.createChat({
550
+ orgId,
551
+ userId,
552
+ metadata
538
553
  });
554
+ setChatKey(response.chatKey);
555
+ return response.chatKey;
539
556
  },
540
557
  [orgId, userId]
541
558
  );
@@ -545,14 +562,15 @@ function useChat(options) {
545
562
  if (!transport) {
546
563
  throw new Error("Transport not initialized");
547
564
  }
548
- setChatKey(key);
549
- await transport.send({
550
- type: "load_chat",
565
+ const response = await transport.loadChatData({
551
566
  orgId,
552
567
  chatKey: key,
553
- userId,
554
- timestamp: Date.now()
568
+ userId
555
569
  });
570
+ setCurrentChat(response.chat);
571
+ setChatKey(response.chat.key);
572
+ setMessages(response.chat.messages || []);
573
+ return response.chat;
556
574
  },
557
575
  [orgId, userId]
558
576
  );
@@ -613,6 +631,19 @@ function useChat(options) {
613
631
  },
614
632
  [orgId, chatKey, userId]
615
633
  );
634
+ const sendEvent = (0, import_react.useCallback)(
635
+ async (event) => {
636
+ const transport = transportRef.current;
637
+ if (!transport) {
638
+ throw new Error("Transport not initialized");
639
+ }
640
+ await transport.send({
641
+ ...event,
642
+ timestamp: Date.now()
643
+ });
644
+ },
645
+ []
646
+ );
616
647
  const startTyping = (0, import_react.useCallback)(() => {
617
648
  const transport = transportRef.current;
618
649
  if (!transport || !chatKey) return;
@@ -687,6 +718,7 @@ function useChat(options) {
687
718
  startChat,
688
719
  loadChat,
689
720
  sendMessage,
721
+ sendEvent,
690
722
  endChat,
691
723
  // Typing
692
724
  startTyping,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../hooks/index.ts","../../hooks/use-chat.ts","../../transport/types.ts","../../transport/sse.ts"],"sourcesContent":["/**\n * Chat Hooks\n *\n * React hooks for chat functionality.\n *\n * @example\n * ```tsx\n * import { useChat } from \"@elqnt/chat/hooks\";\n *\n * function ChatComponent() {\n * const {\n * connect,\n * sendMessage,\n * messages,\n * isConnected,\n * } = useChat({\n * baseUrl: \"https://api.example.com/chat\",\n * orgId: \"org-123\",\n * userId: \"user-456\",\n * });\n *\n * // ...\n * }\n * ```\n */\n\nexport { useChat } from \"./use-chat\";\nexport type { UseChatOptions, UseChatReturn } from \"./use-chat\";\n","\"use client\";\n\n/**\n * useChat Hook\n *\n * A unified React hook for chat functionality with support for\n * multiple transport types (SSE, fetch-based SSE, custom transports).\n *\n * @example Basic usage\n * ```tsx\n * function ChatComponent() {\n * const {\n * connect,\n * sendMessage,\n * messages,\n * isConnected,\n * } = useChat({\n * baseUrl: \"https://api.example.com/chat\",\n * orgId: \"org-123\",\n * userId: \"user-456\",\n * });\n *\n * useEffect(() => {\n * connect();\n * return () => disconnect();\n * }, []);\n *\n * return (\n * <div>\n * {messages.map(msg => <Message key={msg.id} {...msg} />)}\n * <input onSubmit={(content) => sendMessage(content)} />\n * </div>\n * );\n * }\n * ```\n *\n * @example With custom transport\n * ```tsx\n * import { createFetchSSETransport } from \"@elqnt/chat/transport\";\n *\n * const transport = createFetchSSETransport();\n *\n * function App() {\n * const chat = useChat({\n * baseUrl: \"...\",\n * orgId: \"...\",\n * userId: \"...\",\n * transport,\n * });\n * }\n * ```\n */\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { Chat, ChatEvent, ChatMessage } from \"../models\";\nimport type {\n ChatTransport,\n TransportState,\n TransportError,\n ConnectionMetrics,\n RetryConfig,\n Unsubscribe,\n} from \"../transport/types\";\nimport { createSSETransport } from \"../transport/sse\";\n\n/**\n * Chat hook options\n */\nexport interface UseChatOptions {\n /** Base URL for the chat server (e.g., \"https://api.example.com/chat\") */\n baseUrl: string;\n /** Organization ID */\n orgId: string;\n /** User ID */\n userId: string;\n /** Client type for routing */\n clientType?: \"customer\" | \"humanAgent\" | \"observer\";\n /** Transport instance or type */\n transport?: ChatTransport | \"sse\" | \"sse-fetch\";\n /** Callback for all incoming events */\n onMessage?: (event: ChatEvent) => void;\n /** Callback for errors */\n onError?: (error: TransportError) => void;\n /** Callback when connection state changes */\n onConnectionChange?: (state: TransportState) => void;\n /** Auto-connect on mount */\n autoConnect?: boolean;\n /** Retry configuration */\n retryConfig?: RetryConfig;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * Chat hook return type\n */\nexport interface UseChatReturn {\n // Connection\n /** Connect to the chat server */\n connect: () => Promise<void>;\n /** Disconnect from the server */\n disconnect: () => void;\n /** Current connection state */\n connectionState: TransportState;\n /** Whether currently connected */\n isConnected: boolean;\n\n // Chat operations\n /** Start a new chat session */\n startChat: (metadata?: Record<string, unknown>) => Promise<string>;\n /** Load an existing chat */\n loadChat: (chatKey: string) => Promise<void>;\n /** Send a text message */\n sendMessage: (content: string, attachments?: unknown[]) => Promise<void>;\n /** End the current chat */\n endChat: (reason?: string) => Promise<void>;\n\n // Typing indicators\n /** Signal that user is typing */\n startTyping: () => void;\n /** Signal that user stopped typing */\n stopTyping: () => void;\n\n // State\n /** Current chat object */\n currentChat: Chat | null;\n /** Current chat key */\n chatKey: string | null;\n /** Chat messages */\n messages: ChatMessage[];\n /** Current error */\n error: TransportError | null;\n /** Connection metrics */\n metrics: ConnectionMetrics;\n\n // Event subscription\n /** Subscribe to specific event type */\n on: (eventType: string, handler: (event: ChatEvent) => void) => Unsubscribe;\n /** Clear current error */\n clearError: () => void;\n}\n\n/**\n * Default transport factory\n */\nfunction getDefaultTransport(\n type: \"sse\" | \"sse-fetch\" | undefined,\n debug: boolean\n): ChatTransport {\n // For now, always use SSE. In the future, detect environment\n // and use fetch-based SSE for React Native\n return createSSETransport({ debug });\n}\n\n/**\n * useChat Hook\n *\n * Platform-agnostic chat hook with SSE transport support.\n */\nexport function useChat(options: UseChatOptions): UseChatReturn {\n const {\n baseUrl,\n orgId,\n userId,\n clientType = \"customer\",\n transport: transportOption,\n onMessage,\n onError,\n onConnectionChange,\n autoConnect = false,\n retryConfig,\n debug = false,\n } = options;\n\n // State\n const [connectionState, setConnectionState] = useState<TransportState>(\"disconnected\");\n const [currentChat, setCurrentChat] = useState<Chat | null>(null);\n const [chatKey, setChatKey] = useState<string | null>(null);\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [error, setError] = useState<TransportError | null>(null);\n const [metrics, setMetrics] = useState<ConnectionMetrics>({\n latency: 0,\n messagesSent: 0,\n messagesReceived: 0,\n messagesQueued: 0,\n reconnectCount: 0,\n });\n\n // Refs\n const transportRef = useRef<ChatTransport | null>(null);\n const mountedRef = useRef(false);\n const onMessageRef = useRef(onMessage);\n const onErrorRef = useRef(onError);\n const chatCreationResolverRef = useRef<{\n resolve: (chatKey: string) => void;\n reject: (error: Error) => void;\n } | null>(null);\n const typingTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // Update callback refs\n useEffect(() => {\n onMessageRef.current = onMessage;\n onErrorRef.current = onError;\n }, [onMessage, onError]);\n\n // Initialize transport\n useEffect(() => {\n if (typeof transportOption === \"object\") {\n transportRef.current = transportOption;\n } else {\n transportRef.current = getDefaultTransport(\n transportOption as \"sse\" | \"sse-fetch\" | undefined,\n debug\n );\n }\n }, [transportOption, debug]);\n\n // Handle incoming events\n const handleEvent = useCallback((event: ChatEvent) => {\n if (!mountedRef.current) return;\n\n // Update metrics\n setMetrics((prev) => ({\n ...prev,\n messagesReceived: prev.messagesReceived + 1,\n lastMessageAt: Date.now(),\n }));\n\n // Handle specific event types\n switch (event.type) {\n case \"new_chat_created\":\n const newChatKey = event.data?.chatKey as string;\n if (newChatKey) {\n setChatKey(newChatKey);\n if (chatCreationResolverRef.current) {\n chatCreationResolverRef.current.resolve(newChatKey);\n chatCreationResolverRef.current = null;\n }\n }\n break;\n\n case \"load_chat_response\":\n const chat = event.data?.chat as Chat;\n if (chat) {\n setCurrentChat(chat);\n setChatKey(chat.key);\n setMessages(chat.messages || []);\n }\n break;\n\n case \"message\":\n if (event.message) {\n setMessages((prev) => [...prev, event.message!]);\n }\n break;\n\n case \"chat_ended\":\n setCurrentChat(null);\n setChatKey(null);\n break;\n\n case \"error\":\n const errorMsg = event.data?.message as string;\n if (errorMsg) {\n const transportError: TransportError = {\n code: \"NETWORK_ERROR\",\n message: errorMsg,\n retryable: true,\n timestamp: Date.now(),\n };\n setError(transportError);\n onErrorRef.current?.(transportError);\n }\n break;\n }\n\n // Call user's onMessage handler\n onMessageRef.current?.(event);\n }, []);\n\n // Connect to the chat server\n const connect = useCallback(async (): Promise<void> => {\n const transport = transportRef.current;\n if (!transport) {\n throw new Error(\"Transport not initialized\");\n }\n\n if (!orgId) {\n const err: TransportError = {\n code: \"CONNECTION_FAILED\",\n message: \"orgId is required\",\n retryable: false,\n timestamp: Date.now(),\n };\n setError(err);\n throw err;\n }\n\n setConnectionState(\"connecting\");\n\n try {\n // Subscribe to events before connecting\n const unsubscribe = transport.onMessage(handleEvent);\n\n await transport.connect({\n baseUrl,\n orgId,\n userId,\n clientType,\n chatKey: chatKey || undefined,\n debug,\n });\n\n setConnectionState(\"connected\");\n setError(null);\n setMetrics(transport.getMetrics());\n onConnectionChange?.(\"connected\");\n\n // Return cleanup in case caller wants it\n return;\n } catch (err) {\n const transportError = err as TransportError;\n setConnectionState(\"disconnected\");\n setError(transportError);\n onErrorRef.current?.(transportError);\n throw err;\n }\n }, [baseUrl, orgId, userId, clientType, chatKey, debug, handleEvent, onConnectionChange]);\n\n // Disconnect from the server\n const disconnect = useCallback((): void => {\n const transport = transportRef.current;\n if (transport) {\n transport.disconnect(true);\n }\n setConnectionState(\"disconnected\");\n onConnectionChange?.(\"disconnected\");\n }, [onConnectionChange]);\n\n // Start a new chat\n const startChat = useCallback(\n async (metadata?: Record<string, unknown>): Promise<string> => {\n const transport = transportRef.current;\n if (!transport) {\n throw new Error(\"Transport not initialized\");\n }\n\n return new Promise((resolve, reject) => {\n chatCreationResolverRef.current = { resolve, reject };\n\n transport\n .send({\n type: \"new_chat\",\n orgId,\n chatKey: \"\",\n userId,\n timestamp: Date.now(),\n data: metadata,\n })\n .catch((err) => {\n chatCreationResolverRef.current = null;\n reject(err);\n });\n\n // Timeout after 30 seconds\n setTimeout(() => {\n if (chatCreationResolverRef.current) {\n chatCreationResolverRef.current = null;\n reject(new Error(\"Chat creation timed out\"));\n }\n }, 30000);\n });\n },\n [orgId, userId]\n );\n\n // Load an existing chat\n const loadChat = useCallback(\n async (key: string): Promise<void> => {\n const transport = transportRef.current;\n if (!transport) {\n throw new Error(\"Transport not initialized\");\n }\n\n setChatKey(key);\n\n await transport.send({\n type: \"load_chat\",\n orgId,\n chatKey: key,\n userId,\n timestamp: Date.now(),\n });\n },\n [orgId, userId]\n );\n\n // Send a message\n const sendMessage = useCallback(\n async (content: string, attachments?: unknown[]): Promise<void> => {\n const transport = transportRef.current;\n if (!transport) {\n throw new Error(\"Transport not initialized\");\n }\n if (!chatKey) {\n throw new Error(\"No active chat\");\n }\n\n const message: ChatMessage = {\n id: `msg_${Date.now()}_${Math.random().toString(36).slice(2)}`,\n role: \"user\",\n content,\n time: Date.now(),\n status: \"sending\",\n senderId: userId,\n createdAt: Date.now(),\n attachments: attachments as ChatMessage[\"attachments\"],\n };\n\n // Optimistically add message\n setMessages((prev) => [...prev, message]);\n\n await transport.send({\n type: \"message\",\n orgId,\n chatKey,\n userId,\n timestamp: Date.now(),\n message,\n });\n\n setMetrics((prev) => ({\n ...prev,\n messagesSent: prev.messagesSent + 1,\n }));\n },\n [orgId, chatKey, userId]\n );\n\n // End the current chat\n const endChat = useCallback(\n async (reason?: string): Promise<void> => {\n const transport = transportRef.current;\n if (!transport) {\n throw new Error(\"Transport not initialized\");\n }\n if (!chatKey) {\n return;\n }\n\n await transport.send({\n type: \"end_chat\",\n orgId,\n chatKey,\n userId,\n timestamp: Date.now(),\n data: reason ? { reason } : undefined,\n });\n\n setCurrentChat(null);\n setChatKey(null);\n },\n [orgId, chatKey, userId]\n );\n\n // Start typing indicator\n const startTyping = useCallback((): void => {\n const transport = transportRef.current;\n if (!transport || !chatKey) return;\n\n // Clear existing timeout\n if (typingTimeoutRef.current) {\n clearTimeout(typingTimeoutRef.current);\n }\n\n transport\n .send({\n type: \"typing\",\n orgId,\n chatKey,\n userId,\n timestamp: Date.now(),\n })\n .catch(() => {});\n\n // Auto-stop typing after 3 seconds\n typingTimeoutRef.current = setTimeout(() => {\n stopTyping();\n }, 3000);\n }, [orgId, chatKey, userId]);\n\n // Stop typing indicator\n const stopTyping = useCallback((): void => {\n const transport = transportRef.current;\n if (!transport || !chatKey) return;\n\n if (typingTimeoutRef.current) {\n clearTimeout(typingTimeoutRef.current);\n typingTimeoutRef.current = null;\n }\n\n transport\n .send({\n type: \"stopped_typing\",\n orgId,\n chatKey,\n userId,\n timestamp: Date.now(),\n })\n .catch(() => {});\n }, [orgId, chatKey, userId]);\n\n // Subscribe to specific event type\n const on = useCallback(\n (eventType: string, handler: (event: ChatEvent) => void): Unsubscribe => {\n const transport = transportRef.current;\n if (!transport) {\n return () => {};\n }\n return transport.on(eventType, handler);\n },\n []\n );\n\n // Clear error\n const clearError = useCallback((): void => {\n setError(null);\n transportRef.current?.clearError();\n }, []);\n\n // Mount/unmount lifecycle\n useEffect(() => {\n mountedRef.current = true;\n\n if (autoConnect) {\n connect().catch(() => {});\n }\n\n return () => {\n mountedRef.current = false;\n if (typingTimeoutRef.current) {\n clearTimeout(typingTimeoutRef.current);\n }\n disconnect();\n };\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Computed state\n const isConnected = connectionState === \"connected\";\n\n return {\n // Connection\n connect,\n disconnect,\n connectionState,\n isConnected,\n\n // Chat operations\n startChat,\n loadChat,\n sendMessage,\n endChat,\n\n // Typing\n startTyping,\n stopTyping,\n\n // State\n currentChat,\n chatKey,\n messages,\n error,\n metrics,\n\n // Events\n on,\n clearError,\n };\n}\n","/**\n * Transport Abstraction Layer Types\n *\n * Platform-agnostic transport interfaces for chat communication.\n * Supports browser SSE, React Native fetch-based SSE, and extensible\n * transports like WhatsApp Business API.\n */\n\nimport type { ChatEvent, ChatMessage } from \"../models\";\n\n/**\n * Transport connection state\n */\nexport type TransportState =\n | \"disconnected\"\n | \"connecting\"\n | \"connected\"\n | \"reconnecting\";\n\n/**\n * Transport error with retry information\n */\nexport interface TransportError {\n code:\n | \"CONNECTION_FAILED\"\n | \"PARSE_ERROR\"\n | \"SEND_FAILED\"\n | \"TIMEOUT\"\n | \"NETWORK_ERROR\"\n | \"AUTH_FAILED\";\n message: string;\n retryable: boolean;\n timestamp: number;\n originalError?: unknown;\n}\n\n/**\n * Configuration for transport connection\n */\nexport interface TransportConfig {\n /** Base URL for the chat server */\n baseUrl: string;\n /** Organization ID */\n orgId: string;\n /** User ID for authentication */\n userId: string;\n /** Client type for routing */\n clientType: \"customer\" | \"humanAgent\" | \"observer\";\n /** Optional current chat key for reconnection */\n chatKey?: string;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * Retry configuration for connection attempts\n */\nexport interface RetryConfig {\n /** Maximum number of retry attempts */\n maxRetries?: number;\n /** Initial retry intervals in milliseconds */\n intervals?: number[];\n /** Multiplier for exponential backoff */\n backoffMultiplier?: number;\n /** Maximum backoff time in milliseconds */\n maxBackoffTime?: number;\n}\n\n/**\n * Connection metrics for monitoring\n */\nexport interface ConnectionMetrics {\n /** Round-trip latency in milliseconds */\n latency: number;\n /** Total messages sent */\n messagesSent: number;\n /** Total messages received */\n messagesReceived: number;\n /** Messages waiting to be sent */\n messagesQueued: number;\n /** Number of reconnection attempts */\n reconnectCount: number;\n /** Last error encountered */\n lastError?: TransportError;\n /** Timestamp when connection was established */\n connectedAt?: number;\n /** Timestamp of last message */\n lastMessageAt?: number;\n /** Current transport type */\n transportType?: string;\n}\n\n/**\n * Event handler function type\n */\nexport type EventHandler<T = ChatEvent> = (event: T) => void;\n\n/**\n * Unsubscribe function returned by event subscription\n */\nexport type Unsubscribe = () => void;\n\n/**\n * Send message options\n */\nexport interface SendMessageOptions {\n /** Message content */\n content: string;\n /** Optional attachments */\n attachments?: unknown[];\n /** Optional message metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Create chat options\n */\nexport interface CreateChatOptions {\n /** Organization ID */\n orgId: string;\n /** User ID */\n userId: string;\n /** Optional chat metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Load chat options\n */\nexport interface LoadChatOptions {\n /** Organization ID */\n orgId: string;\n /** Chat key to load */\n chatKey: string;\n /** User ID */\n userId: string;\n}\n\n/**\n * End chat options\n */\nexport interface EndChatOptions {\n /** Organization ID */\n orgId: string;\n /** Chat key to end */\n chatKey: string;\n /** User ID */\n userId: string;\n /** Optional end reason */\n reason?: string;\n}\n\n/**\n * Core transport interface\n *\n * Implementations must handle:\n * - Connection lifecycle (connect, disconnect, reconnect)\n * - Message sending (POST requests)\n * - Event receiving (SSE stream)\n * - Error handling and recovery\n */\nexport interface ChatTransport {\n /**\n * Connect to the chat server\n * @param config - Transport configuration\n * @returns Promise that resolves when connected\n */\n connect(config: TransportConfig): Promise<void>;\n\n /**\n * Disconnect from the server\n * @param intentional - Whether disconnect was user-initiated\n */\n disconnect(intentional?: boolean): void;\n\n /**\n * Send a chat event to the server\n * @param event - Chat event to send\n */\n send(event: ChatEvent): Promise<void>;\n\n /**\n * Send a message in the current chat\n * @param message - Message to send\n */\n sendMessage(message: ChatMessage): Promise<void>;\n\n /**\n * Subscribe to incoming events\n * @param handler - Event handler function\n * @returns Unsubscribe function\n */\n onMessage(handler: EventHandler): Unsubscribe;\n\n /**\n * Subscribe to specific event type\n * @param eventType - Type of event to listen for\n * @param handler - Event handler function\n * @returns Unsubscribe function\n */\n on(eventType: string, handler: EventHandler): Unsubscribe;\n\n /**\n * Get current connection state\n */\n getState(): TransportState;\n\n /**\n * Get connection metrics\n */\n getMetrics(): ConnectionMetrics;\n\n /**\n * Get last error\n */\n getError(): TransportError | undefined;\n\n /**\n * Clear error state\n */\n clearError(): void;\n}\n\n/**\n * Transport factory function type\n */\nexport type TransportFactory = (config?: Partial<TransportConfig>) => ChatTransport;\n\n/**\n * Logger interface for transport debugging\n */\nexport interface TransportLogger {\n debug: (message: string, ...args: unknown[]) => void;\n info: (message: string, ...args: unknown[]) => void;\n warn: (message: string, ...args: unknown[]) => void;\n error: (message: string, ...args: unknown[]) => void;\n}\n\n/**\n * Create a default logger\n * @param debug - Enable debug logging\n */\nexport function createLogger(debug: boolean = false): TransportLogger {\n return {\n debug: debug ? console.log.bind(console, \"[chat]\") : () => {},\n info: console.info.bind(console, \"[chat]\"),\n warn: console.warn.bind(console, \"[chat]\"),\n error: console.error.bind(console, \"[chat]\"),\n };\n}\n\n/**\n * Default retry configuration\n */\nexport const DEFAULT_RETRY_CONFIG: Required<RetryConfig> = {\n maxRetries: 10,\n intervals: [1000, 2000, 5000],\n backoffMultiplier: 1.5,\n maxBackoffTime: 30000,\n};\n\n/**\n * Calculate retry interval with exponential backoff\n * @param retryCount - Current retry attempt number\n * @param config - Retry configuration\n */\nexport function calculateRetryInterval(\n retryCount: number,\n config: RetryConfig = DEFAULT_RETRY_CONFIG\n): number {\n const {\n intervals = DEFAULT_RETRY_CONFIG.intervals,\n backoffMultiplier = DEFAULT_RETRY_CONFIG.backoffMultiplier,\n maxBackoffTime = DEFAULT_RETRY_CONFIG.maxBackoffTime,\n } = config;\n\n if (retryCount < intervals.length) {\n return intervals[retryCount];\n }\n\n const baseInterval = intervals[intervals.length - 1] || 5000;\n const backoffTime =\n baseInterval * Math.pow(backoffMultiplier, retryCount - intervals.length + 1);\n return Math.min(backoffTime, maxBackoffTime);\n}\n","/**\n * SSE Transport (Browser)\n *\n * Uses native EventSource for receiving server events and fetch POST for sending.\n * This is the default transport for browser environments.\n *\n * @example\n * ```typescript\n * import { createSSETransport } from \"@elqnt/chat/transport\";\n *\n * const transport = createSSETransport();\n * await transport.connect({ baseUrl, orgId, userId, clientType: \"customer\" });\n * ```\n */\n\nimport type { ChatEvent, ChatMessage } from \"../models\";\nimport type {\n ChatTransport,\n TransportConfig,\n TransportState,\n TransportError,\n ConnectionMetrics,\n EventHandler,\n Unsubscribe,\n RetryConfig,\n TransportLogger,\n} from \"./types\";\nimport { createLogger, calculateRetryInterval, DEFAULT_RETRY_CONFIG } from \"./types\";\n\n/**\n * SSE Transport options\n */\nexport interface SSETransportOptions {\n /** Retry configuration */\n retryConfig?: RetryConfig;\n /** Enable debug logging */\n debug?: boolean;\n /** Custom logger */\n logger?: TransportLogger;\n}\n\n/**\n * Create an SSE transport for browser environments\n */\nexport function createSSETransport(options: SSETransportOptions = {}): ChatTransport {\n const {\n retryConfig = DEFAULT_RETRY_CONFIG,\n debug = false,\n logger = createLogger(debug),\n } = options;\n\n // Internal state\n let eventSource: EventSource | undefined;\n let config: TransportConfig | undefined;\n let state: TransportState = \"disconnected\";\n let error: TransportError | undefined;\n let retryCount = 0;\n let reconnectTimeout: ReturnType<typeof setTimeout> | undefined;\n let intentionalDisconnect = false;\n\n // Metrics\n const metrics: ConnectionMetrics = {\n latency: 0,\n messagesSent: 0,\n messagesReceived: 0,\n messagesQueued: 0,\n reconnectCount: 0,\n transportType: \"sse\",\n };\n\n // Event handlers\n const globalHandlers = new Set<EventHandler>();\n const typeHandlers = new Map<string, Set<EventHandler>>();\n\n // Helper to emit events\n function emit(event: ChatEvent): void {\n // Update metrics\n metrics.messagesReceived++;\n metrics.lastMessageAt = Date.now();\n\n // Call global handlers\n globalHandlers.forEach((handler) => {\n try {\n handler(event);\n } catch (err) {\n logger.error(\"Error in message handler:\", err);\n }\n });\n\n // Call type-specific handlers\n const handlers = typeHandlers.get(event.type);\n if (handlers) {\n handlers.forEach((handler) => {\n try {\n handler(event);\n } catch (err) {\n logger.error(`Error in ${event.type} handler:`, err);\n }\n });\n }\n }\n\n // REST API helper\n async function sendRest(endpoint: string, body: Record<string, unknown>): Promise<unknown> {\n if (!config) {\n throw new Error(\"Transport not connected\");\n }\n\n const url = `${config.baseUrl}/${endpoint}`;\n logger.debug(`POST ${endpoint}`, body);\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`API error: ${response.status} - ${errorText}`);\n }\n\n return response.json();\n }\n\n // Handle SSE message\n function handleMessage(event: MessageEvent): void {\n if (!event.data || event.data === \"\") return;\n\n try {\n const data = JSON.parse(event.data) as ChatEvent;\n logger.debug(\"Received:\", data.type);\n emit(data);\n } catch (err) {\n logger.error(\"Failed to parse SSE message:\", err);\n }\n }\n\n // Setup SSE event listeners\n function setupEventListeners(es: EventSource): void {\n // Generic message handler\n es.addEventListener(\"message\", handleMessage);\n\n // Add handlers for known event types\n const eventTypes = [\n \"reconnected\", \"typing\", \"stopped_typing\", \"waiting\",\n \"waiting_for_agent\", \"human_agent_joined\", \"human_agent_left\",\n \"chat_ended\", \"chat_updated\", \"load_chat_response\",\n \"new_chat_created\", \"show_csat_survey\", \"csat_response\",\n \"user_suggested_actions\", \"agent_execution_started\",\n \"agent_execution_ended\", \"agent_context_update\",\n \"plan_pending_approval\", \"step_started\", \"step_completed\",\n \"step_failed\", \"plan_completed\", \"skills_changed\", \"summary_update\",\n ];\n\n eventTypes.forEach((type) => {\n es.addEventListener(type, handleMessage);\n });\n }\n\n // Schedule reconnect\n function scheduleReconnect(): void {\n if (intentionalDisconnect || !config) return;\n\n const maxRetries = retryConfig.maxRetries ?? DEFAULT_RETRY_CONFIG.maxRetries;\n if (retryCount >= maxRetries) {\n logger.error(`Max retries (${maxRetries}) exceeded`);\n error = {\n code: \"CONNECTION_FAILED\",\n message: `Max retries (${maxRetries}) exceeded`,\n retryable: false,\n timestamp: Date.now(),\n };\n return;\n }\n\n const interval = calculateRetryInterval(retryCount, retryConfig);\n retryCount++;\n metrics.reconnectCount++;\n\n logger.info(`Reconnecting in ${interval}ms (attempt ${retryCount})`);\n state = \"reconnecting\";\n\n reconnectTimeout = setTimeout(() => {\n if (config) {\n transport.connect(config).catch((err) => {\n logger.error(\"Reconnect failed:\", err);\n });\n }\n }, interval);\n }\n\n const transport: ChatTransport = {\n async connect(cfg: TransportConfig): Promise<void> {\n config = cfg;\n intentionalDisconnect = false;\n\n // Clean up existing connection\n if (eventSource) {\n eventSource.close();\n eventSource = undefined;\n }\n if (reconnectTimeout) {\n clearTimeout(reconnectTimeout);\n reconnectTimeout = undefined;\n }\n\n state = retryCount > 0 ? \"reconnecting\" : \"connecting\";\n\n return new Promise((resolve, reject) => {\n const connectionStart = Date.now();\n const url = `${cfg.baseUrl}/stream?orgId=${cfg.orgId}&userId=${cfg.userId}&clientType=${cfg.clientType}${cfg.chatKey ? `&chatId=${cfg.chatKey}` : \"\"}`;\n\n logger.debug(\"Connecting to:\", url);\n const es = new EventSource(url);\n\n es.onopen = () => {\n const connectionTime = Date.now() - connectionStart;\n logger.info(`Connected in ${connectionTime}ms`);\n\n state = \"connected\";\n error = undefined;\n retryCount = 0;\n metrics.connectedAt = Date.now();\n metrics.latency = connectionTime;\n\n setupEventListeners(es);\n resolve();\n };\n\n es.onerror = () => {\n if (es.readyState === EventSource.CLOSED) {\n const sseError: TransportError = {\n code: \"CONNECTION_FAILED\",\n message: \"SSE connection failed\",\n retryable: true,\n timestamp: Date.now(),\n };\n error = sseError;\n metrics.lastError = sseError;\n state = \"disconnected\";\n\n if (!intentionalDisconnect) {\n scheduleReconnect();\n }\n\n // Only reject if this is the initial connection attempt\n if (retryCount === 0) {\n reject(sseError);\n }\n }\n };\n\n eventSource = es;\n });\n },\n\n disconnect(intentional = true): void {\n logger.info(\"Disconnecting\", { intentional });\n intentionalDisconnect = intentional;\n\n if (reconnectTimeout) {\n clearTimeout(reconnectTimeout);\n reconnectTimeout = undefined;\n }\n\n if (eventSource) {\n eventSource.close();\n eventSource = undefined;\n }\n\n state = \"disconnected\";\n retryCount = 0;\n },\n\n async send(event: ChatEvent): Promise<void> {\n if (!config) {\n throw new Error(\"Transport not connected\");\n }\n\n // Map event types to REST endpoints\n switch (event.type) {\n case \"message\":\n await sendRest(\"send\", {\n orgId: event.orgId,\n chatKey: event.chatKey,\n userId: event.userId,\n message: event.message,\n });\n break;\n\n case \"typing\":\n await sendRest(\"typing\", {\n orgId: event.orgId,\n chatKey: event.chatKey,\n userId: event.userId,\n typing: true,\n });\n break;\n\n case \"stopped_typing\":\n await sendRest(\"typing\", {\n orgId: event.orgId,\n chatKey: event.chatKey,\n userId: event.userId,\n typing: false,\n });\n break;\n\n case \"load_chat\":\n await sendRest(\"load\", {\n orgId: event.orgId,\n chatKey: event.chatKey,\n userId: event.userId,\n });\n break;\n\n case \"new_chat\":\n await sendRest(\"create\", {\n orgId: event.orgId,\n userId: event.userId,\n metadata: event.data,\n });\n break;\n\n case \"end_chat\":\n await sendRest(\"end\", {\n orgId: event.orgId,\n chatKey: event.chatKey,\n userId: event.userId,\n data: event.data,\n });\n break;\n\n default:\n // Generic event endpoint for other types\n await sendRest(\"event\", {\n type: event.type,\n orgId: event.orgId,\n chatKey: event.chatKey,\n userId: event.userId,\n data: event.data,\n });\n }\n\n metrics.messagesSent++;\n },\n\n async sendMessage(message: ChatMessage): Promise<void> {\n if (!config) {\n throw new Error(\"Transport not connected\");\n }\n\n await sendRest(\"send\", {\n orgId: config.orgId,\n chatKey: config.chatKey,\n userId: config.userId,\n message,\n });\n\n metrics.messagesSent++;\n },\n\n onMessage(handler: EventHandler): Unsubscribe {\n globalHandlers.add(handler);\n return () => globalHandlers.delete(handler);\n },\n\n on(eventType: string, handler: EventHandler): Unsubscribe {\n if (!typeHandlers.has(eventType)) {\n typeHandlers.set(eventType, new Set());\n }\n typeHandlers.get(eventType)!.add(handler);\n return () => {\n const handlers = typeHandlers.get(eventType);\n if (handlers) {\n handlers.delete(handler);\n if (handlers.size === 0) {\n typeHandlers.delete(eventType);\n }\n }\n };\n },\n\n getState(): TransportState {\n return state;\n },\n\n getMetrics(): ConnectionMetrics {\n return { ...metrics };\n },\n\n getError(): TransportError | undefined {\n return error;\n },\n\n clearError(): void {\n error = undefined;\n },\n };\n\n return transport;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACqDA,mBAAyD;;;AC6LlD,SAAS,aAAa,QAAiB,OAAwB;AACpE,SAAO;AAAA,IACL,OAAO,QAAQ,QAAQ,IAAI,KAAK,SAAS,QAAQ,IAAI,MAAM;AAAA,IAAC;AAAA,IAC5D,MAAM,QAAQ,KAAK,KAAK,SAAS,QAAQ;AAAA,IACzC,MAAM,QAAQ,KAAK,KAAK,SAAS,QAAQ;AAAA,IACzC,OAAO,QAAQ,MAAM,KAAK,SAAS,QAAQ;AAAA,EAC7C;AACF;AAKO,IAAM,uBAA8C;AAAA,EACzD,YAAY;AAAA,EACZ,WAAW,CAAC,KAAM,KAAM,GAAI;AAAA,EAC5B,mBAAmB;AAAA,EACnB,gBAAgB;AAClB;AAOO,SAAS,uBACd,YACA,SAAsB,sBACd;AACR,QAAM;AAAA,IACJ,YAAY,qBAAqB;AAAA,IACjC,oBAAoB,qBAAqB;AAAA,IACzC,iBAAiB,qBAAqB;AAAA,EACxC,IAAI;AAEJ,MAAI,aAAa,UAAU,QAAQ;AACjC,WAAO,UAAU,UAAU;AAAA,EAC7B;AAEA,QAAM,eAAe,UAAU,UAAU,SAAS,CAAC,KAAK;AACxD,QAAM,cACJ,eAAe,KAAK,IAAI,mBAAmB,aAAa,UAAU,SAAS,CAAC;AAC9E,SAAO,KAAK,IAAI,aAAa,cAAc;AAC7C;;;AChPO,SAAS,mBAAmB,UAA+B,CAAC,GAAkB;AACnF,QAAM;AAAA,IACJ,cAAc;AAAA,IACd,QAAQ;AAAA,IACR,SAAS,aAAa,KAAK;AAAA,EAC7B,IAAI;AAGJ,MAAI;AACJ,MAAI;AACJ,MAAI,QAAwB;AAC5B,MAAI;AACJ,MAAI,aAAa;AACjB,MAAI;AACJ,MAAI,wBAAwB;AAG5B,QAAM,UAA6B;AAAA,IACjC,SAAS;AAAA,IACT,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,eAAe;AAAA,EACjB;AAGA,QAAM,iBAAiB,oBAAI,IAAkB;AAC7C,QAAM,eAAe,oBAAI,IAA+B;AAGxD,WAAS,KAAK,OAAwB;AAEpC,YAAQ;AACR,YAAQ,gBAAgB,KAAK,IAAI;AAGjC,mBAAe,QAAQ,CAAC,YAAY;AAClC,UAAI;AACF,gBAAQ,KAAK;AAAA,MACf,SAAS,KAAK;AACZ,eAAO,MAAM,6BAA6B,GAAG;AAAA,MAC/C;AAAA,IACF,CAAC;AAGD,UAAM,WAAW,aAAa,IAAI,MAAM,IAAI;AAC5C,QAAI,UAAU;AACZ,eAAS,QAAQ,CAAC,YAAY;AAC5B,YAAI;AACF,kBAAQ,KAAK;AAAA,QACf,SAAS,KAAK;AACZ,iBAAO,MAAM,YAAY,MAAM,IAAI,aAAa,GAAG;AAAA,QACrD;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAGA,iBAAe,SAAS,UAAkB,MAAiD;AACzF,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,MAAM,yBAAyB;AAAA,IAC3C;AAEA,UAAM,MAAM,GAAG,OAAO,OAAO,IAAI,QAAQ;AACzC,WAAO,MAAM,QAAQ,QAAQ,IAAI,IAAI;AAErC,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,MAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AAED,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,YAAY,MAAM,SAAS,KAAK;AACtC,YAAM,IAAI,MAAM,cAAc,SAAS,MAAM,MAAM,SAAS,EAAE;AAAA,IAChE;AAEA,WAAO,SAAS,KAAK;AAAA,EACvB;AAGA,WAAS,cAAc,OAA2B;AAChD,QAAI,CAAC,MAAM,QAAQ,MAAM,SAAS,GAAI;AAEtC,QAAI;AACF,YAAM,OAAO,KAAK,MAAM,MAAM,IAAI;AAClC,aAAO,MAAM,aAAa,KAAK,IAAI;AACnC,WAAK,IAAI;AAAA,IACX,SAAS,KAAK;AACZ,aAAO,MAAM,gCAAgC,GAAG;AAAA,IAClD;AAAA,EACF;AAGA,WAAS,oBAAoB,IAAuB;AAElD,OAAG,iBAAiB,WAAW,aAAa;AAG5C,UAAM,aAAa;AAAA,MACjB;AAAA,MAAe;AAAA,MAAU;AAAA,MAAkB;AAAA,MAC3C;AAAA,MAAqB;AAAA,MAAsB;AAAA,MAC3C;AAAA,MAAc;AAAA,MAAgB;AAAA,MAC9B;AAAA,MAAoB;AAAA,MAAoB;AAAA,MACxC;AAAA,MAA0B;AAAA,MAC1B;AAAA,MAAyB;AAAA,MACzB;AAAA,MAAyB;AAAA,MAAgB;AAAA,MACzC;AAAA,MAAe;AAAA,MAAkB;AAAA,MAAkB;AAAA,IACrD;AAEA,eAAW,QAAQ,CAAC,SAAS;AAC3B,SAAG,iBAAiB,MAAM,aAAa;AAAA,IACzC,CAAC;AAAA,EACH;AAGA,WAAS,oBAA0B;AACjC,QAAI,yBAAyB,CAAC,OAAQ;AAEtC,UAAM,aAAa,YAAY,cAAc,qBAAqB;AAClE,QAAI,cAAc,YAAY;AAC5B,aAAO,MAAM,gBAAgB,UAAU,YAAY;AACnD,cAAQ;AAAA,QACN,MAAM;AAAA,QACN,SAAS,gBAAgB,UAAU;AAAA,QACnC,WAAW;AAAA,QACX,WAAW,KAAK,IAAI;AAAA,MACtB;AACA;AAAA,IACF;AAEA,UAAM,WAAW,uBAAuB,YAAY,WAAW;AAC/D;AACA,YAAQ;AAER,WAAO,KAAK,mBAAmB,QAAQ,eAAe,UAAU,GAAG;AACnE,YAAQ;AAER,uBAAmB,WAAW,MAAM;AAClC,UAAI,QAAQ;AACV,kBAAU,QAAQ,MAAM,EAAE,MAAM,CAAC,QAAQ;AACvC,iBAAO,MAAM,qBAAqB,GAAG;AAAA,QACvC,CAAC;AAAA,MACH;AAAA,IACF,GAAG,QAAQ;AAAA,EACb;AAEA,QAAM,YAA2B;AAAA,IAC/B,MAAM,QAAQ,KAAqC;AACjD,eAAS;AACT,8BAAwB;AAGxB,UAAI,aAAa;AACf,oBAAY,MAAM;AAClB,sBAAc;AAAA,MAChB;AACA,UAAI,kBAAkB;AACpB,qBAAa,gBAAgB;AAC7B,2BAAmB;AAAA,MACrB;AAEA,cAAQ,aAAa,IAAI,iBAAiB;AAE1C,aAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,cAAM,kBAAkB,KAAK,IAAI;AACjC,cAAM,MAAM,GAAG,IAAI,OAAO,iBAAiB,IAAI,KAAK,WAAW,IAAI,MAAM,eAAe,IAAI,UAAU,GAAG,IAAI,UAAU,WAAW,IAAI,OAAO,KAAK,EAAE;AAEpJ,eAAO,MAAM,kBAAkB,GAAG;AAClC,cAAM,KAAK,IAAI,YAAY,GAAG;AAE9B,WAAG,SAAS,MAAM;AAChB,gBAAM,iBAAiB,KAAK,IAAI,IAAI;AACpC,iBAAO,KAAK,gBAAgB,cAAc,IAAI;AAE9C,kBAAQ;AACR,kBAAQ;AACR,uBAAa;AACb,kBAAQ,cAAc,KAAK,IAAI;AAC/B,kBAAQ,UAAU;AAElB,8BAAoB,EAAE;AACtB,kBAAQ;AAAA,QACV;AAEA,WAAG,UAAU,MAAM;AACjB,cAAI,GAAG,eAAe,YAAY,QAAQ;AACxC,kBAAM,WAA2B;AAAA,cAC/B,MAAM;AAAA,cACN,SAAS;AAAA,cACT,WAAW;AAAA,cACX,WAAW,KAAK,IAAI;AAAA,YACtB;AACA,oBAAQ;AACR,oBAAQ,YAAY;AACpB,oBAAQ;AAER,gBAAI,CAAC,uBAAuB;AAC1B,gCAAkB;AAAA,YACpB;AAGA,gBAAI,eAAe,GAAG;AACpB,qBAAO,QAAQ;AAAA,YACjB;AAAA,UACF;AAAA,QACF;AAEA,sBAAc;AAAA,MAChB,CAAC;AAAA,IACH;AAAA,IAEA,WAAW,cAAc,MAAY;AACnC,aAAO,KAAK,iBAAiB,EAAE,YAAY,CAAC;AAC5C,8BAAwB;AAExB,UAAI,kBAAkB;AACpB,qBAAa,gBAAgB;AAC7B,2BAAmB;AAAA,MACrB;AAEA,UAAI,aAAa;AACf,oBAAY,MAAM;AAClB,sBAAc;AAAA,MAChB;AAEA,cAAQ;AACR,mBAAa;AAAA,IACf;AAAA,IAEA,MAAM,KAAK,OAAiC;AAC1C,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI,MAAM,yBAAyB;AAAA,MAC3C;AAGA,cAAQ,MAAM,MAAM;AAAA,QAClB,KAAK;AACH,gBAAM,SAAS,QAAQ;AAAA,YACrB,OAAO,MAAM;AAAA,YACb,SAAS,MAAM;AAAA,YACf,QAAQ,MAAM;AAAA,YACd,SAAS,MAAM;AAAA,UACjB,CAAC;AACD;AAAA,QAEF,KAAK;AACH,gBAAM,SAAS,UAAU;AAAA,YACvB,OAAO,MAAM;AAAA,YACb,SAAS,MAAM;AAAA,YACf,QAAQ,MAAM;AAAA,YACd,QAAQ;AAAA,UACV,CAAC;AACD;AAAA,QAEF,KAAK;AACH,gBAAM,SAAS,UAAU;AAAA,YACvB,OAAO,MAAM;AAAA,YACb,SAAS,MAAM;AAAA,YACf,QAAQ,MAAM;AAAA,YACd,QAAQ;AAAA,UACV,CAAC;AACD;AAAA,QAEF,KAAK;AACH,gBAAM,SAAS,QAAQ;AAAA,YACrB,OAAO,MAAM;AAAA,YACb,SAAS,MAAM;AAAA,YACf,QAAQ,MAAM;AAAA,UAChB,CAAC;AACD;AAAA,QAEF,KAAK;AACH,gBAAM,SAAS,UAAU;AAAA,YACvB,OAAO,MAAM;AAAA,YACb,QAAQ,MAAM;AAAA,YACd,UAAU,MAAM;AAAA,UAClB,CAAC;AACD;AAAA,QAEF,KAAK;AACH,gBAAM,SAAS,OAAO;AAAA,YACpB,OAAO,MAAM;AAAA,YACb,SAAS,MAAM;AAAA,YACf,QAAQ,MAAM;AAAA,YACd,MAAM,MAAM;AAAA,UACd,CAAC;AACD;AAAA,QAEF;AAEE,gBAAM,SAAS,SAAS;AAAA,YACtB,MAAM,MAAM;AAAA,YACZ,OAAO,MAAM;AAAA,YACb,SAAS,MAAM;AAAA,YACf,QAAQ,MAAM;AAAA,YACd,MAAM,MAAM;AAAA,UACd,CAAC;AAAA,MACL;AAEA,cAAQ;AAAA,IACV;AAAA,IAEA,MAAM,YAAY,SAAqC;AACrD,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI,MAAM,yBAAyB;AAAA,MAC3C;AAEA,YAAM,SAAS,QAAQ;AAAA,QACrB,OAAO,OAAO;AAAA,QACd,SAAS,OAAO;AAAA,QAChB,QAAQ,OAAO;AAAA,QACf;AAAA,MACF,CAAC;AAED,cAAQ;AAAA,IACV;AAAA,IAEA,UAAU,SAAoC;AAC5C,qBAAe,IAAI,OAAO;AAC1B,aAAO,MAAM,eAAe,OAAO,OAAO;AAAA,IAC5C;AAAA,IAEA,GAAG,WAAmB,SAAoC;AACxD,UAAI,CAAC,aAAa,IAAI,SAAS,GAAG;AAChC,qBAAa,IAAI,WAAW,oBAAI,IAAI,CAAC;AAAA,MACvC;AACA,mBAAa,IAAI,SAAS,EAAG,IAAI,OAAO;AACxC,aAAO,MAAM;AACX,cAAM,WAAW,aAAa,IAAI,SAAS;AAC3C,YAAI,UAAU;AACZ,mBAAS,OAAO,OAAO;AACvB,cAAI,SAAS,SAAS,GAAG;AACvB,yBAAa,OAAO,SAAS;AAAA,UAC/B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IAEA,WAA2B;AACzB,aAAO;AAAA,IACT;AAAA,IAEA,aAAgC;AAC9B,aAAO,EAAE,GAAG,QAAQ;AAAA,IACtB;AAAA,IAEA,WAAuC;AACrC,aAAO;AAAA,IACT;AAAA,IAEA,aAAmB;AACjB,cAAQ;AAAA,IACV;AAAA,EACF;AAEA,SAAO;AACT;;;AFjQA,SAAS,oBACP,MACA,OACe;AAGf,SAAO,mBAAmB,EAAE,MAAM,CAAC;AACrC;AAOO,SAAS,QAAQ,SAAwC;AAC9D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc;AAAA,IACd;AAAA,IACA,QAAQ;AAAA,EACV,IAAI;AAGJ,QAAM,CAAC,iBAAiB,kBAAkB,QAAI,uBAAyB,cAAc;AACrF,QAAM,CAAC,aAAa,cAAc,QAAI,uBAAsB,IAAI;AAChE,QAAM,CAAC,SAAS,UAAU,QAAI,uBAAwB,IAAI;AAC1D,QAAM,CAAC,UAAU,WAAW,QAAI,uBAAwB,CAAC,CAAC;AAC1D,QAAM,CAAC,OAAO,QAAQ,QAAI,uBAAgC,IAAI;AAC9D,QAAM,CAAC,SAAS,UAAU,QAAI,uBAA4B;AAAA,IACxD,SAAS;AAAA,IACT,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,EAClB,CAAC;AAGD,QAAM,mBAAe,qBAA6B,IAAI;AACtD,QAAM,iBAAa,qBAAO,KAAK;AAC/B,QAAM,mBAAe,qBAAO,SAAS;AACrC,QAAM,iBAAa,qBAAO,OAAO;AACjC,QAAM,8BAA0B,qBAGtB,IAAI;AACd,QAAM,uBAAmB,qBAA6C,IAAI;AAG1E,8BAAU,MAAM;AACd,iBAAa,UAAU;AACvB,eAAW,UAAU;AAAA,EACvB,GAAG,CAAC,WAAW,OAAO,CAAC;AAGvB,8BAAU,MAAM;AACd,QAAI,OAAO,oBAAoB,UAAU;AACvC,mBAAa,UAAU;AAAA,IACzB,OAAO;AACL,mBAAa,UAAU;AAAA,QACrB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF,GAAG,CAAC,iBAAiB,KAAK,CAAC;AAG3B,QAAM,kBAAc,0BAAY,CAAC,UAAqB;AACpD,QAAI,CAAC,WAAW,QAAS;AAGzB,eAAW,CAAC,UAAU;AAAA,MACpB,GAAG;AAAA,MACH,kBAAkB,KAAK,mBAAmB;AAAA,MAC1C,eAAe,KAAK,IAAI;AAAA,IAC1B,EAAE;AAGF,YAAQ,MAAM,MAAM;AAAA,MAClB,KAAK;AACH,cAAM,aAAa,MAAM,MAAM;AAC/B,YAAI,YAAY;AACd,qBAAW,UAAU;AACrB,cAAI,wBAAwB,SAAS;AACnC,oCAAwB,QAAQ,QAAQ,UAAU;AAClD,oCAAwB,UAAU;AAAA,UACpC;AAAA,QACF;AACA;AAAA,MAEF,KAAK;AACH,cAAM,OAAO,MAAM,MAAM;AACzB,YAAI,MAAM;AACR,yBAAe,IAAI;AACnB,qBAAW,KAAK,GAAG;AACnB,sBAAY,KAAK,YAAY,CAAC,CAAC;AAAA,QACjC;AACA;AAAA,MAEF,KAAK;AACH,YAAI,MAAM,SAAS;AACjB,sBAAY,CAAC,SAAS,CAAC,GAAG,MAAM,MAAM,OAAQ,CAAC;AAAA,QACjD;AACA;AAAA,MAEF,KAAK;AACH,uBAAe,IAAI;AACnB,mBAAW,IAAI;AACf;AAAA,MAEF,KAAK;AACH,cAAM,WAAW,MAAM,MAAM;AAC7B,YAAI,UAAU;AACZ,gBAAM,iBAAiC;AAAA,YACrC,MAAM;AAAA,YACN,SAAS;AAAA,YACT,WAAW;AAAA,YACX,WAAW,KAAK,IAAI;AAAA,UACtB;AACA,mBAAS,cAAc;AACvB,qBAAW,UAAU,cAAc;AAAA,QACrC;AACA;AAAA,IACJ;AAGA,iBAAa,UAAU,KAAK;AAAA,EAC9B,GAAG,CAAC,CAAC;AAGL,QAAM,cAAU,0BAAY,YAA2B;AACrD,UAAM,YAAY,aAAa;AAC/B,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,2BAA2B;AAAA,IAC7C;AAEA,QAAI,CAAC,OAAO;AACV,YAAM,MAAsB;AAAA,QAC1B,MAAM;AAAA,QACN,SAAS;AAAA,QACT,WAAW;AAAA,QACX,WAAW,KAAK,IAAI;AAAA,MACtB;AACA,eAAS,GAAG;AACZ,YAAM;AAAA,IACR;AAEA,uBAAmB,YAAY;AAE/B,QAAI;AAEF,YAAM,cAAc,UAAU,UAAU,WAAW;AAEnD,YAAM,UAAU,QAAQ;AAAA,QACtB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS,WAAW;AAAA,QACpB;AAAA,MACF,CAAC;AAED,yBAAmB,WAAW;AAC9B,eAAS,IAAI;AACb,iBAAW,UAAU,WAAW,CAAC;AACjC,2BAAqB,WAAW;AAGhC;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,iBAAiB;AACvB,yBAAmB,cAAc;AACjC,eAAS,cAAc;AACvB,iBAAW,UAAU,cAAc;AACnC,YAAM;AAAA,IACR;AAAA,EACF,GAAG,CAAC,SAAS,OAAO,QAAQ,YAAY,SAAS,OAAO,aAAa,kBAAkB,CAAC;AAGxF,QAAM,iBAAa,0BAAY,MAAY;AACzC,UAAM,YAAY,aAAa;AAC/B,QAAI,WAAW;AACb,gBAAU,WAAW,IAAI;AAAA,IAC3B;AACA,uBAAmB,cAAc;AACjC,yBAAqB,cAAc;AAAA,EACrC,GAAG,CAAC,kBAAkB,CAAC;AAGvB,QAAM,gBAAY;AAAA,IAChB,OAAO,aAAwD;AAC7D,YAAM,YAAY,aAAa;AAC/B,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,2BAA2B;AAAA,MAC7C;AAEA,aAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,gCAAwB,UAAU,EAAE,SAAS,OAAO;AAEpD,kBACG,KAAK;AAAA,UACJ,MAAM;AAAA,UACN;AAAA,UACA,SAAS;AAAA,UACT;AAAA,UACA,WAAW,KAAK,IAAI;AAAA,UACpB,MAAM;AAAA,QACR,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,kCAAwB,UAAU;AAClC,iBAAO,GAAG;AAAA,QACZ,CAAC;AAGH,mBAAW,MAAM;AACf,cAAI,wBAAwB,SAAS;AACnC,oCAAwB,UAAU;AAClC,mBAAO,IAAI,MAAM,yBAAyB,CAAC;AAAA,UAC7C;AAAA,QACF,GAAG,GAAK;AAAA,MACV,CAAC;AAAA,IACH;AAAA,IACA,CAAC,OAAO,MAAM;AAAA,EAChB;AAGA,QAAM,eAAW;AAAA,IACf,OAAO,QAA+B;AACpC,YAAM,YAAY,aAAa;AAC/B,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,2BAA2B;AAAA,MAC7C;AAEA,iBAAW,GAAG;AAEd,YAAM,UAAU,KAAK;AAAA,QACnB,MAAM;AAAA,QACN;AAAA,QACA,SAAS;AAAA,QACT;AAAA,QACA,WAAW,KAAK,IAAI;AAAA,MACtB,CAAC;AAAA,IACH;AAAA,IACA,CAAC,OAAO,MAAM;AAAA,EAChB;AAGA,QAAM,kBAAc;AAAA,IAClB,OAAO,SAAiB,gBAA2C;AACjE,YAAM,YAAY,aAAa;AAC/B,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,2BAA2B;AAAA,MAC7C;AACA,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,MAAM,gBAAgB;AAAA,MAClC;AAEA,YAAM,UAAuB;AAAA,QAC3B,IAAI,OAAO,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC;AAAA,QAC5D,MAAM;AAAA,QACN;AAAA,QACA,MAAM,KAAK,IAAI;AAAA,QACf,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,WAAW,KAAK,IAAI;AAAA,QACpB;AAAA,MACF;AAGA,kBAAY,CAAC,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC;AAExC,YAAM,UAAU,KAAK;AAAA,QACnB,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA,WAAW,KAAK,IAAI;AAAA,QACpB;AAAA,MACF,CAAC;AAED,iBAAW,CAAC,UAAU;AAAA,QACpB,GAAG;AAAA,QACH,cAAc,KAAK,eAAe;AAAA,MACpC,EAAE;AAAA,IACJ;AAAA,IACA,CAAC,OAAO,SAAS,MAAM;AAAA,EACzB;AAGA,QAAM,cAAU;AAAA,IACd,OAAO,WAAmC;AACxC,YAAM,YAAY,aAAa;AAC/B,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,2BAA2B;AAAA,MAC7C;AACA,UAAI,CAAC,SAAS;AACZ;AAAA,MACF;AAEA,YAAM,UAAU,KAAK;AAAA,QACnB,MAAM;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,QACA,WAAW,KAAK,IAAI;AAAA,QACpB,MAAM,SAAS,EAAE,OAAO,IAAI;AAAA,MAC9B,CAAC;AAED,qBAAe,IAAI;AACnB,iBAAW,IAAI;AAAA,IACjB;AAAA,IACA,CAAC,OAAO,SAAS,MAAM;AAAA,EACzB;AAGA,QAAM,kBAAc,0BAAY,MAAY;AAC1C,UAAM,YAAY,aAAa;AAC/B,QAAI,CAAC,aAAa,CAAC,QAAS;AAG5B,QAAI,iBAAiB,SAAS;AAC5B,mBAAa,iBAAiB,OAAO;AAAA,IACvC;AAEA,cACG,KAAK;AAAA,MACJ,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,IACtB,CAAC,EACA,MAAM,MAAM;AAAA,IAAC,CAAC;AAGjB,qBAAiB,UAAU,WAAW,MAAM;AAC1C,iBAAW;AAAA,IACb,GAAG,GAAI;AAAA,EACT,GAAG,CAAC,OAAO,SAAS,MAAM,CAAC;AAG3B,QAAM,iBAAa,0BAAY,MAAY;AACzC,UAAM,YAAY,aAAa;AAC/B,QAAI,CAAC,aAAa,CAAC,QAAS;AAE5B,QAAI,iBAAiB,SAAS;AAC5B,mBAAa,iBAAiB,OAAO;AACrC,uBAAiB,UAAU;AAAA,IAC7B;AAEA,cACG,KAAK;AAAA,MACJ,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,KAAK,IAAI;AAAA,IACtB,CAAC,EACA,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EACnB,GAAG,CAAC,OAAO,SAAS,MAAM,CAAC;AAG3B,QAAM,SAAK;AAAA,IACT,CAAC,WAAmB,YAAqD;AACvE,YAAM,YAAY,aAAa;AAC/B,UAAI,CAAC,WAAW;AACd,eAAO,MAAM;AAAA,QAAC;AAAA,MAChB;AACA,aAAO,UAAU,GAAG,WAAW,OAAO;AAAA,IACxC;AAAA,IACA,CAAC;AAAA,EACH;AAGA,QAAM,iBAAa,0BAAY,MAAY;AACzC,aAAS,IAAI;AACb,iBAAa,SAAS,WAAW;AAAA,EACnC,GAAG,CAAC,CAAC;AAGL,8BAAU,MAAM;AACd,eAAW,UAAU;AAErB,QAAI,aAAa;AACf,cAAQ,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IAC1B;AAEA,WAAO,MAAM;AACX,iBAAW,UAAU;AACrB,UAAI,iBAAiB,SAAS;AAC5B,qBAAa,iBAAiB,OAAO;AAAA,MACvC;AACA,iBAAW;AAAA,IACb;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,QAAM,cAAc,oBAAoB;AAExC,SAAO;AAAA;AAAA,IAEL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAGA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAGA;AAAA,IACA;AAAA;AAAA,IAGA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAGA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../hooks/index.ts","../../hooks/use-chat.ts","../../transport/types.ts","../../transport/sse.ts"],"sourcesContent":["/**\n * Chat Hooks\n *\n * React hooks for chat functionality.\n *\n * @example\n * ```tsx\n * import { useChat } from \"@elqnt/chat/hooks\";\n *\n * function ChatComponent() {\n * const {\n * connect,\n * sendMessage,\n * messages,\n * isConnected,\n * } = useChat({\n * baseUrl: \"https://api.example.com/chat\",\n * orgId: \"org-123\",\n * userId: \"user-456\",\n * });\n *\n * // ...\n * }\n * ```\n */\n\nexport { useChat } from \"./use-chat\";\nexport type { UseChatOptions, UseChatReturn } from \"./use-chat\";\n","\"use client\";\n\n/**\n * useChat Hook\n *\n * A unified React hook for chat functionality with support for\n * multiple transport types (SSE, fetch-based SSE, custom transports).\n *\n * @example Basic usage\n * ```tsx\n * function ChatComponent() {\n * const {\n * connect,\n * sendMessage,\n * messages,\n * isConnected,\n * } = useChat({\n * baseUrl: \"https://api.example.com/chat\",\n * orgId: \"org-123\",\n * userId: \"user-456\",\n * });\n *\n * useEffect(() => {\n * connect();\n * return () => disconnect();\n * }, []);\n *\n * return (\n * <div>\n * {messages.map(msg => <Message key={msg.id} {...msg} />)}\n * <input onSubmit={(content) => sendMessage(content)} />\n * </div>\n * );\n * }\n * ```\n *\n * @example With custom transport\n * ```tsx\n * import { createFetchSSETransport } from \"@elqnt/chat/transport\";\n *\n * const transport = createFetchSSETransport();\n *\n * function App() {\n * const chat = useChat({\n * baseUrl: \"...\",\n * orgId: \"...\",\n * userId: \"...\",\n * transport,\n * });\n * }\n * ```\n */\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { Chat, ChatEvent, ChatMessage } from \"../models\";\nimport type {\n ChatTransport,\n TransportState,\n TransportError,\n ConnectionMetrics,\n RetryConfig,\n Unsubscribe,\n} from \"../transport/types\";\nimport { createSSETransport } from \"../transport/sse\";\n\n/**\n * Chat hook options\n */\nexport interface UseChatOptions {\n /** Base URL for the chat server (e.g., \"https://api.example.com/chat\") */\n baseUrl: string;\n /** Organization ID */\n orgId: string;\n /** User ID */\n userId: string;\n /** Client type for routing */\n clientType?: \"customer\" | \"humanAgent\" | \"observer\";\n /** Transport instance or type */\n transport?: ChatTransport | \"sse\" | \"sse-fetch\";\n /** Callback for all incoming events */\n onMessage?: (event: ChatEvent) => void;\n /** Callback for errors */\n onError?: (error: TransportError) => void;\n /** Callback when connection state changes */\n onConnectionChange?: (state: TransportState) => void;\n /** Auto-connect on mount */\n autoConnect?: boolean;\n /** Retry configuration */\n retryConfig?: RetryConfig;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * Chat hook return type\n */\nexport interface UseChatReturn {\n // Connection\n /** Connect to the chat server */\n connect: () => Promise<void>;\n /** Disconnect from the server */\n disconnect: () => void;\n /** Current connection state */\n connectionState: TransportState;\n /** Whether currently connected */\n isConnected: boolean;\n\n // Chat operations\n /** Start a new chat session */\n startChat: (metadata?: Record<string, unknown>) => Promise<string>;\n /** Load an existing chat, returns the loaded chat */\n loadChat: (chatKey: string) => Promise<Chat>;\n /** Send a text message */\n sendMessage: (content: string, attachments?: unknown[]) => Promise<void>;\n /** Send a raw chat event (for custom event types) */\n sendEvent: (event: Omit<ChatEvent, \"timestamp\">) => Promise<void>;\n /** End the current chat */\n endChat: (reason?: string) => Promise<void>;\n\n // Typing indicators\n /** Signal that user is typing */\n startTyping: () => void;\n /** Signal that user stopped typing */\n stopTyping: () => void;\n\n // State\n /** Current chat object */\n currentChat: Chat | null;\n /** Current chat key */\n chatKey: string | null;\n /** Chat messages */\n messages: ChatMessage[];\n /** Current error */\n error: TransportError | null;\n /** Connection metrics */\n metrics: ConnectionMetrics;\n\n // Event subscription\n /** Subscribe to specific event type */\n on: (eventType: string, handler: (event: ChatEvent) => void) => Unsubscribe;\n /** Clear current error */\n clearError: () => void;\n}\n\n/**\n * Default transport factory\n */\nfunction getDefaultTransport(\n type: \"sse\" | \"sse-fetch\" | undefined,\n debug: boolean\n): ChatTransport {\n // For now, always use SSE. In the future, detect environment\n // and use fetch-based SSE for React Native\n return createSSETransport({ debug });\n}\n\n/**\n * useChat Hook\n *\n * Platform-agnostic chat hook with SSE transport support.\n */\nexport function useChat(options: UseChatOptions): UseChatReturn {\n const {\n baseUrl,\n orgId,\n userId,\n clientType = \"customer\",\n transport: transportOption,\n onMessage,\n onError,\n onConnectionChange,\n autoConnect = false,\n retryConfig,\n debug = false,\n } = options;\n\n // State\n const [connectionState, setConnectionState] = useState<TransportState>(\"disconnected\");\n const [currentChat, setCurrentChat] = useState<Chat | null>(null);\n const [chatKey, setChatKey] = useState<string | null>(null);\n const [messages, setMessages] = useState<ChatMessage[]>([]);\n const [error, setError] = useState<TransportError | null>(null);\n const [metrics, setMetrics] = useState<ConnectionMetrics>({\n latency: 0,\n messagesSent: 0,\n messagesReceived: 0,\n messagesQueued: 0,\n reconnectCount: 0,\n });\n\n // Refs\n const transportRef = useRef<ChatTransport | null>(null);\n const mountedRef = useRef(false);\n const onMessageRef = useRef(onMessage);\n const onErrorRef = useRef(onError);\n const typingTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // Update callback refs\n useEffect(() => {\n onMessageRef.current = onMessage;\n onErrorRef.current = onError;\n }, [onMessage, onError]);\n\n // Initialize transport\n useEffect(() => {\n if (typeof transportOption === \"object\") {\n transportRef.current = transportOption;\n } else {\n transportRef.current = getDefaultTransport(\n transportOption as \"sse\" | \"sse-fetch\" | undefined,\n debug\n );\n }\n }, [transportOption, debug]);\n\n // Handle incoming events\n const handleEvent = useCallback((event: ChatEvent) => {\n if (!mountedRef.current) return;\n\n // Update metrics\n setMetrics((prev) => ({\n ...prev,\n messagesReceived: prev.messagesReceived + 1,\n lastMessageAt: Date.now(),\n }));\n\n // Handle specific event types\n switch (event.type) {\n case \"new_chat_created\":\n // Handle multi-tab sync when another tab creates a chat\n const newChatKey = event.data?.chatKey as string;\n if (newChatKey) {\n setChatKey(newChatKey);\n }\n break;\n\n case \"load_chat_response\":\n const chat = event.data?.chat as Chat;\n if (chat) {\n setCurrentChat(chat);\n setChatKey(chat.key);\n setMessages(chat.messages || []);\n }\n break;\n\n case \"message\":\n if (event.message) {\n setMessages((prev) => [...prev, event.message!]);\n }\n break;\n\n case \"chat_ended\":\n setCurrentChat(null);\n setChatKey(null);\n break;\n\n case \"error\":\n const errorMsg = event.data?.message as string;\n if (errorMsg) {\n const transportError: TransportError = {\n code: \"NETWORK_ERROR\",\n message: errorMsg,\n retryable: true,\n timestamp: Date.now(),\n };\n setError(transportError);\n onErrorRef.current?.(transportError);\n }\n break;\n }\n\n // Call user's onMessage handler\n onMessageRef.current?.(event);\n }, []);\n\n // Connect to the chat server\n const connect = useCallback(async (): Promise<void> => {\n const transport = transportRef.current;\n if (!transport) {\n throw new Error(\"Transport not initialized\");\n }\n\n if (!orgId) {\n const err: TransportError = {\n code: \"CONNECTION_FAILED\",\n message: \"orgId is required\",\n retryable: false,\n timestamp: Date.now(),\n };\n setError(err);\n throw err;\n }\n\n setConnectionState(\"connecting\");\n\n try {\n // Subscribe to events before connecting\n const unsubscribe = transport.onMessage(handleEvent);\n\n await transport.connect({\n baseUrl,\n orgId,\n userId,\n clientType,\n chatKey: chatKey || undefined,\n debug,\n });\n\n setConnectionState(\"connected\");\n setError(null);\n setMetrics(transport.getMetrics());\n onConnectionChange?.(\"connected\");\n\n // Return cleanup in case caller wants it\n return;\n } catch (err) {\n const transportError = err as TransportError;\n setConnectionState(\"disconnected\");\n setError(transportError);\n onErrorRef.current?.(transportError);\n throw err;\n }\n }, [baseUrl, orgId, userId, clientType, chatKey, debug, handleEvent, onConnectionChange]);\n\n // Disconnect from the server\n const disconnect = useCallback((): void => {\n const transport = transportRef.current;\n if (transport) {\n transport.disconnect(true);\n }\n setConnectionState(\"disconnected\");\n onConnectionChange?.(\"disconnected\");\n }, [onConnectionChange]);\n\n // Start a new chat\n const startChat = useCallback(\n async (metadata?: Record<string, unknown>): Promise<string> => {\n const transport = transportRef.current;\n if (!transport) {\n throw new Error(\"Transport not initialized\");\n }\n\n // Use direct HTTP call - no waiting for SSE events\n const response = await transport.createChat({\n orgId,\n userId,\n metadata,\n });\n\n // Update state with the new chat key\n setChatKey(response.chatKey);\n\n return response.chatKey;\n },\n [orgId, userId]\n );\n\n // Load an existing chat\n const loadChat = useCallback(\n async (key: string): Promise<Chat> => {\n const transport = transportRef.current;\n if (!transport) {\n throw new Error(\"Transport not initialized\");\n }\n\n // Use direct HTTP call - no waiting for SSE events\n const response = await transport.loadChatData({\n orgId,\n chatKey: key,\n userId,\n });\n\n // Update state directly from HTTP response\n setCurrentChat(response.chat);\n setChatKey(response.chat.key);\n setMessages(response.chat.messages || []);\n\n // Return the chat for callers that need it\n return response.chat;\n },\n [orgId, userId]\n );\n\n // Send a message\n const sendMessage = useCallback(\n async (content: string, attachments?: unknown[]): Promise<void> => {\n const transport = transportRef.current;\n if (!transport) {\n throw new Error(\"Transport not initialized\");\n }\n if (!chatKey) {\n throw new Error(\"No active chat\");\n }\n\n const message: ChatMessage = {\n id: `msg_${Date.now()}_${Math.random().toString(36).slice(2)}`,\n role: \"user\",\n content,\n time: Date.now(),\n status: \"sending\",\n senderId: userId,\n createdAt: Date.now(),\n attachments: attachments as ChatMessage[\"attachments\"],\n };\n\n // Optimistically add message\n setMessages((prev) => [...prev, message]);\n\n await transport.send({\n type: \"message\",\n orgId,\n chatKey,\n userId,\n timestamp: Date.now(),\n message,\n });\n\n setMetrics((prev) => ({\n ...prev,\n messagesSent: prev.messagesSent + 1,\n }));\n },\n [orgId, chatKey, userId]\n );\n\n // End the current chat\n const endChat = useCallback(\n async (reason?: string): Promise<void> => {\n const transport = transportRef.current;\n if (!transport) {\n throw new Error(\"Transport not initialized\");\n }\n if (!chatKey) {\n return;\n }\n\n await transport.send({\n type: \"end_chat\",\n orgId,\n chatKey,\n userId,\n timestamp: Date.now(),\n data: reason ? { reason } : undefined,\n });\n\n setCurrentChat(null);\n setChatKey(null);\n },\n [orgId, chatKey, userId]\n );\n\n // Send a raw chat event (for custom event types)\n const sendEvent = useCallback(\n async (event: Omit<ChatEvent, \"timestamp\">): Promise<void> => {\n const transport = transportRef.current;\n if (!transport) {\n throw new Error(\"Transport not initialized\");\n }\n\n await transport.send({\n ...event,\n timestamp: Date.now(),\n } as ChatEvent);\n },\n []\n );\n\n // Start typing indicator\n const startTyping = useCallback((): void => {\n const transport = transportRef.current;\n if (!transport || !chatKey) return;\n\n // Clear existing timeout\n if (typingTimeoutRef.current) {\n clearTimeout(typingTimeoutRef.current);\n }\n\n transport\n .send({\n type: \"typing\",\n orgId,\n chatKey,\n userId,\n timestamp: Date.now(),\n })\n .catch(() => {});\n\n // Auto-stop typing after 3 seconds\n typingTimeoutRef.current = setTimeout(() => {\n stopTyping();\n }, 3000);\n }, [orgId, chatKey, userId]);\n\n // Stop typing indicator\n const stopTyping = useCallback((): void => {\n const transport = transportRef.current;\n if (!transport || !chatKey) return;\n\n if (typingTimeoutRef.current) {\n clearTimeout(typingTimeoutRef.current);\n typingTimeoutRef.current = null;\n }\n\n transport\n .send({\n type: \"stopped_typing\",\n orgId,\n chatKey,\n userId,\n timestamp: Date.now(),\n })\n .catch(() => {});\n }, [orgId, chatKey, userId]);\n\n // Subscribe to specific event type\n const on = useCallback(\n (eventType: string, handler: (event: ChatEvent) => void): Unsubscribe => {\n const transport = transportRef.current;\n if (!transport) {\n return () => {};\n }\n return transport.on(eventType, handler);\n },\n []\n );\n\n // Clear error\n const clearError = useCallback((): void => {\n setError(null);\n transportRef.current?.clearError();\n }, []);\n\n // Mount/unmount lifecycle\n useEffect(() => {\n mountedRef.current = true;\n\n if (autoConnect) {\n connect().catch(() => {});\n }\n\n return () => {\n mountedRef.current = false;\n if (typingTimeoutRef.current) {\n clearTimeout(typingTimeoutRef.current);\n }\n disconnect();\n };\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n // Computed state\n const isConnected = connectionState === \"connected\";\n\n return {\n // Connection\n connect,\n disconnect,\n connectionState,\n isConnected,\n\n // Chat operations\n startChat,\n loadChat,\n sendMessage,\n sendEvent,\n endChat,\n\n // Typing\n startTyping,\n stopTyping,\n\n // State\n currentChat,\n chatKey,\n messages,\n error,\n metrics,\n\n // Events\n on,\n clearError,\n };\n}\n","/**\n * Transport Abstraction Layer Types\n *\n * Platform-agnostic transport interfaces for chat communication.\n * Supports browser SSE, React Native fetch-based SSE, and extensible\n * transports like WhatsApp Business API.\n */\n\nimport type { Chat, ChatEvent, ChatMessage } from \"../models\";\n\n/**\n * Transport connection state\n */\nexport type TransportState =\n | \"disconnected\"\n | \"connecting\"\n | \"connected\"\n | \"reconnecting\";\n\n/**\n * Transport error with retry information\n */\nexport interface TransportError {\n code:\n | \"CONNECTION_FAILED\"\n | \"PARSE_ERROR\"\n | \"SEND_FAILED\"\n | \"TIMEOUT\"\n | \"NETWORK_ERROR\"\n | \"AUTH_FAILED\";\n message: string;\n retryable: boolean;\n timestamp: number;\n originalError?: unknown;\n}\n\n/**\n * Configuration for transport connection\n */\nexport interface TransportConfig {\n /** Base URL for the chat server */\n baseUrl: string;\n /** Organization ID */\n orgId: string;\n /** User ID for authentication */\n userId: string;\n /** Client type for routing */\n clientType: \"customer\" | \"humanAgent\" | \"observer\";\n /** Optional current chat key for reconnection */\n chatKey?: string;\n /** Enable debug logging */\n debug?: boolean;\n}\n\n/**\n * Retry configuration for connection attempts\n */\nexport interface RetryConfig {\n /** Maximum number of retry attempts */\n maxRetries?: number;\n /** Initial retry intervals in milliseconds */\n intervals?: number[];\n /** Multiplier for exponential backoff */\n backoffMultiplier?: number;\n /** Maximum backoff time in milliseconds */\n maxBackoffTime?: number;\n}\n\n/**\n * Connection metrics for monitoring\n */\nexport interface ConnectionMetrics {\n /** Round-trip latency in milliseconds */\n latency: number;\n /** Total messages sent */\n messagesSent: number;\n /** Total messages received */\n messagesReceived: number;\n /** Messages waiting to be sent */\n messagesQueued: number;\n /** Number of reconnection attempts */\n reconnectCount: number;\n /** Last error encountered */\n lastError?: TransportError;\n /** Timestamp when connection was established */\n connectedAt?: number;\n /** Timestamp of last message */\n lastMessageAt?: number;\n /** Current transport type */\n transportType?: string;\n}\n\n/**\n * Event handler function type\n */\nexport type EventHandler<T = ChatEvent> = (event: T) => void;\n\n/**\n * Unsubscribe function returned by event subscription\n */\nexport type Unsubscribe = () => void;\n\n/**\n * Send message options\n */\nexport interface SendMessageOptions {\n /** Message content */\n content: string;\n /** Optional attachments */\n attachments?: unknown[];\n /** Optional message metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Create chat options\n */\nexport interface CreateChatOptions {\n /** Organization ID */\n orgId: string;\n /** User ID */\n userId: string;\n /** Optional chat metadata */\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Load chat options\n */\nexport interface LoadChatOptions {\n /** Organization ID */\n orgId: string;\n /** Chat key to load */\n chatKey: string;\n /** User ID */\n userId: string;\n}\n\n/**\n * End chat options\n */\nexport interface EndChatOptions {\n /** Organization ID */\n orgId: string;\n /** Chat key to end */\n chatKey: string;\n /** User ID */\n userId: string;\n /** Optional end reason */\n reason?: string;\n}\n\n/**\n * Response from creating a new chat\n */\nexport interface CreateChatResponse {\n /** The key of the created chat */\n chatKey: string;\n}\n\n/**\n * Response from loading a chat\n */\nexport interface LoadChatResponse {\n /** The loaded chat object */\n chat: Chat;\n /** Agent ID if applicable */\n agentId?: string;\n}\n\n/**\n * Core transport interface\n *\n * Implementations must handle:\n * - Connection lifecycle (connect, disconnect, reconnect)\n * - Message sending (POST requests)\n * - Event receiving (SSE stream)\n * - Error handling and recovery\n */\nexport interface ChatTransport {\n /**\n * Connect to the chat server\n * @param config - Transport configuration\n * @returns Promise that resolves when connected\n */\n connect(config: TransportConfig): Promise<void>;\n\n /**\n * Disconnect from the server\n * @param intentional - Whether disconnect was user-initiated\n */\n disconnect(intentional?: boolean): void;\n\n /**\n * Send a chat event to the server\n * @param event - Chat event to send\n */\n send(event: ChatEvent): Promise<void>;\n\n /**\n * Send a message in the current chat\n * @param message - Message to send\n */\n sendMessage(message: ChatMessage): Promise<void>;\n\n /**\n * Create a new chat and return the chat key directly\n * @param options - Create chat options\n * @returns Promise with the created chat key\n */\n createChat(options: CreateChatOptions): Promise<CreateChatResponse>;\n\n /**\n * Load an existing chat and return the chat data directly\n * @param options - Load chat options\n * @returns Promise with the loaded chat data\n */\n loadChatData(options: LoadChatOptions): Promise<LoadChatResponse>;\n\n /**\n * Subscribe to incoming events\n * @param handler - Event handler function\n * @returns Unsubscribe function\n */\n onMessage(handler: EventHandler): Unsubscribe;\n\n /**\n * Subscribe to specific event type\n * @param eventType - Type of event to listen for\n * @param handler - Event handler function\n * @returns Unsubscribe function\n */\n on(eventType: string, handler: EventHandler): Unsubscribe;\n\n /**\n * Get current connection state\n */\n getState(): TransportState;\n\n /**\n * Get connection metrics\n */\n getMetrics(): ConnectionMetrics;\n\n /**\n * Get last error\n */\n getError(): TransportError | undefined;\n\n /**\n * Clear error state\n */\n clearError(): void;\n}\n\n/**\n * Transport factory function type\n */\nexport type TransportFactory = (config?: Partial<TransportConfig>) => ChatTransport;\n\n/**\n * Logger interface for transport debugging\n */\nexport interface TransportLogger {\n debug: (message: string, ...args: unknown[]) => void;\n info: (message: string, ...args: unknown[]) => void;\n warn: (message: string, ...args: unknown[]) => void;\n error: (message: string, ...args: unknown[]) => void;\n}\n\n/**\n * Create a default logger\n * @param debug - Enable debug logging\n */\nexport function createLogger(debug: boolean = false): TransportLogger {\n return {\n debug: debug ? console.log.bind(console, \"[chat]\") : () => {},\n info: console.info.bind(console, \"[chat]\"),\n warn: console.warn.bind(console, \"[chat]\"),\n error: console.error.bind(console, \"[chat]\"),\n };\n}\n\n/**\n * Default retry configuration\n */\nexport const DEFAULT_RETRY_CONFIG: Required<RetryConfig> = {\n maxRetries: 10,\n intervals: [1000, 2000, 5000],\n backoffMultiplier: 1.5,\n maxBackoffTime: 30000,\n};\n\n/**\n * Calculate retry interval with exponential backoff\n * @param retryCount - Current retry attempt number\n * @param config - Retry configuration\n */\nexport function calculateRetryInterval(\n retryCount: number,\n config: RetryConfig = DEFAULT_RETRY_CONFIG\n): number {\n const {\n intervals = DEFAULT_RETRY_CONFIG.intervals,\n backoffMultiplier = DEFAULT_RETRY_CONFIG.backoffMultiplier,\n maxBackoffTime = DEFAULT_RETRY_CONFIG.maxBackoffTime,\n } = config;\n\n if (retryCount < intervals.length) {\n return intervals[retryCount];\n }\n\n const baseInterval = intervals[intervals.length - 1] || 5000;\n const backoffTime =\n baseInterval * Math.pow(backoffMultiplier, retryCount - intervals.length + 1);\n return Math.min(backoffTime, maxBackoffTime);\n}\n","/**\n * SSE Transport (Browser)\n *\n * Uses native EventSource for receiving server events and fetch POST for sending.\n * This is the default transport for browser environments.\n *\n * @example\n * ```typescript\n * import { createSSETransport } from \"@elqnt/chat/transport\";\n *\n * const transport = createSSETransport();\n * await transport.connect({ baseUrl, orgId, userId, clientType: \"customer\" });\n * ```\n */\n\nimport type { Chat, ChatEvent, ChatMessage } from \"../models\";\nimport type {\n ChatTransport,\n TransportConfig,\n TransportState,\n TransportError,\n ConnectionMetrics,\n EventHandler,\n Unsubscribe,\n RetryConfig,\n TransportLogger,\n CreateChatOptions,\n CreateChatResponse,\n LoadChatOptions,\n LoadChatResponse,\n} from \"./types\";\nimport { createLogger, calculateRetryInterval, DEFAULT_RETRY_CONFIG } from \"./types\";\n\n/**\n * SSE Transport options\n */\nexport interface SSETransportOptions {\n /** Retry configuration */\n retryConfig?: RetryConfig;\n /** Enable debug logging */\n debug?: boolean;\n /** Custom logger */\n logger?: TransportLogger;\n}\n\n/**\n * Create an SSE transport for browser environments\n */\nexport function createSSETransport(options: SSETransportOptions = {}): ChatTransport {\n const {\n retryConfig = DEFAULT_RETRY_CONFIG,\n debug = false,\n logger = createLogger(debug),\n } = options;\n\n // Internal state\n let eventSource: EventSource | undefined;\n let config: TransportConfig | undefined;\n let state: TransportState = \"disconnected\";\n let error: TransportError | undefined;\n let retryCount = 0;\n let reconnectTimeout: ReturnType<typeof setTimeout> | undefined;\n let intentionalDisconnect = false;\n\n // Metrics\n const metrics: ConnectionMetrics = {\n latency: 0,\n messagesSent: 0,\n messagesReceived: 0,\n messagesQueued: 0,\n reconnectCount: 0,\n transportType: \"sse\",\n };\n\n // Event handlers\n const globalHandlers = new Set<EventHandler>();\n const typeHandlers = new Map<string, Set<EventHandler>>();\n\n // Helper to emit events\n function emit(event: ChatEvent): void {\n // Update metrics\n metrics.messagesReceived++;\n metrics.lastMessageAt = Date.now();\n\n // Call global handlers\n globalHandlers.forEach((handler) => {\n try {\n handler(event);\n } catch (err) {\n logger.error(\"Error in message handler:\", err);\n }\n });\n\n // Call type-specific handlers\n const handlers = typeHandlers.get(event.type);\n if (handlers) {\n handlers.forEach((handler) => {\n try {\n handler(event);\n } catch (err) {\n logger.error(`Error in ${event.type} handler:`, err);\n }\n });\n }\n }\n\n // REST API helper\n async function sendRest(endpoint: string, body: Record<string, unknown>): Promise<unknown> {\n if (!config) {\n throw new Error(\"Transport not connected\");\n }\n\n const url = `${config.baseUrl}/${endpoint}`;\n logger.debug(`POST ${endpoint}`, body);\n\n const response = await fetch(url, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`API error: ${response.status} - ${errorText}`);\n }\n\n const json = await response.json() as { success?: boolean; data?: unknown };\n\n // Backend wraps responses in { success: true, data: {...} }\n // Unwrap to return just the data\n if (json && typeof json === \"object\" && \"data\" in json) {\n return json.data;\n }\n\n return json;\n }\n\n // Handle SSE message\n function handleMessage(event: MessageEvent): void {\n if (!event.data || event.data === \"\") return;\n\n try {\n const data = JSON.parse(event.data) as ChatEvent;\n logger.debug(\"Received:\", data.type);\n emit(data);\n } catch (err) {\n logger.error(\"Failed to parse SSE message:\", err);\n }\n }\n\n // Setup SSE event listeners\n function setupEventListeners(es: EventSource): void {\n // Generic message handler\n es.addEventListener(\"message\", handleMessage);\n\n // Add handlers for known event types\n const eventTypes = [\n \"reconnected\", \"typing\", \"stopped_typing\", \"waiting\",\n \"waiting_for_agent\", \"human_agent_joined\", \"human_agent_left\",\n \"chat_ended\", \"chat_updated\", \"load_chat_response\",\n \"new_chat_created\", \"show_csat_survey\", \"csat_response\",\n \"user_suggested_actions\", \"agent_execution_started\",\n \"agent_execution_ended\", \"agent_context_update\",\n \"plan_pending_approval\", \"step_started\", \"step_completed\",\n \"step_failed\", \"plan_completed\", \"skills_changed\", \"summary_update\",\n ];\n\n eventTypes.forEach((type) => {\n es.addEventListener(type, handleMessage);\n });\n }\n\n // Schedule reconnect\n function scheduleReconnect(): void {\n if (intentionalDisconnect || !config) return;\n\n const maxRetries = retryConfig.maxRetries ?? DEFAULT_RETRY_CONFIG.maxRetries;\n if (retryCount >= maxRetries) {\n logger.error(`Max retries (${maxRetries}) exceeded`);\n error = {\n code: \"CONNECTION_FAILED\",\n message: `Max retries (${maxRetries}) exceeded`,\n retryable: false,\n timestamp: Date.now(),\n };\n return;\n }\n\n const interval = calculateRetryInterval(retryCount, retryConfig);\n retryCount++;\n metrics.reconnectCount++;\n\n logger.info(`Reconnecting in ${interval}ms (attempt ${retryCount})`);\n state = \"reconnecting\";\n\n reconnectTimeout = setTimeout(() => {\n if (config) {\n transport.connect(config).catch((err) => {\n logger.error(\"Reconnect failed:\", err);\n });\n }\n }, interval);\n }\n\n const transport: ChatTransport = {\n async connect(cfg: TransportConfig): Promise<void> {\n config = cfg;\n intentionalDisconnect = false;\n\n // Clean up existing connection\n if (eventSource) {\n eventSource.close();\n eventSource = undefined;\n }\n if (reconnectTimeout) {\n clearTimeout(reconnectTimeout);\n reconnectTimeout = undefined;\n }\n\n state = retryCount > 0 ? \"reconnecting\" : \"connecting\";\n\n return new Promise((resolve, reject) => {\n const connectionStart = Date.now();\n const url = `${cfg.baseUrl}/stream?orgId=${cfg.orgId}&userId=${cfg.userId}&clientType=${cfg.clientType}${cfg.chatKey ? `&chatId=${cfg.chatKey}` : \"\"}`;\n\n logger.debug(\"Connecting to:\", url);\n const es = new EventSource(url);\n\n es.onopen = () => {\n const connectionTime = Date.now() - connectionStart;\n logger.info(`Connected in ${connectionTime}ms`);\n\n state = \"connected\";\n error = undefined;\n retryCount = 0;\n metrics.connectedAt = Date.now();\n metrics.latency = connectionTime;\n\n setupEventListeners(es);\n resolve();\n };\n\n es.onerror = () => {\n if (es.readyState === EventSource.CLOSED) {\n const sseError: TransportError = {\n code: \"CONNECTION_FAILED\",\n message: \"SSE connection failed\",\n retryable: true,\n timestamp: Date.now(),\n };\n error = sseError;\n metrics.lastError = sseError;\n state = \"disconnected\";\n\n if (!intentionalDisconnect) {\n scheduleReconnect();\n }\n\n // Only reject if this is the initial connection attempt\n if (retryCount === 0) {\n reject(sseError);\n }\n }\n };\n\n eventSource = es;\n });\n },\n\n disconnect(intentional = true): void {\n logger.info(\"Disconnecting\", { intentional });\n intentionalDisconnect = intentional;\n\n if (reconnectTimeout) {\n clearTimeout(reconnectTimeout);\n reconnectTimeout = undefined;\n }\n\n if (eventSource) {\n eventSource.close();\n eventSource = undefined;\n }\n\n state = \"disconnected\";\n retryCount = 0;\n },\n\n async send(event: ChatEvent): Promise<void> {\n if (!config) {\n throw new Error(\"Transport not connected\");\n }\n\n // Map event types to REST endpoints\n switch (event.type) {\n case \"message\":\n await sendRest(\"send\", {\n orgId: event.orgId,\n chatKey: event.chatKey,\n userId: event.userId,\n message: event.message,\n });\n break;\n\n case \"typing\":\n await sendRest(\"typing\", {\n orgId: event.orgId,\n chatKey: event.chatKey,\n userId: event.userId,\n typing: true,\n });\n break;\n\n case \"stopped_typing\":\n await sendRest(\"typing\", {\n orgId: event.orgId,\n chatKey: event.chatKey,\n userId: event.userId,\n typing: false,\n });\n break;\n\n case \"load_chat\":\n // Deprecated: Use loadChatData() instead for direct response\n await sendRest(\"load\", {\n orgId: event.orgId,\n chatKey: event.chatKey,\n userId: event.userId,\n });\n break;\n\n case \"new_chat\":\n // Deprecated: Use createChat() instead for direct response\n await sendRest(\"create\", {\n orgId: event.orgId,\n userId: event.userId,\n metadata: event.data,\n });\n break;\n\n case \"end_chat\":\n await sendRest(\"end\", {\n orgId: event.orgId,\n chatKey: event.chatKey,\n userId: event.userId,\n data: event.data,\n });\n break;\n\n default:\n // Generic event endpoint for other types\n await sendRest(\"event\", {\n type: event.type,\n orgId: event.orgId,\n chatKey: event.chatKey,\n userId: event.userId,\n data: event.data,\n });\n }\n\n metrics.messagesSent++;\n },\n\n async sendMessage(message: ChatMessage): Promise<void> {\n if (!config) {\n throw new Error(\"Transport not connected\");\n }\n\n await sendRest(\"send\", {\n orgId: config.orgId,\n chatKey: config.chatKey,\n userId: config.userId,\n message,\n });\n\n metrics.messagesSent++;\n },\n\n async createChat(options: CreateChatOptions): Promise<CreateChatResponse> {\n if (!config) {\n throw new Error(\"Transport not connected\");\n }\n\n const response = await sendRest(\"create\", {\n orgId: options.orgId,\n userId: options.userId,\n metadata: options.metadata,\n }) as { chatKey?: string };\n\n if (!response?.chatKey) {\n throw new Error(\"Failed to create chat: no chatKey returned\");\n }\n\n return { chatKey: response.chatKey };\n },\n\n async loadChatData(options: LoadChatOptions): Promise<LoadChatResponse> {\n if (!config) {\n throw new Error(\"Transport not connected\");\n }\n\n const response = await sendRest(\"load\", {\n orgId: options.orgId,\n chatKey: options.chatKey,\n userId: options.userId,\n }) as { chat?: unknown; agentId?: string };\n\n if (!response?.chat) {\n throw new Error(\"Failed to load chat: no chat data returned\");\n }\n\n return {\n chat: response.chat as Chat,\n agentId: response.agentId,\n };\n },\n\n onMessage(handler: EventHandler): Unsubscribe {\n globalHandlers.add(handler);\n return () => globalHandlers.delete(handler);\n },\n\n on(eventType: string, handler: EventHandler): Unsubscribe {\n if (!typeHandlers.has(eventType)) {\n typeHandlers.set(eventType, new Set());\n }\n typeHandlers.get(eventType)!.add(handler);\n return () => {\n const handlers = typeHandlers.get(eventType);\n if (handlers) {\n handlers.delete(handler);\n if (handlers.size === 0) {\n typeHandlers.delete(eventType);\n }\n }\n };\n },\n\n getState(): TransportState {\n return state;\n },\n\n getMetrics(): ConnectionMetrics {\n return { ...metrics };\n },\n\n getError(): TransportError | undefined {\n return error;\n },\n\n clearError(): void {\n error = undefined;\n },\n };\n\n return transport;\n}\n"],"mappings":"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","names":["options"]}