@aigentyc/chat-sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +156 -0
  3. package/dist/JsonRenderResult-Ftw4AKwb.d.cts +18 -0
  4. package/dist/JsonRenderResult-Ftw4AKwb.d.ts +18 -0
  5. package/dist/JsonRenderResult-GQOYPLVH.cjs +15 -0
  6. package/dist/JsonRenderResult-GQOYPLVH.cjs.map +1 -0
  7. package/dist/JsonRenderResult-ZFJ6VWMS.js +6 -0
  8. package/dist/JsonRenderResult-ZFJ6VWMS.js.map +1 -0
  9. package/dist/SlotsContext-CBtt36al.d.ts +148 -0
  10. package/dist/SlotsContext-CHvISDJT.d.cts +148 -0
  11. package/dist/VisualizationRenderer-FNFYNN66.js +5 -0
  12. package/dist/VisualizationRenderer-FNFYNN66.js.map +1 -0
  13. package/dist/VisualizationRenderer-VKMZXRUX.cjs +20 -0
  14. package/dist/VisualizationRenderer-VKMZXRUX.cjs.map +1 -0
  15. package/dist/ai-elements.cjs +4608 -0
  16. package/dist/ai-elements.cjs.map +1 -0
  17. package/dist/ai-elements.d.cts +897 -0
  18. package/dist/ai-elements.d.ts +897 -0
  19. package/dist/ai-elements.js +4363 -0
  20. package/dist/ai-elements.js.map +1 -0
  21. package/dist/chunk-3MP2EGEJ.cjs +270 -0
  22. package/dist/chunk-3MP2EGEJ.cjs.map +1 -0
  23. package/dist/chunk-3RW7O444.js +26 -0
  24. package/dist/chunk-3RW7O444.js.map +1 -0
  25. package/dist/chunk-42ARGQXE.js +51 -0
  26. package/dist/chunk-42ARGQXE.js.map +1 -0
  27. package/dist/chunk-4FBVV64J.js +257 -0
  28. package/dist/chunk-4FBVV64J.js.map +1 -0
  29. package/dist/chunk-4QT25AXI.js +21 -0
  30. package/dist/chunk-4QT25AXI.js.map +1 -0
  31. package/dist/chunk-525KS5HM.cjs +30 -0
  32. package/dist/chunk-525KS5HM.cjs.map +1 -0
  33. package/dist/chunk-5F3O3ZJH.js +299 -0
  34. package/dist/chunk-5F3O3ZJH.js.map +1 -0
  35. package/dist/chunk-5QSXB6UL.cjs +259 -0
  36. package/dist/chunk-5QSXB6UL.cjs.map +1 -0
  37. package/dist/chunk-5T4FJ2SR.js +664 -0
  38. package/dist/chunk-5T4FJ2SR.js.map +1 -0
  39. package/dist/chunk-7BNYTOTE.cjs +67 -0
  40. package/dist/chunk-7BNYTOTE.cjs.map +1 -0
  41. package/dist/chunk-AWAJOSFP.cjs +96 -0
  42. package/dist/chunk-AWAJOSFP.cjs.map +1 -0
  43. package/dist/chunk-BKDV2H6Z.js +224 -0
  44. package/dist/chunk-BKDV2H6Z.js.map +1 -0
  45. package/dist/chunk-FQN6OBGN.cjs +171 -0
  46. package/dist/chunk-FQN6OBGN.cjs.map +1 -0
  47. package/dist/chunk-FYPJSHCL.js +190 -0
  48. package/dist/chunk-FYPJSHCL.js.map +1 -0
  49. package/dist/chunk-J2H6MLQF.cjs +680 -0
  50. package/dist/chunk-J2H6MLQF.cjs.map +1 -0
  51. package/dist/chunk-J2K7EJYP.cjs +198 -0
  52. package/dist/chunk-J2K7EJYP.cjs.map +1 -0
  53. package/dist/chunk-JI5KCSOI.cjs +23 -0
  54. package/dist/chunk-JI5KCSOI.cjs.map +1 -0
  55. package/dist/chunk-JOO6C3XT.cjs +44 -0
  56. package/dist/chunk-JOO6C3XT.cjs.map +1 -0
  57. package/dist/chunk-KBGPBUTI.cjs +78 -0
  58. package/dist/chunk-KBGPBUTI.cjs.map +1 -0
  59. package/dist/chunk-MT2AMINB.js +75 -0
  60. package/dist/chunk-MT2AMINB.js.map +1 -0
  61. package/dist/chunk-MZQKGNWF.js +4 -0
  62. package/dist/chunk-MZQKGNWF.js.map +1 -0
  63. package/dist/chunk-NG7OTWXQ.cjs +226 -0
  64. package/dist/chunk-NG7OTWXQ.cjs.map +1 -0
  65. package/dist/chunk-NPJKLYLV.js +68 -0
  66. package/dist/chunk-NPJKLYLV.js.map +1 -0
  67. package/dist/chunk-NW2ESHRV.js +685 -0
  68. package/dist/chunk-NW2ESHRV.js.map +1 -0
  69. package/dist/chunk-NWF735F5.js +1631 -0
  70. package/dist/chunk-NWF735F5.js.map +1 -0
  71. package/dist/chunk-NYQSM3EB.cjs +305 -0
  72. package/dist/chunk-NYQSM3EB.cjs.map +1 -0
  73. package/dist/chunk-OU7OROOE.cjs +1643 -0
  74. package/dist/chunk-OU7OROOE.cjs.map +1 -0
  75. package/dist/chunk-PS3U7T37.js +42 -0
  76. package/dist/chunk-PS3U7T37.js.map +1 -0
  77. package/dist/chunk-Q7T3VAJV.cjs +687 -0
  78. package/dist/chunk-Q7T3VAJV.cjs.map +1 -0
  79. package/dist/chunk-QYCEHFAB.js +265 -0
  80. package/dist/chunk-QYCEHFAB.js.map +1 -0
  81. package/dist/chunk-RPDJXB3U.js +676 -0
  82. package/dist/chunk-RPDJXB3U.js.map +1 -0
  83. package/dist/chunk-UKEL7FWS.js +64 -0
  84. package/dist/chunk-UKEL7FWS.js.map +1 -0
  85. package/dist/chunk-VS3NZ7FX.js +164 -0
  86. package/dist/chunk-VS3NZ7FX.js.map +1 -0
  87. package/dist/chunk-WZLWAVSS.cjs +73 -0
  88. package/dist/chunk-WZLWAVSS.cjs.map +1 -0
  89. package/dist/chunk-X5YEOOPK.cjs +758 -0
  90. package/dist/chunk-X5YEOOPK.cjs.map +1 -0
  91. package/dist/chunk-X7R334SB.cjs +5 -0
  92. package/dist/chunk-X7R334SB.cjs.map +1 -0
  93. package/dist/chunk-XXNDL5SJ.cjs +432 -0
  94. package/dist/chunk-XXNDL5SJ.cjs.map +1 -0
  95. package/dist/chunk-YQELMJW5.js +429 -0
  96. package/dist/chunk-YQELMJW5.js.map +1 -0
  97. package/dist/components.cjs +551 -0
  98. package/dist/components.cjs.map +1 -0
  99. package/dist/components.d.cts +181 -0
  100. package/dist/components.d.ts +181 -0
  101. package/dist/components.js +483 -0
  102. package/dist/components.js.map +1 -0
  103. package/dist/core.cjs +283 -0
  104. package/dist/core.cjs.map +1 -0
  105. package/dist/core.d.cts +455 -0
  106. package/dist/core.d.ts +455 -0
  107. package/dist/core.js +241 -0
  108. package/dist/core.js.map +1 -0
  109. package/dist/hooks.cjs +324 -0
  110. package/dist/hooks.cjs.map +1 -0
  111. package/dist/hooks.d.cts +163 -0
  112. package/dist/hooks.d.ts +163 -0
  113. package/dist/hooks.js +277 -0
  114. package/dist/hooks.js.map +1 -0
  115. package/dist/i18n.cjs +26 -0
  116. package/dist/i18n.cjs.map +1 -0
  117. package/dist/i18n.d.cts +50 -0
  118. package/dist/i18n.d.ts +50 -0
  119. package/dist/i18n.js +5 -0
  120. package/dist/i18n.js.map +1 -0
  121. package/dist/index.cjs +466 -0
  122. package/dist/index.cjs.map +1 -0
  123. package/dist/index.d.cts +80 -0
  124. package/dist/index.d.ts +80 -0
  125. package/dist/index.js +438 -0
  126. package/dist/index.js.map +1 -0
  127. package/dist/interaction-tracker-D9P1Oq4j.d.cts +83 -0
  128. package/dist/interaction-tracker-D9P1Oq4j.d.ts +83 -0
  129. package/dist/json-render.cjs +23 -0
  130. package/dist/json-render.cjs.map +1 -0
  131. package/dist/json-render.d.cts +857 -0
  132. package/dist/json-render.d.ts +857 -0
  133. package/dist/json-render.js +6 -0
  134. package/dist/json-render.js.map +1 -0
  135. package/dist/live-chat-transport-4XLOIPOE.js +4 -0
  136. package/dist/live-chat-transport-4XLOIPOE.js.map +1 -0
  137. package/dist/live-chat-transport-ALVRGWX7.cjs +13 -0
  138. package/dist/live-chat-transport-ALVRGWX7.cjs.map +1 -0
  139. package/dist/select-B4l9yoyn.d.cts +99 -0
  140. package/dist/select-B4l9yoyn.d.ts +99 -0
  141. package/dist/styles.css +2 -0
  142. package/dist/theme.cjs +18 -0
  143. package/dist/theme.cjs.map +1 -0
  144. package/dist/theme.d.cts +55 -0
  145. package/dist/theme.d.ts +55 -0
  146. package/dist/theme.js +5 -0
  147. package/dist/theme.js.map +1 -0
  148. package/dist/tools.cjs +32 -0
  149. package/dist/tools.cjs.map +1 -0
  150. package/dist/tools.d.cts +117 -0
  151. package/dist/tools.d.ts +117 -0
  152. package/dist/tools.js +11 -0
  153. package/dist/tools.js.map +1 -0
  154. package/dist/types-DKJ_-nbG.d.cts +349 -0
  155. package/dist/types-DKJ_-nbG.d.ts +349 -0
  156. package/dist/ui.cjs +667 -0
  157. package/dist/ui.cjs.map +1 -0
  158. package/dist/ui.d.cts +95 -0
  159. package/dist/ui.d.ts +95 -0
  160. package/dist/ui.js +414 -0
  161. package/dist/ui.js.map +1 -0
  162. package/package.json +255 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/analytics/interaction-tracker.ts"],"names":[],"mappings":"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","file":"chunk-MT2AMINB.js","sourcesContent":["\"use client\";\n\n/**\n * Interaction tracking hook and utilities.\n *\n * Tracks user interactions (link clicks, copies, feedback, etc.) and\n * sends them in batches to the KB analytics API.\n *\n * All browser API access is guarded against SSR.\n */\n\nimport { useCallback, useRef } from \"react\";\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Supported interaction types for analytics.\n */\nexport type InteractionType =\n | \"link_click\"\n | \"suggestion_click\"\n | \"source_click\"\n | \"copy\"\n | \"expand\"\n | \"collapse\"\n | \"button_click\"\n | \"landing_question_click\"\n | \"tool_ui_interaction\"\n | \"tool_action_click\"\n | \"tool_order_sample\"\n | \"tool_view_details\"\n | \"tool_back_to_list\"\n | \"tool_gallery_image_click\"\n | \"tool_contact_click\"\n | \"tool_pagination_next\"\n | \"tool_pagination_prev\"\n | \"feedback\"\n | \"flag\"\n | \"page_view\";\n\n/**\n * Arbitrary metadata attached to a tracked interaction.\n */\nexport interface InteractionMetadata {\n /** URL that was interacted with */\n url?: string;\n /** Visible text of the element */\n text?: string;\n /** Position / index in a list */\n position?: number;\n /** DOM element type (e.g. `\"a\"`, `\"button\"`) */\n elementType?: string;\n /** Additional key-value pairs */\n [key: string]: unknown;\n}\n\n/**\n * Parameters for a single `trackInteraction` call.\n */\nexport interface TrackInteractionParams {\n /** Interaction type */\n type: InteractionType;\n /** Identifier for the interacted element */\n target?: string;\n /** Human-readable label */\n label?: string;\n /** Extra metadata */\n metadata?: InteractionMetadata;\n /** Associated message ID (for per-message analytics) */\n messageId?: string;\n /** Server event ID (for correlation) */\n eventId?: string;\n}\n\n/**\n * Options for the `useInteractionTracker` hook.\n */\nexport interface UseInteractionTrackerOptions {\n /** Base API endpoint */\n apiEndpoint: string;\n /** Aigentyc project ID */\n projectId: string;\n /** Bearer API key (optional — falls back to session cookies) */\n apiKey?: string;\n /** Current page URL for contextual tracking */\n pageUrl?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\n/** Batch size before auto-flush */\nconst BATCH_SIZE = 5;\n/** Delay before flushing a partial batch (ms) */\nconst BATCH_DELAY_MS = 1000;\n\n/**\n * React hook to track user interactions via the KB analytics API.\n *\n * Interactions are batched (up to `BATCH_SIZE`) and flushed after\n * `BATCH_DELAY_MS` of inactivity.\n *\n * @param sessionId - Current chat session ID (tracking is skipped if `null`)\n * @param options - API configuration\n * @returns `{ trackInteraction, flushOnUnmount }`\n *\n * @example\n * ```tsx\n * const { trackInteraction, flushOnUnmount } = useInteractionTracker(sessionId, {\n * apiEndpoint: \"https://api.example.com\",\n * projectId: \"abc\",\n * });\n *\n * useEffect(() => () => flushOnUnmount(), [flushOnUnmount]);\n *\n * trackInteraction({ type: \"link_click\", target: \"https://example.com\" });\n * ```\n */\nexport function useInteractionTracker(\n sessionId: string | null,\n options: UseInteractionTrackerOptions,\n) {\n const { apiEndpoint, projectId, apiKey, pageUrl } = options;\n const batchRef = useRef<TrackInteractionParams[]>([]);\n const batchTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const flushBatch = useCallback(async () => {\n if (typeof window === \"undefined\") return;\n if (batchRef.current.length === 0 || !sessionId) return;\n\n const interactions = [...batchRef.current];\n batchRef.current = [];\n\n try {\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n };\n if (apiKey) {\n headers[\"Authorization\"] = `Bearer ${apiKey}`;\n }\n\n const response = await fetch(`${apiEndpoint}/api/kb/interactions`, {\n method: \"POST\",\n headers,\n credentials: \"include\",\n body: JSON.stringify({\n projectId,\n sessionId,\n interactions,\n ...(pageUrl ? { pageUrl } : {}),\n }),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({}));\n console.error(\"[Analytics] Failed to track interactions:\", error);\n }\n } catch (error) {\n console.error(\"[Analytics] Error tracking interactions:\", error);\n }\n }, [sessionId, apiEndpoint, projectId, apiKey, pageUrl]);\n\n /**\n * Track a single interaction. Interactions are batched and flushed\n * automatically.\n */\n const trackInteraction = useCallback(\n (params: TrackInteractionParams) => {\n if (typeof window === \"undefined\") return;\n if (!sessionId) {\n console.warn(\"[Analytics] Cannot track interaction: no sessionId\");\n return;\n }\n\n batchRef.current.push(params);\n\n if (batchTimeoutRef.current) {\n clearTimeout(batchTimeoutRef.current);\n }\n\n if (batchRef.current.length >= BATCH_SIZE) {\n flushBatch();\n } else {\n batchTimeoutRef.current = setTimeout(flushBatch, BATCH_DELAY_MS);\n }\n },\n [sessionId, flushBatch],\n );\n\n /**\n * Flush any pending interactions immediately.\n * Call this in a cleanup effect to avoid losing data on unmount.\n */\n const flushOnUnmount = useCallback(() => {\n if (batchTimeoutRef.current) {\n clearTimeout(batchTimeoutRef.current);\n }\n flushBatch();\n }, [flushBatch]);\n\n return { trackInteraction, flushOnUnmount };\n}\n\n// ---------------------------------------------------------------------------\n// Utilities\n// ---------------------------------------------------------------------------\n\n/**\n * Generate a unique session ID for analytics.\n *\n * Format: `kb-<timestamp>-<random>`\n */\nexport function generateSessionId(): string {\n return `kb-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n}\n"]}
@@ -0,0 +1,4 @@
1
+ "use client";
2
+
3
+ //# sourceMappingURL=chunk-MZQKGNWF.js.map
4
+ //# sourceMappingURL=chunk-MZQKGNWF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-MZQKGNWF.js"}
@@ -0,0 +1,226 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ // src/core/live-chat-transport.ts
5
+ var LiveChatTransport = class {
6
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
+ socket = null;
8
+ config;
9
+ state = "ai";
10
+ liveChatSessionId = null;
11
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
12
+ listeners = /* @__PURE__ */ new Map();
13
+ constructor(config) {
14
+ this.config = config;
15
+ }
16
+ /**
17
+ * Establish the Socket.IO connection and wire up all server events.
18
+ *
19
+ * Safe to call in SSR — will resolve immediately without connecting.
20
+ */
21
+ async connect() {
22
+ if (typeof window === "undefined") return;
23
+ const { io } = await import('socket.io-client');
24
+ this.socket = io(`${this.config.chatServiceUrl}/visitor`, {
25
+ path: "/api/chat/socket.io",
26
+ auth: {
27
+ apiKey: this.config.apiKey,
28
+ projectId: this.config.projectId
29
+ },
30
+ transports: ["websocket", "polling"]
31
+ });
32
+ this.socket.on("connect", () => {
33
+ console.log("[LiveChat] Connected");
34
+ });
35
+ this.socket.on("disconnect", () => {
36
+ console.log("[LiveChat] Disconnected");
37
+ });
38
+ this.socket.on(
39
+ "livechat:queued",
40
+ (data) => {
41
+ this.liveChatSessionId = data.liveChatSessionId;
42
+ this.setState("queued");
43
+ this.emit("queued", data);
44
+ }
45
+ );
46
+ this.socket.on("livechat:queue-update", (data) => {
47
+ this.emit("queue-update", data);
48
+ });
49
+ this.socket.on("livechat:accepted", (data) => {
50
+ this.setState("live");
51
+ this.emit("accepted", data);
52
+ });
53
+ this.socket.on("livechat:message", (data) => {
54
+ this.emit("message", {
55
+ id: data.id,
56
+ content: data.content,
57
+ senderType: data.senderType,
58
+ timestamp: data.timestamp
59
+ });
60
+ });
61
+ this.socket.on("livechat:ended", (data) => {
62
+ this.setState("ended");
63
+ this.emit("ended", data);
64
+ });
65
+ this.socket.on("livechat:handback-ai", () => {
66
+ this.setState("ai");
67
+ this.emit("handback-ai", void 0);
68
+ });
69
+ this.socket.on(
70
+ "livechat:system",
71
+ (data) => {
72
+ this.emit("system", data);
73
+ }
74
+ );
75
+ this.socket.on(
76
+ "livechat:error",
77
+ (data) => {
78
+ this.emit("error", data);
79
+ }
80
+ );
81
+ this.socket.on(
82
+ "livechat:rejoin-success",
83
+ (data) => {
84
+ this.emit("rejoin-success", data);
85
+ }
86
+ );
87
+ this.socket.on("livechat:rejoin-failed", (data) => {
88
+ this.emit("rejoin-failed", data);
89
+ });
90
+ this.socket.on("livechat:typing", (data) => {
91
+ this.emit("typing", data);
92
+ });
93
+ }
94
+ /**
95
+ * Request a handoff from AI to a human operator.
96
+ *
97
+ * @param params - Visitor info and AI conversation history
98
+ */
99
+ requestHandoff(params) {
100
+ this.setState("requesting");
101
+ this.socket?.emit("livechat:request", {
102
+ projectId: this.config.projectId,
103
+ sessionId: this.config.visitorSessionId,
104
+ ...params
105
+ });
106
+ }
107
+ /**
108
+ * Send a message to the operator.
109
+ *
110
+ * @param content - Message text
111
+ */
112
+ sendMessage(content) {
113
+ if (!this.liveChatSessionId) return;
114
+ this.socket?.emit("livechat:message", {
115
+ liveChatSessionId: this.liveChatSessionId,
116
+ content
117
+ });
118
+ }
119
+ /**
120
+ * Send a typing indicator to the operator.
121
+ *
122
+ * @param isTyping - `true` if the visitor is currently typing
123
+ */
124
+ sendTyping(isTyping) {
125
+ if (!this.liveChatSessionId) return;
126
+ this.socket?.emit("livechat:typing", {
127
+ liveChatSessionId: this.liveChatSessionId,
128
+ isTyping
129
+ });
130
+ }
131
+ /**
132
+ * Cancel a pending handoff request.
133
+ *
134
+ * @param liveChatSessionId - The session to cancel
135
+ */
136
+ cancelRequest(liveChatSessionId) {
137
+ this.socket?.emit("livechat:cancel", { liveChatSessionId });
138
+ }
139
+ /**
140
+ * End the current live-chat session.
141
+ */
142
+ endChat() {
143
+ if (!this.liveChatSessionId) return;
144
+ this.socket?.emit("livechat:end", {
145
+ liveChatSessionId: this.liveChatSessionId
146
+ });
147
+ }
148
+ /**
149
+ * Submit a satisfaction rating for the ended session.
150
+ *
151
+ * @param rating - `"positive"` or `"negative"`
152
+ * @param comment - Optional free-text feedback
153
+ */
154
+ submitRating(rating, comment) {
155
+ if (!this.liveChatSessionId) return;
156
+ this.socket?.emit("livechat:rating", {
157
+ liveChatSessionId: this.liveChatSessionId,
158
+ rating,
159
+ comment
160
+ });
161
+ }
162
+ /**
163
+ * Rejoin an existing session (e.g. after a page refresh).
164
+ *
165
+ * @param liveChatSessionId - The session to rejoin
166
+ */
167
+ rejoinSession(liveChatSessionId) {
168
+ this.liveChatSessionId = liveChatSessionId;
169
+ this.socket?.emit("livechat:rejoin", { liveChatSessionId });
170
+ }
171
+ /**
172
+ * Disconnect the socket and reset state.
173
+ */
174
+ disconnect() {
175
+ this.socket?.disconnect();
176
+ this.socket = null;
177
+ this.liveChatSessionId = null;
178
+ this.state = "ai";
179
+ }
180
+ /**
181
+ * Get the current live-chat state.
182
+ */
183
+ getState() {
184
+ return this.state;
185
+ }
186
+ /**
187
+ * Get the current live-chat session ID (if any).
188
+ */
189
+ getSessionId() {
190
+ return this.liveChatSessionId;
191
+ }
192
+ // --- Event emitter ---
193
+ setState(state) {
194
+ this.state = state;
195
+ this.emit("state-change", state);
196
+ }
197
+ /**
198
+ * Subscribe to a live-chat event.
199
+ *
200
+ * @param event - Event name
201
+ * @param handler - Callback
202
+ */
203
+ on(event, handler) {
204
+ if (!this.listeners.has(event)) {
205
+ this.listeners.set(event, /* @__PURE__ */ new Set());
206
+ }
207
+ this.listeners.get(event).add(handler);
208
+ }
209
+ /**
210
+ * Unsubscribe from a live-chat event.
211
+ *
212
+ * @param event - Event name
213
+ * @param handler - The same callback reference passed to `on()`
214
+ */
215
+ off(event, handler) {
216
+ this.listeners.get(event)?.delete(handler);
217
+ }
218
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
219
+ emit(event, data) {
220
+ this.listeners.get(event)?.forEach((handler) => handler(data));
221
+ }
222
+ };
223
+
224
+ exports.LiveChatTransport = LiveChatTransport;
225
+ //# sourceMappingURL=chunk-NG7OTWXQ.cjs.map
226
+ //# sourceMappingURL=chunk-NG7OTWXQ.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/live-chat-transport.ts"],"names":[],"mappings":"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","file":"chunk-NG7OTWXQ.cjs","sourcesContent":["\"use client\";\n\n/**\n * Live Chat Transport\n *\n * Socket.IO client for real-time communication with human operators.\n * Lazy-loaded only when live chat is triggered to avoid bundling\n * `socket.io-client` for AI-only use cases.\n *\n * All browser API access is guarded against SSR.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * State machine for live-chat sessions.\n *\n * @see {@link LiveChatTransport.getState}\n */\nexport type LiveChatState = \"ai\" | \"requesting\" | \"queued\" | \"live\" | \"ended\";\n\n/**\n * Configuration required to establish a live-chat connection.\n */\nexport interface LiveChatConfig {\n /** Socket.IO endpoint URL */\n chatServiceUrl: string;\n /** Bearer API key */\n apiKey: string;\n /** Aigentyc project ID */\n projectId: string;\n /** Visitor session identifier (matches the AI chat session) */\n visitorSessionId: string;\n}\n\n/**\n * A single message exchanged during a live-chat session.\n */\nexport interface LiveChatMessage {\n /** Server-assigned message ID */\n id: number;\n /** Message body (plain text or HTML) */\n content: string;\n /** Who sent the message */\n senderType: \"visitor\" | \"operator\" | \"system\";\n /** ISO-8601 timestamp */\n timestamp: string;\n /** Optional system-message sub-type */\n systemMessageType?: string;\n}\n\n/**\n * Typed event map for live-chat transport listeners.\n */\nexport type LiveChatEventMap = {\n /** Fired when the state machine transitions */\n \"state-change\": (state: LiveChatState) => void;\n /** Fired when the request is queued */\n queued: (data: { liveChatSessionId: string; position: number }) => void;\n /** Fired when the queue position updates */\n \"queue-update\": (data: { position: number }) => void;\n /** Fired when an operator accepts the chat */\n accepted: (data: { operatorName: string }) => void;\n /** Fired on every incoming message */\n message: (data: LiveChatMessage) => void;\n /** Fired when the live-chat session ends */\n ended: (data: { endedBy: string }) => void;\n /** Fired when the operator hands the visitor back to AI */\n \"handback-ai\": () => void;\n /** System-level notification */\n system: (data: { message: string; type: string }) => void;\n /** Error notification */\n error: (data: { code: string; message: string }) => void;\n /** Operator typing indicator */\n typing: (data: { isTyping: boolean }) => void;\n /** Successful session rejoin (after page refresh) */\n \"rejoin-success\": (data: {\n state: string;\n operatorName?: string;\n position?: number;\n messages: LiveChatMessage[];\n }) => void;\n /** Failed session rejoin */\n \"rejoin-failed\": (data: { reason: string }) => void;\n};\n\n// ---------------------------------------------------------------------------\n// Transport Class\n// ---------------------------------------------------------------------------\n\n/**\n * Manages the Socket.IO connection for live-chat sessions.\n *\n * Lazily imports `socket.io-client` on first `connect()` call so the\n * dependency is never loaded for AI-only deployments.\n *\n * @example\n * ```ts\n * const transport = new LiveChatTransport({\n * chatServiceUrl: \"https://api.example.com\",\n * apiKey: \"key\",\n * projectId: \"abc\",\n * visitorSessionId: \"sess-123\",\n * });\n *\n * transport.on(\"message\", (msg) => console.log(msg));\n * await transport.connect();\n * transport.requestHandoff({ aiChatHistory: messages });\n * ```\n */\nexport class LiveChatTransport {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private socket: any = null;\n private config: LiveChatConfig;\n private state: LiveChatState = \"ai\";\n private liveChatSessionId: string | null = null;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private listeners = new Map<string, Set<Function>>();\n\n constructor(config: LiveChatConfig) {\n this.config = config;\n }\n\n /**\n * Establish the Socket.IO connection and wire up all server events.\n *\n * Safe to call in SSR — will resolve immediately without connecting.\n */\n async connect(): Promise<void> {\n if (typeof window === \"undefined\") return;\n\n // Lazy import socket.io-client\n const { io } = await import(\"socket.io-client\");\n\n this.socket = io(`${this.config.chatServiceUrl}/visitor`, {\n path: \"/api/chat/socket.io\",\n auth: {\n apiKey: this.config.apiKey,\n projectId: this.config.projectId,\n },\n transports: [\"websocket\", \"polling\"],\n });\n\n this.socket.on(\"connect\", () => {\n console.log(\"[LiveChat] Connected\");\n });\n\n this.socket.on(\"disconnect\", () => {\n console.log(\"[LiveChat] Disconnected\");\n });\n\n this.socket.on(\n \"livechat:queued\",\n (data: { liveChatSessionId: string; position: number }) => {\n this.liveChatSessionId = data.liveChatSessionId;\n this.setState(\"queued\");\n this.emit(\"queued\", data);\n },\n );\n\n this.socket.on(\"livechat:queue-update\", (data: { position: number }) => {\n this.emit(\"queue-update\", data);\n });\n\n this.socket.on(\"livechat:accepted\", (data: { operatorName: string }) => {\n this.setState(\"live\");\n this.emit(\"accepted\", data);\n });\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.socket.on(\"livechat:message\", (data: any) => {\n this.emit(\"message\", {\n id: data.id,\n content: data.content,\n senderType: data.senderType,\n timestamp: data.timestamp,\n });\n });\n\n this.socket.on(\"livechat:ended\", (data: { endedBy: string }) => {\n this.setState(\"ended\");\n this.emit(\"ended\", data);\n });\n\n this.socket.on(\"livechat:handback-ai\", () => {\n this.setState(\"ai\");\n this.emit(\"handback-ai\", undefined);\n });\n\n this.socket.on(\n \"livechat:system\",\n (data: { message: string; type: string }) => {\n this.emit(\"system\", data);\n },\n );\n\n this.socket.on(\n \"livechat:error\",\n (data: { code: string; message: string }) => {\n this.emit(\"error\", data);\n },\n );\n\n this.socket.on(\n \"livechat:rejoin-success\",\n (data: {\n state: string;\n operatorName?: string;\n position?: number;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n messages: any[];\n }) => {\n this.emit(\"rejoin-success\", data);\n },\n );\n\n this.socket.on(\"livechat:rejoin-failed\", (data: { reason: string }) => {\n this.emit(\"rejoin-failed\", data);\n });\n\n this.socket.on(\"livechat:typing\", (data: { isTyping: boolean }) => {\n this.emit(\"typing\", data);\n });\n }\n\n /**\n * Request a handoff from AI to a human operator.\n *\n * @param params - Visitor info and AI conversation history\n */\n requestHandoff(params: {\n visitorName?: string;\n visitorEmail?: string;\n aiChatHistory: unknown[];\n }): void {\n this.setState(\"requesting\");\n this.socket?.emit(\"livechat:request\", {\n projectId: this.config.projectId,\n sessionId: this.config.visitorSessionId,\n ...params,\n });\n }\n\n /**\n * Send a message to the operator.\n *\n * @param content - Message text\n */\n sendMessage(content: string): void {\n if (!this.liveChatSessionId) return;\n this.socket?.emit(\"livechat:message\", {\n liveChatSessionId: this.liveChatSessionId,\n content,\n });\n }\n\n /**\n * Send a typing indicator to the operator.\n *\n * @param isTyping - `true` if the visitor is currently typing\n */\n sendTyping(isTyping: boolean): void {\n if (!this.liveChatSessionId) return;\n this.socket?.emit(\"livechat:typing\", {\n liveChatSessionId: this.liveChatSessionId,\n isTyping,\n });\n }\n\n /**\n * Cancel a pending handoff request.\n *\n * @param liveChatSessionId - The session to cancel\n */\n cancelRequest(liveChatSessionId: string): void {\n this.socket?.emit(\"livechat:cancel\", { liveChatSessionId });\n }\n\n /**\n * End the current live-chat session.\n */\n endChat(): void {\n if (!this.liveChatSessionId) return;\n this.socket?.emit(\"livechat:end\", {\n liveChatSessionId: this.liveChatSessionId,\n });\n }\n\n /**\n * Submit a satisfaction rating for the ended session.\n *\n * @param rating - `\"positive\"` or `\"negative\"`\n * @param comment - Optional free-text feedback\n */\n submitRating(rating: \"positive\" | \"negative\", comment?: string): void {\n if (!this.liveChatSessionId) return;\n this.socket?.emit(\"livechat:rating\", {\n liveChatSessionId: this.liveChatSessionId,\n rating,\n comment,\n });\n }\n\n /**\n * Rejoin an existing session (e.g. after a page refresh).\n *\n * @param liveChatSessionId - The session to rejoin\n */\n rejoinSession(liveChatSessionId: string): void {\n this.liveChatSessionId = liveChatSessionId;\n this.socket?.emit(\"livechat:rejoin\", { liveChatSessionId });\n }\n\n /**\n * Disconnect the socket and reset state.\n */\n disconnect(): void {\n this.socket?.disconnect();\n this.socket = null;\n this.liveChatSessionId = null;\n this.state = \"ai\";\n }\n\n /**\n * Get the current live-chat state.\n */\n getState(): LiveChatState {\n return this.state;\n }\n\n /**\n * Get the current live-chat session ID (if any).\n */\n getSessionId(): string | null {\n return this.liveChatSessionId;\n }\n\n // --- Event emitter ---\n\n private setState(state: LiveChatState): void {\n this.state = state;\n this.emit(\"state-change\", state);\n }\n\n /**\n * Subscribe to a live-chat event.\n *\n * @param event - Event name\n * @param handler - Callback\n */\n on<K extends keyof LiveChatEventMap>(\n event: K,\n handler: LiveChatEventMap[K],\n ): void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(handler);\n }\n\n /**\n * Unsubscribe from a live-chat event.\n *\n * @param event - Event name\n * @param handler - The same callback reference passed to `on()`\n */\n off<K extends keyof LiveChatEventMap>(\n event: K,\n handler: LiveChatEventMap[K],\n ): void {\n this.listeners.get(event)?.delete(handler);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private emit(event: string, data: any): void {\n this.listeners.get(event)?.forEach((handler) => handler(data));\n }\n}\n"]}
@@ -0,0 +1,68 @@
1
+ "use client";
2
+ import { cn } from './chunk-3RW7O444.js';
3
+ import * as React from 'react';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ var Card = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
7
+ "div",
8
+ {
9
+ ref,
10
+ className: cn(
11
+ "rounded-xl border bg-card text-card-foreground shadow",
12
+ className
13
+ ),
14
+ ...props
15
+ }
16
+ ));
17
+ Card.displayName = "Card";
18
+ var CardHeader = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
19
+ "div",
20
+ {
21
+ ref,
22
+ className: cn("flex flex-col space-y-1.5 p-6", className),
23
+ ...props
24
+ }
25
+ ));
26
+ CardHeader.displayName = "CardHeader";
27
+ var CardTitle = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
28
+ "div",
29
+ {
30
+ ref,
31
+ className: cn("font-semibold leading-none tracking-tight", className),
32
+ ...props
33
+ }
34
+ ));
35
+ CardTitle.displayName = "CardTitle";
36
+ var CardDescription = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
37
+ "div",
38
+ {
39
+ ref,
40
+ className: cn("text-sm text-muted-foreground", className),
41
+ ...props
42
+ }
43
+ ));
44
+ CardDescription.displayName = "CardDescription";
45
+ var CardContent = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
46
+ CardContent.displayName = "CardContent";
47
+ var CardFooter = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
48
+ "div",
49
+ {
50
+ ref,
51
+ className: cn("flex items-center p-6 pt-0", className),
52
+ ...props
53
+ }
54
+ ));
55
+ CardFooter.displayName = "CardFooter";
56
+ var CardAction = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
57
+ "div",
58
+ {
59
+ ref,
60
+ className: cn("ml-auto flex items-center gap-2", className),
61
+ ...props
62
+ }
63
+ ));
64
+ CardAction.displayName = "CardAction";
65
+
66
+ export { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle };
67
+ //# sourceMappingURL=chunk-NPJKLYLV.js.map
68
+ //# sourceMappingURL=chunk-NPJKLYLV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/ui/card.tsx"],"names":[],"mappings":";;;;AAMA,IAAM,IAAA,GAAa,iBAGjB,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC1B,GAAA;AAAA,EAAC,KAAA;AAAA,EAAA;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAW,EAAA;AAAA,MACT,uDAAA;AAAA,MACA;AAAA,KACF;AAAA,IACC,GAAG;AAAA;AACN,CACD;AACD,IAAA,CAAK,WAAA,GAAc,MAAA;AAEnB,IAAM,UAAA,GAAmB,iBAGvB,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC1B,GAAA;AAAA,EAAC,KAAA;AAAA,EAAA;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAW,EAAA,CAAG,+BAAA,EAAiC,SAAS,CAAA;AAAA,IACvD,GAAG;AAAA;AACN,CACD;AACD,UAAA,CAAW,WAAA,GAAc,YAAA;AAEzB,IAAM,SAAA,GAAkB,iBAGtB,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC1B,GAAA;AAAA,EAAC,KAAA;AAAA,EAAA;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAW,EAAA,CAAG,2CAAA,EAA6C,SAAS,CAAA;AAAA,IACnE,GAAG;AAAA;AACN,CACD;AACD,SAAA,CAAU,WAAA,GAAc,WAAA;AAExB,IAAM,eAAA,GAAwB,iBAG5B,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC1B,GAAA;AAAA,EAAC,KAAA;AAAA,EAAA;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAW,EAAA,CAAG,+BAAA,EAAiC,SAAS,CAAA;AAAA,IACvD,GAAG;AAAA;AACN,CACD;AACD,eAAA,CAAgB,WAAA,GAAc,iBAAA;AAE9B,IAAM,cAAoB,KAAA,CAAA,UAAA,CAGxB,CAAC,EAAE,SAAA,EAAW,GAAG,OAAM,EAAG,GAAA,yBACzB,KAAA,EAAA,EAAI,GAAA,EAAU,WAAW,EAAA,CAAG,UAAA,EAAY,SAAS,CAAA,EAAI,GAAG,OAAO,CACjE;AACD,WAAA,CAAY,WAAA,GAAc,aAAA;AAE1B,IAAM,UAAA,GAAmB,iBAGvB,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC1B,GAAA;AAAA,EAAC,KAAA;AAAA,EAAA;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAW,EAAA,CAAG,4BAAA,EAA8B,SAAS,CAAA;AAAA,IACpD,GAAG;AAAA;AACN,CACD;AACD,UAAA,CAAW,WAAA,GAAc,YAAA;AAEzB,IAAM,UAAA,GAAmB,iBAGvB,CAAC,EAAE,WAAW,GAAG,KAAA,IAAS,GAAA,qBAC1B,GAAA;AAAA,EAAC,KAAA;AAAA,EAAA;AAAA,IACC,GAAA;AAAA,IACA,SAAA,EAAW,EAAA,CAAG,iCAAA,EAAmC,SAAS,CAAA;AAAA,IACzD,GAAG;AAAA;AACN,CACD;AACD,UAAA,CAAW,WAAA,GAAc,YAAA","file":"chunk-NPJKLYLV.js","sourcesContent":["\"use client\";\n\nimport * as React from \"react\"\n\nimport { cn } from \"../core/utils\"\n\nconst Card = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n \"rounded-xl border bg-card text-card-foreground shadow\",\n className\n )}\n {...props}\n />\n))\nCard.displayName = \"Card\"\n\nconst CardHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"flex flex-col space-y-1.5 p-6\", className)}\n {...props}\n />\n))\nCardHeader.displayName = \"CardHeader\"\n\nconst CardTitle = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"font-semibold leading-none tracking-tight\", className)}\n {...props}\n />\n))\nCardTitle.displayName = \"CardTitle\"\n\nconst CardDescription = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n))\nCardDescription.displayName = \"CardDescription\"\n\nconst CardContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"p-6 pt-0\", className)} {...props} />\n))\nCardContent.displayName = \"CardContent\"\n\nconst CardFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"flex items-center p-6 pt-0\", className)}\n {...props}\n />\n))\nCardFooter.displayName = \"CardFooter\"\n\nconst CardAction = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"ml-auto flex items-center gap-2\", className)}\n {...props}\n />\n))\nCardAction.displayName = \"CardAction\"\n\nexport { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent, CardAction }\n"]}