aizek-chatbot 1.0.30 → 1.0.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -12,12 +12,42 @@ var ReactMarkdown__default = /*#__PURE__*/_interopDefault(ReactMarkdown);
12
12
  var remarkGfm__default = /*#__PURE__*/_interopDefault(remarkGfm);
13
13
  var sanitizeHtml__default = /*#__PURE__*/_interopDefault(sanitizeHtml);
14
14
 
15
- // src/utils/global.ts
16
- var SESSION_TTL_MS = 60 * 60 * 1e3;
15
+ // src/constants/index.ts
16
+ var PROXY_BASE_URL = "http://localhost:3001/api";
17
+ var DEVICE_STORAGE_KEY = "aizek_device_id_v1";
18
+ var ACTIVE_SESSION_STORAGE_KEY = "aizek_active_session_v1";
17
19
  var MAX_SESSIONS = 3;
18
- var DEVICE_KEY = "aizek_device_id_v1";
19
- var ACTIVE_SESSION_KEY = "aizek_active_session_v1";
20
- var LOCAL_SESSIONS_KEY = "aizek_sessions_v1";
20
+ var SESSION_TITLE_MAX_LENGTH = 46;
21
+
22
+ // src/utils/device.ts
23
+ function getOrCreateDeviceId() {
24
+ if (typeof window === "undefined") return "";
25
+ const existing = localStorage.getItem(DEVICE_STORAGE_KEY);
26
+ if (existing) return existing;
27
+ const id = crypto.randomUUID();
28
+ localStorage.setItem(DEVICE_STORAGE_KEY, id);
29
+ return id;
30
+ }
31
+ function getActiveSessionId() {
32
+ if (typeof window === "undefined") return null;
33
+ return localStorage.getItem(ACTIVE_SESSION_STORAGE_KEY);
34
+ }
35
+ function setActiveSessionId(id) {
36
+ if (typeof window === "undefined") return;
37
+ if (!id) localStorage.removeItem(ACTIVE_SESSION_STORAGE_KEY);
38
+ else localStorage.setItem(ACTIVE_SESSION_STORAGE_KEY, id);
39
+ }
40
+
41
+ // src/utils/headers.ts
42
+ function buildRequestHeaders(deviceId, alternateHeaders, sessionId) {
43
+ const headers = {
44
+ "Content-Type": "application/json",
45
+ "x-device-id": deviceId,
46
+ "x-alternate": JSON.stringify(alternateHeaders)
47
+ };
48
+ if (sessionId) headers["x-session-id"] = sessionId;
49
+ return headers;
50
+ }
21
51
  function validateHeaders(headers, authConfig, opts = {}) {
22
52
  if (headers && (!authConfig || Object.keys(authConfig).length === 0)) {
23
53
  return {
@@ -30,82 +60,558 @@ function validateHeaders(headers, authConfig, opts = {}) {
30
60
  }
31
61
  const { caseSensitive = false, allowExtra = false } = opts;
32
62
  const normalize = (s) => caseSensitive ? s : s.toLowerCase();
33
- const headerEntries = Object.entries(headers).map(([k, v]) => [normalize(k), v.trim()]);
34
- const authEntries = Object.entries(authConfig).map(([k, v]) => [normalize(k), v.trim()]);
63
+ const headerEntries = Object.entries(headers).map(([k, v]) => [
64
+ normalize(k),
65
+ v.trim()
66
+ ]);
67
+ const authEntries = Object.entries(authConfig).map(([k, v]) => [
68
+ normalize(k),
69
+ v.trim()
70
+ ]);
35
71
  const headerKeys = headerEntries.map(([k]) => k);
36
72
  const authKeys = authEntries.map(([k]) => k);
37
73
  const requiredSet = new Set(authKeys);
38
74
  const missingKeys = authKeys.filter((k) => !headerKeys.includes(k));
39
75
  const extraKeys = headerKeys.filter((k) => !requiredSet.has(k));
40
- const hasAllRequired = missingKeys.length === 0;
41
- const hasExtraKeys = extraKeys.length > 0 && !allowExtra;
42
76
  const emptyValueKeys = authKeys.filter((k) => {
43
77
  const val = headerEntries.find(([key]) => key === k)?.[1];
44
78
  return !val || val.length === 0;
45
79
  });
80
+ const hasAllRequired = missingKeys.length === 0;
81
+ const hasExtraKeys = extraKeys.length > 0 && !allowExtra;
46
82
  const isValid = hasAllRequired && !hasExtraKeys && emptyValueKeys.length === 0;
47
83
  return { isValid, missingKeys, extraKeys, emptyValueKeys };
48
84
  }
49
- function getOrCreateDeviceId() {
50
- if (typeof window === "undefined") return "";
51
- const existing = localStorage.getItem(DEVICE_KEY);
52
- if (existing) return existing;
53
- const id = crypto.randomUUID();
54
- localStorage.setItem(DEVICE_KEY, id);
55
- return id;
85
+
86
+ // src/utils/message.ts
87
+ function extractTextFromContent(content) {
88
+ if (typeof content === "string") return content;
89
+ if (Array.isArray(content)) {
90
+ return content.filter((item) => item.type === "text" && typeof item.text === "string").map((item) => item.text).join("\n");
91
+ }
92
+ return "";
56
93
  }
57
- function now() {
58
- return Date.now();
94
+ function normalizeComponent(component, index) {
95
+ const normalized = { ...component };
96
+ if (!normalized.id?.trim()) {
97
+ normalized.id = `ui-comp-${index}-${Date.now()}`;
98
+ }
99
+ if (normalized.type === "button" && !normalized.buttonType) {
100
+ normalized.buttonType = "click";
101
+ }
102
+ if (normalized.type === "input" && !normalized.fieldType) {
103
+ normalized.fieldType = "text";
104
+ }
105
+ if (normalized.type === "select" && Array.isArray(normalized.options)) {
106
+ normalized.options = normalizeStringArray(normalized.options);
107
+ }
108
+ if (normalized.type === "table") {
109
+ normalized.columns = normalizeTableColumns(normalized.columns);
110
+ normalized.rows = normalizeTableRows(normalized.rows);
111
+ }
112
+ if (normalized.type === "form" && Array.isArray(normalized.items)) {
113
+ normalized.items = normalized.items.map(normalizeFormField);
114
+ }
115
+ if (normalized.type === "list" && Array.isArray(normalized.items)) {
116
+ normalized.items = normalized.items.map(normalizeListItem);
117
+ }
118
+ return normalized;
59
119
  }
60
- function readStoredSessions() {
61
- try {
62
- const raw = localStorage.getItem(LOCAL_SESSIONS_KEY);
63
- const parsed = JSON.parse(raw ?? "[]");
64
- if (!Array.isArray(parsed)) return [];
65
- return parsed.filter((x) => x && typeof x.sessionId === "string" && typeof x.lastActive === "number").slice(0, MAX_SESSIONS);
66
- } catch {
67
- return [];
120
+ function normalizeStringArray(items) {
121
+ return items.map(
122
+ (item) => typeof item === "object" && item !== null ? item.label ?? item.value ?? String(item) : String(item)
123
+ );
124
+ }
125
+ function normalizeTableColumns(columns) {
126
+ if (!Array.isArray(columns)) return columns;
127
+ return columns.map(
128
+ (col) => typeof col === "object" && col !== null ? col.label ?? col.id ?? String(col) : String(col)
129
+ );
130
+ }
131
+ function normalizeTableRows(rows) {
132
+ if (!Array.isArray(rows)) return rows;
133
+ return rows.map((row) => {
134
+ if (Array.isArray(row)) {
135
+ return row.map((cell) => String(cell ?? ""));
136
+ }
137
+ return Object.values(row).map((val) => {
138
+ if (typeof val === "object" && val !== null && val.type === "image") {
139
+ return val.src;
140
+ }
141
+ const record = val;
142
+ return String(record?.value ?? val ?? "");
143
+ });
144
+ });
145
+ }
146
+ function normalizeFormField(field, fieldIndex) {
147
+ const normalized = { ...field };
148
+ if (!normalized.id?.trim()) {
149
+ normalized.id = `field-${fieldIndex}-${Date.now()}`;
150
+ }
151
+ const raw = field;
152
+ if ("optional" in raw) {
153
+ normalized.requiredField = !raw.optional;
154
+ }
155
+ if ("required" in raw) {
156
+ normalized.requiredField = !!raw.required;
157
+ }
158
+ if (normalized.type === "input" && !normalized.fieldType) {
159
+ normalized.fieldType = "text";
160
+ }
161
+ if (normalized.type === "select" && Array.isArray(normalized.options)) {
162
+ normalized.options = normalizeStringArray(normalized.options);
163
+ }
164
+ return normalized;
165
+ }
166
+ function normalizeListItem(item, itemIndex) {
167
+ if (typeof item === "string") {
168
+ return {
169
+ id: `list-item-${itemIndex}-${Date.now()}`,
170
+ type: "text",
171
+ label: item,
172
+ value: item
173
+ };
68
174
  }
175
+ const comp = item;
176
+ if (!comp.id?.trim()) {
177
+ comp.id = `list-item-${itemIndex}-${Date.now()}`;
178
+ }
179
+ return comp;
69
180
  }
70
- function writeStoredSessions(list) {
71
- localStorage.setItem(LOCAL_SESSIONS_KEY, JSON.stringify(list.slice(0, MAX_SESSIONS)));
181
+ function extractUIJsonFromText(text) {
182
+ const UI_COMPONENT_REGEX = /```ui-component\s*([\s\S]*?)```/g;
183
+ const matches = Array.from(text.matchAll(UI_COMPONENT_REGEX));
184
+ if (matches.length === 0) {
185
+ return { cleanedText: text.trim(), uiData: null };
186
+ }
187
+ let cleanedText = text;
188
+ let mergedUIData = null;
189
+ for (const match of matches) {
190
+ const fullBlock = match[0];
191
+ const jsonBlock = match[1]?.trim();
192
+ cleanedText = cleanedText.replace(fullBlock, "").trim();
193
+ try {
194
+ const parsed = JSON.parse(jsonBlock);
195
+ if (parsed && Array.isArray(parsed.components)) {
196
+ parsed.components = parsed.components.map(normalizeComponent);
197
+ if (!mergedUIData) {
198
+ mergedUIData = parsed;
199
+ } else {
200
+ mergedUIData.components = [
201
+ ...mergedUIData.components,
202
+ ...parsed.components
203
+ ];
204
+ }
205
+ }
206
+ } catch (err) {
207
+ console.error("Invalid ui-component JSON:", err, jsonBlock);
208
+ }
209
+ }
210
+ cleanedText = cleanedText.replace(/\n{3,}/g, "\n\n").trim();
211
+ return { cleanedText, uiData: mergedUIData };
72
212
  }
73
- function purgeExpiredLocalSessions(setActiveSessionIdState) {
74
- const list = readStoredSessions();
75
- const filtered = list.filter((s) => now() - s.lastActive <= SESSION_TTL_MS);
76
- if (filtered.length !== list.length) writeStoredSessions(filtered);
77
- const active = getActiveSessionId();
78
- if (active && !filtered.some((s) => s.sessionId === active)) {
79
- setActiveSessionId(null);
80
- setActiveSessionIdState(null);
213
+ function parseRawMessages(rawMessages) {
214
+ const result = [];
215
+ for (const msg of rawMessages) {
216
+ const textContent = extractTextFromContent(msg.content);
217
+ let cleanText = textContent;
218
+ let uiData = null;
219
+ if (textContent) {
220
+ const extracted = extractUIJsonFromText(textContent);
221
+ cleanText = extracted.cleanedText;
222
+ uiData = extracted.uiData;
223
+ }
224
+ if (cleanText.trim() || uiData) {
225
+ result.push({
226
+ text: cleanText.trim() || void 0,
227
+ ui: uiData ?? void 0,
228
+ role: msg.role === "user" ? "user" : "assistant",
229
+ timestamp: /* @__PURE__ */ new Date()
230
+ });
231
+ }
81
232
  }
82
- return filtered;
233
+ return result;
83
234
  }
84
- function getActiveSessionId() {
85
- return localStorage.getItem(ACTIVE_SESSION_KEY);
235
+
236
+ // src/services/chat-api.ts
237
+ async function fetchWidgetConfig(clientId, headers) {
238
+ const deviceId = getOrCreateDeviceId();
239
+ const response = await fetch(
240
+ `${PROXY_BASE_URL}/aizek-connect?clientId=${clientId}`,
241
+ {
242
+ method: "POST",
243
+ headers: buildRequestHeaders(deviceId, headers)
244
+ }
245
+ );
246
+ return response.json();
86
247
  }
87
- function setActiveSessionId(id) {
88
- if (!id) localStorage.removeItem(ACTIVE_SESSION_KEY);
89
- else localStorage.setItem(ACTIVE_SESSION_KEY, id);
248
+ async function createSession(clientId, headers) {
249
+ const deviceId = getOrCreateDeviceId();
250
+ const response = await fetch(
251
+ `${PROXY_BASE_URL}/aizek-sessions/new?clientId=${clientId}`,
252
+ {
253
+ method: "POST",
254
+ headers: buildRequestHeaders(deviceId, headers)
255
+ }
256
+ );
257
+ return response.json();
258
+ }
259
+ async function sendChatMessage(clientId, sessionId, message, headers) {
260
+ const deviceId = getOrCreateDeviceId();
261
+ return fetch(`${PROXY_BASE_URL}/aizek-chat?clientId=${clientId}`, {
262
+ method: "POST",
263
+ headers: buildRequestHeaders(deviceId, headers, sessionId),
264
+ body: JSON.stringify({ message })
265
+ });
266
+ }
267
+ async function fetchMessageHistory(sessionId, headers) {
268
+ const deviceId = getOrCreateDeviceId();
269
+ const response = await fetch(`${PROXY_BASE_URL}/aizek-messages`, {
270
+ method: "GET",
271
+ headers: buildRequestHeaders(deviceId, headers, sessionId)
272
+ });
273
+ const data = await response.json();
274
+ if (!data.success)
275
+ throw new Error(data.message || "Failed to fetch messages");
276
+ return parseRawMessages(data.data?.messages ?? []);
90
277
  }
91
- function touchSession(sessionId) {
92
- const list = readStoredSessions();
93
- const next = list.map((s) => s.sessionId === sessionId ? { ...s, lastActive: now() } : s);
94
- if (!next.some((s) => s.sessionId === sessionId)) next.unshift({ sessionId, lastActive: now() });
95
- writeStoredSessions(next.slice(0, MAX_SESSIONS));
278
+ async function fetchSessionTitle(sessionId, headers) {
279
+ const deviceId = getOrCreateDeviceId();
280
+ const res = await fetch(`${PROXY_BASE_URL}/aizek-last-message`, {
281
+ method: "GET",
282
+ headers: buildRequestHeaders(deviceId, headers, sessionId)
283
+ });
284
+ const json = await res.json();
285
+ if (!json?.success) return null;
286
+ const last = json.data?.lastMessage;
287
+ if (!last) return null;
288
+ const textContent = extractTextFromContent(last.content);
289
+ if (!textContent.trim()) return null;
290
+ const { cleanedText } = extractUIJsonFromText(textContent);
291
+ const firstLine = (cleanedText.split("\n").find((l) => l.trim()) || "").trim();
292
+ const title = firstLine || cleanedText;
293
+ if (!title) return null;
294
+ return title.length > SESSION_TITLE_MAX_LENGTH ? `${title.slice(0, SESSION_TITLE_MAX_LENGTH).trim()}\u2026` : title;
96
295
  }
97
- function upsertSessionsFromServer(serverSessionIds, setSessions) {
98
- const local = readStoredSessions();
99
- const map = new Map(local.map((s) => [s.sessionId, s.lastActive]));
100
- const merged = serverSessionIds.slice(0, MAX_SESSIONS).map((sid) => ({
101
- sessionId: sid,
102
- lastActive: map.get(sid) ?? now()
103
- }));
104
- writeStoredSessions(merged);
105
- setSessions(merged.map((x) => x.sessionId));
106
- return merged;
296
+
297
+ // src/hooks/use-chat-session.ts
298
+ function useChatSession({
299
+ clientId,
300
+ headers,
301
+ onReady,
302
+ onToolCall
303
+ }) {
304
+ const [config, setConfig] = react.useState();
305
+ const [messages, setMessages] = react.useState([]);
306
+ const [isLoading, setIsLoading] = react.useState(false);
307
+ const [isConfigLoading, setIsConfigLoading] = react.useState(true);
308
+ const [sessions, setSessions] = react.useState([]);
309
+ const [activeSession, setActiveSession] = react.useState(null);
310
+ const [headerValidation, setHeaderValidation] = react.useState(null);
311
+ const [sessionTitleById, setSessionTitleById] = react.useState({});
312
+ const messagesEndRef = react.useRef(null);
313
+ const loadConfig = react.useCallback(async () => {
314
+ try {
315
+ setIsConfigLoading(true);
316
+ const localActive = getActiveSessionId();
317
+ const data = await fetchWidgetConfig(clientId, headers);
318
+ if (!data.success) return;
319
+ setConfig(data.data);
320
+ const serverSessions = data.data.sessions ?? [];
321
+ setSessions(serverSessions);
322
+ if (serverSessions.length === 0) {
323
+ setActiveSession(null);
324
+ setActiveSessionId(null);
325
+ } else {
326
+ const nextActive = (localActive && serverSessions.includes(localActive) ? localActive : null) ?? serverSessions[0] ?? null;
327
+ setActiveSession(nextActive);
328
+ setActiveSessionId(nextActive);
329
+ }
330
+ if (headers) {
331
+ const validationResult = validateHeaders(
332
+ headers,
333
+ data.data.auth_config,
334
+ { allowExtra: false, caseSensitive: true }
335
+ );
336
+ setHeaderValidation(validationResult);
337
+ }
338
+ onReady?.({ config: { ...data.data } });
339
+ } catch (error) {
340
+ console.error("Failed to load chat widget config:", error);
341
+ } finally {
342
+ setIsConfigLoading(false);
343
+ }
344
+ }, [clientId]);
345
+ const createNewSession = react.useCallback(async () => {
346
+ if (sessions.length >= MAX_SESSIONS) {
347
+ throw new Error(`You can open up to ${MAX_SESSIONS} sessions.`);
348
+ }
349
+ const data = await createSession(clientId, headers);
350
+ if (!data.success) throw new Error(data.message || "Session create failed");
351
+ const sid = data.data.sessionId;
352
+ const updatedSessions = data.data.sessions ?? [sid];
353
+ setSessions(updatedSessions);
354
+ setActiveSession(sid);
355
+ setActiveSessionId(sid);
356
+ setMessages([]);
357
+ return sid;
358
+ }, [clientId, headers, sessions.length]);
359
+ const handleStreamResponse = react.useCallback(
360
+ async (response, onFinish) => {
361
+ if (!response.body) {
362
+ throw new Error("Streaming not supported (no response body)");
363
+ }
364
+ const reader = response.body.getReader();
365
+ const decoder = new TextDecoder();
366
+ let text = "";
367
+ let buffer = "";
368
+ try {
369
+ while (true) {
370
+ const { value, done } = await reader.read();
371
+ if (done) break;
372
+ buffer += decoder.decode(value, { stream: true });
373
+ const chunks = buffer.split("\n\n");
374
+ buffer = chunks.pop() ?? "";
375
+ for (const rawChunk of chunks) {
376
+ const line = rawChunk.split("\n").find((l) => l.startsWith("data:"));
377
+ if (!line) continue;
378
+ const jsonStr = line.replace(/^data:\s*/, "").trim();
379
+ if (!jsonStr) continue;
380
+ try {
381
+ const event = JSON.parse(jsonStr);
382
+ if (event.type === "response.output_text.delta" && event.delta) {
383
+ setIsLoading(false);
384
+ text += event.delta;
385
+ setMessages((prev) => {
386
+ const lastMsg = prev[prev.length - 1];
387
+ if (lastMsg?.role === "assistant") {
388
+ return [...prev.slice(0, -1), { ...lastMsg, text }];
389
+ }
390
+ return [
391
+ ...prev,
392
+ { text, role: "assistant", timestamp: /* @__PURE__ */ new Date() }
393
+ ];
394
+ });
395
+ }
396
+ if (event.type === "response.output_item.done" && event.item.type === "mcp_call") {
397
+ onToolCall?.({
398
+ name: event.item.name,
399
+ args: JSON.parse(event.item.arguments),
400
+ result: JSON.parse(event.item.output)
401
+ });
402
+ }
403
+ } catch (e) {
404
+ console.error("Error parsing stream event", e);
405
+ }
406
+ }
407
+ }
408
+ } finally {
409
+ onFinish?.();
410
+ }
411
+ },
412
+ [onToolCall]
413
+ );
414
+ const sendMessage = react.useCallback(
415
+ async (message, approval) => {
416
+ if (!message.trim() || isLoading) return;
417
+ setIsLoading(true);
418
+ setMessages((prev) => [
419
+ ...prev,
420
+ {
421
+ text: message,
422
+ ui: void 0,
423
+ role: approval ? "approval" : "user",
424
+ timestamp: /* @__PURE__ */ new Date()
425
+ }
426
+ ]);
427
+ try {
428
+ let sid = activeSession;
429
+ if (!sid) sid = await createNewSession();
430
+ let response = await sendChatMessage(clientId, sid, message, headers);
431
+ if (response.status === 401) {
432
+ console.log("Session expired, renewing...");
433
+ const filtered = sessions.filter((s) => s !== sid);
434
+ setSessions(filtered);
435
+ setActiveSession(null);
436
+ setActiveSessionId(null);
437
+ const newSid = await createNewSession();
438
+ response = await sendChatMessage(clientId, newSid, message, headers);
439
+ }
440
+ if (!response.ok) throw new Error(`HTTP error ${response.status}`);
441
+ await handleStreamResponse(response);
442
+ } catch (error) {
443
+ console.error("Error sending message:", error);
444
+ setMessages((prev) => {
445
+ const last = prev[prev.length - 1];
446
+ const errorMessage = {
447
+ text: "Sorry, something went wrong. Please try again.",
448
+ role: "assistant",
449
+ timestamp: /* @__PURE__ */ new Date()
450
+ };
451
+ if (last?.role === "assistant" && !last.text) {
452
+ return [...prev.slice(0, -1), errorMessage];
453
+ }
454
+ return [...prev, errorMessage];
455
+ });
456
+ } finally {
457
+ setIsLoading(false);
458
+ }
459
+ },
460
+ [
461
+ activeSession,
462
+ clientId,
463
+ createNewSession,
464
+ handleStreamResponse,
465
+ headers,
466
+ isLoading,
467
+ sessions
468
+ ]
469
+ );
470
+ const selectSession = react.useCallback((sid) => {
471
+ setActiveSession(sid);
472
+ setActiveSessionId(sid);
473
+ }, []);
474
+ const getSessionTitle = react.useCallback(
475
+ (sid) => sessionTitleById[sid] ?? "New conversation",
476
+ [sessionTitleById]
477
+ );
478
+ react.useEffect(() => {
479
+ loadConfig();
480
+ }, [loadConfig]);
481
+ react.useEffect(() => {
482
+ messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
483
+ }, [messages]);
484
+ react.useEffect(() => {
485
+ if (activeSession && !isConfigLoading) {
486
+ fetchMessageHistory(activeSession, headers).then(setMessages).catch(
487
+ (error) => console.error("Failed to load message history:", error)
488
+ );
489
+ } else if (!activeSession) {
490
+ setMessages([]);
491
+ }
492
+ }, [activeSession, isConfigLoading]);
493
+ react.useEffect(() => {
494
+ if (!sessions.length) return;
495
+ const missing = sessions.filter((sid) => !sessionTitleById[sid]);
496
+ if (!missing.length) return;
497
+ let cancelled = false;
498
+ (async () => {
499
+ for (const sid of missing) {
500
+ if (cancelled) return;
501
+ const title = await fetchSessionTitle(sid, headers);
502
+ if (cancelled || !title) continue;
503
+ setSessionTitleById(
504
+ (prev) => prev[sid] ? prev : { ...prev, [sid]: title }
505
+ );
506
+ }
507
+ })();
508
+ return () => {
509
+ cancelled = true;
510
+ };
511
+ }, [sessions]);
512
+ return {
513
+ config,
514
+ messages,
515
+ isLoading,
516
+ isConfigLoading,
517
+ sessions,
518
+ activeSessionId: activeSession,
519
+ headerValidation,
520
+ sessionTitleById,
521
+ createNewSession,
522
+ sendMessage,
523
+ selectSession,
524
+ getSessionTitle
525
+ };
107
526
  }
108
- var HeaderAlert = ({ headerValidation, showAlert, setShowAlert }) => {
527
+ var IconClose = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" }) });
528
+ var IconChat = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h4l4 4 4-4h4c1.1 0-2 .9-2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z" }) });
529
+ var IconBack = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 18l-6-6 6-6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) });
530
+ var IconBubble = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 3c-4.418 0-8 3.134-8 7 0 2.382 1.362 4.486 3.5 5.737V21l4.07-2.13c.14.008.283.013.43.013 4.418 0 8-3.134 8-7s-3.582-7-8-7z", stroke: "currentColor", strokeWidth: "2", strokeLinejoin: "round" }) });
531
+ var IconInfo = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: [
532
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 17v-6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
533
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 8h.01", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round" }),
534
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "9", stroke: "currentColor", strokeWidth: "2" })
535
+ ] });
536
+ var IconTrash = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: [
537
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 6h18", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" }),
538
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 6V4h8v2", stroke: "currentColor", strokeWidth: "2", strokeLinejoin: "round" }),
539
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 6l1 16h10l1-16", stroke: "currentColor", strokeWidth: "2", strokeLinejoin: "round" })
540
+ ] });
541
+ var HomePanel = ({
542
+ companyName,
543
+ isLoading,
544
+ sessionsCount,
545
+ onNewSession,
546
+ onViewConversations
547
+ }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "home-panel", children: [
548
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "eyebrow", children: "Welcome" }),
549
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "panel-title", children: companyName }),
550
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "panel-subtitle", children: "Ask anything. We keep your history and respond instantly." }),
551
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "home-actions", children: [
552
+ /* @__PURE__ */ jsxRuntime.jsx(
553
+ "button",
554
+ {
555
+ className: "primary-button",
556
+ onClick: onNewSession,
557
+ disabled: isLoading || sessionsCount >= MAX_SESSIONS,
558
+ children: "Start a new conversation"
559
+ }
560
+ ),
561
+ /* @__PURE__ */ jsxRuntime.jsx("button", { className: "ghost-button", onClick: onViewConversations, children: "View conversations" })
562
+ ] })
563
+ ] });
564
+ var ConversationListPanel = ({
565
+ sessions,
566
+ activeSessionId,
567
+ getSessionTitle,
568
+ onNewSession,
569
+ onSelectSession
570
+ }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "conversation-list", children: [
571
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "list-header", children: [
572
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
573
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "eyebrow", children: "Conversations" }),
574
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "panel-title", children: "Inbox" })
575
+ ] }),
576
+ /* @__PURE__ */ jsxRuntime.jsx(
577
+ "button",
578
+ {
579
+ className: "session-new-button",
580
+ onClick: onNewSession,
581
+ disabled: sessions.length >= MAX_SESSIONS,
582
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: "+ New" })
583
+ }
584
+ )
585
+ ] }),
586
+ sessions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "empty-list", children: [
587
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "empty-state-icon", children: "\u{1F4AC}" }),
588
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "empty-state-title", children: "No conversations yet" }),
589
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "empty-state-description", children: "Start a new conversation to see it appear here." })
590
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "conversation-items", children: sessions.map((sid) => /* @__PURE__ */ jsxRuntime.jsxs(
591
+ "button",
592
+ {
593
+ className: `conversation-item ${sid === activeSessionId ? "active" : ""}`,
594
+ onClick: () => onSelectSession(sid),
595
+ children: [
596
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "conversation-meta", children: [
597
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "conversation-title", children: getSessionTitle(sid) }),
598
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "conversation-sub", children: [
599
+ "Session ID: ",
600
+ sid.slice(0, 8),
601
+ "..."
602
+ ] })
603
+ ] }),
604
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "conversation-pill", children: "Open" })
605
+ ]
606
+ },
607
+ sid
608
+ )) })
609
+ ] });
610
+ var HeaderAlert = ({
611
+ headerValidation,
612
+ showAlert,
613
+ setShowAlert
614
+ }) => {
109
615
  if (!headerValidation || !showAlert) return null;
110
616
  const { isValid, missingKeys, extraKeys, emptyValueKeys, warning } = headerValidation;
111
617
  if (isValid && missingKeys.length === 0 && extraKeys.length === 0 && emptyValueKeys.length === 0 && !warning) {
@@ -114,14 +620,14 @@ var HeaderAlert = ({ headerValidation, showAlert, setShowAlert }) => {
114
620
  const hasErrors = missingKeys.length > 0 || emptyValueKeys.length > 0;
115
621
  const hasWarnings = extraKeys.length > 0 || !!warning;
116
622
  const alertType = hasErrors ? "error" : "warning";
117
- const getAlertIcon = () => {
623
+ const renderAlertIcon = () => {
118
624
  if (hasErrors) {
119
625
  return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z" }) });
120
626
  }
121
627
  return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z" }) });
122
628
  };
123
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `alert-container ${alertType}`, children: [
124
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "alert-icon-container", children: getAlertIcon() }),
629
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `alert-container ${alertType}`, children: [
630
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "alert-icon-container", children: renderAlertIcon() }),
125
631
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "alert-content", children: [
126
632
  /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "alert-title", children: hasErrors ? "Header Do\u011Frulama Hatas\u0131" : "Header Uyar\u0131s\u0131" }),
127
633
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "alert-message", children: hasErrors && hasWarnings ? "Header yap\u0131land\u0131rman\u0131zda hatalar ve uyar\u0131lar bulundu." : hasErrors ? "Header yap\u0131land\u0131rman\u0131zda hatalar bulundu." : "Header yap\u0131land\u0131rman\u0131zda fazla anahtarlar bulundu." }),
@@ -161,18 +667,22 @@ var HeaderAlert = ({ headerValidation, showAlert, setShowAlert }) => {
161
667
  children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" }) })
162
668
  }
163
669
  )
164
- ] }) });
670
+ ] });
165
671
  };
166
672
  var LoadingSpinner = () => {
167
673
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "loading-spinner" });
168
674
  };
169
- var ChatInput = ({ isLoading, placeholder, handleSendMessage }) => {
675
+ var ChatInput = ({
676
+ isLoading,
677
+ placeholder,
678
+ onSendMessage
679
+ }) => {
170
680
  const [message, setMessage] = react.useState("");
171
681
  const textareaRef = react.useRef(null);
172
682
  const handleSubmit = (e) => {
173
683
  e.preventDefault();
174
684
  if (message.trim() && !isLoading) {
175
- handleSendMessage(message.trim());
685
+ onSendMessage(message.trim());
176
686
  setMessage("");
177
687
  if (textareaRef.current) {
178
688
  textareaRef.current.style.height = "auto";
@@ -215,109 +725,130 @@ var ChatInput = ({ isLoading, placeholder, handleSendMessage }) => {
215
725
  )
216
726
  ] });
217
727
  };
218
- var GenericUIRenderer = ({ uiData, onInteraction }) => {
728
+ var GenUIText = ({ component }) => /* @__PURE__ */ jsxRuntime.jsx("p", { className: "gen-ui-text", children: component.value ?? component.label }, component.id);
729
+ var GenUIInput = ({ component }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gen-ui-input-wrapper", children: [
730
+ component.label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "gen-ui-input-label", children: component.label }),
731
+ component.fieldType === "textarea" ? /* @__PURE__ */ jsxRuntime.jsx(
732
+ "textarea",
733
+ {
734
+ name: component.id,
735
+ placeholder: component.placeholder,
736
+ className: "gen-ui-textarea"
737
+ }
738
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
739
+ "input",
740
+ {
741
+ name: component.id,
742
+ type: component.fieldType || "text",
743
+ placeholder: component.placeholder,
744
+ className: "gen-ui-input"
745
+ }
746
+ )
747
+ ] }, component.id);
748
+ var GenUISelect = ({ component }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gen-ui-select-wrapper", children: [
749
+ component.label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "gen-ui-select-label", children: component.label }),
750
+ /* @__PURE__ */ jsxRuntime.jsx("select", { name: component.id, className: "gen-ui-select", children: component.options?.map((opt) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: opt, children: opt }, opt)) })
751
+ ] }, component.id);
752
+ var GenUIButton = ({
753
+ component,
754
+ onInteraction,
755
+ collectFormValues
756
+ }) => /* @__PURE__ */ jsxRuntime.jsx(
757
+ "button",
758
+ {
759
+ onClick: () => {
760
+ const formValues = collectFormValues();
761
+ onInteraction({
762
+ action: component.label ?? "",
763
+ buttonId: component.buttonType,
764
+ formData: formValues
765
+ });
766
+ },
767
+ className: "gen-ui-button",
768
+ children: component.label
769
+ },
770
+ component.id
771
+ );
772
+ var GenUICard = ({ component }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gen-ui-card", children: [
773
+ component.label && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "gen-ui-card-title", children: component.label }),
774
+ component.value && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "gen-ui-card-content", children: component.value })
775
+ ] }, component.id);
776
+ var GenUIList = ({ component }) => /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "gen-ui-list", children: component.items?.map((item) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: "gen-ui-list-item", children: item.label ?? String(item.value ?? "") }, item.id)) }, component.id);
777
+ var GenUIImage = ({ component }) => /* @__PURE__ */ jsxRuntime.jsx(
778
+ "img",
779
+ {
780
+ src: component.url,
781
+ alt: component.label || "",
782
+ className: "gen-ui-image"
783
+ },
784
+ component.id
785
+ );
786
+ var GenUILink = ({ component }) => /* @__PURE__ */ jsxRuntime.jsx(
787
+ "a",
788
+ {
789
+ href: component.url,
790
+ className: "gen-ui-link",
791
+ children: component.label || component.url
792
+ },
793
+ component.id
794
+ );
795
+ var GenUITable = ({ component }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gen-ui-table-wrapper", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "gen-ui-table", children: [
796
+ component.columns && /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "gen-ui-table-header", children: /* @__PURE__ */ jsxRuntime.jsx("tr", { children: component.columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx("th", { className: "gen-ui-table-th", children: col }, col)) }) }),
797
+ component.rows && /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "gen-ui-table-body", children: component.rows.map((row, rowIndex) => /* @__PURE__ */ jsxRuntime.jsx("tr", { children: row.map((cell, cellIndex) => /* @__PURE__ */ jsxRuntime.jsx("td", { className: "gen-ui-table-td", children: cell }, cellIndex)) }, rowIndex)) })
798
+ ] }) }, component.id);
799
+ var GenericUIRenderer = ({
800
+ uiData,
801
+ onInteraction
802
+ }) => {
219
803
  const containerRef = react.useRef(null);
220
- if (!uiData || !uiData.components) return null;
804
+ if (!uiData?.components) return null;
221
805
  const collectFormValues = () => {
222
806
  if (!containerRef.current) return {};
223
807
  const formData = {};
224
808
  const inputs = containerRef.current.querySelectorAll("input, textarea, select");
225
809
  inputs.forEach((element) => {
226
810
  const name = element.getAttribute("name");
227
- if (name) {
228
- if (element instanceof HTMLInputElement && element.type === "checkbox") {
229
- formData[name] = element.checked;
230
- } else if (element instanceof HTMLInputElement && element.type === "radio") {
231
- if (element.checked) {
232
- formData[name] = element.value;
233
- }
234
- } else {
235
- formData[name] = element.value;
236
- }
811
+ if (!name) return;
812
+ if (element instanceof HTMLInputElement && element.type === "checkbox") {
813
+ formData[name] = element.checked;
814
+ } else if (element instanceof HTMLInputElement && element.type === "radio") {
815
+ if (element.checked) formData[name] = element.value;
816
+ } else {
817
+ formData[name] = element.value;
237
818
  }
238
819
  });
239
820
  return formData;
240
821
  };
241
- const renderComponent = (comp) => {
242
- switch (comp.type) {
822
+ const renderComponent = (component) => {
823
+ switch (component.type) {
243
824
  case "text":
244
- return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "gen-ui-text", children: comp.value ?? comp.label }, comp.id);
825
+ return /* @__PURE__ */ jsxRuntime.jsx(GenUIText, { component }, component.id);
245
826
  case "input":
246
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gen-ui-input-wrapper", children: [
247
- comp.label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "gen-ui-input-label", children: comp.label }),
248
- comp.fieldType === "textarea" ? /* @__PURE__ */ jsxRuntime.jsx(
249
- "textarea",
250
- {
251
- name: comp.id,
252
- placeholder: comp.placeholder,
253
- className: "gen-ui-textarea"
254
- }
255
- ) : /* @__PURE__ */ jsxRuntime.jsx(
256
- "input",
257
- {
258
- name: comp.id,
259
- type: comp.fieldType || "text",
260
- placeholder: comp.placeholder,
261
- className: "gen-ui-input"
262
- }
263
- )
264
- ] }, comp.id);
827
+ return /* @__PURE__ */ jsxRuntime.jsx(GenUIInput, { component }, component.id);
265
828
  case "select":
266
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gen-ui-select-wrapper", children: [
267
- comp.label && /* @__PURE__ */ jsxRuntime.jsx("label", { className: "gen-ui-select-label", children: comp.label }),
268
- /* @__PURE__ */ jsxRuntime.jsx("select", { name: comp.id, className: "gen-ui-select", children: comp.options?.map((opt) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: opt, children: opt }, opt)) })
269
- ] }, comp.id);
829
+ return /* @__PURE__ */ jsxRuntime.jsx(GenUISelect, { component }, component.id);
270
830
  case "button":
271
831
  return /* @__PURE__ */ jsxRuntime.jsx(
272
- "button",
832
+ GenUIButton,
273
833
  {
274
- onClick: () => {
275
- const formValues = collectFormValues();
276
- onInteraction({
277
- action: comp.label,
278
- buttonId: comp.buttonType,
279
- formData: formValues
280
- });
281
- },
282
- className: "gen-ui-button",
283
- children: comp.label
834
+ component,
835
+ onInteraction,
836
+ collectFormValues
284
837
  },
285
- comp.id
838
+ component.id
286
839
  );
287
840
  case "card":
288
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "gen-ui-card", children: [
289
- comp.label && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "gen-ui-card-title", children: comp.label }),
290
- comp.value && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "gen-ui-card-content", children: comp.value })
291
- ] }, comp.id);
841
+ return /* @__PURE__ */ jsxRuntime.jsx(GenUICard, { component }, component.id);
292
842
  case "list":
293
- return /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "gen-ui-list", children: comp.items?.map((item) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: "gen-ui-list-item", children: item.label ?? String(item.value ?? "") }, item.id)) }, comp.id);
843
+ return /* @__PURE__ */ jsxRuntime.jsx(GenUIList, { component }, component.id);
294
844
  case "image":
295
- return /* @__PURE__ */ jsxRuntime.jsx(
296
- "img",
297
- {
298
- src: comp.url,
299
- alt: comp.label || "",
300
- className: "gen-ui-image"
301
- },
302
- comp.id
303
- );
845
+ return /* @__PURE__ */ jsxRuntime.jsx(GenUIImage, { component }, component.id);
304
846
  case "link":
305
- return /* @__PURE__ */ jsxRuntime.jsx(
306
- "a",
307
- {
308
- href: comp.url,
309
- className: "gen-ui-link",
310
- children: comp.label || comp.url
311
- },
312
- comp.id
313
- );
847
+ return /* @__PURE__ */ jsxRuntime.jsx(GenUILink, { component }, component.id);
314
848
  case "table":
315
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gen-ui-table-wrapper", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "gen-ui-table", children: [
316
- comp.columns && /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "gen-ui-table-header", children: /* @__PURE__ */ jsxRuntime.jsx("tr", { children: comp.columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx("th", { className: "gen-ui-table-th", children: col }, col)) }) }),
317
- comp.rows && /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "gen-ui-table-body", children: comp.rows.map((row, ridx) => /* @__PURE__ */ jsxRuntime.jsx("tr", { children: row.map((cell, cidx) => /* @__PURE__ */ jsxRuntime.jsx("td", { className: "gen-ui-table-td", children: cell }, cidx)) }, ridx)) })
318
- ] }) }, comp.id);
849
+ return /* @__PURE__ */ jsxRuntime.jsx(GenUITable, { component }, component.id);
319
850
  case "form":
320
- return /* @__PURE__ */ jsxRuntime.jsx("form", { className: "gen-ui-form", children: comp.items?.map((field) => renderComponent(field)) }, comp.id);
851
+ return /* @__PURE__ */ jsxRuntime.jsx("form", { className: "gen-ui-form", children: component.items?.map((field) => renderComponent(field)) }, component.id);
321
852
  default:
322
853
  return null;
323
854
  }
@@ -331,12 +862,8 @@ var GenericUIRenderer = ({ uiData, onInteraction }) => {
331
862
  ] });
332
863
  };
333
864
  var MessageBubble = ({ message, onAction }) => {
334
- console.log("MESSAGE", message);
335
865
  const isUser = message.role === "user";
336
- const approval = message.role === "approval";
337
- if (approval) {
338
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, {});
339
- }
866
+ if (message.role === "approval") return null;
340
867
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `message-container ${isUser ? "user" : "assistant"}`, children: [
341
868
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: `message-bubble ${isUser ? "user" : "assistant"}`, children: isUser ? message.text && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "markdown-content", children: message.text }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
342
869
  message.text && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "markdown-content", children: /* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown__default.default, { remarkPlugins: [remarkGfm__default.default], children: message.text }) }),
@@ -345,7 +872,6 @@ var MessageBubble = ({ message, onAction }) => {
345
872
  {
346
873
  uiData: message.ui,
347
874
  onInteraction: (event) => {
348
- console.log("event", event);
349
875
  if (event.buttonId === "submit") {
350
876
  onAction(JSON.stringify(event.formData), true);
351
877
  } else {
@@ -374,277 +900,137 @@ var TypingDots = () => {
374
900
  }, []);
375
901
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "message-container assistant", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "message-bubble assistant", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "message-typing-indicator", children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: dots }) }) }) });
376
902
  };
377
-
378
- // src/utils/chatbot.ts
379
- var extractUIJsonFromText = (text) => {
380
- const regex = /```ui-component([\s\S]*?)```/g;
381
- let cleaned = text;
382
- let match;
383
- let uiData = null;
384
- while ((match = regex.exec(text)) !== null) {
385
- const block = match[1].trim();
386
- try {
387
- const parsed = JSON.parse(block);
388
- if (parsed && parsed.components && Array.isArray(parsed.components)) {
389
- parsed.components = parsed.components.map((comp, index) => {
390
- if (!comp.id || typeof comp.id !== "string" || !comp.id.trim()) {
391
- comp.id = `ui-comp-${index}-${Date.now()}`;
392
- }
393
- if (comp.type === "button") {
394
- if (!comp.buttonType) {
395
- comp.buttonType = "click";
396
- }
397
- }
398
- if (comp.type === "input") {
399
- if (!comp.fieldType) {
400
- comp.fieldType = "text";
401
- }
402
- }
403
- if (comp.type === "select") {
404
- if (comp.options && Array.isArray(comp.options)) {
405
- const firstOption = comp.options[0];
406
- if (typeof firstOption === "object" && firstOption !== null) {
407
- if ("label" in firstOption || "value" in firstOption) {
408
- comp.options = comp.options.map(
409
- (opt) => opt.label || opt.value || String(opt)
410
- );
411
- }
412
- }
413
- }
414
- }
415
- if (comp.type === "table") {
416
- if (comp.columns && Array.isArray(comp.columns)) {
417
- const firstCol = comp.columns[0];
418
- if (typeof firstCol === "object" && firstCol !== null) {
419
- comp.columns = comp.columns.map(
420
- (col) => col.label || col.id || String(col)
421
- );
422
- }
423
- }
424
- if (comp.rows && Array.isArray(comp.rows)) {
425
- const firstRow = comp.rows[0];
426
- if (typeof firstRow === "object" && !Array.isArray(firstRow)) {
427
- comp.rows = comp.rows.map((row) => {
428
- if (Array.isArray(row)) return row;
429
- return Object.values(row).map((val) => {
430
- if (typeof val === "object" && val !== null) {
431
- if (val.type === "image" && val.src) return val.src;
432
- if (val.value !== void 0) return String(val.value);
433
- }
434
- return String(val || "");
435
- });
436
- });
437
- }
903
+ var ConversationDetailPanel = ({
904
+ activeSessionId,
905
+ isLoading,
906
+ messages,
907
+ headerValidation,
908
+ showAlert,
909
+ setShowAlert,
910
+ sanitizedWelcome,
911
+ messagesEndRef,
912
+ config,
913
+ getSessionTitle,
914
+ onBack,
915
+ onInfo,
916
+ onSendMessage,
917
+ placeholder
918
+ }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "conversation-detail", children: [
919
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "detail-header", children: [
920
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "detail-header-left", children: /* @__PURE__ */ jsxRuntime.jsx("button", { className: "icon-button", onClick: onBack, "aria-label": "Back", children: /* @__PURE__ */ jsxRuntime.jsx(IconBack, {}) }) }),
921
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "detail-header-center", children: [
922
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "detail-avatar", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(IconBubble, {}) }),
923
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "detail-title", children: [
924
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "detail-title-row", children: [
925
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { className: "detail-title-text", children: activeSessionId ? getSessionTitle(activeSessionId) : "Chat" }),
926
+ /* @__PURE__ */ jsxRuntime.jsx(
927
+ "span",
928
+ {
929
+ className: `status-dot ${isLoading ? "typing" : "online"}`,
930
+ "aria-hidden": "true"
438
931
  }
439
- }
440
- if (comp.type === "form" && comp.items && Array.isArray(comp.items)) {
441
- comp.items = comp.items.map((field, fieldIndex) => {
442
- if (!field.id || !field.id.trim()) {
443
- field.id = `field-${fieldIndex}-${Date.now()}`;
444
- }
445
- if (field.optional !== void 0) {
446
- field.requiredField = !field.optional;
447
- delete field.optional;
448
- }
449
- if (field.required !== void 0) {
450
- field.requiredField = field.required;
451
- delete field.required;
452
- }
453
- if (field.type === "input" && !field.fieldType) {
454
- field.fieldType = "text";
455
- }
456
- if (field.type === "select" && field.options && Array.isArray(field.options)) {
457
- const firstOpt = field.options[0];
458
- if (typeof firstOpt === "object" && firstOpt !== null) {
459
- field.options = field.options.map(
460
- (opt) => opt.label || opt.value || String(opt)
461
- );
462
- }
463
- }
464
- return field;
465
- });
466
- }
467
- if (comp.type === "list" && comp.items && Array.isArray(comp.items)) {
468
- comp.items = comp.items.map((item, itemIndex) => {
469
- if (typeof item === "string") {
470
- return {
471
- id: `list-item-${itemIndex}-${Date.now()}`,
472
- type: "text",
473
- value: item,
474
- label: item
475
- };
476
- }
477
- if (!item.id || !item.id.trim()) {
478
- item.id = `list-item-${itemIndex}-${Date.now()}`;
479
- }
480
- return item;
481
- });
482
- }
483
- return comp;
484
- });
485
- uiData = parsed;
932
+ )
933
+ ] }),
934
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "detail-subtitle", children: isLoading ? "Typing..." : "Online" })
935
+ ] })
936
+ ] }),
937
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "detail-header-right", children: [
938
+ /* @__PURE__ */ jsxRuntime.jsx("button", { className: "icon-button", onClick: onInfo, "aria-label": "Bilgi", children: /* @__PURE__ */ jsxRuntime.jsx(IconInfo, {}) }),
939
+ /* @__PURE__ */ jsxRuntime.jsx(
940
+ "button",
941
+ {
942
+ className: "icon-button danger",
943
+ disabled: !activeSessionId,
944
+ "aria-label": "End conversation",
945
+ children: /* @__PURE__ */ jsxRuntime.jsx(IconTrash, {})
946
+ }
947
+ )
948
+ ] })
949
+ ] }),
950
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "messages-container", children: [
951
+ /* @__PURE__ */ jsxRuntime.jsx(
952
+ HeaderAlert,
953
+ {
954
+ headerValidation,
955
+ setShowAlert,
956
+ showAlert
486
957
  }
487
- cleaned = cleaned.replace(match[0], "").trim();
488
- break;
489
- } catch (e) {
490
- console.error("Invalid ui-component JSON:", e, block);
958
+ ),
959
+ messages.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "empty-state", children: /* @__PURE__ */ jsxRuntime.jsx("span", { dangerouslySetInnerHTML: { __html: sanitizedWelcome } }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
960
+ messages.map((message, index) => /* @__PURE__ */ jsxRuntime.jsx(
961
+ MessageBubble,
962
+ {
963
+ message,
964
+ onAction: onSendMessage
965
+ },
966
+ index
967
+ )),
968
+ config?.widget_config.show_typing_indicator && isLoading && /* @__PURE__ */ jsxRuntime.jsx(TypingDots, {})
969
+ ] }),
970
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: messagesEndRef })
971
+ ] }),
972
+ /* @__PURE__ */ jsxRuntime.jsx(
973
+ ChatInput,
974
+ {
975
+ onSendMessage,
976
+ isLoading,
977
+ placeholder
491
978
  }
492
- }
493
- return {
494
- cleanedText: cleaned,
495
- uiData
496
- };
497
- };
498
- var AizekChatBot = ({ clientId, headers, onMounted, onReady, onOpen, onClose, onMessage, onToolCall, onDisconnect }) => {
979
+ )
980
+ ] });
981
+ var InfoPanel = ({
982
+ companyName,
983
+ isLoading,
984
+ sessionsCount
985
+ }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "info-panel", children: [
986
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "eyebrow", children: "Info" }),
987
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "panel-title", children: "Widget Details" }),
988
+ /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "info-list", children: [
989
+ /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
990
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Company" }),
991
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: companyName })
992
+ ] }),
993
+ /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
994
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Status" }),
995
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: isLoading ? "Typing..." : "Online" })
996
+ ] }),
997
+ /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
998
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Conversations" }),
999
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: sessionsCount })
1000
+ ] })
1001
+ ] })
1002
+ ] });
1003
+ var AizekChatBot = ({
1004
+ clientId,
1005
+ headers,
1006
+ onMounted,
1007
+ onReady,
1008
+ onOpen,
1009
+ onClose,
1010
+ onMessage,
1011
+ onToolCall,
1012
+ onDisconnect
1013
+ }) => {
499
1014
  const messagesEndRef = react.useRef(null);
500
- const [config, setConfig] = react.useState();
501
- const [messages, setMessages] = react.useState([]);
502
- const [isLoading, setIsLoading] = react.useState(false);
503
- const [isConfigLoading, setIsConfigLoading] = react.useState(true);
1015
+ const {
1016
+ config,
1017
+ messages,
1018
+ isLoading,
1019
+ isConfigLoading,
1020
+ sessions,
1021
+ activeSessionId,
1022
+ headerValidation,
1023
+ createNewSession,
1024
+ sendMessage,
1025
+ selectSession,
1026
+ getSessionTitle
1027
+ } = useChatSession({ clientId, headers, onReady, onToolCall, onDisconnect });
504
1028
  const [isOpen, setIsOpen] = react.useState(false);
505
- const [headerValidation, setHeaderValidation] = react.useState(null);
506
1029
  const [showAlert, setShowAlert] = react.useState(true);
507
- const [sessions, setSessions] = react.useState([]);
508
- const [activeSessionId, setActiveSessionIdState] = react.useState(null);
509
1030
  const [activeTab, setActiveTab] = react.useState("home");
510
1031
  const [messageView, setMessageView] = react.useState("list");
511
- const [sessionTitleById, setSessionTitleById] = react.useState({});
512
- const PROXY_BASE_URL = "https://proxy.aizek.ai/api";
513
- const createNewSession = async () => {
514
- const deviceId = getOrCreateDeviceId();
515
- if (sessions.length >= MAX_SESSIONS) {
516
- throw new Error(`You can open up to ${MAX_SESSIONS} sessions.`);
517
- }
518
- const res = await fetch(`${PROXY_BASE_URL}/aizek-sessions/new?clientId=${clientId}`, {
519
- method: "POST",
520
- headers: {
521
- "Content-Type": "application/json",
522
- "x-device-id": deviceId,
523
- "x-alternate": JSON.stringify(headers)
524
- }
525
- });
526
- const data = await res.json();
527
- if (!data.success) throw new Error(data.message || "session create failed");
528
- const sid = data.data.sessionId;
529
- const updatedSessions = data.data.sessions ?? [sid];
530
- upsertSessionsFromServer(updatedSessions, setSessions);
531
- setActiveSessionIdState(sid);
532
- setActiveSessionId(sid);
533
- setActiveTab("messages");
534
- setMessageView("detail");
535
- touchSession(sid);
536
- setMessages([]);
537
- return sid;
538
- };
539
- const loadConfig = async () => {
540
- try {
541
- setIsConfigLoading(true);
542
- const deviceId = getOrCreateDeviceId();
543
- purgeExpiredLocalSessions(setActiveSessionIdState);
544
- const localActive = getActiveSessionId();
545
- const response = await fetch(`${PROXY_BASE_URL}/aizek-connect?clientId=${clientId}`, {
546
- method: "POST",
547
- headers: {
548
- "Content-Type": "application/json",
549
- "x-device-id": deviceId,
550
- "x-alternate": JSON.stringify(headers)
551
- }
552
- });
553
- const data = await response.json();
554
- if (!data.success) {
555
- setIsOpen(false);
556
- return;
557
- }
558
- setIsOpen(!!data.data.widget_config.initial_open);
559
- setConfig(data.data);
560
- const serverSessions = data.data.sessions ?? [];
561
- const merged = upsertSessionsFromServer(serverSessions, setSessions);
562
- if (merged.length === 0) {
563
- const newSid = await createNewSession();
564
- setActiveSessionIdState(newSid);
565
- setActiveSessionId(newSid);
566
- return;
567
- }
568
- const mergedIds = merged.map((s) => s.sessionId);
569
- const nextActive = (localActive && mergedIds.includes(localActive) ? localActive : null) ?? mergedIds[0] ?? null;
570
- setActiveSessionIdState(nextActive);
571
- setActiveSessionId(nextActive);
572
- if (headers) {
573
- const validationResult = validateHeaders(headers, data.data.auth_config, {
574
- allowExtra: false,
575
- caseSensitive: true
576
- });
577
- setHeaderValidation(validationResult);
578
- }
579
- onReady?.({ config: { ...data.data } });
580
- } catch (error) {
581
- console.error("Failed to load chat widget config:", error);
582
- } finally {
583
- setIsConfigLoading(false);
584
- }
585
- };
586
- const getHistoryMessageBySessionId = async (sid) => {
587
- try {
588
- const deviceId = getOrCreateDeviceId();
589
- const response = await fetch(`${PROXY_BASE_URL}/aizek-messages`, {
590
- method: "GET",
591
- headers: {
592
- "Content-Type": "application/json",
593
- "x-device-id": deviceId,
594
- "x-session-id": sid,
595
- "x-alternate": JSON.stringify(headers)
596
- }
597
- });
598
- const data = await response.json();
599
- if (!data.success) {
600
- throw new Error(data.message || "Failed to fetch messages");
601
- }
602
- const historyMessages = [];
603
- if (data.data?.messages && Array.isArray(data.data.messages)) {
604
- for (const msg of data.data.messages) {
605
- let textContent = "";
606
- let uiData = null;
607
- if (typeof msg.content === "string") {
608
- textContent = msg.content;
609
- } else if (Array.isArray(msg.content)) {
610
- const textParts = [];
611
- for (const item of msg.content) {
612
- if (item.type === "text" && item.text) {
613
- textParts.push(item.text);
614
- }
615
- }
616
- textContent = textParts.join("\n");
617
- }
618
- if (textContent) {
619
- const extracted = extractUIJsonFromText(textContent);
620
- textContent = extracted.cleanedText;
621
- uiData = extracted.uiData;
622
- }
623
- if (textContent.trim() || uiData) {
624
- historyMessages.push({
625
- text: textContent.trim() || void 0,
626
- ui: uiData,
627
- role: msg.role === "user" ? "user" : msg.role === "assistant" ? "assistant" : "user",
628
- timestamp: /* @__PURE__ */ new Date()
629
- });
630
- }
631
- }
632
- }
633
- return historyMessages;
634
- } catch (error) {
635
- console.error("Error fetching message history:", error);
636
- return [];
637
- }
638
- };
639
1032
  react.useEffect(() => {
640
1033
  onMounted?.();
641
- loadConfig();
642
- }, []);
643
- react.useEffect(() => {
644
- const t = setInterval(() => {
645
- purgeExpiredLocalSessions(setActiveSessionIdState);
646
- }, 1e3);
647
- return () => clearInterval(t);
648
1034
  }, []);
649
1035
  react.useEffect(() => {
650
1036
  if (typeof config?.widget_config.initial_open === "boolean") {
@@ -657,519 +1043,147 @@ var AizekChatBot = ({ clientId, headers, onMounted, onReady, onOpen, onClose, on
657
1043
  react.useEffect(() => {
658
1044
  messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
659
1045
  }, [messages]);
660
- react.useEffect(() => {
661
- if (activeSessionId && !isConfigLoading) {
662
- getHistoryMessageBySessionId(activeSessionId).then((historyMessages) => {
663
- setMessages(historyMessages);
664
- }).catch((error) => {
665
- console.error("Failed to load message history:", error);
666
- });
667
- } else if (!activeSessionId) {
668
- setMessages([]);
669
- }
670
- }, [activeSessionId, isConfigLoading]);
671
- react.useEffect(() => {
672
- if (!sessions.length) return;
673
- const missing = sessions.filter((sid) => !sessionTitleById[sid]);
674
- if (!missing.length) return;
675
- let cancelled = false;
676
- (async () => {
677
- for (const sid of missing) {
678
- if (cancelled) return;
679
- const title = await fetchLastMessageTitle(sid);
680
- if (cancelled) return;
681
- if (!title) continue;
682
- setSessionTitleById((prev) => prev[sid] ? prev : { ...prev, [sid]: title });
683
- }
684
- })();
685
- return () => {
686
- cancelled = true;
687
- };
688
- }, [sessions]);
689
- const addMessage = (payload) => {
690
- const newMessage = {
691
- text: payload.text,
692
- ui: payload.ui,
693
- role: payload.role,
694
- timestamp: /* @__PURE__ */ new Date()
695
- };
696
- onMessage?.(newMessage);
697
- setMessages((prev) => [...prev, newMessage]);
698
- messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
699
- return newMessage;
700
- };
701
- const sendMessage = async (message, approval) => {
702
- if (!message.trim() || isLoading) return;
703
- setMessages((prev) => [
704
- ...prev,
705
- { text: message, ui: void 0, role: approval ? "approval" : "user", timestamp: /* @__PURE__ */ new Date() }
706
- ]);
707
- setIsLoading(true);
708
- try {
709
- const deviceId = getOrCreateDeviceId();
710
- purgeExpiredLocalSessions(setActiveSessionIdState);
711
- let sid = activeSessionId;
712
- if (!sid) sid = await createNewSession();
713
- const response = await fetch(`${PROXY_BASE_URL}/aizek-chat?clientId=${clientId}`, {
714
- method: "POST",
715
- headers: {
716
- "Content-Type": "application/json",
717
- "x-device-id": deviceId,
718
- "x-session-id": sid,
719
- "x-alternate": JSON.stringify(headers)
720
- },
721
- body: JSON.stringify({ message })
722
- });
723
- if (response.status === 401) {
724
- const local = readStoredSessions().filter((s) => s.sessionId !== sid);
725
- writeStoredSessions(local);
726
- setSessions(local.map((x) => x.sessionId));
727
- setActiveSessionId(null);
728
- setActiveSessionIdState(null);
729
- const newSid = await createNewSession();
730
- const retry = await fetch(`${PROXY_BASE_URL}/aizek-chat?clientId=${clientId}`, {
731
- method: "POST",
732
- headers: {
733
- "Content-Type": "application/json",
734
- "x-device-id": deviceId,
735
- "x-session-id": newSid,
736
- "x-alternate": JSON.stringify(headers)
737
- },
738
- body: JSON.stringify({ message })
739
- });
740
- if (!retry.ok) throw new Error(`HTTP error ${retry.status}`);
741
- const retryJson = await retry.json();
742
- const text = JSON.stringify(retryJson.data);
743
- const { cleanedText, uiData } = extractUIJsonFromText(text);
744
- addMessage({ text: cleanedText, ui: uiData, role: "assistant" });
745
- touchSession(newSid);
746
- return;
747
- }
748
- if (!response.ok) {
749
- throw new Error(`HTTP error ${response.status}`);
750
- }
751
- if (!response.body) {
752
- throw new Error("Streaming desteklenmiyor (response.body yok)");
753
- }
754
- const reader = response.body.getReader();
755
- const decoder = new TextDecoder();
756
- let buffer = "";
757
- while (true) {
758
- const { value, done } = await reader.read();
759
- if (done) break;
760
- buffer += decoder.decode(value, { stream: true });
761
- const chunks = buffer.split("\n\n");
762
- buffer = chunks.pop() ?? "";
763
- for (const rawChunk of chunks) {
764
- const line = rawChunk.split("\n").find((l) => l.startsWith("data:"));
765
- if (!line) continue;
766
- const jsonStr = line.replace(/^data:\s*/, "").trim();
767
- if (!jsonStr) continue;
768
- const event = JSON.parse(jsonStr);
769
- if (event.type === "assistant_text" && event.content) {
770
- const { cleanedText, uiData } = extractUIJsonFromText(event.content);
771
- addMessage({
772
- text: cleanedText,
773
- ui: uiData,
774
- role: "assistant"
775
- });
776
- }
777
- if (event.type === "assistant_tool_result" && event.content) {
778
- const toolInfoParsed = JSON.parse(event.content);
779
- onToolCall?.(toolInfoParsed);
780
- }
781
- if (event.type === "error" && event.content) {
782
- const { cleanedText, uiData } = extractUIJsonFromText(event.content);
783
- addMessage({
784
- text: cleanedText,
785
- ui: uiData,
786
- role: "assistant"
787
- });
788
- }
789
- }
790
- }
791
- touchSession(sid);
792
- } catch (error) {
793
- console.error("Error sending message:", error);
794
- addMessage({ text: "Sorry, something went wrong. Please try again.", role: "assistant" });
795
- } finally {
796
- setIsLoading(false);
797
- }
1046
+ const toggleChat = () => {
1047
+ const next = !isOpen;
1048
+ setIsOpen(next);
1049
+ next ? onOpen?.() : onClose?.();
798
1050
  };
799
- const disconnectActiveSession = async () => {
1051
+ const handleCreateSession = async () => {
800
1052
  try {
801
- const deviceId = getOrCreateDeviceId();
802
- const sid = activeSessionId;
803
- if (!sid) return;
804
- await fetch(`${PROXY_BASE_URL}/aizek-disconnect?clientId=${clientId}`, {
805
- method: "POST",
806
- headers: {
807
- "Content-Type": "application/json",
808
- "x-device-id": deviceId,
809
- "x-session-id": sid,
810
- "x-alternate": JSON.stringify(headers)
811
- },
812
- body: JSON.stringify({ sessionId: sid })
813
- });
814
- const nextStored = readStoredSessions().filter((s) => s.sessionId !== sid);
815
- writeStoredSessions(nextStored);
816
- const nextSessions = nextStored.map((x) => x.sessionId);
817
- setSessions(nextSessions);
818
- const nextActive = nextSessions[0] ?? null;
819
- setActiveSessionIdState(nextActive);
820
- setActiveSessionId(nextActive);
821
- setMessages([]);
822
- onDisconnect?.();
1053
+ await createNewSession();
1054
+ setActiveTab("messages");
1055
+ setMessageView("detail");
823
1056
  } catch (e) {
824
1057
  console.error(e);
825
1058
  }
826
1059
  };
827
1060
  const handleSelectSession = (sid) => {
828
- setActiveSessionIdState(sid);
829
- setActiveSessionId(sid);
1061
+ selectSession(sid);
830
1062
  setActiveTab("messages");
831
1063
  setMessageView("detail");
832
1064
  };
833
- const getSessionTitle = (sid) => {
834
- if (sessionTitleById[sid]) return sessionTitleById[sid];
835
- return "New conversation";
836
- };
837
- const fetchLastMessageTitle = async (sid) => {
838
- try {
839
- const deviceId = getOrCreateDeviceId();
840
- const res = await fetch(`${PROXY_BASE_URL}/aizek-last-message`, {
841
- method: "GET",
842
- headers: {
843
- "Content-Type": "application/json",
844
- "x-device-id": deviceId,
845
- "x-session-id": sid,
846
- "x-alternate": JSON.stringify(headers)
847
- }
848
- });
849
- const json = await res.json();
850
- if (!json?.success) return null;
851
- const last = json?.data?.lastMessage;
852
- if (!last) return null;
853
- let textContent = "";
854
- if (typeof last.content === "string") {
855
- textContent = last.content;
856
- } else if (Array.isArray(last.content)) {
857
- const parts = [];
858
- for (const item of last.content) {
859
- if (item?.type === "text" && typeof item.text === "string") parts.push(item.text);
860
- }
861
- textContent = parts.join("\n");
862
- }
863
- if (!textContent.trim()) return null;
864
- const extracted = extractUIJsonFromText(textContent);
865
- const cleaned = (extracted.cleanedText || "").trim();
866
- const firstLine = (cleaned.split("\n").find((l) => l.trim()) || "").trim();
867
- const title = firstLine || cleaned;
868
- if (!title) return null;
869
- const compact = title.length > 46 ? `${title.slice(0, 46).trim()}\u2026` : title;
870
- return compact;
871
- } catch (e) {
872
- console.error("Failed to fetch last message title:", e);
873
- return null;
874
- }
875
- };
876
- const toggleChat = () => {
877
- const newIsOpen = !isOpen;
878
- setIsOpen(newIsOpen);
879
- if (newIsOpen) onOpen?.();
880
- else onClose?.();
881
- };
882
- const clean = sanitizeHtml__default.default(config?.widget_config.welcome_message ?? "", {
883
- allowedTags: ["b", "i", "em", "strong", "a", "p", "br"],
884
- allowedAttributes: {
885
- a: ["href", "target", "rel"]
886
- }
887
- });
888
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: isConfigLoading ? /* @__PURE__ */ jsxRuntime.jsx(
889
- "button",
1065
+ const sanitizedWelcome = sanitizeHtml__default.default(
1066
+ config?.widget_config.welcome_message ?? "",
890
1067
  {
891
- className: "floating-button bottom-right button-sizes medium loading-state",
892
- style: { background: "#4f46e5" },
893
- "aria-label": "Loading",
894
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "loading-spinner" })
1068
+ allowedTags: ["b", "i", "em", "strong", "a", "p", "br"],
1069
+ allowedAttributes: { a: ["href", "target", "rel"] }
895
1070
  }
896
- ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
897
- isOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `overlay floating-chat-overlay ${isOpen ? "is-open" : ""}`, onClick: toggleChat }),
1071
+ );
1072
+ if (isConfigLoading) {
1073
+ return /* @__PURE__ */ jsxRuntime.jsx(
1074
+ "button",
1075
+ {
1076
+ className: "floating-button bottom-right button-sizes medium loading-state",
1077
+ style: { background: "#4f46e5" },
1078
+ "aria-label": "Loading",
1079
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "loading-spinner" })
1080
+ }
1081
+ );
1082
+ }
1083
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1084
+ isOpen && /* @__PURE__ */ jsxRuntime.jsx(
1085
+ "div",
1086
+ {
1087
+ className: `overlay floating-chat-overlay ${isOpen ? "is-open" : ""}`,
1088
+ onClick: toggleChat
1089
+ }
1090
+ ),
898
1091
  /* @__PURE__ */ jsxRuntime.jsx(
899
1092
  "div",
900
1093
  {
901
1094
  className: `chat-container ${config?.widget_config.button_position} ${isOpen ? "is-open" : ""}`,
902
- style: { width: config?.widget_config.chat_width, height: config?.widget_config.chat_height },
1095
+ style: {
1096
+ width: config?.widget_config.chat_width,
1097
+ height: config?.widget_config.chat_height
1098
+ },
903
1099
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "chatbot-container", children: [
904
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "header", style: { background: config?.widget_config.header_background }, children: [
905
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "logo-container", children: config?.widget_config.company_logo ? config?.widget_config.company_logo.startsWith("http") || config?.widget_config.company_logo.startsWith("data:") ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: config?.widget_config.company_logo, alt: "Company Logo", className: "logo-image" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "logo-text", children: config?.widget_config.company_logo }) : "\u{1F916}" }),
906
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
907
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "company-name", children: config?.widget_config.company_name }),
908
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "status-text", children: isLoading ? "Typing..." : "Online" })
909
- ] })
910
- ] }),
911
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "chat-content", children: [
912
- activeTab === "home" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "home-panel", children: [
913
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "eyebrow", children: "Welcome" }),
914
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "panel-title", children: config?.widget_config.company_name }),
915
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "panel-subtitle", children: "Ask anything. We keep your history and respond instantly." }),
916
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "home-actions", children: [
917
- /* @__PURE__ */ jsxRuntime.jsx(
918
- "button",
919
- {
920
- className: "primary-button",
921
- onClick: async () => {
922
- try {
923
- await createNewSession();
924
- } catch (e) {
925
- console.error(e);
926
- }
927
- },
928
- disabled: isLoading || sessions.length >= MAX_SESSIONS,
929
- children: "Start a new conversation"
930
- }
931
- ),
932
- /* @__PURE__ */ jsxRuntime.jsx(
933
- "button",
1100
+ /* @__PURE__ */ jsxRuntime.jsxs(
1101
+ "div",
1102
+ {
1103
+ className: "header",
1104
+ style: { background: config?.widget_config.header_background },
1105
+ children: [
1106
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "logo-container", children: config?.widget_config.company_logo ? config.widget_config.company_logo.startsWith("http") || config.widget_config.company_logo.startsWith("data:") ? /* @__PURE__ */ jsxRuntime.jsx(
1107
+ "img",
934
1108
  {
935
- className: "ghost-button",
936
- onClick: () => {
937
- setActiveTab("messages");
938
- setMessageView("list");
939
- },
940
- children: "View conversations"
1109
+ src: config.widget_config.company_logo,
1110
+ alt: "Company Logo",
1111
+ className: "logo-image"
941
1112
  }
942
- )
943
- ] })
944
- ] }),
945
- activeTab === "messages" && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: messageView === "list" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "conversation-list", children: [
946
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "list-header", children: [
1113
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "logo-text", children: config.widget_config.company_logo }) : "\u{1F916}" }),
947
1114
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
948
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "eyebrow", children: "Conversations" }),
949
- /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "panel-title", children: "Inbox" })
950
- ] }),
951
- /* @__PURE__ */ jsxRuntime.jsx(
952
- "button",
953
- {
954
- className: "session-new-button",
955
- onClick: async () => {
956
- try {
957
- await createNewSession();
958
- } catch (e) {
959
- console.error(e);
960
- }
961
- },
962
- disabled: sessions.length >= MAX_SESSIONS,
963
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: "+ New" })
964
- }
965
- )
966
- ] }),
967
- sessions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "empty-list", children: [
968
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "empty-state-icon", children: "\u{1F4AC}" }),
969
- /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "empty-state-title", children: "No conversations yet" }),
970
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "empty-state-description", children: "Start a new conversation to see it appear here." })
971
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "conversation-items", children: sessions.map((sid) => /* @__PURE__ */ jsxRuntime.jsxs(
972
- "button",
973
- {
974
- className: `conversation-item ${sid === activeSessionId ? "active" : ""}`,
975
- onClick: () => handleSelectSession(sid),
976
- children: [
977
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "conversation-meta", children: [
978
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "conversation-title", children: getSessionTitle(sid) }),
979
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "conversation-sub", children: [
980
- "Session ID: ",
981
- sid.slice(0, 8),
982
- "..."
983
- ] })
984
- ] }),
985
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "conversation-pill", children: "Open" })
986
- ]
987
- },
988
- sid
989
- )) })
990
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "conversation-detail", children: [
991
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "detail-header", children: [
992
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "detail-header-left", children: /* @__PURE__ */ jsxRuntime.jsx("button", { className: "icon-button", onClick: () => setMessageView("list"), "aria-label": "Back", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
993
- "path",
994
- {
995
- d: "M15 18l-6-6 6-6",
996
- stroke: "currentColor",
997
- strokeWidth: "2",
998
- strokeLinecap: "round",
999
- strokeLinejoin: "round"
1000
- }
1001
- ) }) }) }),
1002
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "detail-header-center", children: [
1003
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "detail-avatar", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
1004
- "path",
1005
- {
1006
- d: "M12 3c-4.418 0-8 3.134-8 7 0 2.382 1.362 4.486 3.5 5.737V21l4.07-2.13c.14.008.283.013.43.013 4.418 0 8-3.134 8-7s-3.582-7-8-7z",
1007
- stroke: "currentColor",
1008
- strokeWidth: "2",
1009
- strokeLinejoin: "round"
1010
- }
1011
- ) }) }),
1012
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "detail-title", children: [
1013
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "detail-title-row", children: [
1014
- /* @__PURE__ */ jsxRuntime.jsx("strong", { className: "detail-title-text", children: activeSessionId ? getSessionTitle(activeSessionId) : "Chat" }),
1015
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `status-dot ${isLoading ? "typing" : "online"}`, "aria-hidden": "true" })
1016
- ] }),
1017
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "detail-subtitle", children: isLoading ? "Yaz\u0131yor\u2026" : "Online" })
1018
- ] })
1019
- ] }),
1020
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "detail-header-right", children: [
1021
- /* @__PURE__ */ jsxRuntime.jsx(
1022
- "button",
1023
- {
1024
- className: "icon-button",
1025
- onClick: () => {
1026
- setActiveTab("info");
1027
- setMessageView("list");
1028
- },
1029
- "aria-label": "Bilgi",
1030
- children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: [
1031
- /* @__PURE__ */ jsxRuntime.jsx(
1032
- "path",
1033
- {
1034
- d: "M12 17v-6",
1035
- stroke: "currentColor",
1036
- strokeWidth: "2",
1037
- strokeLinecap: "round"
1038
- }
1039
- ),
1040
- /* @__PURE__ */ jsxRuntime.jsx(
1041
- "path",
1042
- {
1043
- d: "M12 8h.01",
1044
- stroke: "currentColor",
1045
- strokeWidth: "2.5",
1046
- strokeLinecap: "round"
1047
- }
1048
- ),
1049
- /* @__PURE__ */ jsxRuntime.jsx(
1050
- "circle",
1051
- {
1052
- cx: "12",
1053
- cy: "12",
1054
- r: "9",
1055
- stroke: "currentColor",
1056
- strokeWidth: "2"
1057
- }
1058
- )
1059
- ] })
1060
- }
1061
- ),
1062
- /* @__PURE__ */ jsxRuntime.jsx(
1063
- "button",
1064
- {
1065
- className: "icon-button danger",
1066
- onClick: disconnectActiveSession,
1067
- disabled: !activeSessionId,
1068
- "aria-label": "End conversation",
1069
- children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", children: [
1070
- /* @__PURE__ */ jsxRuntime.jsx(
1071
- "path",
1072
- {
1073
- d: "M3 6h18",
1074
- stroke: "currentColor",
1075
- strokeWidth: "2",
1076
- strokeLinecap: "round"
1077
- }
1078
- ),
1079
- /* @__PURE__ */ jsxRuntime.jsx(
1080
- "path",
1081
- {
1082
- d: "M8 6V4h8v2",
1083
- stroke: "currentColor",
1084
- strokeWidth: "2",
1085
- strokeLinejoin: "round"
1086
- }
1087
- ),
1088
- /* @__PURE__ */ jsxRuntime.jsx(
1089
- "path",
1090
- {
1091
- d: "M6 6l1 16h10l1-16",
1092
- stroke: "currentColor",
1093
- strokeWidth: "2",
1094
- strokeLinejoin: "round"
1095
- }
1096
- )
1097
- ] })
1098
- }
1099
- )
1100
- ] })
1101
- ] }),
1102
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "messages-container", children: [
1103
- /* @__PURE__ */ jsxRuntime.jsx(HeaderAlert, { headerValidation, setShowAlert, showAlert }),
1104
- messages.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "empty-state", children: /* @__PURE__ */ jsxRuntime.jsx("span", { dangerouslySetInnerHTML: { __html: clean } }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1105
- messages.map((message, index) => /* @__PURE__ */ jsxRuntime.jsx(MessageBubble, { message, onAction: sendMessage }, index)),
1106
- config?.widget_config.show_typing_indicator && isLoading && /* @__PURE__ */ jsxRuntime.jsx(TypingDots, {})
1107
- ] }),
1108
- /* @__PURE__ */ jsxRuntime.jsx("div", { ref: messagesEndRef })
1109
- ] }),
1110
- /* @__PURE__ */ jsxRuntime.jsx(
1111
- ChatInput,
1112
- {
1113
- handleSendMessage: sendMessage,
1114
- isLoading,
1115
- placeholder: config?.widget_config.placeholder ?? ""
1116
- }
1117
- )
1118
- ] }) }),
1119
- activeTab === "info" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "info-panel", children: [
1120
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "eyebrow", children: "Info" }),
1121
- /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "panel-title", children: "Widget Details" }),
1122
- /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "info-list", children: [
1123
- /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
1124
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Company" }),
1125
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: config?.widget_config.company_name })
1126
- ] }),
1127
- /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
1128
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Status" }),
1129
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: isLoading ? "Typing..." : "Online" })
1130
- ] }),
1131
- /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
1132
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Conversations" }),
1133
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: sessions.length })
1115
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "company-name", children: config?.widget_config.company_name }),
1116
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "status-text", children: isLoading ? "Typing..." : "Online" })
1134
1117
  ] })
1135
- ] })
1136
- ] })
1137
- ] }),
1138
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bottom-nav", children: [
1139
- /* @__PURE__ */ jsxRuntime.jsx(
1140
- "button",
1118
+ ]
1119
+ }
1120
+ ),
1121
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "chat-content", children: [
1122
+ activeTab === "home" && /* @__PURE__ */ jsxRuntime.jsx(
1123
+ HomePanel,
1141
1124
  {
1142
- className: `nav-button ${activeTab === "home" ? "active" : ""}`,
1143
- onClick: () => {
1144
- setActiveTab("home");
1125
+ companyName: config?.widget_config.company_name ?? "",
1126
+ isLoading,
1127
+ sessionsCount: sessions.length,
1128
+ onNewSession: handleCreateSession,
1129
+ onViewConversations: () => {
1130
+ setActiveTab("messages");
1145
1131
  setMessageView("list");
1146
- },
1147
- children: "Home"
1132
+ }
1148
1133
  }
1149
1134
  ),
1150
- /* @__PURE__ */ jsxRuntime.jsx(
1151
- "button",
1135
+ activeTab === "messages" && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: messageView === "list" ? /* @__PURE__ */ jsxRuntime.jsx(
1136
+ ConversationListPanel,
1152
1137
  {
1153
- className: `nav-button ${activeTab === "messages" ? "active" : ""}`,
1154
- onClick: () => {
1155
- setActiveTab("messages");
1156
- setMessageView("list");
1157
- },
1158
- children: "Messages"
1138
+ sessions,
1139
+ activeSessionId,
1140
+ getSessionTitle,
1141
+ onNewSession: handleCreateSession,
1142
+ onSelectSession: handleSelectSession
1159
1143
  }
1160
- ),
1161
- /* @__PURE__ */ jsxRuntime.jsx(
1162
- "button",
1144
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1145
+ ConversationDetailPanel,
1163
1146
  {
1164
- className: `nav-button ${activeTab === "info" ? "active" : ""}`,
1165
- onClick: () => {
1147
+ activeSessionId,
1148
+ isLoading,
1149
+ messages,
1150
+ headerValidation,
1151
+ showAlert,
1152
+ setShowAlert,
1153
+ sanitizedWelcome,
1154
+ messagesEndRef,
1155
+ config,
1156
+ getSessionTitle,
1157
+ onBack: () => setMessageView("list"),
1158
+ onInfo: () => {
1166
1159
  setActiveTab("info");
1167
1160
  setMessageView("list");
1168
1161
  },
1169
- children: "Info"
1162
+ onSendMessage: sendMessage,
1163
+ placeholder: config?.widget_config.placeholder ?? ""
1164
+ }
1165
+ ) }),
1166
+ activeTab === "info" && /* @__PURE__ */ jsxRuntime.jsx(
1167
+ InfoPanel,
1168
+ {
1169
+ companyName: config?.widget_config.company_name ?? "",
1170
+ isLoading,
1171
+ sessionsCount: sessions.length
1170
1172
  }
1171
1173
  )
1172
- ] })
1174
+ ] }),
1175
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bottom-nav", children: ["home", "messages", "info"].map((tab) => /* @__PURE__ */ jsxRuntime.jsx(
1176
+ "button",
1177
+ {
1178
+ className: `nav-button ${activeTab === tab ? "active" : ""}`,
1179
+ onClick: () => {
1180
+ setActiveTab(tab);
1181
+ setMessageView("list");
1182
+ },
1183
+ children: tab.charAt(0).toUpperCase() + tab.slice(1)
1184
+ },
1185
+ tab
1186
+ )) })
1173
1187
  ] })
1174
1188
  }
1175
1189
  ),
@@ -1179,10 +1193,10 @@ var AizekChatBot = ({ clientId, headers, onMounted, onReady, onOpen, onClose, on
1179
1193
  onClick: toggleChat,
1180
1194
  className: `floating-button ${config?.widget_config.button_position} button-sizes ${config?.widget_config.button_size} ${isOpen ? "is-open" : ""}`,
1181
1195
  style: { background: config?.widget_config.button_background },
1182
- children: isOpen ? /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" }) }) : /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 2H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h4l4 4 4-4h4c1.1 0-2 .9-2-2V4c0-1.1-.9-2-2-2zm-2 12H6v-2h12v2zm0-3H6V9h12v2zm0-3H6V6h12v2z" }) })
1196
+ children: isOpen ? /* @__PURE__ */ jsxRuntime.jsx(IconClose, {}) : /* @__PURE__ */ jsxRuntime.jsx(IconChat, {})
1183
1197
  }
1184
1198
  )
1185
- ] }) });
1199
+ ] });
1186
1200
  };
1187
1201
 
1188
1202
  exports.AizekChatBot = AizekChatBot;