aizek-chatbot 1.0.13 → 1.0.15
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 +628 -1106
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +358 -516
- package/dist/index.css.map +1 -1
- package/dist/index.mjs +779 -1142
- package/dist/index.mjs.map +1 -1
- package/package.json +52 -50
package/dist/index.mjs
CHANGED
|
@@ -1,518 +1,11 @@
|
|
|
1
|
-
import { useState, useEffect
|
|
2
|
-
import
|
|
3
|
-
import ReactMarkdown from
|
|
4
|
-
import remarkGfm from
|
|
5
|
-
import
|
|
6
|
-
import "
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
var instructions = `You are Aizek, an AI assistant running in an environment with Model Context Protocol (MCP) tools.
|
|
10
|
-
|
|
11
|
-
Your top priority is to USE MCP TOOLS whenever they can handle the user's request.
|
|
12
|
-
Do NOT bypass available tools to answer from generic knowledge, web browsing, or other external sources if a suitable MCP tool exists.
|
|
13
|
-
|
|
14
|
-
==================================================
|
|
15
|
-
1. GENERAL BEHAVIOR
|
|
16
|
-
==================================================
|
|
17
|
-
|
|
18
|
-
- Default language: reply in the same language as the user (Turkish/English).
|
|
19
|
-
- Be concise and task-focused. Avoid small talk, philosophy, or meta-chat unless the user explicitly asks.
|
|
20
|
-
- Do not invent capabilities or tools that are not actually defined in the MCP tool list.
|
|
21
|
-
- If a tool call fails or returns an error, explain briefly and either:
|
|
22
|
-
- try again with a corrected call, or
|
|
23
|
-
- ask the user for the minimal extra info required.
|
|
24
|
-
|
|
25
|
-
==================================================
|
|
26
|
-
2. MCP TOOL PRIORITY RULES
|
|
27
|
-
==================================================
|
|
28
|
-
|
|
29
|
-
ALWAYS prefer MCP tools over any other strategy WHEN:
|
|
30
|
-
|
|
31
|
-
- The user asks for information that matches a tool's domain (weather, products, etc.).
|
|
32
|
-
- The user asks to perform an action (create/update/delete something) that an MCP tool can perform.
|
|
33
|
-
|
|
34
|
-
Only if NO provided MCP tool is relevant may you fall back to:
|
|
35
|
-
1) other tools such as web/browsing, or
|
|
36
|
-
2) your own internal knowledge.
|
|
37
|
-
|
|
38
|
-
When deciding whether a tool is relevant:
|
|
39
|
-
- Read the tool name, description, and parameters.
|
|
40
|
-
- If it is even moderately related to what the user wants, you SHOULD try using it.
|
|
41
|
-
- Do NOT choose external (e.g., MGM, random APIs) sources when a matching MCP tool exists.
|
|
42
|
-
|
|
43
|
-
If multiple tools could work:
|
|
44
|
-
- Choose the single BEST-FIT tool first.
|
|
45
|
-
- If the task clearly requires multiple tools (e.g., get weather then log it), you may call them sequentially.
|
|
46
|
-
|
|
47
|
-
==================================================
|
|
48
|
-
3. ACTION TOOLS VS. DRAFTS (IKAS MCP, PRODUCT CREATION)
|
|
49
|
-
==================================================
|
|
50
|
-
|
|
51
|
-
Some MCP tools can PERFORM REAL ACTIONS (e.g., create a product in an e-commerce system via ikas MCP).
|
|
52
|
-
|
|
53
|
-
Critical rule:
|
|
54
|
-
- If the user's intent is to PERFORM an action, you MUST call the appropriate tool.
|
|
55
|
-
- Do NOT just "simulate" the action or write a draft object.
|
|
56
|
-
- Do NOT stop at: "Burada \u015F\xF6yle bir \xFCr\xFCn olu\u015Fturabilirim..." and then not call the tool.
|
|
57
|
-
- The goal is that the side effect actually happens through the tool.
|
|
58
|
-
|
|
59
|
-
Examples (Turkish / ikas):
|
|
60
|
-
|
|
61
|
-
1) User:
|
|
62
|
-
"\u0130kas'ta yeni bir \xFCr\xFCn olu\u015Ftur:
|
|
63
|
-
isim: Siyah T-Shirt,
|
|
64
|
-
fiyat: 299 TL,
|
|
65
|
-
stok: 50,
|
|
66
|
-
kategori: Ti\u015F\xF6rtler."
|
|
67
|
-
|
|
68
|
-
\u2192 You MUST:
|
|
69
|
-
- Map these fields to the ikas product-creation tool schema.
|
|
70
|
-
- CALL the ikas MCP tool to actually create the product.
|
|
71
|
-
- Then answer with something like:
|
|
72
|
-
"\xDCr\xFCn ba\u015Far\u0131yla olu\u015Fturuldu. ID: <tool_output_id>, ad: Siyah T-Shirt, fiyat: 299 TL, stok: 50."
|
|
73
|
-
|
|
74
|
-
\u2192 You MUST NOT:
|
|
75
|
-
- Only respond with a JSON draft or description like:
|
|
76
|
-
"\u015E\xF6yle bir taslak \xFCr\xFCn olu\u015Fturabilirsin: {...}"
|
|
77
|
-
without calling the tool.
|
|
78
|
-
|
|
79
|
-
2) If the tool requires fields that the user didn't provide (e.g. currency code, SKU):
|
|
80
|
-
- Ask ONLY the minimal clarifying question needed.
|
|
81
|
-
- Or, if the field is safely inferrable by convention (e.g. default currency for a given store), use the default.
|
|
82
|
-
|
|
83
|
-
3) If the tool response indicates "draft" vs. "published" status:
|
|
84
|
-
- Respect the user's explicit intention.
|
|
85
|
-
- If the user says "taslak olarak kaydet", then request draft=true.
|
|
86
|
-
- If the user says "direkt yay\u0131na al" or clearly wants the product live, then request published/active status.
|
|
87
|
-
- Do NOT downgrade a clear "publish" intent into just a draft.
|
|
88
|
-
|
|
89
|
-
==================================================
|
|
90
|
-
4. INTERPRETING USER INTENT
|
|
91
|
-
==================================================
|
|
92
|
-
|
|
93
|
-
- Treat verbs like "olu\u015Ftur", "yarat", "ekle", "sil", "g\xFCncelle", "publish et", "yay\u0131na al"
|
|
94
|
-
as strong indicators that an ACTION tool call is expected, not just text output.
|
|
95
|
-
|
|
96
|
-
- Treat questions like "nas\u0131l yap\u0131l\u0131r?", "bana g\xF6ster", "\xF6rnek ver", "JSON tasla\u011F\u0131 olu\u015Ftur"
|
|
97
|
-
as more educational; then you may provide drafts/examples without executing tools,
|
|
98
|
-
UNLESS the user explicitly says they want the real action too.
|
|
99
|
-
|
|
100
|
-
Examples:
|
|
101
|
-
|
|
102
|
-
- "\u0130kas'ta \xFCr\xFCn olu\u015Fturmay\u0131 bana JSON \xF6rne\u011Fiyle anlat\u0131r m\u0131s\u0131n?"
|
|
103
|
-
\u2192 Explain the schema, show a draft, you may skip real tool call unless they also say "ve bunu benim i\xE7in \u015Fimdi olu\u015Ftur."
|
|
104
|
-
|
|
105
|
-
- "Benim ad\u0131ma bu \xFCr\xFCn\xFC ger\xE7ekten olu\u015Ftur ve yay\u0131na al."
|
|
106
|
-
\u2192 This MUST trigger the actual ikas MCP product-creation tool call.
|
|
107
|
-
|
|
108
|
-
==================================================
|
|
109
|
-
5. IRRELEVANT TOPICS & SCOPE
|
|
110
|
-
==================================================
|
|
111
|
-
|
|
112
|
-
- Aizek's primary job in this environment is:
|
|
113
|
-
- Using MCP tools effectively (weather, e-commerce, etc.).
|
|
114
|
-
- Providing concise, helpful answers strictly related to the user's requests.
|
|
115
|
-
|
|
116
|
-
- Avoid:
|
|
117
|
-
- Long off-topic chats.
|
|
118
|
-
- Unnecessary explanations of MCP internals or tool schemas unless the user specifically asks.
|
|
119
|
-
- Using random non-MCP APIs or external services when an MCP tool already exists in that domain.
|
|
120
|
-
|
|
121
|
-
==================================================
|
|
122
|
-
6. TOOL-CALLING STYLE
|
|
123
|
-
==================================================
|
|
124
|
-
|
|
125
|
-
When you decide to call a tool:
|
|
126
|
-
- Use the exact tool name and parameter schema given by the environment.
|
|
127
|
-
- Provide all required parameters; do NOT omit fields the schema marks as required.
|
|
128
|
-
- Prefer a single well-structured call over multiple fragmented ones whenever possible.
|
|
129
|
-
|
|
130
|
-
Once you receive tool results:
|
|
131
|
-
- Summarize them clearly for the user in natural language.
|
|
132
|
-
- If the user requested an action (e.g., create product, update something), confirm:
|
|
133
|
-
- What was done,
|
|
134
|
-
- Any IDs or references returned,
|
|
135
|
-
- Any next steps they might need.
|
|
136
|
-
|
|
137
|
-
==================================================
|
|
138
|
-
7. FALLBACK LOGIC
|
|
139
|
-
==================================================
|
|
140
|
-
|
|
141
|
-
In this order of priority:
|
|
142
|
-
|
|
143
|
-
1) If an MCP tool matches the user's request \u2192 USE IT.
|
|
144
|
-
2) If no tool fits, and the user just needs information \u2192 answer from your own knowledge or other allowed tools.
|
|
145
|
-
3) If the user asks something completely outside your domain/scope \u2192
|
|
146
|
-
- Briefly explain that it is outside Aizek's scope or that you have limited info,
|
|
147
|
-
- Offer to help only if you can still add value without contradicting previous rules.
|
|
148
|
-
|
|
149
|
-
Always keep in mind:
|
|
150
|
-
Your core value in this environment is to be an intelligent router and operator for MCP tools, not a generic, unconstrained chatbot.`;
|
|
151
|
-
var SYSTEM_PROMPT = `
|
|
152
|
-
You are a helpful assistant that can generate both natural language responses and UI components.
|
|
153
|
-
|
|
154
|
-
You MUST:
|
|
155
|
-
- Always respond with normal conversational text.
|
|
156
|
-
- Optionally include one or more UI components inside code blocks with language "ui-component".
|
|
157
|
-
|
|
158
|
-
IMPORTANT:
|
|
159
|
-
- Do NOT invent HTML. Only JSON as described.
|
|
160
|
-
- Keep JSON strictly valid.
|
|
161
|
-
- Text response should be outside of code blocks.
|
|
162
|
-
|
|
163
|
-
STRICT REQUIREMENTS (CRITICAL):
|
|
164
|
-
- All component JSON must STRICTLY MATCH the TypeScript types given below.
|
|
165
|
-
- You MUST NOT create extra fields not defined in the types.
|
|
166
|
-
- You MUST NOT rename keys. Example: using "key" instead of "id" in a form field is INVALID.
|
|
167
|
-
- Only use the exact field names defined in the interfaces below.
|
|
168
|
-
- All JSON must be strictly valid.
|
|
169
|
-
|
|
170
|
-
-------------------------------------------
|
|
171
|
-
TYPES YOU MUST FOLLOW EXACTLY:
|
|
172
|
-
|
|
173
|
-
UIField =
|
|
174
|
-
UITextField | UIImageField | UILinkField | UIBadgeField | UIListField
|
|
175
|
-
|
|
176
|
-
UITextField:
|
|
177
|
-
{
|
|
178
|
-
"type": "text",
|
|
179
|
-
"value": string
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
UIImageField:
|
|
183
|
-
{
|
|
184
|
-
"type": "image",
|
|
185
|
-
"src": string,
|
|
186
|
-
"alt"?: string
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
UILinkField:
|
|
190
|
-
{
|
|
191
|
-
"type": "link",
|
|
192
|
-
"label": string,
|
|
193
|
-
"href": string
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
UIBadgeField:
|
|
197
|
-
{
|
|
198
|
-
"type": "badge",
|
|
199
|
-
"label": string,
|
|
200
|
-
"tone"?: "success" | "warning" | "danger" | "info" | "neutral"
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
UIListField:
|
|
204
|
-
{
|
|
205
|
-
"type": "list",
|
|
206
|
-
"items": UIField[]
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
-------------------------------------------------
|
|
210
|
-
|
|
211
|
-
UIFormData:
|
|
212
|
-
{
|
|
213
|
-
"id": string,
|
|
214
|
-
"title"?: string,
|
|
215
|
-
"fields": UIFormField[],
|
|
216
|
-
"submitLabel"?: string
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
UIFormField:
|
|
220
|
-
{
|
|
221
|
-
"id": string,
|
|
222
|
-
"name": string,
|
|
223
|
-
"label": string,
|
|
224
|
-
"placeholder"?: string,
|
|
225
|
-
"type": "text" | "select" | "number" | "file",
|
|
226
|
-
"accept"?: string,
|
|
227
|
-
"required"?: boolean,
|
|
228
|
-
"validation"?: string,
|
|
229
|
-
"options"?: { "label": string, "value": string }[],
|
|
230
|
-
"value"?: string | number,
|
|
231
|
-
"min"?: number,
|
|
232
|
-
"max"?: number
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
-------------------------------------------------
|
|
236
|
-
|
|
237
|
-
UIButtonData:
|
|
238
|
-
{
|
|
239
|
-
"label": string,
|
|
240
|
-
"value": string,
|
|
241
|
-
"variant"?: "primary" | "secondary" | "danger"
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
-------------------------------------------------
|
|
245
|
-
|
|
246
|
-
UITableData:
|
|
247
|
-
{
|
|
248
|
-
"caption"?: string,
|
|
249
|
-
"columns": UITableColumn[] | string[],
|
|
250
|
-
"rows": Array<Record<string, UIField | string>> | string[][]
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
UITableColumn:
|
|
254
|
-
{
|
|
255
|
-
"id"?: string,
|
|
256
|
-
"key"?: string,
|
|
257
|
-
"label": string,
|
|
258
|
-
"type"?: "image" | "text" | "badge"
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
-------------------------------------------------
|
|
262
|
-
|
|
263
|
-
UICardData:
|
|
264
|
-
{
|
|
265
|
-
"title"?: string,
|
|
266
|
-
"description"?: string,
|
|
267
|
-
"image"?: string,
|
|
268
|
-
"status"?: string,
|
|
269
|
-
"subtitle"?: string,
|
|
270
|
-
"fields"?: UICardField[],
|
|
271
|
-
"attributes"?: UICardField[],
|
|
272
|
-
"items"?: UICardItem[],
|
|
273
|
-
"[key: string]": any
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
UICardField:
|
|
277
|
-
{
|
|
278
|
-
"label": string,
|
|
279
|
-
"value": string
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
UICardItem:
|
|
283
|
-
{
|
|
284
|
-
"id"?: string,
|
|
285
|
-
"title"?: string,
|
|
286
|
-
"subtitle"?: string,
|
|
287
|
-
"image"?: string,
|
|
288
|
-
"label"?: string,
|
|
289
|
-
"value"?: string
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
-------------------------------------------------
|
|
293
|
-
|
|
294
|
-
UIComponent:
|
|
295
|
-
{
|
|
296
|
-
"type": "form" | "buttons" | "table" | "card",
|
|
297
|
-
"data": (the relevant data according to type)
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
-------------------------------------------
|
|
301
|
-
|
|
302
|
-
RULES FOR WHEN TO USE COMPONENTS:
|
|
303
|
-
- User needs to provide multiple structured values \u2192 generate a FORM
|
|
304
|
-
- User must choose among options \u2192 generate BUTTONS
|
|
305
|
-
- User must see structured data comparison \u2192 generate a TABLE
|
|
306
|
-
- User must see entity details/summary \u2192 generate a CARD
|
|
307
|
-
|
|
308
|
-
FORMAT FOR EACH COMPONENT:
|
|
309
|
-
|
|
310
|
-
\`\`\`ui-component
|
|
311
|
-
{
|
|
312
|
-
"type": "...",
|
|
313
|
-
"data": { ... }
|
|
314
|
-
}
|
|
315
|
-
\`\`\`
|
|
316
|
-
`;
|
|
317
|
-
|
|
318
|
-
// src/hooks/use-chatbot.ts
|
|
319
|
-
var useChatbot = (options = {}) => {
|
|
320
|
-
const { mcpUrl, apiKey, config } = options;
|
|
321
|
-
const client = new OpenAI({
|
|
322
|
-
apiKey,
|
|
323
|
-
baseURL: "https://api.anthropic.com/v1/",
|
|
324
|
-
dangerouslyAllowBrowser: true
|
|
325
|
-
});
|
|
326
|
-
const [responseId, setResponseId] = useState(null);
|
|
327
|
-
const [messages, setMessages] = useState([]);
|
|
328
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
329
|
-
const generateId = () => {
|
|
330
|
-
return Date.now().toString() + Math.random().toString(36).substr(2, 9);
|
|
331
|
-
};
|
|
332
|
-
const addMessage = (payload, role) => {
|
|
333
|
-
const newMessage = {
|
|
334
|
-
id: generateId(),
|
|
335
|
-
text: payload.text,
|
|
336
|
-
ui: payload.ui,
|
|
337
|
-
role,
|
|
338
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
339
|
-
};
|
|
340
|
-
setMessages((prev) => [...prev, newMessage]);
|
|
341
|
-
return newMessage;
|
|
342
|
-
};
|
|
343
|
-
const extractUiComponents = (raw) => {
|
|
344
|
-
const regex = /```ui-component([\s\S]*?)```/g;
|
|
345
|
-
const components = [];
|
|
346
|
-
let cleaned = raw;
|
|
347
|
-
let match;
|
|
348
|
-
let componentIndex = 0;
|
|
349
|
-
while ((match = regex.exec(raw)) !== null) {
|
|
350
|
-
const block = match[1].trim();
|
|
351
|
-
try {
|
|
352
|
-
const json = JSON.parse(block);
|
|
353
|
-
if (json.type === "buttons" && json.data && typeof json.data === "object" && !Array.isArray(json.data)) {
|
|
354
|
-
if (json.data.options && Array.isArray(json.data.options)) {
|
|
355
|
-
json.data = json.data.options.map((opt) => {
|
|
356
|
-
if (opt.id && opt.label) {
|
|
357
|
-
return {
|
|
358
|
-
label: opt.label,
|
|
359
|
-
value: opt.id,
|
|
360
|
-
variant: opt.variant
|
|
361
|
-
};
|
|
362
|
-
}
|
|
363
|
-
return opt;
|
|
364
|
-
});
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
if (json.type === "table" && json.data) {
|
|
368
|
-
if (Array.isArray(json.data.columns) && json.data.columns.length > 0) {
|
|
369
|
-
const firstCol = json.data.columns[0];
|
|
370
|
-
if (typeof firstCol === "string") {
|
|
371
|
-
json.data.columns = json.data.columns.map(
|
|
372
|
-
(col, idx) => ({
|
|
373
|
-
id: `col-${idx}`,
|
|
374
|
-
label: col
|
|
375
|
-
})
|
|
376
|
-
);
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
if (Array.isArray(json.data.rows) && json.data.rows.length > 0) {
|
|
380
|
-
const firstRow = json.data.rows[0];
|
|
381
|
-
if (Array.isArray(firstRow) && typeof firstRow[0] === "string") {
|
|
382
|
-
json.data.rows = json.data.rows.map((row) => {
|
|
383
|
-
const rowObj = {};
|
|
384
|
-
json.data.columns.forEach((col, idx) => {
|
|
385
|
-
const colId = typeof col === "string" ? `col-${idx}` : col.id;
|
|
386
|
-
const cellValue = row[idx];
|
|
387
|
-
if (typeof cellValue === "string" && (cellValue.startsWith("http") || cellValue.startsWith("data:"))) {
|
|
388
|
-
rowObj[colId] = {
|
|
389
|
-
type: "image",
|
|
390
|
-
src: cellValue,
|
|
391
|
-
alt: ""
|
|
392
|
-
};
|
|
393
|
-
} else {
|
|
394
|
-
rowObj[colId] = {
|
|
395
|
-
type: "text",
|
|
396
|
-
value: cellValue || ""
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
});
|
|
400
|
-
return rowObj;
|
|
401
|
-
});
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
if (json.type === "form" && json.data) {
|
|
406
|
-
if (!json.data.id) {
|
|
407
|
-
json.data.id = json.id || `form-${componentIndex}`;
|
|
408
|
-
}
|
|
409
|
-
if (json.data.fields && Array.isArray(json.data.fields)) {
|
|
410
|
-
json.data.fields = json.data.fields.map((field) => {
|
|
411
|
-
if (field.optional !== void 0) {
|
|
412
|
-
field.required = !field.optional;
|
|
413
|
-
delete field.optional;
|
|
414
|
-
}
|
|
415
|
-
if (!field.type) {
|
|
416
|
-
field.type = "text";
|
|
417
|
-
}
|
|
418
|
-
if (field.options && Array.isArray(field.options)) {
|
|
419
|
-
const firstOption = field.options[0];
|
|
420
|
-
if (typeof firstOption === "string") {
|
|
421
|
-
field.options = field.options.map((opt) => ({
|
|
422
|
-
label: opt,
|
|
423
|
-
value: opt
|
|
424
|
-
}));
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
return field;
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
if (json.id && typeof json.id !== "string") {
|
|
432
|
-
json.id = String(json.id);
|
|
433
|
-
}
|
|
434
|
-
if (!json.id || !json.id.trim()) {
|
|
435
|
-
json.id = `ui-comp-${componentIndex}-${Date.now()}`;
|
|
436
|
-
}
|
|
437
|
-
components.push(json);
|
|
438
|
-
componentIndex++;
|
|
439
|
-
} catch (e) {
|
|
440
|
-
console.error("Invalid ui-component JSON:", e, block);
|
|
441
|
-
}
|
|
442
|
-
cleaned = cleaned.replace(match[0], "").trim();
|
|
443
|
-
}
|
|
444
|
-
return { text: cleaned, components };
|
|
445
|
-
};
|
|
446
|
-
const sendMessage = async (message, approval) => {
|
|
447
|
-
if (!message.trim() || isLoading) return;
|
|
448
|
-
if (approval) {
|
|
449
|
-
addMessage({ text: message }, "approval");
|
|
450
|
-
} else {
|
|
451
|
-
addMessage({ text: message }, "user");
|
|
452
|
-
}
|
|
453
|
-
setIsLoading(true);
|
|
454
|
-
try {
|
|
455
|
-
let resp;
|
|
456
|
-
resp = await client.responses.create({
|
|
457
|
-
model: "claude-sonnet-4-5",
|
|
458
|
-
tools: [
|
|
459
|
-
{
|
|
460
|
-
type: "mcp",
|
|
461
|
-
server_label: "aizek-mcp",
|
|
462
|
-
server_url: mcpUrl,
|
|
463
|
-
require_approval: "never",
|
|
464
|
-
headers: options.headers || {}
|
|
465
|
-
}
|
|
466
|
-
],
|
|
467
|
-
input: [
|
|
468
|
-
{ role: "system", content: SYSTEM_PROMPT },
|
|
469
|
-
{ role: "user", content: message }
|
|
470
|
-
],
|
|
471
|
-
previous_response_id: responseId || void 0,
|
|
472
|
-
instructions
|
|
473
|
-
});
|
|
474
|
-
console.log("Response:", resp);
|
|
475
|
-
setResponseId(resp.id);
|
|
476
|
-
let rawText = "";
|
|
477
|
-
const output = resp.output;
|
|
478
|
-
if (Array.isArray(output) && output.length > 0) {
|
|
479
|
-
const assistantMsg = output.find((o) => o.role === "assistant") ?? output[0];
|
|
480
|
-
if (assistantMsg && Array.isArray(assistantMsg.content)) {
|
|
481
|
-
const textItem = assistantMsg.content.find(
|
|
482
|
-
(c) => c.type === "output_text"
|
|
483
|
-
);
|
|
484
|
-
if (textItem?.text?.value) {
|
|
485
|
-
rawText = textItem.text.value;
|
|
486
|
-
} else if (textItem?.text?.annotations?.[0]?.text) {
|
|
487
|
-
rawText = textItem.text.annotations[0].text;
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
if (!rawText && resp.output_text) {
|
|
492
|
-
rawText = resp.output_text;
|
|
493
|
-
}
|
|
494
|
-
if (!rawText) {
|
|
495
|
-
rawText = `"${message}" mesaj\u0131n\u0131z\u0131 ald\u0131m. Size nas\u0131l yard\u0131mc\u0131 olabilirim?`;
|
|
496
|
-
}
|
|
497
|
-
const { text, components } = extractUiComponents(rawText);
|
|
498
|
-
addMessage({ text, ui: components }, "assistant");
|
|
499
|
-
setIsLoading(false);
|
|
500
|
-
} catch (error) {
|
|
501
|
-
console.error("Error sending message:", error);
|
|
502
|
-
addMessage(
|
|
503
|
-
{ text: "\xDCzg\xFCn\xFCm, bir hata olu\u015Ftu. L\xFCtfen tekrar deneyin." },
|
|
504
|
-
"assistant"
|
|
505
|
-
);
|
|
506
|
-
setIsLoading(false);
|
|
507
|
-
}
|
|
508
|
-
};
|
|
509
|
-
return {
|
|
510
|
-
messages,
|
|
511
|
-
isLoading,
|
|
512
|
-
sendMessage,
|
|
513
|
-
addMessage
|
|
514
|
-
};
|
|
515
|
-
};
|
|
1
|
+
import { useRef, useState, useEffect } from "react";
|
|
2
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
3
|
+
import ReactMarkdown from "react-markdown";
|
|
4
|
+
import remarkGfm from "remark-gfm";
|
|
5
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
6
|
+
import { Client } from "@modelcontextprotocol/sdk/client";
|
|
7
|
+
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
8
|
+
import "./index.css";
|
|
516
9
|
|
|
517
10
|
// src/services/chat-widget-api.ts
|
|
518
11
|
var API_BASE_URL = "https://api-alpha.aizek.ai";
|
|
@@ -521,8 +14,8 @@ var fetchChatWidgetSettings = async (clientId) => {
|
|
|
521
14
|
const response = await fetch(`${API_BASE_URL}/ChatWidgetSettings/GetByClientId?client_id=${clientId}`, {
|
|
522
15
|
method: "GET",
|
|
523
16
|
headers: {
|
|
524
|
-
"Content-Type": "application/json"
|
|
525
|
-
}
|
|
17
|
+
"Content-Type": "application/json",
|
|
18
|
+
},
|
|
526
19
|
});
|
|
527
20
|
if (!response.ok) {
|
|
528
21
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
@@ -534,35 +27,11 @@ var fetchChatWidgetSettings = async (clientId) => {
|
|
|
534
27
|
throw error;
|
|
535
28
|
}
|
|
536
29
|
};
|
|
537
|
-
var mapApiSettingsToConfig = (apiSettings) => {
|
|
538
|
-
if (!apiSettings) {
|
|
539
|
-
return null;
|
|
540
|
-
}
|
|
541
|
-
const buttonSizeMap = {
|
|
542
|
-
"small": "sm",
|
|
543
|
-
"medium": "md",
|
|
544
|
-
"large": "lg"
|
|
545
|
-
};
|
|
546
|
-
return {
|
|
547
|
-
welcomeMessage: apiSettings.welcome_message,
|
|
548
|
-
buttonBackground: apiSettings.button_background,
|
|
549
|
-
placeholder: apiSettings.placeholder,
|
|
550
|
-
buttonPosition: apiSettings.button_position,
|
|
551
|
-
buttonSize: buttonSizeMap[apiSettings.button_size] || "md",
|
|
552
|
-
chatWidth: apiSettings.chat_width,
|
|
553
|
-
chatHeight: apiSettings.chat_height,
|
|
554
|
-
showTypingIndicator: apiSettings.show_typing_indicator,
|
|
555
|
-
initialOpen: apiSettings.initial_open,
|
|
556
|
-
headerBackground: apiSettings.header_background,
|
|
557
|
-
companyLogo: apiSettings.company_logo || void 0,
|
|
558
|
-
companyName: apiSettings.company_name
|
|
559
|
-
};
|
|
560
|
-
};
|
|
561
30
|
|
|
562
31
|
// src/utils/cx.ts
|
|
563
32
|
function validateHeaders(headers, authConfig, opts = {}) {
|
|
564
33
|
const { caseSensitive = false, allowExtra = false } = opts;
|
|
565
|
-
const normalize = (s) => caseSensitive ? s : s.toLowerCase();
|
|
34
|
+
const normalize = (s) => (caseSensitive ? s : s.toLowerCase());
|
|
566
35
|
const headerEntries = Object.entries(headers).map(([k, v]) => [normalize(k), v.trim()]);
|
|
567
36
|
const authEntries = Object.entries(authConfig).map(([k, v]) => [normalize(k), v.trim()]);
|
|
568
37
|
const headerKeys = headerEntries.map(([k]) => k);
|
|
@@ -579,663 +48,831 @@ function validateHeaders(headers, authConfig, opts = {}) {
|
|
|
579
48
|
const isValid = hasAllRequired && !hasExtraKeys && emptyValueKeys.length === 0;
|
|
580
49
|
return { isValid, missingKeys, extraKeys, emptyValueKeys };
|
|
581
50
|
}
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
51
|
+
|
|
52
|
+
// src/store/static.ts
|
|
53
|
+
var defaultConfig = {
|
|
54
|
+
auth_config: {
|
|
55
|
+
header: "",
|
|
56
|
+
},
|
|
57
|
+
chat_widget_settings: {
|
|
58
|
+
welcome_message: "Merhaba! Size nas\u0131l yard\u0131mc\u0131 olabilirim?",
|
|
59
|
+
button_background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
|
|
60
|
+
placeholder: "Mesaj\u0131n\u0131z\u0131 yaz\u0131n...",
|
|
61
|
+
button_position: "bottom-left",
|
|
62
|
+
button_size: "medium",
|
|
63
|
+
chat_width: "400px",
|
|
64
|
+
chat_height: "600px",
|
|
65
|
+
show_typing_indicator: true,
|
|
66
|
+
initial_open: true,
|
|
67
|
+
header_background: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
|
|
68
|
+
company_logo: "",
|
|
69
|
+
company_name: "Aizek",
|
|
70
|
+
api_source_id: 0,
|
|
71
|
+
chat_widget_settings_id: 0,
|
|
72
|
+
created_at: "",
|
|
73
|
+
updated_at: "",
|
|
74
|
+
},
|
|
75
|
+
mcp_url: "",
|
|
76
|
+
openai_key: "",
|
|
77
|
+
};
|
|
78
|
+
var GENERATIVE_UI_SYSTEM_PROMPT = `
|
|
79
|
+
You can generate interactive UI components as part of your responses.
|
|
80
|
+
When users need to:
|
|
81
|
+
- Provide multiple pieces of information \u2192 Generate a FORM
|
|
82
|
+
- Make a choice between options \u2192 Generate BUTTONS
|
|
83
|
+
- View structured data \u2192 Generate a TABLE or LIST
|
|
84
|
+
- See entity details \u2192 Generate a CARD
|
|
85
|
+
|
|
86
|
+
For each component type, include JSON in this format:
|
|
87
|
+
|
|
88
|
+
\`\`\`ui-component
|
|
89
|
+
{
|
|
90
|
+
"version": "1.0",
|
|
91
|
+
"title": string,
|
|
92
|
+
"description"?: string,
|
|
93
|
+
"components": Array<{
|
|
94
|
+
id: string,
|
|
95
|
+
type:
|
|
96
|
+
| "text"
|
|
97
|
+
| "input"
|
|
98
|
+
| "button"
|
|
99
|
+
| "select"
|
|
100
|
+
| "card"
|
|
101
|
+
| "list"
|
|
102
|
+
| "image"
|
|
103
|
+
| "link"
|
|
104
|
+
| "table"
|
|
105
|
+
| "form",
|
|
106
|
+
label?: string,
|
|
107
|
+
fieldType?: "text" | "number" | "date" | "textarea",
|
|
108
|
+
requiredField?: boolean,
|
|
109
|
+
placeholder?: string,
|
|
110
|
+
options?: string[],
|
|
111
|
+
columns?: string[],
|
|
112
|
+
rows?: string[][],
|
|
113
|
+
url?: string,
|
|
114
|
+
fieldName?: string
|
|
115
|
+
buttonType?: click | submit
|
|
116
|
+
}>
|
|
613
117
|
}
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
alt: data.title || "Card image",
|
|
628
|
-
className: "card-image",
|
|
629
|
-
onError: (e) => {
|
|
630
|
-
e.target.style.display = "none";
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
),
|
|
634
|
-
/* @__PURE__ */ jsxs("div", { className: "card-info", children: [
|
|
635
|
-
/* @__PURE__ */ jsx("h4", { className: "card-title", children: data.title }),
|
|
636
|
-
hasStatus && /* @__PURE__ */ jsxs("div", { className: "card-status", children: [
|
|
637
|
-
/* @__PURE__ */ jsx("span", { className: "card-status-label", children: "Durum:" }),
|
|
638
|
-
/* @__PURE__ */ jsx("span", { className: "card-status-value", children: data.status })
|
|
639
|
-
] }),
|
|
640
|
-
hasSubtitle && /* @__PURE__ */ jsx("p", { className: "card-subtitle", children: data.subtitle }),
|
|
641
|
-
displayFields && displayFields.length > 0 && /* @__PURE__ */ jsx("div", { className: "card-fields", children: displayFields.map((field, i) => /* @__PURE__ */ jsxs("div", { className: "card-field", children: [
|
|
642
|
-
/* @__PURE__ */ jsxs("span", { className: "card-field-label", children: [
|
|
643
|
-
field.label,
|
|
644
|
-
":"
|
|
645
|
-
] }),
|
|
646
|
-
/* @__PURE__ */ jsx("span", { className: "card-field-value", children: field.value })
|
|
647
|
-
] }, i)) }),
|
|
648
|
-
data.description && /* @__PURE__ */ jsx("p", { className: "card-description", children: data.description })
|
|
649
|
-
] })
|
|
650
|
-
] }) });
|
|
651
|
-
}
|
|
652
|
-
if (!data.items || !Array.isArray(data.items) || data.items.length === 0) {
|
|
118
|
+
\`\`\`
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
Always provide both a conversational text response AND appropriate UI components.
|
|
125
|
+
|
|
126
|
+
`;
|
|
127
|
+
var HeaderAlert = ({ headerValidation, showAlert, setShowAlert }) => {
|
|
128
|
+
if (!headerValidation || !showAlert) return null;
|
|
129
|
+
const { isValid, missingKeys, extraKeys, emptyValueKeys } = headerValidation;
|
|
130
|
+
if (isValid && missingKeys.length === 0 && extraKeys.length === 0 && emptyValueKeys.length === 0) {
|
|
653
131
|
return null;
|
|
654
132
|
}
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
133
|
+
const hasErrors = missingKeys.length > 0 || emptyValueKeys.length > 0;
|
|
134
|
+
const hasWarnings = extraKeys.length > 0;
|
|
135
|
+
const alertType = hasErrors ? "error" : "warning";
|
|
136
|
+
const getAlertIcon = () => {
|
|
137
|
+
if (hasErrors) {
|
|
138
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
139
|
+
width: "20",
|
|
140
|
+
height: "20",
|
|
141
|
+
viewBox: "0 0 24 24",
|
|
142
|
+
fill: "currentColor",
|
|
143
|
+
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" }),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
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" }) });
|
|
147
|
+
};
|
|
148
|
+
return /* @__PURE__ */ jsx(Fragment, {
|
|
149
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
150
|
+
className: `alert-container ${alertType}`,
|
|
151
|
+
children: [
|
|
152
|
+
/* @__PURE__ */ jsx("div", { className: "alert-icon-container", children: getAlertIcon() }),
|
|
153
|
+
/* @__PURE__ */ jsxs("div", {
|
|
154
|
+
className: "alert-content",
|
|
155
|
+
children: [
|
|
156
|
+
/* @__PURE__ */ jsx("h4", { className: "alert-title", children: hasErrors ? "Header Do\u011Frulama Hatas\u0131" : "Header Uyar\u0131s\u0131" }),
|
|
157
|
+
/* @__PURE__ */ jsx("p", {
|
|
158
|
+
className: "alert-message",
|
|
159
|
+
children:
|
|
160
|
+
hasErrors && hasWarnings
|
|
161
|
+
? "Header yap\u0131land\u0131rman\u0131zda hatalar ve uyar\u0131lar bulundu."
|
|
162
|
+
: hasErrors
|
|
163
|
+
? "Header yap\u0131land\u0131rman\u0131zda hatalar bulundu."
|
|
164
|
+
: "Header yap\u0131land\u0131rman\u0131zda fazla anahtarlar bulundu.",
|
|
165
|
+
}),
|
|
166
|
+
missingKeys.length > 0 &&
|
|
167
|
+
/* @__PURE__ */ jsxs("div", {
|
|
168
|
+
children: [
|
|
169
|
+
/* @__PURE__ */ jsx("strong", { children: "Eksik Header'lar:" }),
|
|
170
|
+
/* @__PURE__ */ jsx("ul", {
|
|
171
|
+
className: "alert-list",
|
|
172
|
+
children: missingKeys.map((key, index) => /* @__PURE__ */ jsxs("li", { className: "alert-list-item", children: [/* @__PURE__ */ jsx("span", { children: "\u2022" }), /* @__PURE__ */ jsx("code", { children: key })] }, index)),
|
|
173
|
+
}),
|
|
174
|
+
],
|
|
175
|
+
}),
|
|
176
|
+
emptyValueKeys.length > 0 &&
|
|
177
|
+
/* @__PURE__ */ jsxs("div", {
|
|
178
|
+
children: [
|
|
179
|
+
/* @__PURE__ */ jsx("strong", { children: "Bo\u015F De\u011Ferli Header'lar:" }),
|
|
180
|
+
/* @__PURE__ */ jsx("ul", {
|
|
181
|
+
className: "alert-list",
|
|
182
|
+
children: emptyValueKeys.map((key, index) =>
|
|
183
|
+
/* @__PURE__ */ jsxs(
|
|
184
|
+
"li",
|
|
185
|
+
{ className: "alert-list-item", children: [/* @__PURE__ */ jsx("span", { children: "\u2022" }), /* @__PURE__ */ jsx("code", { children: key }), /* @__PURE__ */ jsx("span", { children: "(de\u011Fer bo\u015F olamaz)" })] },
|
|
186
|
+
index
|
|
187
|
+
)
|
|
188
|
+
),
|
|
189
|
+
}),
|
|
190
|
+
],
|
|
191
|
+
}),
|
|
192
|
+
extraKeys.length > 0 &&
|
|
193
|
+
/* @__PURE__ */ jsxs("div", {
|
|
194
|
+
children: [
|
|
195
|
+
/* @__PURE__ */ jsx("strong", { children: "Fazla Header'lar:" }),
|
|
196
|
+
/* @__PURE__ */ jsx("ul", {
|
|
197
|
+
className: "alert-list",
|
|
198
|
+
children: extraKeys.map((key, index) => /* @__PURE__ */ jsxs("li", { className: "alert-list-item", children: [/* @__PURE__ */ jsx("span", { children: "\u2022" }), /* @__PURE__ */ jsx("code", { children: key })] }, index)),
|
|
199
|
+
}),
|
|
200
|
+
],
|
|
201
|
+
}),
|
|
202
|
+
],
|
|
203
|
+
}),
|
|
204
|
+
/* @__PURE__ */ jsx("button", {
|
|
205
|
+
onClick: () => setShowAlert(false),
|
|
206
|
+
className: "alert-close-button",
|
|
207
|
+
"aria-label": "Uyar\u0131y\u0131 kapat",
|
|
208
|
+
children: /* @__PURE__ */ jsx("svg", {
|
|
209
|
+
width: "16",
|
|
210
|
+
height: "16",
|
|
211
|
+
viewBox: "0 0 24 24",
|
|
212
|
+
fill: "currentColor",
|
|
213
|
+
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" }),
|
|
214
|
+
}),
|
|
215
|
+
}),
|
|
216
|
+
],
|
|
217
|
+
}),
|
|
218
|
+
});
|
|
219
|
+
};
|
|
220
|
+
var LoadingSpinner = () => {
|
|
221
|
+
return /* @__PURE__ */ jsx("div", { className: "loading-spinner" });
|
|
222
|
+
};
|
|
223
|
+
var ChatInput = ({ isLoading, placeholder, handleSendMessage }) => {
|
|
224
|
+
const [message, setMessage] = useState("");
|
|
225
|
+
const textareaRef = useRef(null);
|
|
694
226
|
const handleSubmit = (e) => {
|
|
695
227
|
e.preventDefault();
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
if (f.type === "file") {
|
|
702
|
-
const file = formData.get(fieldName);
|
|
703
|
-
values[fieldName] = JSON.stringify({
|
|
704
|
-
name: file?.name,
|
|
705
|
-
size: file?.size,
|
|
706
|
-
type: file?.type
|
|
707
|
-
});
|
|
228
|
+
if (message.trim() && !isLoading) {
|
|
229
|
+
handleSendMessage(message.trim());
|
|
230
|
+
setMessage("");
|
|
231
|
+
if (textareaRef.current) {
|
|
232
|
+
textareaRef.current.style.height = "auto";
|
|
708
233
|
}
|
|
709
|
-
}
|
|
710
|
-
console.log(values);
|
|
711
|
-
onSubmit(values);
|
|
234
|
+
}
|
|
712
235
|
};
|
|
713
|
-
|
|
714
|
-
"
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
className: "form-component",
|
|
718
|
-
children: [
|
|
719
|
-
data.title && /* @__PURE__ */ jsx("h3", { className: "form-title", children: data.title }),
|
|
720
|
-
/* @__PURE__ */ jsx("div", { className: "form-fields", children: data.fields.map((field, fieldIdx) => {
|
|
721
|
-
return /* @__PURE__ */ jsxs("div", { className: "form-field", children: [
|
|
722
|
-
/* @__PURE__ */ jsxs("label", { className: "form-label", children: [
|
|
723
|
-
field.label,
|
|
724
|
-
field.required && /* @__PURE__ */ jsx("span", { children: "*" })
|
|
725
|
-
] }),
|
|
726
|
-
field.type === "select" ? /* @__PURE__ */ jsxs(
|
|
727
|
-
"select",
|
|
728
|
-
{
|
|
729
|
-
name: field.id || field.name,
|
|
730
|
-
required: field.required,
|
|
731
|
-
defaultValue: field.value ? String(field.value) : "",
|
|
732
|
-
className: "form-select",
|
|
733
|
-
children: [
|
|
734
|
-
/* @__PURE__ */ jsx("option", { value: "", children: "Se\xE7iniz" }),
|
|
735
|
-
field.options?.map((opt, optIdx) => {
|
|
736
|
-
const optKey = typeof opt.value === "string" ? opt.value : `opt-${fieldIdx}-${optIdx}`;
|
|
737
|
-
return /* @__PURE__ */ jsx("option", { value: opt.value, children: opt.label }, optKey);
|
|
738
|
-
})
|
|
739
|
-
]
|
|
740
|
-
}
|
|
741
|
-
) : field.type === "file" ? /* @__PURE__ */ jsx(
|
|
742
|
-
"input",
|
|
743
|
-
{
|
|
744
|
-
type: "file",
|
|
745
|
-
name: field.id || field.name,
|
|
746
|
-
required: field.required,
|
|
747
|
-
className: "form-input",
|
|
748
|
-
accept: field.accept || "*"
|
|
749
|
-
}
|
|
750
|
-
) : /* @__PURE__ */ jsx(
|
|
751
|
-
"input",
|
|
752
|
-
{
|
|
753
|
-
type: field.type === "number" ? "number" : "text",
|
|
754
|
-
name: field.id || field.name,
|
|
755
|
-
required: field.required,
|
|
756
|
-
defaultValue: field.value ? String(field.value) : "",
|
|
757
|
-
placeholder: field.placeholder || "",
|
|
758
|
-
min: field.min,
|
|
759
|
-
max: field.max,
|
|
760
|
-
className: "form-input"
|
|
761
|
-
}
|
|
762
|
-
)
|
|
763
|
-
] }, fieldIdx);
|
|
764
|
-
}) }),
|
|
765
|
-
/* @__PURE__ */ jsx("button", { type: "submit", className: "form-submit-button", children: data.submitLabel ?? "G\xF6nder" })
|
|
766
|
-
]
|
|
236
|
+
const handleKeyDown = (e) => {
|
|
237
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
238
|
+
e.preventDefault();
|
|
239
|
+
handleSubmit(e);
|
|
767
240
|
}
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
}) }) }),
|
|
815
|
-
/* @__PURE__ */ jsx("tbody", { className: "table-tbody", children: data.rows && data.rows.length > 0 ? data.rows.map((row, rowIdx) => /* @__PURE__ */ jsx("tr", { children: data.columns.map((col, colIdx) => {
|
|
816
|
-
const colKey = typeof col === "string" ? `col-${colIdx}` : col.key || col.id || `col-${colIdx}`;
|
|
817
|
-
const colType = typeof col === "object" ? col.type : void 0;
|
|
818
|
-
const cellKey = `cell-${rowIdx}-${colIdx}`;
|
|
819
|
-
let cellContent = null;
|
|
820
|
-
if (typeof row === "object" && row !== null && !Array.isArray(row)) {
|
|
821
|
-
const cellValue = row[colKey];
|
|
822
|
-
if (cellValue !== void 0 && cellValue !== null) {
|
|
823
|
-
if (typeof cellValue === "object" && "type" in cellValue) {
|
|
824
|
-
cellContent = renderField(cellValue);
|
|
825
|
-
} else {
|
|
826
|
-
const stringValue = String(cellValue);
|
|
827
|
-
const isImageUrl = typeof stringValue === "string" && (stringValue.startsWith("http") || stringValue.startsWith("data:") || stringValue.startsWith("/")) && (stringValue.match(
|
|
828
|
-
/\.(jpg|jpeg|png|gif|webp|svg)$/i
|
|
829
|
-
) || stringValue.includes("image") || stringValue.includes("avatar"));
|
|
830
|
-
if (colType === "image" || !colType && isImageUrl) {
|
|
831
|
-
cellContent = /* @__PURE__ */ jsx("div", { className: "table-cell-image", children: /* @__PURE__ */ jsx(
|
|
832
|
-
"img",
|
|
833
|
-
{
|
|
834
|
-
src: stringValue,
|
|
835
|
-
alt: "",
|
|
836
|
-
className: "table-image",
|
|
837
|
-
onError: (e) => {
|
|
838
|
-
e.target.style.display = "none";
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
) });
|
|
842
|
-
} else {
|
|
843
|
-
cellContent = /* @__PURE__ */ jsx("span", { className: "table-cell-text", children: stringValue });
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
} else if (Array.isArray(row)) {
|
|
848
|
-
const cellValue = row[colIdx];
|
|
849
|
-
if (cellValue !== void 0 && cellValue !== null) {
|
|
850
|
-
const stringValue = String(cellValue);
|
|
851
|
-
const isImageUrl = typeof stringValue === "string" && (stringValue.startsWith("http") || stringValue.startsWith("data:") || stringValue.startsWith("/")) && (stringValue.match(
|
|
852
|
-
/\.(jpg|jpeg|png|gif|webp|svg)$/i
|
|
853
|
-
) || stringValue.includes("image") || stringValue.includes("avatar"));
|
|
854
|
-
if (colType === "image" || !colType && isImageUrl) {
|
|
855
|
-
cellContent = /* @__PURE__ */ jsx("div", { className: "table-cell-image", children: /* @__PURE__ */ jsx(
|
|
856
|
-
"img",
|
|
857
|
-
{
|
|
858
|
-
src: stringValue,
|
|
859
|
-
alt: "",
|
|
860
|
-
className: "table-image",
|
|
861
|
-
onError: (e) => {
|
|
862
|
-
e.target.style.display = "none";
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
) });
|
|
866
|
-
} else {
|
|
867
|
-
cellContent = /* @__PURE__ */ jsx("span", { className: "table-cell-text", children: stringValue });
|
|
868
|
-
}
|
|
241
|
+
};
|
|
242
|
+
const handleInputChange = (e) => {
|
|
243
|
+
setMessage(e.target.value);
|
|
244
|
+
const textarea = e.target;
|
|
245
|
+
textarea.style.height = "auto";
|
|
246
|
+
textarea.style.height = Math.min(textarea.scrollHeight, 120) + "px";
|
|
247
|
+
};
|
|
248
|
+
return /* @__PURE__ */ jsxs("form", {
|
|
249
|
+
onSubmit: handleSubmit,
|
|
250
|
+
className: "input-container",
|
|
251
|
+
children: [
|
|
252
|
+
/* @__PURE__ */ jsx("textarea", {
|
|
253
|
+
ref: textareaRef,
|
|
254
|
+
value: message,
|
|
255
|
+
onChange: handleInputChange,
|
|
256
|
+
onKeyDown: handleKeyDown,
|
|
257
|
+
placeholder,
|
|
258
|
+
disabled: isLoading,
|
|
259
|
+
className: "textarea",
|
|
260
|
+
}),
|
|
261
|
+
/* @__PURE__ */ jsx("button", {
|
|
262
|
+
type: "submit",
|
|
263
|
+
disabled: isLoading || !message.trim(),
|
|
264
|
+
className: "send-button",
|
|
265
|
+
children: isLoading
|
|
266
|
+
? /* @__PURE__ */ jsx(LoadingSpinner, {})
|
|
267
|
+
: /* @__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" }) }),
|
|
268
|
+
}),
|
|
269
|
+
],
|
|
270
|
+
});
|
|
271
|
+
};
|
|
272
|
+
var GenericUIRenderer = ({ uiData, onInteraction }) => {
|
|
273
|
+
const containerRef = useRef(null);
|
|
274
|
+
if (!uiData || !uiData.components) return null;
|
|
275
|
+
const collectFormValues = () => {
|
|
276
|
+
if (!containerRef.current) return {};
|
|
277
|
+
const formData = {};
|
|
278
|
+
const inputs = containerRef.current.querySelectorAll("input, textarea, select");
|
|
279
|
+
inputs.forEach((element) => {
|
|
280
|
+
const name = element.getAttribute("name");
|
|
281
|
+
if (name) {
|
|
282
|
+
if (element instanceof HTMLInputElement && element.type === "checkbox") {
|
|
283
|
+
formData[name] = element.checked;
|
|
284
|
+
} else if (element instanceof HTMLInputElement && element.type === "radio") {
|
|
285
|
+
if (element.checked) {
|
|
286
|
+
formData[name] = element.value;
|
|
869
287
|
}
|
|
288
|
+
} else {
|
|
289
|
+
formData[name] = element.value;
|
|
870
290
|
}
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
function GenerativeUI({ components, onInteraction }) {
|
|
877
|
-
console.log(components);
|
|
878
|
-
if (!Array.isArray(components) || components.length === 0) {
|
|
879
|
-
return null;
|
|
880
|
-
}
|
|
881
|
-
return /* @__PURE__ */ jsx("div", { className: "ui-renderer", children: components.map((comp, idx) => {
|
|
882
|
-
if (!comp || typeof comp !== "object" || !comp.type) {
|
|
883
|
-
return null;
|
|
884
|
-
}
|
|
885
|
-
const key = typeof comp.id === "string" && comp.id.trim() ? comp.id : `${comp.type}-${idx}`;
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
return formData;
|
|
294
|
+
};
|
|
295
|
+
const renderComponent = (comp) => {
|
|
886
296
|
switch (comp.type) {
|
|
887
|
-
case "
|
|
297
|
+
case "text":
|
|
298
|
+
return /* @__PURE__ */ jsx("p", { className: "gen-ui-text", children: comp.value ?? comp.label }, comp.id);
|
|
299
|
+
case "input":
|
|
300
|
+
return /* @__PURE__ */ jsxs(
|
|
301
|
+
"div",
|
|
302
|
+
{
|
|
303
|
+
className: "gen-ui-input-wrapper",
|
|
304
|
+
children: [
|
|
305
|
+
comp.label && /* @__PURE__ */ jsx("label", { className: "gen-ui-input-label", children: comp.label }),
|
|
306
|
+
comp.fieldType === "textarea"
|
|
307
|
+
? /* @__PURE__ */ jsx("textarea", {
|
|
308
|
+
name: comp.id,
|
|
309
|
+
placeholder: comp.placeholder,
|
|
310
|
+
className: "gen-ui-textarea",
|
|
311
|
+
})
|
|
312
|
+
: /* @__PURE__ */ jsx("input", {
|
|
313
|
+
name: comp.id,
|
|
314
|
+
type: comp.fieldType || "text",
|
|
315
|
+
placeholder: comp.placeholder,
|
|
316
|
+
className: "gen-ui-input",
|
|
317
|
+
}),
|
|
318
|
+
],
|
|
319
|
+
},
|
|
320
|
+
comp.id
|
|
321
|
+
);
|
|
322
|
+
case "select":
|
|
323
|
+
return /* @__PURE__ */ jsxs(
|
|
324
|
+
"div",
|
|
325
|
+
{
|
|
326
|
+
className: "gen-ui-select-wrapper",
|
|
327
|
+
children: [
|
|
328
|
+
comp.label && /* @__PURE__ */ jsx("label", { className: "gen-ui-select-label", children: comp.label }),
|
|
329
|
+
/* @__PURE__ */ jsx("select", { name: comp.id, className: "gen-ui-select", children: comp.options?.map((opt) => /* @__PURE__ */ jsx("option", { value: opt, children: opt }, opt)) }),
|
|
330
|
+
],
|
|
331
|
+
},
|
|
332
|
+
comp.id
|
|
333
|
+
);
|
|
334
|
+
case "button":
|
|
888
335
|
return /* @__PURE__ */ jsx(
|
|
889
|
-
|
|
336
|
+
"button",
|
|
890
337
|
{
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
338
|
+
onClick: () => {
|
|
339
|
+
const formValues = collectFormValues();
|
|
340
|
+
onInteraction({
|
|
341
|
+
action: comp.label,
|
|
342
|
+
buttonId: comp.buttonType,
|
|
343
|
+
formData: formValues,
|
|
344
|
+
});
|
|
345
|
+
},
|
|
346
|
+
className: "gen-ui-button",
|
|
347
|
+
children: comp.label,
|
|
897
348
|
},
|
|
898
|
-
|
|
349
|
+
comp.id
|
|
899
350
|
);
|
|
900
|
-
case "
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
351
|
+
case "card":
|
|
352
|
+
return /* @__PURE__ */ jsxs(
|
|
353
|
+
"div",
|
|
354
|
+
{ className: "gen-ui-card", children: [comp.label && /* @__PURE__ */ jsx("h2", { className: "gen-ui-card-title", children: comp.label }), comp.value && /* @__PURE__ */ jsx("p", { className: "gen-ui-card-content", children: comp.value })] },
|
|
355
|
+
comp.id
|
|
356
|
+
);
|
|
357
|
+
case "list":
|
|
358
|
+
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);
|
|
359
|
+
case "image":
|
|
904
360
|
return /* @__PURE__ */ jsx(
|
|
905
|
-
|
|
361
|
+
"img",
|
|
906
362
|
{
|
|
907
|
-
|
|
908
|
-
|
|
363
|
+
src: comp.url,
|
|
364
|
+
alt: comp.label || "",
|
|
365
|
+
className: "gen-ui-image",
|
|
909
366
|
},
|
|
910
|
-
|
|
367
|
+
comp.id
|
|
368
|
+
);
|
|
369
|
+
case "link":
|
|
370
|
+
return /* @__PURE__ */ jsx(
|
|
371
|
+
"a",
|
|
372
|
+
{
|
|
373
|
+
href: comp.url,
|
|
374
|
+
className: "gen-ui-link",
|
|
375
|
+
children: comp.label || comp.url,
|
|
376
|
+
},
|
|
377
|
+
comp.id
|
|
911
378
|
);
|
|
912
379
|
case "table":
|
|
913
|
-
return /* @__PURE__ */ jsx(
|
|
914
|
-
|
|
915
|
-
|
|
380
|
+
return /* @__PURE__ */ jsx(
|
|
381
|
+
"div",
|
|
382
|
+
{
|
|
383
|
+
className: "gen-ui-table-wrapper",
|
|
384
|
+
children: /* @__PURE__ */ jsxs("table", {
|
|
385
|
+
className: "gen-ui-table",
|
|
386
|
+
children: [
|
|
387
|
+
comp.columns &&
|
|
388
|
+
/* @__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)) }) }),
|
|
389
|
+
comp.rows &&
|
|
390
|
+
/* @__PURE__ */ jsx("tbody", {
|
|
391
|
+
className: "gen-ui-table-body",
|
|
392
|
+
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)),
|
|
393
|
+
}),
|
|
394
|
+
],
|
|
395
|
+
}),
|
|
396
|
+
},
|
|
397
|
+
comp.id
|
|
398
|
+
);
|
|
399
|
+
case "form":
|
|
400
|
+
return /* @__PURE__ */ jsx("form", { className: "gen-ui-form", children: comp.items?.map((field) => renderComponent(field)) }, comp.id);
|
|
916
401
|
default:
|
|
917
402
|
return null;
|
|
918
403
|
}
|
|
919
|
-
}) });
|
|
920
|
-
}
|
|
921
|
-
var AizekChatBot = ({
|
|
922
|
-
clientId,
|
|
923
|
-
headers
|
|
924
|
-
}) => {
|
|
925
|
-
const defaultConfig = {
|
|
926
|
-
welcomeMessage: "Merhaba! Size nas\u0131l yard\u0131mc\u0131 olabilirimmmmm?",
|
|
927
|
-
buttonBackground: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
|
|
928
|
-
placeholder: "Mesaj\u0131n\u0131z\u0131 yaz\u0131n...",
|
|
929
|
-
buttonPosition: "bottom-left",
|
|
930
|
-
buttonSize: "md",
|
|
931
|
-
chatWidth: "400px",
|
|
932
|
-
chatHeight: "600px",
|
|
933
|
-
showTypingIndicator: true,
|
|
934
|
-
initialOpen: true,
|
|
935
|
-
headerBackground: "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
|
|
936
|
-
companyLogo: void 0,
|
|
937
|
-
companyName: "AI Asistan"
|
|
938
404
|
};
|
|
405
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
406
|
+
className: "generative-ui-container",
|
|
407
|
+
ref: containerRef,
|
|
408
|
+
children: [
|
|
409
|
+
(uiData.title || uiData.description) &&
|
|
410
|
+
/* @__PURE__ */ jsxs("div", {
|
|
411
|
+
className: "generative-ui-header",
|
|
412
|
+
children: [uiData.title && /* @__PURE__ */ jsx("h1", { className: "generative-ui-title", children: uiData.title }), uiData.description && /* @__PURE__ */ jsx("p", { className: "generative-ui-description", children: uiData.description })],
|
|
413
|
+
}),
|
|
414
|
+
uiData.components.map((comp) => renderComponent(comp)),
|
|
415
|
+
],
|
|
416
|
+
});
|
|
417
|
+
};
|
|
418
|
+
var MessageBubble = ({ message, onAction }) => {
|
|
419
|
+
console.log("MESSAGE", message);
|
|
420
|
+
const isUser = message.role === "user";
|
|
421
|
+
const approval = message.role === "approval";
|
|
422
|
+
if (approval) {
|
|
423
|
+
return /* @__PURE__ */ jsx(Fragment, {});
|
|
424
|
+
}
|
|
425
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
426
|
+
className: `message-container ${isUser ? "user" : "assistant"}`,
|
|
427
|
+
children: [
|
|
428
|
+
/* @__PURE__ */ jsx("div", {
|
|
429
|
+
className: `message-bubble ${isUser ? "user" : "assistant"}`,
|
|
430
|
+
children: isUser
|
|
431
|
+
? message.text && /* @__PURE__ */ jsx("div", { className: "markdown-content", children: message.text })
|
|
432
|
+
: /* @__PURE__ */ jsxs(Fragment, {
|
|
433
|
+
children: [
|
|
434
|
+
message.text && /* @__PURE__ */ jsx("div", { className: "markdown-content", children: /* @__PURE__ */ jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: message.text }) }),
|
|
435
|
+
message.ui &&
|
|
436
|
+
/* @__PURE__ */ jsx(GenericUIRenderer, {
|
|
437
|
+
uiData: message.ui,
|
|
438
|
+
onInteraction: (event) => {
|
|
439
|
+
console.log("event", event);
|
|
440
|
+
if (event.buttonId === "submit") {
|
|
441
|
+
onAction(JSON.stringify(event.formData), true);
|
|
442
|
+
} else {
|
|
443
|
+
onAction(event.action, true);
|
|
444
|
+
}
|
|
445
|
+
},
|
|
446
|
+
}),
|
|
447
|
+
],
|
|
448
|
+
}),
|
|
449
|
+
}),
|
|
450
|
+
/* @__PURE__ */ jsx("div", {
|
|
451
|
+
className: `message-time ${isUser ? "user" : "assistant"}`,
|
|
452
|
+
children: message.timestamp.toLocaleTimeString("tr-TR", {
|
|
453
|
+
hour: "2-digit",
|
|
454
|
+
minute: "2-digit",
|
|
455
|
+
}),
|
|
456
|
+
}),
|
|
457
|
+
],
|
|
458
|
+
});
|
|
459
|
+
};
|
|
460
|
+
var TypingDots = () => {
|
|
461
|
+
const [dots, setDots] = useState("");
|
|
462
|
+
useEffect(() => {
|
|
463
|
+
const interval = setInterval(() => {
|
|
464
|
+
setDots((prev) => {
|
|
465
|
+
if (prev === "...") return "";
|
|
466
|
+
return prev + ".";
|
|
467
|
+
});
|
|
468
|
+
}, 500);
|
|
469
|
+
return () => clearInterval(interval);
|
|
470
|
+
}, []);
|
|
471
|
+
return /* @__PURE__ */ jsx("div", {
|
|
472
|
+
className: "message-container assistant",
|
|
473
|
+
children: /* @__PURE__ */ jsx("div", { className: "message-bubble assistant", children: /* @__PURE__ */ jsx("div", { className: "message-typing-indicator", children: /* @__PURE__ */ jsx("span", { children: dots }) }) }),
|
|
474
|
+
});
|
|
475
|
+
};
|
|
476
|
+
|
|
477
|
+
// src/utils/chatbot.ts
|
|
478
|
+
var extractUIJsonFromText = (text) => {
|
|
479
|
+
const regex = /```ui-component([\s\S]*?)```/g;
|
|
480
|
+
let cleaned = text;
|
|
481
|
+
let match;
|
|
482
|
+
let uiData = null;
|
|
483
|
+
while ((match = regex.exec(text)) !== null) {
|
|
484
|
+
const block = match[1].trim();
|
|
485
|
+
try {
|
|
486
|
+
const parsed = JSON.parse(block);
|
|
487
|
+
if (parsed && parsed.components && Array.isArray(parsed.components)) {
|
|
488
|
+
parsed.components = parsed.components.map((comp, index) => {
|
|
489
|
+
if (!comp.id || typeof comp.id !== "string" || !comp.id.trim()) {
|
|
490
|
+
comp.id = `ui-comp-${index}-${Date.now()}`;
|
|
491
|
+
}
|
|
492
|
+
if (comp.type === "button") {
|
|
493
|
+
if (!comp.buttonType) {
|
|
494
|
+
comp.buttonType = "click";
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
if (comp.type === "input") {
|
|
498
|
+
if (!comp.fieldType) {
|
|
499
|
+
comp.fieldType = "text";
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
if (comp.type === "select") {
|
|
503
|
+
if (comp.options && Array.isArray(comp.options)) {
|
|
504
|
+
const firstOption = comp.options[0];
|
|
505
|
+
if (typeof firstOption === "object" && firstOption !== null) {
|
|
506
|
+
if ("label" in firstOption || "value" in firstOption) {
|
|
507
|
+
comp.options = comp.options.map((opt) => opt.label || opt.value || String(opt));
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
if (comp.type === "table") {
|
|
513
|
+
if (comp.columns && Array.isArray(comp.columns)) {
|
|
514
|
+
const firstCol = comp.columns[0];
|
|
515
|
+
if (typeof firstCol === "object" && firstCol !== null) {
|
|
516
|
+
comp.columns = comp.columns.map((col) => col.label || col.id || String(col));
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
if (comp.rows && Array.isArray(comp.rows)) {
|
|
520
|
+
const firstRow = comp.rows[0];
|
|
521
|
+
if (typeof firstRow === "object" && !Array.isArray(firstRow)) {
|
|
522
|
+
comp.rows = comp.rows.map((row) => {
|
|
523
|
+
if (Array.isArray(row)) return row;
|
|
524
|
+
return Object.values(row).map((val) => {
|
|
525
|
+
if (typeof val === "object" && val !== null) {
|
|
526
|
+
if (val.type === "image" && val.src) return val.src;
|
|
527
|
+
if (val.value !== void 0) return String(val.value);
|
|
528
|
+
}
|
|
529
|
+
return String(val || "");
|
|
530
|
+
});
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
if (comp.type === "form" && comp.items && Array.isArray(comp.items)) {
|
|
536
|
+
comp.items = comp.items.map((field, fieldIndex) => {
|
|
537
|
+
if (!field.id || !field.id.trim()) {
|
|
538
|
+
field.id = `field-${fieldIndex}-${Date.now()}`;
|
|
539
|
+
}
|
|
540
|
+
if (field.optional !== void 0) {
|
|
541
|
+
field.requiredField = !field.optional;
|
|
542
|
+
delete field.optional;
|
|
543
|
+
}
|
|
544
|
+
if (field.required !== void 0) {
|
|
545
|
+
field.requiredField = field.required;
|
|
546
|
+
delete field.required;
|
|
547
|
+
}
|
|
548
|
+
if (field.type === "input" && !field.fieldType) {
|
|
549
|
+
field.fieldType = "text";
|
|
550
|
+
}
|
|
551
|
+
if (field.type === "select" && field.options && Array.isArray(field.options)) {
|
|
552
|
+
const firstOpt = field.options[0];
|
|
553
|
+
if (typeof firstOpt === "object" && firstOpt !== null) {
|
|
554
|
+
field.options = field.options.map((opt) => opt.label || opt.value || String(opt));
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
return field;
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
if (comp.type === "list" && comp.items && Array.isArray(comp.items)) {
|
|
561
|
+
comp.items = comp.items.map((item, itemIndex) => {
|
|
562
|
+
if (typeof item === "string") {
|
|
563
|
+
return {
|
|
564
|
+
id: `list-item-${itemIndex}-${Date.now()}`,
|
|
565
|
+
type: "text",
|
|
566
|
+
value: item,
|
|
567
|
+
label: item,
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
if (!item.id || !item.id.trim()) {
|
|
571
|
+
item.id = `list-item-${itemIndex}-${Date.now()}`;
|
|
572
|
+
}
|
|
573
|
+
return item;
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
return comp;
|
|
577
|
+
});
|
|
578
|
+
uiData = parsed;
|
|
579
|
+
}
|
|
580
|
+
cleaned = cleaned.replace(match[0], "").trim();
|
|
581
|
+
break;
|
|
582
|
+
} catch (e) {
|
|
583
|
+
console.error("Invalid ui-component JSON:", e, block);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
return {
|
|
587
|
+
cleanedText: cleaned,
|
|
588
|
+
uiData,
|
|
589
|
+
};
|
|
590
|
+
};
|
|
591
|
+
var generateId = () => Date.now().toString() + Math.random().toString(36).substr(2, 9);
|
|
592
|
+
var normalizeHeaders = (headers) => {
|
|
593
|
+
const result = {};
|
|
594
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
595
|
+
if (!value) continue;
|
|
596
|
+
if (key.toLowerCase() === "cookie") {
|
|
597
|
+
result["x-cookie"] = value;
|
|
598
|
+
} else {
|
|
599
|
+
result[key] = value;
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
return result;
|
|
603
|
+
};
|
|
604
|
+
var AizekChatBot = ({ clientId, headers }) => {
|
|
605
|
+
const messagesEndRef = useRef(null);
|
|
939
606
|
const [config, setConfig] = useState(defaultConfig);
|
|
607
|
+
const [anthropic, setAnthropic] = useState();
|
|
608
|
+
const [messages, setMessages] = useState([]);
|
|
609
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
610
|
+
const [mcpClient, setMcpClient] = useState();
|
|
940
611
|
const [isConfigLoading, setIsConfigLoading] = useState(true);
|
|
941
|
-
const [finalMcpUrl, setFinalMcpUrl] = useState("");
|
|
942
|
-
const [apiKey, setApiKey] = useState("");
|
|
943
|
-
const {
|
|
944
|
-
welcomeMessage,
|
|
945
|
-
buttonBackground,
|
|
946
|
-
placeholder,
|
|
947
|
-
buttonPosition,
|
|
948
|
-
buttonSize,
|
|
949
|
-
chatWidth,
|
|
950
|
-
chatHeight,
|
|
951
|
-
showTypingIndicator,
|
|
952
|
-
initialOpen,
|
|
953
|
-
headerBackground,
|
|
954
|
-
companyLogo,
|
|
955
|
-
companyName
|
|
956
|
-
} = config;
|
|
957
612
|
const [isOpen, setIsOpen] = useState(false);
|
|
958
613
|
const [headerValidation, setHeaderValidation] = useState(null);
|
|
959
614
|
const [showAlert, setShowAlert] = useState(true);
|
|
615
|
+
const { button_background, button_position, button_size, chat_height, chat_width, company_logo, company_name, header_background, initial_open, placeholder, show_typing_indicator, welcome_message } = config.chat_widget_settings;
|
|
960
616
|
useEffect(() => {
|
|
961
617
|
const loadConfig = async () => {
|
|
962
618
|
try {
|
|
963
619
|
setIsConfigLoading(true);
|
|
964
620
|
const apiResponse = await fetchChatWidgetSettings(clientId);
|
|
965
|
-
if (
|
|
966
|
-
const
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
{
|
|
621
|
+
if (apiResponse.success) {
|
|
622
|
+
const anthropic2 = new Anthropic({ apiKey: apiResponse.data.openai_key, dangerouslyAllowBrowser: true });
|
|
623
|
+
const mcpClient2 = new Client({ name: "mcp-client-cli", version: "1.0.0" });
|
|
624
|
+
const transport = new SSEClientTransport(new URL("", apiResponse.data.mcp_url), {
|
|
625
|
+
eventSourceInit: {
|
|
626
|
+
fetch: (url, init) => {
|
|
627
|
+
if (headers) {
|
|
628
|
+
const dynamicHeaders = normalizeHeaders(headers);
|
|
629
|
+
return fetch(url, {
|
|
630
|
+
headers: {
|
|
631
|
+
...(init?.headers ?? {}),
|
|
632
|
+
...dynamicHeaders,
|
|
633
|
+
},
|
|
634
|
+
});
|
|
635
|
+
} else {
|
|
636
|
+
return fetch(url, {
|
|
637
|
+
headers: {
|
|
638
|
+
...(init?.headers ?? {}),
|
|
639
|
+
},
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
},
|
|
643
|
+
},
|
|
644
|
+
});
|
|
645
|
+
await mcpClient2.connect(transport);
|
|
646
|
+
setMcpClient(mcpClient2);
|
|
647
|
+
setAnthropic(anthropic2);
|
|
648
|
+
if (headers && apiResponse.data.auth_config) {
|
|
649
|
+
const validationResult = validateHeaders(headers, apiResponse.data.auth_config, {
|
|
970
650
|
allowExtra: false,
|
|
971
|
-
caseSensitive: true
|
|
972
|
-
}
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
651
|
+
caseSensitive: true,
|
|
652
|
+
});
|
|
653
|
+
setHeaderValidation(validationResult);
|
|
654
|
+
}
|
|
655
|
+
if (!apiResponse.data.chat_widget_settings) {
|
|
656
|
+
setConfig({
|
|
657
|
+
auth_config: apiResponse.data.auth_config,
|
|
658
|
+
mcp_url: apiResponse.data.mcp_url,
|
|
659
|
+
openai_key: apiResponse.data.openai_key,
|
|
660
|
+
chat_widget_settings: {
|
|
661
|
+
api_source_id: 0,
|
|
662
|
+
chat_widget_settings_id: 0,
|
|
663
|
+
created_at: "",
|
|
664
|
+
updated_at: "",
|
|
665
|
+
button_background: defaultConfig.chat_widget_settings.button_background,
|
|
666
|
+
button_position: defaultConfig.chat_widget_settings.button_position,
|
|
667
|
+
button_size: defaultConfig.chat_widget_settings.button_size,
|
|
668
|
+
chat_height: defaultConfig.chat_widget_settings.chat_height,
|
|
669
|
+
chat_width: defaultConfig.chat_widget_settings.chat_width,
|
|
670
|
+
company_logo: defaultConfig.chat_widget_settings.company_logo,
|
|
671
|
+
company_name: defaultConfig.chat_widget_settings.company_name,
|
|
672
|
+
header_background: defaultConfig.chat_widget_settings.header_background,
|
|
673
|
+
initial_open: defaultConfig.chat_widget_settings.initial_open,
|
|
674
|
+
placeholder: defaultConfig.chat_widget_settings.placeholder,
|
|
675
|
+
show_typing_indicator: defaultConfig.chat_widget_settings.show_typing_indicator,
|
|
676
|
+
welcome_message: defaultConfig.chat_widget_settings.welcome_message,
|
|
677
|
+
},
|
|
678
|
+
});
|
|
679
|
+
} else {
|
|
680
|
+
setConfig(apiResponse.data);
|
|
681
|
+
}
|
|
983
682
|
}
|
|
984
683
|
} catch (error) {
|
|
985
684
|
console.error("Failed to load chat widget config:", error);
|
|
986
|
-
setFinalMcpUrl("");
|
|
987
685
|
} finally {
|
|
988
686
|
setIsConfigLoading(false);
|
|
989
687
|
}
|
|
990
688
|
};
|
|
991
689
|
loadConfig();
|
|
992
|
-
}, [
|
|
993
|
-
const internalChatbot = useChatbot({
|
|
994
|
-
mcpUrl: finalMcpUrl,
|
|
995
|
-
apiKey,
|
|
996
|
-
headers,
|
|
997
|
-
config
|
|
998
|
-
});
|
|
999
|
-
const messages = internalChatbot.messages;
|
|
1000
|
-
const isLoading = internalChatbot.isLoading;
|
|
1001
|
-
const handleSendMessage = internalChatbot.sendMessage;
|
|
1002
|
-
const toggleChat = () => {
|
|
1003
|
-
const newIsOpen = !isOpen;
|
|
1004
|
-
setIsOpen(newIsOpen);
|
|
1005
|
-
};
|
|
690
|
+
}, []);
|
|
1006
691
|
useEffect(() => {
|
|
1007
|
-
setIsOpen(
|
|
1008
|
-
}, [
|
|
1009
|
-
const messagesEndRef = useRef(null);
|
|
692
|
+
setIsOpen(initial_open);
|
|
693
|
+
}, [initial_open]);
|
|
1010
694
|
useEffect(() => {
|
|
1011
695
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
1012
696
|
}, [messages]);
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
{
|
|
1029
|
-
components: message.ui,
|
|
1030
|
-
onInteraction: (event) => {
|
|
1031
|
-
console.log(event);
|
|
1032
|
-
if (event.type === "buttonClick" && typeof event.value === "string") {
|
|
1033
|
-
onAction(event.value, true);
|
|
1034
|
-
} else if (event.type === "formSubmit") {
|
|
1035
|
-
onAction(JSON.stringify(event.values), true);
|
|
1036
|
-
}
|
|
1037
|
-
}
|
|
1038
|
-
}
|
|
1039
|
-
)
|
|
1040
|
-
] }) }),
|
|
1041
|
-
/* @__PURE__ */ jsx("div", { className: `message-time ${isUser ? "user" : "assistant"}`, children: message.timestamp.toLocaleTimeString("tr-TR", {
|
|
1042
|
-
hour: "2-digit",
|
|
1043
|
-
minute: "2-digit"
|
|
1044
|
-
}) })
|
|
1045
|
-
] })
|
|
1046
|
-
] });
|
|
1047
|
-
};
|
|
1048
|
-
const TypingDots = () => {
|
|
1049
|
-
const [dots, setDots] = useState("");
|
|
1050
|
-
useEffect(() => {
|
|
1051
|
-
const interval = setInterval(() => {
|
|
1052
|
-
setDots((prev) => {
|
|
1053
|
-
if (prev === "...") return "";
|
|
1054
|
-
return prev + ".";
|
|
1055
|
-
});
|
|
1056
|
-
}, 500);
|
|
1057
|
-
return () => clearInterval(interval);
|
|
1058
|
-
}, []);
|
|
1059
|
-
return /* @__PURE__ */ jsx("span", { children: dots });
|
|
697
|
+
if (isConfigLoading || !mcpClient || !anthropic) {
|
|
698
|
+
return /* @__PURE__ */ jsx("button", { className: `floating-button ${button_position} button-sizes ${button_size}`, style: { background: button_background }, children: /* @__PURE__ */ jsx("div", { className: "loading-spinner" }) });
|
|
699
|
+
}
|
|
700
|
+
const historyMessages = (history, currentUserText) => {
|
|
701
|
+
const claudeHistory = history
|
|
702
|
+
.filter((m) => m.role === "user" || m.role === "assistant")
|
|
703
|
+
.map((m) => ({
|
|
704
|
+
role: m.role,
|
|
705
|
+
content: m.text ?? JSON.stringify(m.ui ?? ""),
|
|
706
|
+
}));
|
|
707
|
+
claudeHistory.push({
|
|
708
|
+
role: "user",
|
|
709
|
+
content: currentUserText,
|
|
710
|
+
});
|
|
711
|
+
return claudeHistory;
|
|
1060
712
|
};
|
|
1061
|
-
const
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
const hasWarnings = extraKeys.length > 0;
|
|
1069
|
-
const alertType = hasErrors ? "error" : "warning";
|
|
1070
|
-
const getAlertIcon = () => {
|
|
1071
|
-
if (hasErrors) {
|
|
1072
|
-
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" }) });
|
|
1073
|
-
}
|
|
1074
|
-
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" }) });
|
|
713
|
+
const addMessage = (payload) => {
|
|
714
|
+
const newMessage = {
|
|
715
|
+
id: generateId(),
|
|
716
|
+
text: payload.text,
|
|
717
|
+
ui: payload.ui,
|
|
718
|
+
role: payload.role,
|
|
719
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
1075
720
|
};
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
/* @__PURE__ */ jsx("h4", { className: "alert-title", children: hasErrors ? "Header Do\u011Frulama Hatas\u0131" : "Header Uyar\u0131s\u0131" }),
|
|
1080
|
-
/* @__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." }),
|
|
1081
|
-
missingKeys.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
1082
|
-
/* @__PURE__ */ jsx("strong", { children: "Eksik Header'lar:" }),
|
|
1083
|
-
/* @__PURE__ */ jsx("ul", { className: "alert-list", children: missingKeys.map((key, index) => /* @__PURE__ */ jsxs("li", { className: "alert-list-item", children: [
|
|
1084
|
-
/* @__PURE__ */ jsx("span", { children: "\u2022" }),
|
|
1085
|
-
/* @__PURE__ */ jsx("code", { children: key })
|
|
1086
|
-
] }, index)) })
|
|
1087
|
-
] }),
|
|
1088
|
-
emptyValueKeys.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
1089
|
-
/* @__PURE__ */ jsx("strong", { children: "Bo\u015F De\u011Ferli Header'lar:" }),
|
|
1090
|
-
/* @__PURE__ */ jsx("ul", { className: "alert-list", children: emptyValueKeys.map((key, index) => /* @__PURE__ */ jsxs("li", { className: "alert-list-item", children: [
|
|
1091
|
-
/* @__PURE__ */ jsx("span", { children: "\u2022" }),
|
|
1092
|
-
/* @__PURE__ */ jsx("code", { children: key }),
|
|
1093
|
-
/* @__PURE__ */ jsx("span", { children: "(de\u011Fer bo\u015F olamaz)" })
|
|
1094
|
-
] }, index)) })
|
|
1095
|
-
] }),
|
|
1096
|
-
extraKeys.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
1097
|
-
/* @__PURE__ */ jsx("strong", { children: "Fazla Header'lar:" }),
|
|
1098
|
-
/* @__PURE__ */ jsx("ul", { className: "alert-list", children: extraKeys.map((key, index) => /* @__PURE__ */ jsxs("li", { className: "alert-list-item", children: [
|
|
1099
|
-
/* @__PURE__ */ jsx("span", { children: "\u2022" }),
|
|
1100
|
-
/* @__PURE__ */ jsx("code", { children: key })
|
|
1101
|
-
] }, index)) })
|
|
1102
|
-
] })
|
|
1103
|
-
] }),
|
|
1104
|
-
/* @__PURE__ */ jsx(
|
|
1105
|
-
"button",
|
|
1106
|
-
{
|
|
1107
|
-
onClick: () => setShowAlert(false),
|
|
1108
|
-
className: "alert-close-button",
|
|
1109
|
-
"aria-label": "Uyar\u0131y\u0131 kapat",
|
|
1110
|
-
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" }) })
|
|
1111
|
-
}
|
|
1112
|
-
)
|
|
1113
|
-
] }) });
|
|
721
|
+
setMessages((prev) => [...prev, newMessage]);
|
|
722
|
+
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
723
|
+
return newMessage;
|
|
1114
724
|
};
|
|
1115
|
-
const
|
|
1116
|
-
|
|
1117
|
-
const
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
if (textareaRef.current) {
|
|
1124
|
-
textareaRef.current.style.height = "auto";
|
|
1125
|
-
}
|
|
1126
|
-
}
|
|
1127
|
-
};
|
|
1128
|
-
const handleKeyDown = (e) => {
|
|
1129
|
-
if (e.key === "Enter" && !e.shiftKey) {
|
|
1130
|
-
e.preventDefault();
|
|
1131
|
-
handleSubmit(e);
|
|
1132
|
-
}
|
|
1133
|
-
};
|
|
1134
|
-
const handleInputChange = (e) => {
|
|
1135
|
-
setMessage(e.target.value);
|
|
1136
|
-
const textarea = e.target;
|
|
1137
|
-
textarea.style.height = "auto";
|
|
1138
|
-
textarea.style.height = Math.min(textarea.scrollHeight, 120) + "px";
|
|
725
|
+
const sendMessage = async (message, approval) => {
|
|
726
|
+
if (!message.trim() || isLoading) return;
|
|
727
|
+
const newMessage = {
|
|
728
|
+
id: generateId(),
|
|
729
|
+
text: message,
|
|
730
|
+
ui: void 0,
|
|
731
|
+
role: approval ? "approval" : "user",
|
|
732
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
1139
733
|
};
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
"
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
734
|
+
setMessages((prev) => [...prev, newMessage]);
|
|
735
|
+
setIsLoading(true);
|
|
736
|
+
const toolsResult = await mcpClient.listTools();
|
|
737
|
+
const tools = toolsResult.tools.map((tool) => {
|
|
738
|
+
return {
|
|
739
|
+
name: tool.name,
|
|
740
|
+
description: tool.description,
|
|
741
|
+
input_schema: tool.inputSchema,
|
|
742
|
+
};
|
|
743
|
+
});
|
|
744
|
+
try {
|
|
745
|
+
const historyForContext = historyMessages([...messages, newMessage], message);
|
|
746
|
+
const response = await anthropic.beta.messages.create({
|
|
747
|
+
model: "claude-sonnet-4-5",
|
|
748
|
+
betas: ["structured-outputs-2025-11-13"],
|
|
749
|
+
max_tokens: 5e3,
|
|
750
|
+
messages: historyForContext,
|
|
751
|
+
tools,
|
|
752
|
+
system: GENERATIVE_UI_SYSTEM_PROMPT,
|
|
753
|
+
});
|
|
754
|
+
for (const content of response.content) {
|
|
755
|
+
if (content.type === "tool_use") {
|
|
756
|
+
const toolCall = await mcpClient.callTool({ name: content.name, arguments: content.input });
|
|
757
|
+
const toolMessagesForContext = historyMessages([...messages, newMessage], JSON.stringify(toolCall.structuredContent));
|
|
758
|
+
const finalResponse = await anthropic.beta.messages.create({
|
|
759
|
+
model: "claude-sonnet-4-5",
|
|
760
|
+
max_tokens: 1024,
|
|
761
|
+
betas: ["structured-outputs-2025-11-13"],
|
|
762
|
+
messages: toolMessagesForContext,
|
|
763
|
+
tools,
|
|
764
|
+
system: GENERATIVE_UI_SYSTEM_PROMPT,
|
|
765
|
+
});
|
|
766
|
+
const textBlock = finalResponse.content.find((x) => x.type === "text");
|
|
767
|
+
const { cleanedText, uiData } = extractUIJsonFromText(textBlock?.text ?? "");
|
|
768
|
+
addMessage({ ui: uiData, text: cleanedText || void 0, role: "assistant" });
|
|
769
|
+
} else if (content.type === "text") {
|
|
770
|
+
const { cleanedText, uiData } = extractUIJsonFromText(content?.text);
|
|
771
|
+
console.log(cleanedText, uiData);
|
|
772
|
+
addMessage({ ui: uiData, text: cleanedText || void 0, role: "assistant" });
|
|
1160
773
|
}
|
|
1161
|
-
|
|
1162
|
-
|
|
774
|
+
}
|
|
775
|
+
setIsLoading(false);
|
|
776
|
+
} catch (error) {
|
|
777
|
+
console.error("Error sending message:", error);
|
|
778
|
+
addMessage({ text: "\xDCzg\xFCn\xFCm, bir hata olu\u015Ftu. L\xFCtfen tekrar deneyin.", role: "assistant" });
|
|
779
|
+
setIsLoading(false);
|
|
780
|
+
}
|
|
1163
781
|
};
|
|
1164
|
-
const
|
|
1165
|
-
|
|
782
|
+
const toggleChat = () => {
|
|
783
|
+
const newIsOpen = !isOpen;
|
|
784
|
+
setIsOpen(newIsOpen);
|
|
1166
785
|
};
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
"
|
|
1170
|
-
{
|
|
1171
|
-
className: `
|
|
1172
|
-
style: {
|
|
1173
|
-
children: /* @__PURE__ */
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
786
|
+
return /* @__PURE__ */ jsxs(Fragment, {
|
|
787
|
+
children: [
|
|
788
|
+
isOpen && /* @__PURE__ */ jsx("div", { className: `overlay floating-chat-overlay ${isOpen ? "is-open" : ""}`, onClick: toggleChat }),
|
|
789
|
+
/* @__PURE__ */ jsx("div", {
|
|
790
|
+
className: `chat-container ${button_position} ${isOpen ? "is-open" : ""}`,
|
|
791
|
+
style: { width: chat_width, height: chat_height },
|
|
792
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
793
|
+
className: "chatbot-container",
|
|
794
|
+
children: [
|
|
795
|
+
/* @__PURE__ */ jsxs("div", {
|
|
796
|
+
className: "header",
|
|
797
|
+
style: { background: header_background },
|
|
798
|
+
children: [
|
|
799
|
+
/* @__PURE__ */ jsx("div", {
|
|
800
|
+
className: "logo-container",
|
|
801
|
+
children: company_logo
|
|
802
|
+
? company_logo.startsWith("http") || company_logo.startsWith("data:")
|
|
803
|
+
? /* @__PURE__ */ jsx("img", {
|
|
804
|
+
src: company_logo,
|
|
805
|
+
alt: "Company Logo",
|
|
806
|
+
className: "logo-image",
|
|
807
|
+
})
|
|
808
|
+
: /* @__PURE__ */ jsx("span", { className: "logo-text", children: company_logo })
|
|
809
|
+
: "\u{1F916}",
|
|
810
|
+
}),
|
|
811
|
+
/* @__PURE__ */ jsxs("div", {
|
|
812
|
+
children: [/* @__PURE__ */ jsx("h3", { className: "company-name", children: company_name }), /* @__PURE__ */ jsx("p", { className: "status-text", children: isLoading ? "Yaz\u0131yor..." : "\xC7evrimi\xE7i" })],
|
|
813
|
+
}),
|
|
814
|
+
],
|
|
815
|
+
}),
|
|
816
|
+
/* @__PURE__ */ jsxs("div", {
|
|
817
|
+
className: "messages-container",
|
|
818
|
+
children: [
|
|
819
|
+
/* @__PURE__ */ jsx(HeaderAlert, { headerValidation, setShowAlert, showAlert }),
|
|
820
|
+
messages.length === 0
|
|
821
|
+
? /* @__PURE__ */ jsxs("div", {
|
|
822
|
+
className: "empty-state",
|
|
823
|
+
children: [
|
|
824
|
+
/* @__PURE__ */ jsx("div", { className: "empty-state-icon", children: "\u{1F4AC}" }),
|
|
825
|
+
/* @__PURE__ */ jsx("h4", { className: "empty-state-title", children: welcome_message }),
|
|
826
|
+
/* @__PURE__ */ jsx("p", { className: "empty-state-description", children: "A\u015Fa\u011F\u0131daki alana mesaj\u0131n\u0131z\u0131 yazarak ba\u015Flayabilirsiniz." }),
|
|
827
|
+
],
|
|
828
|
+
})
|
|
829
|
+
: /* @__PURE__ */ jsxs(Fragment, {
|
|
830
|
+
children: [
|
|
831
|
+
messages.map((message) =>
|
|
832
|
+
/* @__PURE__ */ jsx(
|
|
833
|
+
MessageBubble,
|
|
834
|
+
{
|
|
835
|
+
message,
|
|
836
|
+
onAction: sendMessage,
|
|
837
|
+
},
|
|
838
|
+
message.id
|
|
839
|
+
)
|
|
840
|
+
),
|
|
841
|
+
show_typing_indicator && isLoading && /* @__PURE__ */ jsx(TypingDots, {}),
|
|
842
|
+
],
|
|
843
|
+
}),
|
|
844
|
+
/* @__PURE__ */ jsx("div", { ref: messagesEndRef }),
|
|
845
|
+
],
|
|
846
|
+
}),
|
|
847
|
+
/* @__PURE__ */ jsx(ChatInput, { handleSendMessage: sendMessage, isLoading, placeholder }),
|
|
848
|
+
],
|
|
849
|
+
}),
|
|
850
|
+
}),
|
|
851
|
+
/* @__PURE__ */ jsx("button", {
|
|
1229
852
|
onClick: toggleChat,
|
|
1230
|
-
className: `floating-button ${
|
|
1231
|
-
style: { background:
|
|
853
|
+
className: `floating-button ${button_position} button-sizes ${button_size} ${isOpen ? "is-open" : ""}`,
|
|
854
|
+
style: { background: button_background },
|
|
1232
855
|
"aria-label": isOpen ? "Chati kapat" : "Chati a\xE7",
|
|
1233
|
-
children: isOpen
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
856
|
+
children: isOpen
|
|
857
|
+
? /* @__PURE__ */ jsx("svg", {
|
|
858
|
+
width: "24",
|
|
859
|
+
height: "24",
|
|
860
|
+
viewBox: "0 0 24 24",
|
|
861
|
+
fill: "currentColor",
|
|
862
|
+
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" }),
|
|
863
|
+
})
|
|
864
|
+
: /* @__PURE__ */ jsx("svg", {
|
|
865
|
+
width: "24",
|
|
866
|
+
height: "24",
|
|
867
|
+
viewBox: "0 0 24 24",
|
|
868
|
+
fill: "currentColor",
|
|
869
|
+
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" }),
|
|
870
|
+
}),
|
|
871
|
+
}),
|
|
872
|
+
],
|
|
873
|
+
});
|
|
1237
874
|
};
|
|
1238
875
|
|
|
1239
876
|
export { AizekChatBot };
|
|
1240
877
|
//# sourceMappingURL=index.mjs.map
|
|
1241
|
-
//# sourceMappingURL=index.mjs.map
|
|
878
|
+
//# sourceMappingURL=index.mjs.map
|