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