aizek-chatbot 1.0.25 → 1.0.26

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,669 @@
1
+ import { useRef, useState, useEffect } from 'react';
2
+ import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
3
+ import ReactMarkdown from 'react-markdown';
4
+ import remarkGfm from 'remark-gfm';
5
+
6
+ // src/utils/cx.ts
7
+ function validateHeaders(headers, authConfig, opts = {}) {
8
+ if (headers && (!authConfig || Object.keys(authConfig).length === 0)) {
9
+ return {
10
+ isValid: false,
11
+ missingKeys: [],
12
+ extraKeys: [],
13
+ emptyValueKeys: [],
14
+ warning: "Auth config bo\u015F ya da tan\u0131ms\u0131z, header do\u011Frulamas\u0131 yap\u0131lam\u0131yor."
15
+ };
16
+ }
17
+ const { caseSensitive = false, allowExtra = false } = opts;
18
+ const normalize = (s) => caseSensitive ? s : s.toLowerCase();
19
+ const headerEntries = Object.entries(headers).map(([k, v]) => [normalize(k), v.trim()]);
20
+ const authEntries = Object.entries(authConfig).map(([k, v]) => [normalize(k), v.trim()]);
21
+ const headerKeys = headerEntries.map(([k]) => k);
22
+ const authKeys = authEntries.map(([k]) => k);
23
+ const requiredSet = new Set(authKeys);
24
+ const missingKeys = authKeys.filter((k) => !headerKeys.includes(k));
25
+ const extraKeys = headerKeys.filter((k) => !requiredSet.has(k));
26
+ const hasAllRequired = missingKeys.length === 0;
27
+ const hasExtraKeys = extraKeys.length > 0 && !allowExtra;
28
+ const emptyValueKeys = authKeys.filter((k) => {
29
+ const val = headerEntries.find(([key]) => key === k)?.[1];
30
+ return !val || val.length === 0;
31
+ });
32
+ const isValid = hasAllRequired && !hasExtraKeys && emptyValueKeys.length === 0;
33
+ return { isValid, missingKeys, extraKeys, emptyValueKeys };
34
+ }
35
+ var HeaderAlert = ({ headerValidation, showAlert, setShowAlert }) => {
36
+ if (!headerValidation || !showAlert) return null;
37
+ const { isValid, missingKeys, extraKeys, emptyValueKeys, warning } = headerValidation;
38
+ if (isValid && missingKeys.length === 0 && extraKeys.length === 0 && emptyValueKeys.length === 0 && !warning) {
39
+ return null;
40
+ }
41
+ const hasErrors = missingKeys.length > 0 || emptyValueKeys.length > 0;
42
+ const hasWarnings = extraKeys.length > 0 || !!warning;
43
+ const alertType = hasErrors ? "error" : "warning";
44
+ const getAlertIcon = () => {
45
+ if (hasErrors) {
46
+ return /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ 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" }) });
47
+ }
48
+ return /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z" }) });
49
+ };
50
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs("div", { className: `alert-container ${alertType}`, children: [
51
+ /* @__PURE__ */ jsx("div", { className: "alert-icon-container", children: getAlertIcon() }),
52
+ /* @__PURE__ */ jsxs("div", { className: "alert-content", children: [
53
+ /* @__PURE__ */ jsx("h4", { className: "alert-title", children: hasErrors ? "Header Do\u011Frulama Hatas\u0131" : "Header Uyar\u0131s\u0131" }),
54
+ /* @__PURE__ */ 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." }),
55
+ missingKeys.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
56
+ /* @__PURE__ */ jsx("strong", { children: "Eksik Header'lar:" }),
57
+ /* @__PURE__ */ jsx("ul", { className: "alert-list", children: missingKeys.map((key, index) => /* @__PURE__ */ jsxs("li", { className: "alert-list-item", children: [
58
+ /* @__PURE__ */ jsx("span", { children: "\u2022" }),
59
+ /* @__PURE__ */ jsx("code", { children: key })
60
+ ] }, index)) })
61
+ ] }),
62
+ emptyValueKeys.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
63
+ /* @__PURE__ */ jsx("strong", { children: "Bo\u015F De\u011Ferli Header'lar:" }),
64
+ /* @__PURE__ */ jsx("ul", { className: "alert-list", children: emptyValueKeys.map((key, index) => /* @__PURE__ */ jsxs("li", { className: "alert-list-item", children: [
65
+ /* @__PURE__ */ jsx("span", { children: "\u2022" }),
66
+ /* @__PURE__ */ jsx("code", { children: key }),
67
+ /* @__PURE__ */ jsx("span", { children: "(de\u011Fer bo\u015F olamaz)" })
68
+ ] }, index)) })
69
+ ] }),
70
+ extraKeys.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
71
+ /* @__PURE__ */ jsx("strong", { children: "Fazla Header'lar:" }),
72
+ /* @__PURE__ */ jsx("ul", { className: "alert-list", children: extraKeys.map((key, index) => /* @__PURE__ */ jsxs("li", { className: "alert-list-item", children: [
73
+ /* @__PURE__ */ jsx("span", { children: "\u2022" }),
74
+ /* @__PURE__ */ jsx("code", { children: key })
75
+ ] }, index)) })
76
+ ] }),
77
+ warning && /* @__PURE__ */ jsxs("div", { children: [
78
+ /* @__PURE__ */ jsx("strong", { children: "Uyar\u0131:" }),
79
+ /* @__PURE__ */ jsx("p", { className: "alert-message", children: warning })
80
+ ] })
81
+ ] }),
82
+ /* @__PURE__ */ jsx(
83
+ "button",
84
+ {
85
+ onClick: () => setShowAlert(false),
86
+ className: "alert-close-button",
87
+ "aria-label": "Uyar\u0131y\u0131 kapat",
88
+ children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ 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" }) })
89
+ }
90
+ )
91
+ ] }) });
92
+ };
93
+ var LoadingSpinner = () => {
94
+ return /* @__PURE__ */ jsx("div", { className: "loading-spinner" });
95
+ };
96
+ var ChatInput = ({ isLoading, placeholder, handleSendMessage }) => {
97
+ const [message, setMessage] = useState("");
98
+ const textareaRef = useRef(null);
99
+ const handleSubmit = (e) => {
100
+ e.preventDefault();
101
+ if (message.trim() && !isLoading) {
102
+ handleSendMessage(message.trim());
103
+ setMessage("");
104
+ if (textareaRef.current) {
105
+ textareaRef.current.style.height = "auto";
106
+ }
107
+ }
108
+ };
109
+ const handleKeyDown = (e) => {
110
+ if (e.key === "Enter" && !e.shiftKey) {
111
+ e.preventDefault();
112
+ handleSubmit(e);
113
+ }
114
+ };
115
+ const handleInputChange = (e) => {
116
+ setMessage(e.target.value);
117
+ const textarea = e.target;
118
+ textarea.style.height = "auto";
119
+ textarea.style.height = Math.min(textarea.scrollHeight, 120) + "px";
120
+ };
121
+ return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "input-container", children: [
122
+ /* @__PURE__ */ jsx(
123
+ "textarea",
124
+ {
125
+ ref: textareaRef,
126
+ value: message,
127
+ onChange: handleInputChange,
128
+ onKeyDown: handleKeyDown,
129
+ placeholder,
130
+ disabled: isLoading,
131
+ className: "textarea"
132
+ }
133
+ ),
134
+ /* @__PURE__ */ jsx(
135
+ "button",
136
+ {
137
+ type: "submit",
138
+ disabled: isLoading || !message.trim(),
139
+ className: "send-button",
140
+ children: isLoading ? /* @__PURE__ */ jsx(LoadingSpinner, {}) : /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { d: "M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" }) })
141
+ }
142
+ )
143
+ ] });
144
+ };
145
+ var GenericUIRenderer = ({ uiData, onInteraction }) => {
146
+ const containerRef = useRef(null);
147
+ if (!uiData || !uiData.components) return null;
148
+ const collectFormValues = () => {
149
+ if (!containerRef.current) return {};
150
+ const formData = {};
151
+ const inputs = containerRef.current.querySelectorAll("input, textarea, select");
152
+ inputs.forEach((element) => {
153
+ const name = element.getAttribute("name");
154
+ if (name) {
155
+ if (element instanceof HTMLInputElement && element.type === "checkbox") {
156
+ formData[name] = element.checked;
157
+ } else if (element instanceof HTMLInputElement && element.type === "radio") {
158
+ if (element.checked) {
159
+ formData[name] = element.value;
160
+ }
161
+ } else {
162
+ formData[name] = element.value;
163
+ }
164
+ }
165
+ });
166
+ return formData;
167
+ };
168
+ const renderComponent = (comp) => {
169
+ switch (comp.type) {
170
+ case "text":
171
+ return /* @__PURE__ */ jsx("p", { className: "gen-ui-text", children: comp.value ?? comp.label }, comp.id);
172
+ case "input":
173
+ return /* @__PURE__ */ jsxs("div", { className: "gen-ui-input-wrapper", children: [
174
+ comp.label && /* @__PURE__ */ jsx("label", { className: "gen-ui-input-label", children: comp.label }),
175
+ comp.fieldType === "textarea" ? /* @__PURE__ */ jsx(
176
+ "textarea",
177
+ {
178
+ name: comp.id,
179
+ placeholder: comp.placeholder,
180
+ className: "gen-ui-textarea"
181
+ }
182
+ ) : /* @__PURE__ */ jsx(
183
+ "input",
184
+ {
185
+ name: comp.id,
186
+ type: comp.fieldType || "text",
187
+ placeholder: comp.placeholder,
188
+ className: "gen-ui-input"
189
+ }
190
+ )
191
+ ] }, comp.id);
192
+ case "select":
193
+ return /* @__PURE__ */ jsxs("div", { className: "gen-ui-select-wrapper", children: [
194
+ comp.label && /* @__PURE__ */ jsx("label", { className: "gen-ui-select-label", children: comp.label }),
195
+ /* @__PURE__ */ jsx("select", { name: comp.id, className: "gen-ui-select", children: comp.options?.map((opt) => /* @__PURE__ */ jsx("option", { value: opt, children: opt }, opt)) })
196
+ ] }, comp.id);
197
+ case "button":
198
+ return /* @__PURE__ */ jsx(
199
+ "button",
200
+ {
201
+ onClick: () => {
202
+ const formValues = collectFormValues();
203
+ onInteraction({
204
+ action: comp.label,
205
+ buttonId: comp.buttonType,
206
+ formData: formValues
207
+ });
208
+ },
209
+ className: "gen-ui-button",
210
+ children: comp.label
211
+ },
212
+ comp.id
213
+ );
214
+ case "card":
215
+ return /* @__PURE__ */ jsxs("div", { className: "gen-ui-card", children: [
216
+ comp.label && /* @__PURE__ */ jsx("h2", { className: "gen-ui-card-title", children: comp.label }),
217
+ comp.value && /* @__PURE__ */ jsx("p", { className: "gen-ui-card-content", children: comp.value })
218
+ ] }, comp.id);
219
+ case "list":
220
+ return /* @__PURE__ */ jsx("ul", { className: "gen-ui-list", children: comp.items?.map((item) => /* @__PURE__ */ jsx("li", { className: "gen-ui-list-item", children: item.label ?? String(item.value ?? "") }, item.id)) }, comp.id);
221
+ case "image":
222
+ return /* @__PURE__ */ jsx(
223
+ "img",
224
+ {
225
+ src: comp.url,
226
+ alt: comp.label || "",
227
+ className: "gen-ui-image"
228
+ },
229
+ comp.id
230
+ );
231
+ case "link":
232
+ return /* @__PURE__ */ jsx(
233
+ "a",
234
+ {
235
+ href: comp.url,
236
+ className: "gen-ui-link",
237
+ children: comp.label || comp.url
238
+ },
239
+ comp.id
240
+ );
241
+ case "table":
242
+ return /* @__PURE__ */ jsx("div", { className: "gen-ui-table-wrapper", children: /* @__PURE__ */ jsxs("table", { className: "gen-ui-table", children: [
243
+ comp.columns && /* @__PURE__ */ jsx("thead", { className: "gen-ui-table-header", children: /* @__PURE__ */ jsx("tr", { children: comp.columns.map((col) => /* @__PURE__ */ jsx("th", { className: "gen-ui-table-th", children: col }, col)) }) }),
244
+ comp.rows && /* @__PURE__ */ jsx("tbody", { className: "gen-ui-table-body", children: comp.rows.map((row, ridx) => /* @__PURE__ */ jsx("tr", { children: row.map((cell, cidx) => /* @__PURE__ */ jsx("td", { className: "gen-ui-table-td", children: cell }, cidx)) }, ridx)) })
245
+ ] }) }, comp.id);
246
+ case "form":
247
+ return /* @__PURE__ */ jsx("form", { className: "gen-ui-form", children: comp.items?.map((field) => renderComponent(field)) }, comp.id);
248
+ default:
249
+ return null;
250
+ }
251
+ };
252
+ return /* @__PURE__ */ jsxs("div", { className: "generative-ui-container", ref: containerRef, children: [
253
+ (uiData.title || uiData.description) && /* @__PURE__ */ jsxs("div", { className: "generative-ui-header", children: [
254
+ uiData.title && /* @__PURE__ */ jsx("h1", { className: "generative-ui-title", children: uiData.title }),
255
+ uiData.description && /* @__PURE__ */ jsx("p", { className: "generative-ui-description", children: uiData.description })
256
+ ] }),
257
+ uiData.components.map((comp) => renderComponent(comp))
258
+ ] });
259
+ };
260
+ var MessageBubble = ({ message, onAction }) => {
261
+ console.log("MESSAGE", message);
262
+ const isUser = message.role === "user";
263
+ const approval = message.role === "approval";
264
+ if (approval) {
265
+ return /* @__PURE__ */ jsx(Fragment, {});
266
+ }
267
+ return /* @__PURE__ */ jsxs("div", { className: `message-container ${isUser ? "user" : "assistant"}`, children: [
268
+ /* @__PURE__ */ jsx("div", { className: `message-bubble ${isUser ? "user" : "assistant"}`, children: isUser ? message.text && /* @__PURE__ */ jsx("div", { className: "markdown-content", children: message.text }) : /* @__PURE__ */ jsxs(Fragment, { children: [
269
+ message.text && /* @__PURE__ */ jsx("div", { className: "markdown-content", children: /* @__PURE__ */ jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: message.text }) }),
270
+ message.ui && /* @__PURE__ */ jsx(
271
+ GenericUIRenderer,
272
+ {
273
+ uiData: message.ui,
274
+ onInteraction: (event) => {
275
+ console.log("event", event);
276
+ if (event.buttonId === "submit") {
277
+ onAction(JSON.stringify(event.formData), true);
278
+ } else {
279
+ onAction(event.action, true);
280
+ }
281
+ }
282
+ }
283
+ )
284
+ ] }) }),
285
+ /* @__PURE__ */ jsx("div", { className: `message-time ${isUser ? "user" : "assistant"}`, children: message.timestamp.toLocaleTimeString("tr-TR", {
286
+ hour: "2-digit",
287
+ minute: "2-digit"
288
+ }) })
289
+ ] });
290
+ };
291
+ var TypingDots = () => {
292
+ const [dots, setDots] = useState("");
293
+ useEffect(() => {
294
+ const interval = setInterval(() => {
295
+ setDots((prev) => {
296
+ if (prev === "...") return "";
297
+ return prev + ".";
298
+ });
299
+ }, 500);
300
+ return () => clearInterval(interval);
301
+ }, []);
302
+ return /* @__PURE__ */ jsx("div", { className: "message-container assistant", children: /* @__PURE__ */ jsx("div", { className: "message-bubble assistant", children: /* @__PURE__ */ jsx("div", { className: "message-typing-indicator", children: /* @__PURE__ */ jsx("span", { children: dots }) }) }) });
303
+ };
304
+
305
+ // src/utils/chatbot.ts
306
+ var extractUIJsonFromText = (text) => {
307
+ const regex = /```ui-component([\s\S]*?)```/g;
308
+ let cleaned = text;
309
+ let match;
310
+ let uiData = null;
311
+ while ((match = regex.exec(text)) !== null) {
312
+ const block = match[1].trim();
313
+ try {
314
+ const parsed = JSON.parse(block);
315
+ if (parsed && parsed.components && Array.isArray(parsed.components)) {
316
+ parsed.components = parsed.components.map((comp, index) => {
317
+ if (!comp.id || typeof comp.id !== "string" || !comp.id.trim()) {
318
+ comp.id = `ui-comp-${index}-${Date.now()}`;
319
+ }
320
+ if (comp.type === "button") {
321
+ if (!comp.buttonType) {
322
+ comp.buttonType = "click";
323
+ }
324
+ }
325
+ if (comp.type === "input") {
326
+ if (!comp.fieldType) {
327
+ comp.fieldType = "text";
328
+ }
329
+ }
330
+ if (comp.type === "select") {
331
+ if (comp.options && Array.isArray(comp.options)) {
332
+ const firstOption = comp.options[0];
333
+ if (typeof firstOption === "object" && firstOption !== null) {
334
+ if ("label" in firstOption || "value" in firstOption) {
335
+ comp.options = comp.options.map(
336
+ (opt) => opt.label || opt.value || String(opt)
337
+ );
338
+ }
339
+ }
340
+ }
341
+ }
342
+ if (comp.type === "table") {
343
+ if (comp.columns && Array.isArray(comp.columns)) {
344
+ const firstCol = comp.columns[0];
345
+ if (typeof firstCol === "object" && firstCol !== null) {
346
+ comp.columns = comp.columns.map(
347
+ (col) => col.label || col.id || String(col)
348
+ );
349
+ }
350
+ }
351
+ if (comp.rows && Array.isArray(comp.rows)) {
352
+ const firstRow = comp.rows[0];
353
+ if (typeof firstRow === "object" && !Array.isArray(firstRow)) {
354
+ comp.rows = comp.rows.map((row) => {
355
+ if (Array.isArray(row)) return row;
356
+ return Object.values(row).map((val) => {
357
+ if (typeof val === "object" && val !== null) {
358
+ if (val.type === "image" && val.src) return val.src;
359
+ if (val.value !== void 0) return String(val.value);
360
+ }
361
+ return String(val || "");
362
+ });
363
+ });
364
+ }
365
+ }
366
+ }
367
+ if (comp.type === "form" && comp.items && Array.isArray(comp.items)) {
368
+ comp.items = comp.items.map((field, fieldIndex) => {
369
+ if (!field.id || !field.id.trim()) {
370
+ field.id = `field-${fieldIndex}-${Date.now()}`;
371
+ }
372
+ if (field.optional !== void 0) {
373
+ field.requiredField = !field.optional;
374
+ delete field.optional;
375
+ }
376
+ if (field.required !== void 0) {
377
+ field.requiredField = field.required;
378
+ delete field.required;
379
+ }
380
+ if (field.type === "input" && !field.fieldType) {
381
+ field.fieldType = "text";
382
+ }
383
+ if (field.type === "select" && field.options && Array.isArray(field.options)) {
384
+ const firstOpt = field.options[0];
385
+ if (typeof firstOpt === "object" && firstOpt !== null) {
386
+ field.options = field.options.map(
387
+ (opt) => opt.label || opt.value || String(opt)
388
+ );
389
+ }
390
+ }
391
+ return field;
392
+ });
393
+ }
394
+ if (comp.type === "list" && comp.items && Array.isArray(comp.items)) {
395
+ comp.items = comp.items.map((item, itemIndex) => {
396
+ if (typeof item === "string") {
397
+ return {
398
+ id: `list-item-${itemIndex}-${Date.now()}`,
399
+ type: "text",
400
+ value: item,
401
+ label: item
402
+ };
403
+ }
404
+ if (!item.id || !item.id.trim()) {
405
+ item.id = `list-item-${itemIndex}-${Date.now()}`;
406
+ }
407
+ return item;
408
+ });
409
+ }
410
+ return comp;
411
+ });
412
+ uiData = parsed;
413
+ }
414
+ cleaned = cleaned.replace(match[0], "").trim();
415
+ break;
416
+ } catch (e) {
417
+ console.error("Invalid ui-component JSON:", e, block);
418
+ }
419
+ }
420
+ return {
421
+ cleanedText: cleaned,
422
+ uiData
423
+ };
424
+ };
425
+ var AizekChatBot = ({ clientId, headers, onMounted, onReady, onOpen, onClose, onMessage, onToolCall, onDisconnect }) => {
426
+ const messagesEndRef = useRef(null);
427
+ const [config, setConfig] = useState();
428
+ const [messages, setMessages] = useState([]);
429
+ const [isLoading, setIsLoading] = useState(false);
430
+ const [isConfigLoading, setIsConfigLoading] = useState(true);
431
+ const [isOpen, setIsOpen] = useState(false);
432
+ const [headerValidation, setHeaderValidation] = useState(null);
433
+ const [showAlert, setShowAlert] = useState(true);
434
+ const PROXY_BASE_URL = "https://proxy.aizek.ai/api";
435
+ const loadConfig = async () => {
436
+ try {
437
+ setIsConfigLoading(true);
438
+ const response = await fetch(`${PROXY_BASE_URL}/aizek-connect`, {
439
+ method: "POST",
440
+ headers: {
441
+ "Content-Type": "application/json",
442
+ "x-alternate": JSON.stringify(headers)
443
+ },
444
+ credentials: "include",
445
+ body: JSON.stringify({ clientId })
446
+ });
447
+ const data = await response.json();
448
+ if (data.success) {
449
+ setIsOpen(data.data.widget_config.initial_open);
450
+ setConfig(data.data);
451
+ if (headers) {
452
+ const validationResult = validateHeaders(
453
+ headers,
454
+ data.data.auth_config,
455
+ {
456
+ allowExtra: false,
457
+ caseSensitive: true
458
+ }
459
+ );
460
+ setHeaderValidation(validationResult);
461
+ }
462
+ onReady?.({ config: { ...data.data } });
463
+ } else {
464
+ setIsOpen(false);
465
+ }
466
+ } catch (error) {
467
+ console.error("Failed to load chat widget config:", error);
468
+ } finally {
469
+ setIsConfigLoading(false);
470
+ }
471
+ };
472
+ const disconnect = async () => {
473
+ try {
474
+ setIsConfigLoading(true);
475
+ await fetch(`${PROXY_BASE_URL}/aizek-disconnect`, {
476
+ method: "POST",
477
+ headers: {
478
+ "Content-Type": "application/json",
479
+ "x-alternate": JSON.stringify(headers)
480
+ },
481
+ credentials: "include"
482
+ });
483
+ onDisconnect?.();
484
+ } catch (error) {
485
+ console.error("Failed to load chat widget config:", error);
486
+ } finally {
487
+ setIsConfigLoading(false);
488
+ }
489
+ };
490
+ useEffect(() => {
491
+ onMounted?.();
492
+ loadConfig();
493
+ return () => {
494
+ disconnect();
495
+ };
496
+ }, []);
497
+ useEffect(() => {
498
+ const newIsOpen = !isOpen;
499
+ setIsOpen(newIsOpen);
500
+ if (newIsOpen) onOpen?.();
501
+ else onClose?.();
502
+ }, [config?.widget_config.initial_open]);
503
+ useEffect(() => {
504
+ messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
505
+ }, [messages]);
506
+ const addMessage = (payload) => {
507
+ const newMessage = {
508
+ text: payload.text,
509
+ ui: payload.ui,
510
+ role: payload.role,
511
+ timestamp: /* @__PURE__ */ new Date()
512
+ };
513
+ onMessage?.(newMessage);
514
+ setMessages((prev) => [...prev, newMessage]);
515
+ messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
516
+ return newMessage;
517
+ };
518
+ const sendMessage = async (message, approval) => {
519
+ if (!message.trim() || isLoading) return;
520
+ const newMessage = {
521
+ text: message,
522
+ ui: void 0,
523
+ role: approval ? "approval" : "user",
524
+ timestamp: /* @__PURE__ */ new Date()
525
+ };
526
+ setMessages((prev) => [...prev, newMessage]);
527
+ setIsLoading(true);
528
+ try {
529
+ const response = await fetch(`${PROXY_BASE_URL}/aizek-chat`, {
530
+ method: "POST",
531
+ headers: {
532
+ "Content-Type": "application/json",
533
+ "x-alternate": JSON.stringify(headers)
534
+ },
535
+ body: JSON.stringify({ message }),
536
+ credentials: "include"
537
+ });
538
+ if (!response.ok) {
539
+ throw new Error(`HTTP error ${response.status}`);
540
+ }
541
+ if (!response.body) {
542
+ throw new Error("Streaming desteklenmiyor (response.body yok)");
543
+ }
544
+ const reader = response.body.getReader();
545
+ const decoder = new TextDecoder();
546
+ let buffer = "";
547
+ while (true) {
548
+ const { value, done } = await reader.read();
549
+ if (done) break;
550
+ buffer += decoder.decode(value, { stream: true });
551
+ const chunks = buffer.split("\n\n");
552
+ buffer = chunks.pop() ?? "";
553
+ for (const rawChunk of chunks) {
554
+ const line = rawChunk.split("\n").find((l) => l.startsWith("data:"));
555
+ if (!line) continue;
556
+ const jsonStr = line.replace(/^data:\s*/, "").trim();
557
+ if (!jsonStr) continue;
558
+ const event = JSON.parse(jsonStr);
559
+ if (event.type === "assistant_text" && event.content) {
560
+ const { cleanedText, uiData } = extractUIJsonFromText(event.content);
561
+ addMessage({
562
+ text: cleanedText,
563
+ ui: uiData,
564
+ role: "assistant"
565
+ });
566
+ }
567
+ if (event.type === "assistant_tool_result" && event.content) {
568
+ const toolInfoParsed = JSON.parse(event.content);
569
+ onToolCall?.(toolInfoParsed);
570
+ }
571
+ if (event.type === "error" && event.content) {
572
+ const { cleanedText, uiData } = extractUIJsonFromText(event.content);
573
+ addMessage({
574
+ text: cleanedText,
575
+ ui: uiData,
576
+ role: "assistant"
577
+ });
578
+ }
579
+ }
580
+ }
581
+ } catch (error) {
582
+ console.error("Error sending message:", error);
583
+ addMessage({ text: "\xDCzg\xFCn\xFCm, bir hata olu\u015Ftu. L\xFCtfen tekrar deneyin.", role: "assistant" });
584
+ } finally {
585
+ setIsLoading(false);
586
+ }
587
+ };
588
+ const toggleChat = () => {
589
+ const newIsOpen = !isOpen;
590
+ setIsOpen(newIsOpen);
591
+ if (newIsOpen) onOpen?.();
592
+ else onClose?.();
593
+ };
594
+ return /* @__PURE__ */ jsx(Fragment, { children: isConfigLoading ? /* @__PURE__ */ jsx(
595
+ "button",
596
+ {
597
+ className: "floating-button bottom-right button-sizes medium loading-state",
598
+ style: { background: "#4f46e5" },
599
+ "aria-label": "Y\xFCkleniyor",
600
+ children: /* @__PURE__ */ jsx("div", { className: "loading-spinner" })
601
+ }
602
+ ) : /* @__PURE__ */ jsxs(Fragment, { children: [
603
+ isOpen && /* @__PURE__ */ jsx("div", { className: `overlay floating-chat-overlay ${isOpen ? "is-open" : ""}`, onClick: toggleChat }),
604
+ /* @__PURE__ */ jsx("div", { className: `chat-container ${config?.widget_config.button_position} ${isOpen ? "is-open" : ""}`, style: { width: config?.widget_config.chat_width, height: config?.widget_config.chat_height }, children: /* @__PURE__ */ jsxs("div", { className: "chatbot-container", children: [
605
+ /* @__PURE__ */ jsxs("div", { className: "header", style: { background: config?.widget_config.header_background }, children: [
606
+ /* @__PURE__ */ 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__ */ jsx(
607
+ "img",
608
+ {
609
+ src: config?.widget_config.company_logo,
610
+ alt: "Company Logo",
611
+ className: "logo-image"
612
+ }
613
+ ) : /* @__PURE__ */ jsx("span", { className: "logo-text", children: config?.widget_config.company_logo }) : "\u{1F916}" }),
614
+ /* @__PURE__ */ jsxs("div", { children: [
615
+ /* @__PURE__ */ jsx("h3", { className: "company-name", children: config?.widget_config.company_name }),
616
+ /* @__PURE__ */ jsx("p", { className: "status-text", children: isLoading ? "Yaz\u0131yor..." : "\xC7evrimi\xE7i" })
617
+ ] })
618
+ ] }),
619
+ /* @__PURE__ */ jsxs("div", { className: "messages-container", children: [
620
+ /* @__PURE__ */ jsx(
621
+ HeaderAlert,
622
+ {
623
+ headerValidation,
624
+ setShowAlert,
625
+ showAlert
626
+ }
627
+ ),
628
+ messages.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "empty-state", children: [
629
+ /* @__PURE__ */ jsx("div", { className: "empty-state-icon", children: "\u{1F4AC}" }),
630
+ /* @__PURE__ */ jsx("h4", { className: "empty-state-title", children: config?.widget_config.welcome_message }),
631
+ /* @__PURE__ */ jsx("p", { className: "empty-state-description", children: "A\u015Fa\u011F\u0131daki alana mesaj\u0131n\u0131z\u0131 yazarak ba\u015Flayabilirsiniz." })
632
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
633
+ messages.map((message, index) => /* @__PURE__ */ jsx(
634
+ MessageBubble,
635
+ {
636
+ message,
637
+ onAction: sendMessage
638
+ },
639
+ index
640
+ )),
641
+ config?.widget_config.show_typing_indicator && isLoading && /* @__PURE__ */ jsx(TypingDots, {})
642
+ ] }),
643
+ /* @__PURE__ */ jsx("div", { ref: messagesEndRef })
644
+ ] }),
645
+ /* @__PURE__ */ jsx(
646
+ ChatInput,
647
+ {
648
+ handleSendMessage: sendMessage,
649
+ isLoading,
650
+ placeholder: config?.widget_config.placeholder ?? ""
651
+ }
652
+ )
653
+ ] }) }),
654
+ /* @__PURE__ */ jsx(
655
+ "button",
656
+ {
657
+ onClick: toggleChat,
658
+ className: `floating-button ${config?.widget_config.button_position} button-sizes ${config?.widget_config.button_size} ${isOpen ? "is-open" : ""}`,
659
+ style: { background: config?.widget_config.button_background },
660
+ "aria-label": isOpen ? "Chati kapat" : "Chati a\xE7",
661
+ children: isOpen ? /* @__PURE__ */ jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ 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__ */ jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ 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" }) })
662
+ }
663
+ )
664
+ ] }) });
665
+ };
666
+
667
+ export { AizekChatBot };
668
+ //# sourceMappingURL=index.mjs.map
669
+ //# sourceMappingURL=index.mjs.map